Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
delone_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"
24
25#define MMG2D_AREAMIN 1e-15 //1e-20 failed : creation of too bad element
26
27#define KTA 7
28#define KTB 11
29
30/* Cavity correction for quality */
31static int MMG2D_correction_iso(MMG5_pMesh mesh,MMG5_int ip,MMG5_int *list,int ilist,int nedep) {
32 MMG5_pTria pt;
33 MMG5_pPoint ppt,p1,p2;
34 double dd,ux,uy,vx,vy;
35 MMG5_int *adja,iel,iadr,adj,ib,ic,ncor,nei[3],base;
36 int lon,i,ipil;
37
38 ppt = &mesh->point[ip];
39 if ( !MG_VOK(ppt) ) return ilist;
40 base = mesh->base;
41 lon = ilist;
42 do {
43 ipil = lon-1;
44 ncor = 0;
45
46 while ( ipil >= 0 ) {
47 iel = list[ipil];
48 iadr = (iel-1)*3 + 1;
49 adja = &mesh->adja[iadr];
50 nei[0] = adja[0] /3;
51 nei[1] = adja[1] /3;
52 nei[2] = adja[2] /3;
53 pt = &mesh->tria[iel];
54
55 for (i=0; i<3; i++) {
56 adj = nei[i];
57 /* Consider only the external faces of the cavity */
58 if ( adj && mesh->tria[adj].base == base ) continue;
59
60 ib = pt->v[ MMG5_inxt2[i] ];
61 ic = pt->v[ MMG5_iprv2[i] ];
62
63 p1 = &mesh->point[ib];
64 p2 = &mesh->point[ic];
65
66 ux = p2->c[0] - p1->c[0];
67 uy = p2->c[1] - p1->c[1];
68
69 vx = ppt->c[0] - p1->c[0];
70 vy = ppt->c[1] - p1->c[1];
71
72 /* area PBC */
73 dd = ux*vy - uy*vx;
74 if ( dd < MMG2D_AREAMIN ) break;
75
76 }
77
78 /* Remove triangle iel from the cavity if it leads to a degenerate triangle after insertion of ppt */
79 if ( i < 3 /*|| pt->tag & MG_REQ*/ ) {
80 /* remove iel from list */
81 pt->base = base-1;
82 list[ipil] = list[--lon];
83 ncor = 1;
84 break;
85 }
86 else
87 ipil--;
88 }
89 }
90 while ( ncor > 0 && lon >= nedep );
91 return lon;
92}
93
107static int MMG2D_hashEdgeDelone(MMG5_pMesh mesh,MMG5_Hash *hash,MMG5_int iel,int i) {
108 MMG5_pTria pt;
109 MMG5_int *adja,iadr,jel,ip1,ip2;
110 int j;
111 int16_t i1,i2;
112
113 pt = &mesh->tria[iel];
114 i1 = MMG5_inxt2[i];
115 i2 = MMG5_iprv2[i];
116 ip1 = pt->v[i1];
117 ip2 = pt->v[i2];
118
119 /* Search if the face is already hashed */
120 jel = MMG5_hashGet(hash,ip1,ip2);
121
122 if ( !jel ) {
123 /* if not, hash the edge and store its unique key */
124 jel = MMG5_hashEdge(mesh,hash,ip1,ip2,3*iel+i);
125 if ( !jel ) {
126 printf(" # Error: %s: Unable to add edge %" MMG5_PRId " %" MMG5_PRId " within the hash table\n",
127 __func__,MMG2D_indPt(mesh,ip1),MMG2D_indPt(mesh,ip2));
128 return 0;
129 }
130 }
131 else {
132 /* otherwise, update the adjacency array */
133 iadr = (iel-1)*3 + 1;
134 adja = &mesh->adja[iadr];
135 adja[i] = jel;
136
137 j = jel % 3;
138 jel /= 3;
139 iadr = (jel-1)*3 + 1;
140 adja = &mesh->adja[iadr];
141 adja[j] = iel*3 + i;
142 }
143
144 return 1;
145}
146
149int MMG2D_cavity(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int ip,MMG5_int *list) {
150 MMG5_pTria pt,pt1,ptc;
151 MMG5_pPoint ppt;
152 double c[2],crit,dd,eps,rad,ct[6];
153 MMG5_int tref,*adja,*adjb,adj,adi,jel,iadr,nei[3],l,base; //isreq;
154 int voy,ilist,ipil;
155 int i,j;
156 static int8_t mmgWarn0=0;
157
158 ppt = &mesh->point[ip];
159 base = ++mesh->base;
160 //isreq = 0;
161 tref = mesh->tria[list[0]].ref;
162 mesh->tria[list[0]].base = base;
163
164 /* Pile up cavity by adjacency */
165 eps = 1. + MMG5_EPSOK;
166 ilist = 1;
167 ipil = 0;
168
169 do {
170 jel = list[ipil];
171 iadr = (jel-1)*3 + 1;
172 adja = &mesh->adja[iadr];
173 nei[0] = adja[0];
174 nei[1] = adja[1];
175 nei[2] = adja[2];
176 ptc = &mesh->tria[jel];
177
178 for (i=0; i<3; i++) {
179 adj = nei[i] /3;
180 voy = nei[i] % 3;
181 if ( !adj ) continue;
182 pt = &mesh->tria[adj];
183
184 /* Case where the triangle has already been piled, or a boundary face is hit */
185 if ( pt->base == base || pt->ref != ptc->ref ) continue;
186
187 /* Store the 6 coordinates of the vertices of pt */
188 for (j=0,l=0; j<3; j++,l+=2) {
189 memcpy(&ct[l],mesh->point[pt->v[j]].c,2*sizeof(double));
190 }
191
192 if ( !MMG2D_cenrad_iso(mesh,ct,c,&rad) ) continue;
193 crit = eps * rad;
194
195 /* Delaunay criterion */
196 dd = (ppt->c[0] - c[0]) * (ppt->c[0] - c[0]) + (ppt->c[1] - c[1]) * (ppt->c[1] - c[1]);
197 if ( dd > crit ) continue;
198
199 /* Lost face(s); I don't understand this test: the algorithm is supposed to stop when changing references */
200 iadr = (adj-1)*3 + 1;
201 adjb = &mesh->adja[iadr];
202
203 for (j=0; j<3; j++) {
204 if ( j == voy ) continue;
205 adi = adjb[j] /3;
206 if ( !adi ) continue;
207 pt1 = &mesh->tria[adi];
208 if ( pt1->base == base && adi != jel ) {
209 if ( pt1->ref != tref ) {
210 break;
211 }
212 }
213 }
214 /* store tria */
215 if ( j == 3 ) {
216 //if ( pt->tag & MG_REQ ) isreq = 1;
217 pt->base = base;
218 list[ilist++] = adj;
219 }
220 else {
221 if ( !mmgWarn0 ) {
222 mmgWarn0 = 1;
223 fprintf(stderr,"\n ## Error: %s: we pass here at least one time but one"
224 " should never go through here.\n",__func__);
225 }
226 }
227 }
228 if ( ilist > MMG5_TRIA_LMAX - 3 ) return -1;
229
230 ++ipil;
231 }
232 while ( ipil < ilist );
233
234 ilist = MMG2D_correction_iso(mesh,ip,list,ilist,1);
235 //if ( isreq ) ilist = -fabs(ilist);
236 return ilist;
237}
238
251int MMG2D_delone(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int ip,MMG5_int *list,int ilist) {
252 MMG5_pTria pt,pt1;
253 MMG5_pPoint ppt;
254 MMG5_int base,*adja,*adjb,iel,jel,old,iadr,size,nei[3],iadrold;
255 int i,j,k;
256 MMG5_int ielnum[3*MMG5_TRIA_LMAX+1],tref;
257 int8_t ier;
258 short i1;
259 int8_t alert;
260 MMG5_Hash hedg;
261 static int8_t mmgWarn0=0,mmgWarn1=0;
262
263 /* Reset tagdel field */
264 for (k=1; k<ilist; k++)
265 mesh->point[k].tagdel = 0;
266
267 /* Triangles in the cavity are those s.t. pt->base == base */
268 base = mesh->base;
269 /* Count the number of external faces in the cavity, and tag the corresponding vertices */
270 size = 0;
271 for (k=0; k<ilist; k++) {
272 old = list[k];
273 pt1 = &mesh->tria[old];
274 iadr = (old-1)*3 + 1;
275 adja = &mesh->adja[iadr];
276 nei[0] = adja[0]/3 ;
277 nei[1] = adja[1]/3 ;
278 nei[2] = adja[2]/3 ;
279 for (i=0; i<3; i++) {
280 jel = nei[i];
281 if ( (!jel) || (mesh->tria[jel].base != base) ) {
282 for (j=0; j<2; j++) {
283 i1 = MMG2D_iare[i][j];
284 ppt = &mesh->point[ pt1->v[i1] ];
285 ppt->tagdel = 1;
286 }
287 size++;
288 }
289 }
290 }
291
292 /* Check for an isolated vertex (the cavity should ne contain any internal vertex) */
293 alert = 0;
294 for (k=0; k<ilist; k++) {
295 old = list[k];
296 pt1 = &mesh->tria[old];
297 for (i=0; i<3; i++) {
298 ppt = &mesh->point[ pt1->v[i] ];
299 if ( !ppt->tagdel ) {
300 alert = 1;
301 }
302 }
303 }
304 /* Reset tagdel field */
305 for (k=0; k<ilist; k++) {
306 old = list[k];
307 pt1 = &mesh->tria[old];
308 for (i=0; i<3; i++) {
309 ppt = &mesh->point[ pt1->v[i] ];
310 ppt->tagdel = 0;
311 }
312 }
313 if ( alert ) return 0;
314
315 /* Hash table parameters */
316 if ( size >= 3*MMG5_TRIA_LMAX ) return 0;
317 if ( !MMG5_hashNew(mesh,&hedg,size,3*size) ) {
318 fprintf(stderr,"\n ## Warning: %s: unable to allocate hash table.\n",__func__);
319 return -1;
320 }
321
322 /* Allocate memory for "size" new triangles */
323 ielnum[0] = size;
324 for (k=1; k<=size; k++) {
325 ielnum[k] = MMG2D_newElt(mesh);
326 if ( !ielnum[k] ) {
327 MMG2D_TRIA_REALLOC(mesh,ielnum[k],mesh->gap,
328 fprintf(stderr,"\n ## Error: %s: unable to allocate"
329 " a new element.\n",__func__);
331 printf(" Exit program.\n");return -1);
332 }
333 }
334
335 size = 1;
336 for (k=0; k<ilist; k++) {
337 old = list[k];
338 pt = &mesh->tria[old];
339
340 iadrold = (old-1)*3 + 1;
341 adja = &mesh->adja[iadrold];
342 nei[0] = adja[0];
343 nei[1] = adja[1];
344 nei[2] = adja[2];
345
346 for (i=0; i<3; i++) {
347 jel = nei[i] / 3;
348 j = nei[i] % 3;
349
350 /* Catch the associated external face */
351 if ( (!jel) || (mesh->tria[jel].base != base) ) {
352 assert ( size <= ielnum[0] );
353 iel = ielnum[size++];
354 assert(iel);
355
356 pt1 = &mesh->tria[iel];
357 memcpy(pt1,pt,sizeof(MMG5_Tria));
358 pt1->v[i] = ip;
359 pt1->qual = MMG2D_caltri_iso(mesh,sol,pt1);
360 pt1->ref = pt->ref;
361
362 if ( (!mmgWarn0) && (pt1->qual < MMG2D_AREAMIN) ) {
363 mmgWarn0 = 1;
364 fprintf(stderr," ## Warning: %s: creation of a very bad element.\n",
365 __func__);
366 }
367
368 /* Update adjacency via the external face */
369 iadr = (iel-1)*3 + 1;
370 adjb = &mesh->adja[iadr];
371 adjb[i] = adja[i];
372
373 if ( jel ) {
374 iadr = (jel-1)*3 + 1;
375 adjb = &mesh->adja[iadr];
376 adjb[j] = iel*3 + i;
377 }
378 /* Update adjacency via the internal faces */
379 for (j=0; j<3; j++) {
380 if ( j != i ) {
381 ier = MMG2D_hashEdgeDelone(mesh,&hedg,iel,j);
382 if ( !ier ) {
383 fprintf(stderr," ## Warning: %s: unable to update adjacency"
384 " relationship (elt %" MMG5_PRId ", edge %d).\n",
385 __func__,MMG2D_indElt(mesh,iel),j);
386 return -1;
387 }
388 }
389 }
390 }
391 }
392 }
393
394 /* Remove the old triangles */
395 tref = mesh->tria[list[0]].ref;
396 for (k=0; k<ilist; k++) {
397 if ( (!mmgWarn1) && (tref != mesh->tria[list[k]].ref) ) {
398 mmgWarn1 = 1;
399 fprintf(stderr,"\n ## Warning: %s: sud-domain ignored.\n",__func__);
400 }
401 MMG2D_delElt(mesh,list[k]);
402 }
403
404 //ppt = &mesh->point[ip];
405 // ppt->flag = mesh->flag;
406 MMG5_SAFE_FREE(hedg.item);
407 return 1;
408}
int ier
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
int MMG2D_cenrad_iso(MMG5_pMesh mesh, double *ct, double *c, double *rad)
Definition: cenrad_2d.c:42
int MMG2D_delone(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int ip, MMG5_int *list, int ilist)
Definition: delone_2d.c:251
#define MMG2D_AREAMIN
Definition: delone_2d.c:25
int MMG2D_cavity(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int ip, MMG5_int *list)
Definition: delone_2d.c:149
static int MMG2D_correction_iso(MMG5_pMesh mesh, MMG5_int ip, MMG5_int *list, int ilist, int nedep)
Definition: delone_2d.c:31
static int MMG2D_hashEdgeDelone(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int iel, int i)
Definition: delone_2d.c:107
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:526
MMG5_int MMG5_hashGet(MMG5_Hash *hash, MMG5_int a, MMG5_int b)
Definition: hash.c:495
int MMG5_hashEdge(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:345
MMG5_int MMG2D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_2d.c:70
int MMG2D_delElt(MMG5_pMesh mesh, MMG5_int iel)
Definition: zaldy_2d.c:105
#define MMG2D_TRIA_REALLOC(mesh, jel, wantedGap, law)
static const int MMG2D_iare[3][2]
double MMG2D_caltri_iso(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pTria)
Definition: quality_2d.c:107
MMG5_int MMG2D_indElt(MMG5_pMesh mesh, MMG5_int kel)
Definition: tools_2d.c:46
MMG5_int MMG2D_newElt(MMG5_pMesh mesh)
Definition: zaldy_2d.c:85
#define MG_REQ
#define MMG5_EPSOK
#define MMG5_INCREASE_MEM_MESSAGE()
static const uint8_t MMG5_iprv2[3]
#define MMG5_TRIA_LMAX
static const uint8_t MMG5_inxt2[6]
#define MG_VOK(ppt)
#define MMG5_SAFE_FREE(ptr)
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:595
MMG5_hedge * item
Definition: libmmgtypes.h:597
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
double gap
Definition: libmmgtypes.h:608
MMG5_int base
Definition: libmmgtypes.h:616
MMG5_pTria tria
Definition: libmmgtypes.h:647
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int8_t tagdel
Definition: libmmgtypes.h:286
double c[3]
Definition: libmmgtypes.h:271
double qual
Definition: libmmgtypes.h:333
MMG5_int ref
Definition: libmmgtypes.h:335
MMG5_int base
Definition: libmmgtypes.h:336
MMG5_int v[3]
Definition: libmmgtypes.h:334