Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
boulep_2d.c
Go to the documentation of this file.
1/* =============================================================================
2** This file is part of the mmg software package for the tetrahedral
3** mesh modification.
4** Copyright (c) Bx INP/CNRS/Inria/UBordeaux/UPMC, 2004-
5**
6** mmg is free software: you can redistribute it and/or modify it
7** under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation, either version 3 of the License, or
9** (at your option) any later version.
10**
11** mmg is distributed in the hope that it will be useful, but WITHOUT
12** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14** License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public
17** License and of the GNU General Public License along with mmg (in
18** files COPYING.LESSER and COPYING). If not, see
19** <http://www.gnu.org/licenses/>. Please read their terms carefully and
20** use this copy of the mmg distribution only if you accept them.
21** =============================================================================
22*/
23
24#include "libmmg2d.h"
25#include "libmmg2d_private.h"
26
27
28static uint8_t inxt[3] = {1,2,0};
29static uint8_t iprev[3] = {2,0,1};
30
31/* Function boulep should be eventually removed (after all its occurences are removed) */
32/* Find all triangles sharing P
33 in: ifirst : triangle containing p
34 iploc : index of p in start
35 out: list : list of triangles */
36int MMG2D_boulep(MMG5_pMesh mesh, MMG5_int ifirst, int iploc, MMG5_int * list) {
37 MMG5_pTria pt;
38 MMG5_pPoint ppt;
39 MMG5_int ip,iel,*adja,iadr;
40 int voy,ilist,i;
41
42 if ( ifirst < 1 ) return 0;
43 pt = &mesh->tria[ifirst];
44 if ( !MG_EOK(pt) ) return 0;
45 ip = pt->v[iploc];
46 ppt = &mesh->point[ip];
47 if ( !MG_VOK(ppt) ) return 0;
48
49 /* init list */
50 ilist = 1;
51 list[ilist] = 3*ifirst + iploc;
52
53 iadr = 3*(ifirst-1) + 1;
54 adja = &mesh->adja[iadr];
55 iel = adja[inxt[iploc]]/3;
56 voy = adja[inxt[iploc]]%3;
57 i = inxt[voy];
58
59 while ( iel && (iel != ifirst) && mesh->tria[iel].v[0]){
60 if(ilist==MMG2D_LMAX-1) return 0;
61 list[++ilist] = 3*iel + i;
62 assert( ip==(&mesh->tria[iel])->v[i] );
63 iadr = 3*(iel-1) + 1;
64 adja = &mesh->adja[iadr];
65 iel = adja[inxt[i]]/3;
66 voy = adja[inxt[i]]%3;
67 i = inxt[voy];
68 }
69
70 if ( iel!=ifirst ) {
71 iadr = 3*(ifirst-1) + 1;
72 adja = &mesh->adja[iadr];
73 iel = adja[iprev[iploc]]/3;
74 voy = adja[iprev[iploc]]%3;
75 i = iprev[voy];
76
77 while ( iel && (iel != ifirst) && mesh->tria[iel].v[0]) {
78 if(ilist==MMG2D_LMAX-1) return 0;
79 list[++ilist] = 3*iel + i;
80 assert( ip==(&mesh->tria[iel])->v[i] );
81 iadr = 3*(iel-1) + 1;
82 adja = &mesh->adja[iadr];
83 iel = adja[iprev[i]]/3;
84 if (!iel) break;
85 voy = adja[iprev[i]]%3;
86 i = iprev[voy];
87
88 }
89 }
90
91 return ilist;
92}
93
115int MMG2D_boulen(MMG5_pMesh mesh, MMG5_int start,int8_t ip, MMG5_int *pleft, MMG5_int *pright, double *nn) {
116 MMG5_pTria pt;
117 MMG5_pPoint p1,p2;
118 double ux,uy,dd,n1[2],n2[2];
119 MMG5_int *adja,k,kk,refs;
120 int8_t notedg;
121 int8_t i,ii,i1,i2;
122
123 /* First travel of the ball of ip; initialization */
124 kk = start;
125 ii = MMG5_iprv2[ip];
126 refs = mesh->tria[start].ref;
127
128 do {
129 k = kk;
130 i = MMG5_iprv2[ii];
131 adja = &mesh->adja[3*(k-1)+1];
132 kk = adja[i] / 3;
133 ii = adja[i] % 3;
134
135 notedg = mesh->info.opnbdy ?
136 (!mesh->tria[k].tag[i]) : (mesh->tria[kk].ref == refs);
137 }
138 while ( kk && (kk != start) && notedg );
139
140 if ( kk == start ) {
141 fprintf(stderr," ## Error: %s: Unable to find a boundary edge in"
142 " the ball of point %" MMG5_PRId ".\n",__func__,MMG2D_indPt(mesh,mesh->tria[start].v[ip]));
143 return 0;
144 }
145
146 /* Calculation of the first normal vector */
147 pt = &mesh->tria[k];
148 i1 = MMG5_iprv2[i];
149 i2 = MMG5_inxt2[i];
150
151 p1 = &mesh->point[pt->v[i1]];
152 p2 = &mesh->point[pt->v[i2]];
153 ux = p2->c[0] - p1->c[0];
154 uy = p2->c[1] - p1->c[1];
155 dd = ux*ux + uy*uy;
156
157 if ( dd < MMG5_EPSD ) {
158 fprintf(stderr,"\n ## Error: %s: Null edge"
159 " length (%e).\n",__func__,dd);
160 return 0;
161 }
162
163 dd = 1.0 / sqrt(dd);
164 n1[0] = -uy*dd;
165 n1[1] = ux*dd;
166
167 *pright = 3*k+i1;
168
169 /* Second travel */
170 kk = start;
171 ii = MMG5_inxt2[ip];
172
173 do {
174 k = kk;
175 i = MMG5_inxt2[ii];
176 adja = &mesh->adja[3*(k-1)+1];
177 kk = adja[i] / 3;
178 ii = adja[i] % 3;
179
180 notedg = mesh->info.opnbdy ?
181 !mesh->tria[k].tag[i] : mesh->tria[kk].ref == refs;
182 }
183 while ( kk && (kk != start) && notedg );
184
185 /* Calculation of the second normal vector */
186 pt = &mesh->tria[k];
187 i1 = MMG5_inxt2[i];
188 i2 = MMG5_iprv2[i];
189
190 p1 = &mesh->point[pt->v[i1]];
191 p2 = &mesh->point[pt->v[i2]];
192 ux = p2->c[0] - p1->c[0];
193 uy = p2->c[1] - p1->c[1];
194 dd = ux*ux + uy*uy;
195
196 if ( dd < MMG5_EPSD ) {
197 fprintf(stderr,"\n ## Error: %s: Null edge length"
198 " (%e).\n",__func__,dd);
199 return 0;
200 }
201
202 dd = 1.0 / sqrt(dd);
203 n2[0] = uy*dd;
204 n2[1] = -ux*dd;
205
206 *pleft = 3*k+i1;
207
208 /* Averaging of normal vectors */
209 nn[0] = n1[0] + n2[0];
210 nn[1] = n1[1] + n2[1];
211 dd = nn[0]*nn[0] + nn[1]*nn[1];
212 if ( dd > MMG5_EPSD ){
213 dd = 1.0 / sqrt(dd);
214 nn[0] *= dd;
215 nn[1] *= dd;
216 }
217
218 return 1;
219}
220
231int MMG2D_bouleendp(MMG5_pMesh mesh,MMG5_int start,int8_t ip,MMG5_int *ip1,MMG5_int *ip2,MMG5_int *list) {
232 MMG5_pTria pt;
233 MMG5_int *adja,k;
234 int8_t i,i1,i2;
235 static int8_t mmgWarn0=0;
236 int ilist;
237
238 *ip1 = 0;
239 *ip2 = 0;
240 if ( start < 1 ) return 0;
241 pt = &mesh->tria[start];
242 if ( !MG_EOK(pt) ) return 0;
243
244 /* Travel elements in the forward sense */
245 ilist= 0;
246 k = start;
247 i = ip;
248 do {
249
250 if ( ilist > MMG2D_LMAX-2 ) return -ilist;
251 list[ilist] = k;
252 ++ilist;
253
254 pt = &mesh->tria[k];
255 adja = &mesh->adja[3*(k-1)+1];
256 i1 = MMG5_inxt2[i];
257 i2 = MMG5_iprv2[i];
258
259 if ( MG_EDG(pt->tag[i1]) ) {
260 if ( *ip1 == 0 ) *ip1 = pt->v[i2];
261 else {
262 if ( *ip2 != 0 && *ip1 != pt->v[i2] && *ip2 != pt->v[i2] ) {
263 if ( !mmgWarn0 ) {
264 mmgWarn0 = 1;
265 fprintf(stderr,"\n ## Error: %s: at least 1 non singular"
266 " point at the intersection of 3 edges.\n",
267 __func__);
268 }
269 return 0;
270 }
271 if ( *ip1 != pt->v[i2] ) *ip2 = pt->v[i2];
272 }
273 }
274
275 if ( MG_EDG(pt->tag[i2]) ) {
276 if ( *ip1 == 0 )
277 *ip1 = pt->v[i1];
278 else {
279 if ( *ip2 != 0 && *ip1 != pt->v[i1] && *ip2 != pt->v[i1] ) {
280 if ( !mmgWarn0 ) {
281 mmgWarn0 = 1;
282 fprintf(stderr,"\n ## Error: %s: at least 1 non singular"
283 " point at the intersection of 3 edges.\n",
284 __func__);
285 }
286 return 0;
287 }
288 if ( *ip1 != pt->v[i1] ) *ip2 = pt->v[i1];
289 }
290 }
291
292 k = adja[i1] / 3;
293 i = adja[i1] % 3;
294 i = MMG5_inxt2[i];
295
296 }
297 while ( k && k != start );
298 if ( k > 0 ) return ilist;
299
300 /* Travel the ball in the reverse sense when a boundary is hit, starting from the neighbor of k */
301 k = start;
302 i = ip;
303 adja = &mesh->adja[3*(k-1)+1];
304 i2 = MMG5_iprv2[i];
305 k = adja[i2] / 3;
306 i = adja[i2] % 3;
307 i = MMG5_iprv2[i];
308
309 if ( !k ) return ilist;
310
311 do {
312
313 if ( ilist > MMG2D_LMAX-2 ) return -ilist;
314 list[ilist] = k ;
315 ++ilist;
316
317 pt = &mesh->tria[k];
318 adja = &mesh->adja[3*(k-1)+1];
319 i1 = MMG5_inxt2[i];
320 i2 = MMG5_iprv2[i];
321
322 if ( MG_EDG(pt->tag[i1]) ) {
323 if ( *ip1 == 0 )
324 *ip1 = pt->v[i2];
325 else {
326 if ( *ip2 != 0 && *ip1 != pt->v[i2] && *ip2 != pt->v[i2] ) {
327 if ( !mmgWarn0 ) {
328 mmgWarn0 = 1;
329 fprintf(stderr,"\n ## Error: %s: at least 1 non singular"
330 " point at the intersection of 3 edges.\n",
331 __func__);
332 }
333 return 0;
334 }
335 if ( *ip1 != pt->v[i2] ) *ip2 = pt->v[i2];
336 }
337 }
338
339 if ( MG_EDG(pt->tag[i2]) ) {
340 if ( *ip1 == 0 ) *ip1 = pt->v[i1];
341 else {
342 if ( *ip2 != 0 && *ip1 != pt->v[i1] && *ip2 != pt->v[i1] ) {
343 if ( !mmgWarn0 ) {
344 mmgWarn0 = 1;
345 fprintf(stderr,"\n ## Error: %s: at least 1 non singular"
346 " point at the intersection of 3 edges.\n",
347 __func__);
348 }
349 return 0;
350 }
351 if ( *ip1 != pt->v[i1] ) *ip2 = pt->v[i1];
352 }
353 }
354
355 k = adja[i2] / 3;
356 if ( k == 0 ) break;
357 i = adja[i2] % 3;
358 i = MMG5_iprv2[i];
359
360 }
361 while ( k );
362
363 return ilist;
364}
365
MMG5_pMesh * mesh
int MMG2D_boulep(MMG5_pMesh mesh, MMG5_int ifirst, int iploc, MMG5_int *list)
Definition: boulep_2d.c:36
static uint8_t iprev[3]
Definition: boulep_2d.c:29
int MMG2D_bouleendp(MMG5_pMesh mesh, MMG5_int start, int8_t ip, MMG5_int *ip1, MMG5_int *ip2, MMG5_int *list)
Definition: boulep_2d.c:231
static uint8_t inxt[3]
Definition: boulep_2d.c:28
int MMG2D_boulen(MMG5_pMesh mesh, MMG5_int start, int8_t ip, MMG5_int *pleft, MMG5_int *pright, double *nn)
Definition: boulep_2d.c:115
#define MMG5_EPSD
API headers for the mmg2d library.
#define MMG2D_LMAX
Definition: libmmg2d.h:47
MMG5_int MMG2D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_2d.c:70
#define MG_EOK(pt)
#define MG_EDG(tag)
static const uint8_t MMG5_iprv2[3]
static const uint8_t MMG5_inxt2[6]
#define MG_VOK(ppt)
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pTria tria
Definition: libmmgtypes.h:647
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
int16_t tag[3]
Definition: libmmgtypes.h:342
MMG5_int ref
Definition: libmmgtypes.h:335
MMG5_int v[3]
Definition: libmmgtypes.h:334