Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmg3d2s.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
36#include "libmmg3d.h"
37#include "libmmg3d_private.h"
38
39extern int8_t ddb;
40
52 MMG5_pTetra pt;
53 MMG5_pPoint p1,p2;
54 MMG5_pxTetra pxt;
55 MMG5_int k,ref,ip1,ip2;
56 int8_t i,ia,j,j1,j2;
57
58 for (k=1; k<=mesh->ne; k++) {
59 pt = &mesh->tetra[k];
60 if ( !MG_EOK(pt) ) continue;
61
62 if ( !pt->xt ) continue;
63 pxt = &mesh->xtetra[pt->xt];
64
65 /* Reset face and edge references */
66 for (i=0; i<4; i++) {
67 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
68
69 if( !MMG5_getStartRef(mesh,pxt->ref[i],&ref) ) return 0;
70 pxt->ref[i] = ref;
71
72 for (j=0; j<3; j++) {
73 ia = MMG5_iarf[i][j];
74
75 if ( pxt->edg[ia] == mesh->info.isoref ) {
76 pxt->edg[ia] = 0;
77 pxt->tag[ia] &= ~MG_REF;
78 // pxt->tag[ia] &= ~MG_BDY;
79
80 j1 = MMG5_inxt2[j];
81 j2 = MMG5_iprv2[j];
82 ip1 = pt->v[MMG5_idir[i][j1]];
83 ip2 = pt->v[MMG5_idir[i][j2]];
84
85 p1 = &mesh->point[ip1];
86 p2 = &mesh->point[ip2];
87
88 p1->ref = 0;
89 p2->ref = 0;
90 }
91 }
92 }
93 }
94
95 return 1;
96}
97
108 MMG5_pPoint p0;
109 double *tmp;
110 MMG5_int k,ns;
111
112 /* create tetra adjacency */
113 if ( !MMG3D_hashTetra(mesh,1) ) {
114 fprintf(stderr,"\n ## Error: %s: hashing problem (1). Exit program.\n",
115 __func__);
116 return 0;
117 }
118
119 /* Reset point flags */
120 for (k=1; k<=mesh->np; k++)
121 mesh->point[k].flag = 0;
122
123 MMG5_ADD_MEM(mesh,(mesh->npmax+1)*sizeof(double),"temporary table",
124 fprintf(stderr," Exit program.\n");
125 return 0);
126 MMG5_SAFE_CALLOC(tmp,mesh->npmax+1,double,return 0);
127
128 /* Snap values of sol that are close to 0 to 0 exactly */
129 ns = 0;
130 for (k=1; k<=mesh->np; k++) {
131 p0 = &mesh->point[k];
132 if ( !MG_VOK(p0) ) continue;
133 if ( fabs(sol->m[k]-mesh->info.ls) < MMG5_EPS ) {
134 if ( mesh->info.ddebug )
135 fprintf(stderr," ## Warning: %s: snapping value %" MMG5_PRId "; "
136 "previous value: %E.\n",__func__,k,fabs(sol->m[k]));
137
138 tmp[k] = ( fabs(sol->m[k]-mesh->info.ls) < MMG5_EPSD ) ?
139 (mesh->info.ls-100.0*MMG5_EPS) : sol->m[k];
140 p0->flag = 1;
141 sol->m[k] = mesh->info.ls;
142 ns++;
143 }
144 }
145
146 return 1;
147}
148
161 MMG5_pTetra pt;
162 MMG5_pxTetra pxt;
163 MMG5_pPoint p0,p1;
164 MMG5_Hash hash;
165 double c[3],v0,v1,s;
166 MMG5_int vx[6],nb,k,ip0,ip1,np,ns,ne,ier,src,refext,refint;
167 int8_t ia,iface,j,npneg;
168 static int8_t mmgWarn = 0;
169
170 /* Reset point flags */
171 for (k=1; k<=mesh->np; k++)
172 mesh->point[k].flag = 0;
173
174 /* Compute the number nb of intersection points on edges */
175 nb = 0;
176 for (k=1; k<=mesh->ne; k++) {
177 pt = &mesh->tetra[k];
178 if ( !pt->xt ) continue;
179 pxt = &mesh->xtetra[pt->xt];
180
181 for (iface=0; iface<4; iface++) {
182 if ( !(pxt->ftag[iface] & MG_BDY) ) continue;
183 for (j=0; j<3; j++) {
184 ia = MMG5_iarf[iface][j];
185 ip0 = pt->v[MMG5_iare[ia][0]];
186 ip1 = pt->v[MMG5_iare[ia][1]];
187
188 p0 = &mesh->point[ip0];
189 p1 = &mesh->point[ip1];
190
191 if ( p0->flag && p1->flag ) continue;
192
193 v0 = sol->m[ip0]-mesh->info.ls;
194 v1 = sol->m[ip1]-mesh->info.ls;
195
196 if ( fabs(v0) > MMG5_EPSD2 && fabs(v1) > MMG5_EPSD2 && v0*v1 < 0.0 ) {
197 nb ++;
198 if ( !p0->flag ) p0->flag = nb;
199 if ( !p1->flag ) p1->flag = nb;
200 }
201 }
202 }
203 }
204 if ( ! nb ) return 1;
205
206 /* Create intersection points at 0 isovalue and set flags to tetras */
207 if ( !MMG5_hashNew(mesh,&hash,nb,7*nb) ) return 0;
208
209 /* Hash all required edges, and put ip = -1 in hash structure */
210 for (k=1; k<=mesh->ne; k++) {
211 pt = &mesh->tetra[k];
212 if ( !MG_EOK(pt) ) continue;
213
214 /* avoid split of edges belonging to a required tet */
215 if ( pt->tag & MG_REQ ) {
216 for (ia=0; ia<6; ia++) {
217 ip0 = pt->v[MMG5_iare[ia][0]];
218 ip1 = pt->v[MMG5_iare[ia][1]];
219 np = -1;
220 if ( !MMG5_hashEdge(mesh,&hash,ip0,ip1,np) ) return -1;
221 }
222 continue;
223 }
224
225 if ( !pt->xt ) continue;
226
227 pxt = &mesh->xtetra[pt->xt];
228 for (ia=0; ia<4; ia++) {
229 if ( !(pxt->ftag[ia] & MG_BDY) ) continue;
230
231 for (j=0; j<3; j++) {
232 if ( !(pxt->tag[ MMG5_iarf[ia][j] ] & MG_REQ) ) continue;
233
234 ip0 = pt->v[MMG5_idir[ia][MMG5_inxt2[j]]];
235 ip1 = pt->v[MMG5_idir[ia][MMG5_iprv2[j]]];
236 np = -1;
237 if ( !MMG5_hashEdge(mesh,&hash,ip0,ip1,np) ) return -1;
238 }
239 }
240 }
241
242 for (k=1; k<=mesh->ne; k++) {
243 pt = &mesh->tetra[k];
244 if ( !MG_EOK(pt) ) continue;
245 if ( !pt->xt ) continue;
246 pxt = &mesh->xtetra[pt->xt];
247
248 for (iface=0; iface<4; iface++) {
249 if ( !(pxt->ftag[iface] & MG_BDY) ) continue;
250 for (j=0; j<3; j++) {
251 ia = MMG5_iarf[iface][j];
252 ip0 = pt->v[MMG5_iare[ia][0]];
253 ip1 = pt->v[MMG5_iare[ia][1]];
254
255 np = MMG5_hashGet(&hash,ip0,ip1);
256 if ( np>0 ) continue;
257 if ( !MMG5_isSplit(mesh,pxt->ref[iface],&refint,&refext) ) continue;
258
259 p0 = &mesh->point[ip0];
260 p1 = &mesh->point[ip1];
261 v0 = sol->m[ip0]-mesh->info.ls;
262 v1 = sol->m[ip1]-mesh->info.ls;
263 if ( fabs(v0) < MMG5_EPSD2 || fabs(v1) < MMG5_EPSD2 ) continue;
264 else if ( MG_SMSGN(v0,v1) ) continue;
265 else if ( !p0->flag || !p1->flag ) continue;
266
267 npneg = (np<0);
268
269 s = v0 / (v0-v1);
270
271 s = MG_MAX(MG_MIN(s,1.0-MMG5_EPS),MMG5_EPS);
272 c[0] = p0->c[0] + s*(p1->c[0]-p0->c[0]);
273 c[1] = p0->c[1] + s*(p1->c[1]-p0->c[1]);
274 c[2] = p0->c[2] + s*(p1->c[2]-p0->c[2]);
275
276#ifdef USE_POINTMAP
277 src = p0->src;
278#else
279 src = 1;
280#endif
281 np = MMG3D_newPt(mesh,c,0,src);
282 if ( !np ) {
283 int oldnpmax = mesh->npmax;
285 fprintf(stderr,"\n ## Error: %s: unable to"
286 " allocate a new point\n",__func__);
288 return 0
289 ,c,0,src);
290 if( met ) {
291 if( met->m ) {
292 MMG5_ADD_MEM(mesh,(met->size*(mesh->npmax-met->npmax))*sizeof(double),
293 "larger solution",
295 mesh->memCur -= (mesh->npmax - oldnpmax)*sizeof(MMG5_Point);
296 mesh->npmax = oldnpmax;
297 mesh->np = mesh->npmax-1;
298 mesh->npnil = 0;
299 return 0);
300 MMG5_SAFE_REALLOC(met->m,met->size*(met->npmax+1),
301 met->size*(mesh->npmax+1),
302 double,"larger solution",
304 mesh->memCur -= (mesh->npmax - oldnpmax)*sizeof(MMG5_Point);
305 mesh->npmax = oldnpmax;
306 mesh->np = mesh->npmax-1;
307 mesh->npnil = 0;
308 return 0);
309 }
310 met->npmax = mesh->npmax;
311 }
312 }
313
314 sol->m[np] = mesh->info.ls;
315
316 /* If user provide a metric, interpolate it at the new point */
317 if ( met && met->m ) {
318 if ( met->size > 1 ) {
319 ier = MMG3D_intmet33_ani(mesh,met,k,ia,np,s);
320 }
321 else {
322 ier = MMG5_intmet_iso(mesh,met,k,ia,np,s);
323 }
324 if ( ier <= 0 ) {
325 // Unable to compute the metric
326 fprintf(stderr,"\n ## Error: %s: unable to"
327 " interpolate the metric during the level-set"
328 " discretization\n",__func__);
329 return 0;
330 }
331 }
332
333 if ( npneg ) {
334 /* We split a required edge */
335 if ( !mmgWarn ) {
336 mmgWarn = 1;
337 fprintf(stderr," ## Warning: %s: the level-set intersect at least"
338 " one required entity. Required entity ignored.\n\n",__func__);
339 }
340 MMG5_hashUpdate(&hash,ip0,ip1,np);
341 }
342 else
343 MMG5_hashEdge(mesh,&hash,ip0,ip1,np);
344
345 }
346 }
347 }
348
349 /* Proceed to splitting, according to flags to tets */
350 ne = mesh->ne;
351 ns = 0;
352 ier = 1;
353 for (k=1; k<=ne; k++) {
354 pt = &mesh->tetra[k];
355 if ( !MG_EOK(pt) ) continue;
356 pt->flag = 0;
357 memset(vx,0,6*sizeof(int));
358
359 for (ia=0; ia<6; ia++) {
360 vx[ia] = MMG5_hashGet(&hash,pt->v[MMG5_iare[ia][0]],pt->v[MMG5_iare[ia][1]]);
361 if ( vx[ia] > 0 ) MG_SET(pt->flag,ia);
362 }
363
364 switch (pt->flag) {
365 case 1: case 2: case 4: case 8: case 16: case 32: /* 1 edge split */
366 ier = MMG5_split1(mesh,met,k,vx,1);
367 ns++;
368 break;
369
370 case 48: case 24: case 40: case 6: case 34: case 36:
371 case 20: case 5: case 17: case 9: case 3: case 10: /* 2 edges (same face) split */
372 ier = MMG5_split2sf(mesh,met,k,vx,1);
373 ns++;
374 break;
375
376 case 12: case 18: case 33: /* 2 edges (opposite face) split */
377 ier = MMG5_split2(mesh,met,k,vx,1);
378 ns++;
379 break;
380
381 case 7: case 25: case 42: case 52: /* 3 edges on conic configuration splitted */
382 ier = MMG5_split3cone(mesh,met,k,vx,1);
383 ns++;
384 break;
385
386 case 35: case 19: case 13: case 37: case 22: case 28: case 26:
387 case 14: case 49: case 50: case 44: case 41: /* 3 edges on opposite conf splitted */
388 ier = MMG5_split3op(mesh,met,k,vx,1);
389 ns++;
390 break;
391
392 case 30: case 45: case 51:
393 ier = MMG5_split4op(mesh,met,k,vx,1);
394 ns++;
395 break;
396
397 default :
398 assert(pt->flag == 0);
399 break;
400 }
401
402 if ( !ier ) return 0;
403 }
404 if ( (mesh->info.ddebug || abs(mesh->info.imprim) > 5) && ns > 0 )
405 fprintf(stdout," %7" MMG5_PRId " splitted\n",ns);
406
407 MMG5_DEL_MEM(mesh,hash.item);
408 return ns;
409}
410
420 MMG5_pTetra pt;
421 MMG5_pxTetra pxt;
422 double v,v1,v2;
423 MMG5_int k,ip,ip1,ip2,ref,refint,refext;
424 int8_t nmns,npls,nz,i,ia,j,j1,j2,ier;
425
426 /* Travel all boundary faces (via tetra) */
427 for (k=1; k<=mesh->ne; k++) {
428 pt = &mesh->tetra[k];
429 if ( !MG_EOK(pt) ) continue;
430
431 if ( !pt->xt ) continue;
432 pxt = &mesh->xtetra[pt->xt];
433
434 for (i=0; i<4; i++) {
435 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
436 ref = pxt->ref[i];
437 nmns = npls = nz = 0;
438
439 /* Set face ref */
440 for (j=0; j<3; j++) {
441 ip = pt->v[MMG5_idir[i][j]];
442 v = sol->m[ip]-mesh->info.ls;
443 if ( v > 0.0 )
444 npls++;
445 else if ( v < 0.0 )
446 nmns++;
447 else
448 nz ++;
449 }
450
451 /* Remark: this test is not consistent with the test of the ls option
452 * where the level-set can be superposed with the surface */
453 if ( nz == 3 ) {
454 fprintf(stderr, " ## Error: at least 1 triangle with its 3 vertices over the level-set.\n"
455 " Undetermined case.\n");
456 return 0;
457 }
458
459 ier = MMG5_isSplit(mesh,ref,&refint,&refext);
460
461 if ( npls ) {
462 if ( ier ) {
463 assert(!nmns);
464 pxt->ref[i] = refext;
465 }
466 }
467 else {
468 if ( ier ) {
469 assert(nmns);
470 pxt->ref[i] = refint;
471 }
472 }
473
474 /* Set edge and point refs */
475 for (j=0; j<3; j++) {
476 ia = MMG5_iarf[i][j];
477 j1 = MMG5_inxt2[j];
478 j2 = MMG5_iprv2[j];
479 ip1 = pt->v[MMG5_idir[i][j1]];
480 ip2 = pt->v[MMG5_idir[i][j2]];
481 v1 = sol->m[ip1];
482 v2 = sol->m[ip2];
483
484 if ( fabs(v1) < MMG5_EPSD && fabs(v2) < MMG5_EPSD ) {
485 pxt->edg[ia] = mesh->info.isoref;
486 pxt->tag[ia] |= MG_REF;
487 }
488 if ( fabs(v1) < MMG5_EPSD ) mesh->point[ip1].ref = mesh->info.isoref;
489 if ( fabs(v2) < MMG5_EPSD ) mesh->point[ip2].ref = mesh->info.isoref;
490 }
491 }
492 }
493 return 1;
494}
int ier
tmp[*strlen0]
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
#define MMG5_EPSD
#define MMG5_EPS
int MMG5_hashUpdate(MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:400
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
int MMG3D_hashTetra(MMG5_pMesh mesh, int pack)
Definition: hash_3d.c:122
int MMG3D_intmet33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_3d.c:101
int MMG5_intmet_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_3d.c:131
API headers for the mmg3d library.
MMG5_int MMG3D_newPt(MMG5_pMesh mesh, double c[3], int16_t tag, MMG5_int src)
Definition: zaldy_3d.c:39
int MMG5_split4op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t)
Definition: split_3d.c:3676
int MMG5_split3op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t)
Definition: split_3d.c:2574
int MMG5_split1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:136
static const int8_t MMG5_iarf[4][3]
iarf[i]: edges of face opposite to vertex i
static const uint8_t MMG5_iare[6][2]
vertices of extremities of the edges of the tetra
int MMG5_split2(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t)
Definition: split_3d.c:1430
int MMG5_split2sf(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t)
Definition: split_3d.c:1228
#define MMG3D_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag, src)
int MMG5_split3cone(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t)
Definition: split_3d.c:1971
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
int MMG5_isSplit(MMG5_pMesh mesh, MMG5_int ref, MMG5_int *refint, MMG5_int *refext)
Definition: mmg2.c:411
int MMG5_getStartRef(MMG5_pMesh mesh, MMG5_int ref, MMG5_int *pref)
Definition: mmg2.c:213
int MMG3D_cuttet_lssurf(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: mmg3d2s.c:160
int MMG3D_snpval_lssurf(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg3d2s.c:107
int MMG3D_setref_lssurf(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg3d2s.c:419
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG3D_resetRef_lssurf(MMG5_pMesh mesh)
Definition: mmg3d2s.c:51
#define MG_REQ
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MMG5_GAP
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MMG5_SAFE_REALLOC(ptr, prevSize, newSize, type, message, law)
static const uint8_t MMG5_iprv2[3]
static const uint8_t MMG5_inxt2[6]
#define MG_VOK(ppt)
#define MG_BDY
#define MG_SMSGN(a, b)
#define MMG5_EPSD2
#define MG_REF
#define MMG5_DEL_MEM(mesh, ptr)
#define MG_SET(flag, bit)
#define MMG5_SAFE_RECALLOC(ptr, prevSize, newSize, type, message, law)
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
int8_t ddebug
Definition: libmmgtypes.h:532
MMG5_int isoref
Definition: libmmgtypes.h:521
double ls
Definition: libmmgtypes.h:519
MMG mesh structure.
Definition: libmmgtypes.h:605
size_t memCur
Definition: libmmgtypes.h:607
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int npmax
Definition: libmmgtypes.h:612
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
MMG5_int npnil
Definition: libmmgtypes.h:621
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
MMG5_int ref
Definition: libmmgtypes.h:278
MMG5_int flag
Definition: libmmgtypes.h:282
MMG5_int npmax
Definition: libmmgtypes.h:666
double * m
Definition: libmmgtypes.h:671
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int flag
Definition: libmmgtypes.h:409
int16_t tag
Definition: libmmgtypes.h:410
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
MMG5_int edg[6]
Definition: libmmgtypes.h:421
MMG5_int ref[4]
Definition: libmmgtypes.h:419