Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
colver_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#include "libmmg2d_private.h"
25
26extern uint8_t ddb;
27
42int MMG2D_chkcol(MMG5_pMesh mesh, MMG5_pSol met,MMG5_int k,int8_t i,MMG5_int *list,int8_t typchk) {
43 MMG5_pTria pt0,pt,pt1,pt2;
44 MMG5_pPoint ppt,p2;
45 double lon,len,calold,calnew,caltmp;
46 MMG5_int ip1,ip2,ipb,l,ll,lj,jel,kel,*adja;
47 int ilist;
48 uint8_t i1,i2,j,jj,j2,voy,open;
49
50 pt0 = &mesh->tria[0];
51 pt = &mesh->tria[k];
52
53 i1 = MMG5_inxt2[i];
54 i2 = MMG5_iprv2[i];
55
56 ip1 = pt->v[i1];
57 ip2 = pt->v[i2];
58
59 open = 1;
60 adja = &mesh->adja[3*(k-1)+1];
61
62 calold = calnew = DBL_MAX;
63
64 /* If typchk == 2, avoid recreating long edges */
65 lon = 0.0;
66 if ( typchk == 2 && met->m ) {
67 lon = MMG2D_lencurv(mesh,met,ip1,ip2);
68 lon = MG_MAX(2.-lon,1.6);
69 }
70
71 /* Avoid collapsing a boundary point over a regular one (leads to boundary degeneration) */
72 if ( MG_EDG(mesh->point[ip1].tag) && !MG_EDG(mesh->point[ip2].tag) ) return 0;
73
74 /* Avoid subdivising one ref. component consisting of only one layer of elements */
75 if ( MG_EDG(mesh->point[ip1].tag) && (pt->tag[i1]||pt->tag[i2]) ) return 0;
76
77 /* Avoid closing one ref. component consisting of only one element (maybe
78 * redondant with previous test)*/
79 if ( MG_EDG(pt->tag[i1]) && MG_EDG(pt->tag[i2]) ) return 0;
80
81 jel = adja[i] / 3;
82 if ( jel ) {
83 open = 0;
84 pt1 = &mesh->tria[jel];
85 j = adja[i] % 3;
86 jj = MMG5_inxt2[j];
87 j2 = MMG5_iprv2[j];
88 if ( MG_EDG(pt1->tag[jj]) && MG_EDG(pt1->tag[j2]) ) return 0;
89 }
90
91 /* collect all triangles around vertex i1
92 simplification w.r.to the surface case: no need to use spacial ball boulechknm (impossible situation in 2d) */
93 int8_t dummy;
94 ilist = MMG5_boulet(mesh,k,i1,list,0,&dummy);
95 if ( ilist <= 0 )
96 return 0;
97
98 /* Avoid collapsing a "void triangle" */
99 if ( open ) {
100 jel = list[ilist-1] / 3;
101 pt1 = &mesh->tria[jel];
102 j = list[ilist-1] % 3;
103 j2 = MMG5_iprv2[j];
104 ipb = pt1->v[j2];
105
106 /* Travel the ball of ip2 until a boundary is met */
107 jel = k;
108 pt1 = &mesh->tria[jel];
109 j = i1;
110
111 while ( jel && !MG_EDG(pt1->tag[j]) ) {
112 adja = &mesh->adja[3*(jel-1)+1];
113 jel = adja[j] / 3;
114 pt1 = &mesh->tria[jel];
115 j = MMG5_inxt2[adja[j] % 3];
116 }
117 j = MMG5_iprv2[j];
118
119 if ( ipb == pt1->v[j] ) return 0;
120 }
121
122 /* Avoid creating edges with two BDY endpoints, which are not themselves BDY */
123 if ( mesh->info.fem ) {
124 p2 = &mesh->point[ip2];
125 if ( p2->tag & MG_BDY ) {
126 /* Travel all edges in the ball but for the first and last */
127 for (l=0; l<ilist-1; l++) {
128 jel = list[l] / 3;
129 j = list[l] % 3;
130 jj = MMG5_inxt2[j];
131 j2 = MMG5_iprv2[j];
132 pt1 = &mesh->tria[jel];
133 p2 = &mesh->point[pt1->v[j2]];
134 if ( (p2->tag & MG_BDY) && !(pt1->tag[jj] & MG_BDY) ) return 0;
135 }
136 }
137 }
138
139 if ( ilist > 3 || ( ilist == 3 && open ) ) { // ADD : Second test should work too
140 /* Avoid a collapse that would close one ref. component that consists only of one element */
141 /* Useless test I believe */
142 /*if ( MG_EDG(pt->tag[i2]) ) {
143 jel = list[1] / 3;
144 if ( ! jel ) return 0;
145 pt1 = &mesh->tria[jel];
146 if ( MMG5_abs(pt->ref) != MMG5_abs(pt1->ref) ) return 0;
147 }*/
148
149 /* Travel the ball of i1 (but for the two elements 0 and ilist-1 (the last one in the case of
150 a closed ball) which will disappear */
151 for (l=1; l<ilist-1+open; l++) {
152 jel = list[l] / 3;
153 j = list[l] % 3;
154 jj = MMG5_inxt2[j];
155 j2 = MMG5_iprv2[j];
156 pt1 = &mesh->tria[jel];
157
158 memcpy(pt0,pt1,sizeof(MMG5_Tria));
159 pt0->v[j] = ip2;
160
161 /* Check length to avoid recreating long elements */
162 if ( typchk == 2 && met->m && !MG_EDG(mesh->point[ip2].tag) ) {
163 ip1 = pt1->v[j2];
164 len = MMG2D_lencurv(mesh,met,ip1,ip2);
165 if ( len > lon ) return 0;
166 }
167
168 /* Check that the newly created triangles will not have to be split again */
169 if ( l == 1 ) {
170 pt0->tag[j2] |= pt->tag[i1];
171 }
172 else if ( l == ilist-2 && !open ) {
173 ll = list[ilist-1+open] / 3;
174
175 if ( ll > mesh->nt ) return 0;
176 lj = list[ilist-1+open] % 3;
177 pt0->tag[jj] |= mesh->tria[ll].tag[lj];
178 }
179
180 if ( typchk == 1 )
181 if ( MMG2D_chkedg(mesh,0) ) return 0;
182
183
184 /* Check quality and volume inversion */
185 if ( typchk == 2 && met->m && met->size == 3 )
186 caltmp = MMG2D_ALPHAD*MMG2D_caltri_ani(mesh,met,pt1);
187 else
188 caltmp = MMG2D_ALPHAD*MMG2D_caltri_iso(mesh,NULL,pt1);
189
190 calold = MG_MIN(calold,caltmp);
191
192 if ( typchk == 2 && met->m && met->size == 3 )
193 caltmp = MMG2D_ALPHAD*MMG2D_caltri_ani(mesh,met,pt0);
194 else
195 caltmp = MMG2D_ALPHAD*MMG2D_caltri_iso(mesh,NULL,pt0);
196
197 if ( caltmp < MMG2D_NULKAL ) return 0;
198 calnew = MG_MIN(calnew,caltmp);
199 if ( calold < MMG2D_NULKAL && calnew <= calold ) return 0;
200 else if ( calnew < MMG2D_NULKAL || calnew < 0.001*calold ) return 0;
201 }
202 }
203
204 /* Specific test: no collapse if any interior edge is EDG */
205 else if ( ilist == 3 ) {
206 ppt = &mesh->point[pt->v[i1]];
207 if ( MG_SIN(ppt->tag) ) return 0;
208 else if ( MG_EDG(pt->tag[i2]) && !MG_EDG(pt->tag[i]) ) return 0;
209 else if ( !MG_EDG(pt->tag[i2]) && MG_EDG(pt->tag[i]) ) return 0; // What is the use of that?
210 else if ( MG_EDG(pt->tag[i2]) && MG_EDG(pt->tag[i]) && MG_EDG(pt->tag[i1]) ) return 0;
211
212 /* Check geometric approximation */
213 jel = list[1] / 3;
214 j = list[1] % 3;
215 jj = MMG5_inxt2[j];
216 j2 = MMG5_iprv2[j];
217 pt0 = &mesh->tria[0];
218 pt1 = &mesh->tria[jel];
219 memcpy(pt0,pt1,sizeof(MMG5_Tria));
220 pt0->v[j] = ip2;
221
222 jel = list[2] / 3;
223 j = list[2] % 3;
224 pt1 = &mesh->tria[jel];
225 pt0->tag[jj] |= pt1->tag[j];
226 pt0->tag[j2] |= pt1->tag[MMG5_inxt2[j]];
227
228 if ( typchk == 1 )
229 if ( MMG2D_chkedg(mesh,0) ) return 0;
230
231 }
232
233 /* Particular case when there are two triangles in the ball of the collapsed point ip1 */
234 else {
235 assert ( ilist == 2 ); // Not necessarily! Check for that case too!
236 if ( ilist !=2 ) return 0;
237 if ( !open ) return 0;
238
239 jel = list[1] / 3;
240 j = list[1] % 3;
241
242 /* Topological test : avoid creating twice the same triangle */
243 adja = &mesh->adja[3*(jel-1)+1];
244 kel = adja[j] / 3;
245 voy = adja[j] % 3;
246 pt2 = &mesh->tria[kel];
247 if ( pt2->v[voy] == ip2 ) return 0;
248
249 jj = MMG5_inxt2[j];
250 pt1 = &mesh->tria[jel];
251 if ( MMG5_abs(pt->ref) != MMG5_abs(pt1->ref) ) return 0;
252 else if ( !(pt1->tag[jj] & MG_GEO) ) return 0;
253
254 /* Check quality and geometric approximation: elements with two trias in the
255 * ball should be removed */
256 pt0 = &mesh->tria[0];
257 memcpy(pt0,pt1,sizeof(MMG5_Tria));
258 pt0->v[j] = ip2;
259
260 calold = MMG2D_ALPHAD*MMG2D_caltri_iso(mesh,NULL,pt1);
261 calnew = MMG2D_ALPHAD*MMG2D_caltri_iso(mesh,NULL,pt0);
262 if ( calnew < MMG2D_NULKAL ) return 0;
263 if ( calold < MMG2D_NULKAL && calnew <= calold ) return 0;
264
265 if ( typchk == 1 )
266 if ( MMG2D_chkedg(mesh,0) ) return 0;
267 }
268
269 return ilist;
270}
271
272/* Perform effective collapse of edge i in tria k, i1->i2 */
273int MMG2D_colver(MMG5_pMesh mesh,int ilist,MMG5_int *list) {
274 MMG5_pTria pt,pt1,pt2;
275 MMG5_int iel,jel,ip1,ip2,k,kel,*adja;
276 uint8_t i,j,jj,i1,i2,open;
277
278 iel = list[0] / 3;
279 i1 = list[0] % 3;
280 i = MMG5_iprv2[i1];
281 i2 = MMG5_inxt2[i1];
282 pt = &mesh->tria[iel];
283 ip1 = pt->v[i1];
284 ip2 = pt->v[i2];
285
286 /* Check for open ball */
287 adja = &mesh->adja[3*(iel-1)+1];
288 open = adja[i] == 0;
289
290 /* Update of the vertex ip1 -> ip2 */
291 mesh->point[ip2].tag |= mesh->point[ip1].tag;
292
293 for (k=1; k<ilist-1+open; k++) {
294 jel = list[k] / 3;
295 jj = list[k] % 3;
296 pt1 = &mesh->tria[jel];
297 pt1->v[jj] = ip2;
298 pt1->base = mesh->base; // What is the use of updating the base field?
299 }
300
301 /* Update adjacent with the first element (which necessarily exists) */
302 jel = list[1] / 3;
303 jj = list[1] % 3;
304 j = MMG5_iprv2[jj];
305 pt1 = &mesh->tria[jel];
306
307 pt1->tag[j] |= pt->tag[i1];
308 pt1->edg[j] = MG_MAX(pt1->edg[j],pt->edg[i1]);
309
310 if ( adja[i1] ) {
311 kel = adja[i1] / 3;
312 k = adja[i1] % 3;
313 mesh->adja[3*(kel-1)+1+k] = 3*jel+j;
314 mesh->adja[3*(jel-1)+1+j] = 3*kel+k;
315 pt2 = &mesh->tria[kel];
316 pt2->tag[k] |= pt1->tag[j];
317 pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]);
318 }
319 else
320 mesh->adja[3*(jel-1)+1+j] = 0;
321
322 /* When the boundary is not open, update the adjacency relation with the second element */
323 if ( !open ) {
324 iel = list[ilist-1] / 3;
325 i1 = list[ilist-1] % 3;
326 pt = &mesh->tria[iel];
327
328 jel = list[ilist-2] / 3;
329 jj = list[ilist-2] % 3;
330 j = MMG5_inxt2[jj];
331 pt1 = &mesh->tria[jel];
332 pt1->tag[j] |= pt->tag[i1];
333 pt1->edg[j] = MG_MAX(pt->edg[i1],pt1->edg[j]);
334 adja = &mesh->adja[3*(iel-1)+1];
335
336 if ( adja[i1] ) {
337 kel = adja[i1] / 3;
338 k = adja[i1] % 3;
339 mesh->adja[3*(kel-1)+1+k] = 3*jel + j;
340 mesh->adja[3*(jel-1)+1+j] = 3*kel + k;
341 pt2 = &mesh->tria[kel];
342 pt2->tag[k] |= pt1->tag[j];
343 pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]);
344 }
345 else
346 mesh->adja[3*(jel-1)+1+j] = 0;
347 }
348
349 /* Delete removed point and elements */
350 MMG2D_delPt(mesh,ip1);
351 MMG2D_delElt(mesh,list[0] / 3);
352 if ( !open ) MMG2D_delElt(mesh,list[ilist-1] / 3);
353
354 return 1;
355}
356
357/* Perform effective collapse of edge i in tria k, i1->i2
358 in the particular case where only three elements are in the ball of i */
359int MMG2D_colver3(MMG5_pMesh mesh,MMG5_int *list) {
360 MMG5_pTria pt,pt1,pt2;
361 MMG5_int iel,jel,kel,mel,ip,*adja;
362 uint8_t i,i1,j,j1,j2,k,m;
363
364 /* Update of the new point for triangle list[0] */
365 iel = list[0] / 3;
366 i = list[0] % 3;
367 i1 = MMG5_inxt2[i];
368 pt = &mesh->tria[iel];
369 ip = pt->v[i];
370 jel = list[1] / 3;
371 j = list[1] % 3;
372 j1 = MMG5_inxt2[j];
373 j2 = MMG5_iprv2[j];
374 pt1 = &mesh->tria[jel];
375
376 kel = list[2] / 3;
377 k = list[2] % 3;
378 pt2 = &mesh->tria[kel];
379
380 /* update info */
381 pt1->v[j] = pt->v[i1];
382 pt1->tag[j1] |= pt2->tag[k];
383 pt1->edg[j1] = MG_MAX(pt1->edg[j1],pt2->edg[k]);
384 pt1->tag[j2] |= pt->tag[i];
385 pt1->edg[j2] = MG_MAX(pt1->edg[j2],pt->edg[i]);
386 pt1->base = mesh->base;
387
388 /* Update adjacency relations */
389 adja = &mesh->adja[3*(jel-1)+1];
390 adja[j1] = mesh->adja[3*(kel-1)+1+k];
391 adja[j2] = mesh->adja[3*(iel-1)+1+i];
392
393 mel = adja[j2] / 3;
394 if ( mel ) {
395 m = adja[j2] % 3;
396 pt = &mesh->tria[mel];
397 pt->tag[m] = pt1->tag[j2];
398 pt->edg[m] = pt1->edg[j2];
399 mesh->adja[3*(mel-1)+1+m] = 3*jel + j2;
400 }
401
402 mel = adja[j1] / 3;
403 if ( mel ) {
404 m = adja[j1] % 3;
405 pt = &mesh->tria[mel];
406 pt->tag[m] = pt1->tag[j1];
407 pt->edg[m] = pt1->edg[j1];
408 mesh->adja[3*(mel-1)+1+m] = 3*jel + j1;
409 }
410
411 /* remove vertex + elements */
412 MMG2D_delPt(mesh,ip);
413 MMG2D_delElt(mesh,iel);
414 MMG2D_delElt(mesh,kel);
415
416 return 1;
417}
418
419/* Perform effective collapse of edge i in tria k, i1->i2
420 in the particular case where only two elements are in the ball of i */
421int MMG2D_colver2(MMG5_pMesh mesh,MMG5_int *list) {
422 MMG5_pTria pt,pt1;
423 MMG5_int *adja,iel,jel,kel,ip1,ip2;
424 int8_t i1,i2,jj,j2,k;
425
426 /* update of new point for triangle list[0] */
427 iel = list[0] / 3;
428 i1 = list[0] % 3;
429 i2 = MMG5_inxt2[i1];
430 pt = &mesh->tria[iel];
431 ip1 = pt->v[i1];
432 ip2 = pt->v[i2];
433
434 jel = list[1] / 3;
435 j2 = list[1] % 3;
436 jj = MMG5_iprv2[j2];
437 pt1 = &mesh->tria[jel];
438
439 /* update info */
440 pt1->v[j2] = ip2;
441 pt1->tag[jj] |= pt->tag[i1];
442 pt1->edg[jj] = pt->edg[i1];
443 pt1->base = mesh->base;
444
445 /* update neighbours of new triangle */
446 adja = &mesh->adja[3*(jel-1)+1];
447 adja[jj] = mesh->adja[3*(iel-1)+1+i1];
448 adja = &mesh->adja[3*(iel-1)+1];
449 kel = adja[i1] / 3;
450 k = adja[i1] % 3;
451 if ( kel )
452 mesh->adja[3*(kel-1)+1+k] = 3*jel + jj;
453
454 /* remove vertex + element */
455 MMG2D_delPt(mesh,ip1);
456 MMG2D_delElt(mesh,iel);
457
458 return 1;
459}
MMG5_pMesh * mesh
int MMG2D_chkedg(MMG5_pMesh mesh, MMG5_int k)
Definition: bezier_2d.c:28
int MMG5_boulet(MMG5_pMesh mesh, MMG5_int start, int ip, MMG5_int *list, int8_t s, int8_t *opn)
Definition: boulep.c:363
int MMG2D_colver(MMG5_pMesh mesh, int ilist, MMG5_int *list)
Definition: colver_2d.c:273
int MMG2D_chkcol(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int *list, int8_t typchk)
Definition: colver_2d.c:42
uint8_t ddb
Definition: mmg3d1_delone.c:42
int MMG2D_colver3(MMG5_pMesh mesh, MMG5_int *list)
Definition: colver_2d.c:359
int MMG2D_colver2(MMG5_pMesh mesh, MMG5_int *list)
Definition: colver_2d.c:421
double MMG2D_caltri_ani(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pTria)
Definition: quality_2d.c:121
int MMG2D_delElt(MMG5_pMesh mesh, MMG5_int iel)
Definition: zaldy_2d.c:105
#define MMG2D_NULKAL
void MMG2D_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_2d.c:57
double MMG2D_caltri_iso(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pTria)
Definition: quality_2d.c:107
#define MMG2D_ALPHAD
#define MG_GEO
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MG_EDG(tag)
static const uint8_t MMG5_iprv2[3]
#define MG_SIN(tag)
static const uint8_t MMG5_inxt2[6]
#define MG_BDY
int8_t fem
Definition: libmmgtypes.h:539
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_int base
Definition: libmmgtypes.h:616
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
double * m
Definition: libmmgtypes.h:671
MMG5_int edg[3]
Definition: libmmgtypes.h:339
int16_t tag[3]
Definition: libmmgtypes.h:342
MMG5_int ref
Definition: libmmgtypes.h:335
MMG5_int base
Definition: libmmgtypes.h:336
MMG5_int v[3]
Definition: libmmgtypes.h:334