Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmg2.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 "mmgcommon_private.h"
37#include "mmgexterns_private.h"
38
46static MMG5_int MMG5_InvMat_key(MMG5_pInvMat pim,int ref) {
47 return (ref - pim->offset);
48}
49
58static int MMG5_InvMat_code(int k,int attr) {
59 return 4*(k+1)+attr;
60}
61
69static int MMG5_InvMat_getIndex(MMG5_pInvMat pim,int ref) {
70 int key = MMG5_InvMat_key(pim,ref);
71 /* The parent index is stored as 4*(k+1) */
72 return (pim->lookup[key] / 4 - 1);
73}
74
84static int MMG5_InvMat_getAttrib(MMG5_pInvMat pim,int ref) {
85 int key = MMG5_InvMat_key(pim,ref);
86 /* The nosplit/split/plus/minus attribute is stored as the rest of the
87 * integer division. */
88 return (pim->lookup[key] % 4);
89}
90
98static int MMG5_InvMat_check(MMG5_pInvMat pim,int key) {
99 return pim->lookup[key] ? 0 : 1;
100}
101
111static void MMG5_InvMat_error(MMG5_pInvMat pim,int ref,int k) {
112 fprintf(stderr,"\n ## Warning: Overwrite material reference %d"
113 " (from LSReferences line %d) with another entry from LSReferences line %d."
114 ,ref,MMG5_InvMat_getIndex(pim,ref)+1,k+1);
115 fprintf(stderr,"\n Check your LSReferences table: if possible,"
116 " each material reference should be unique,\n"
117 " if not possible, you may"
118 " encounter unexpected issues (wrong domain mapping or erroneous"
119 " detection of non-manifold level-set)!\n");
120}
121
130 MMG5_pMat pm;
131 int key;
132
133 /* Get material */
134 pm = &mesh->info.mat[k];
135
137 key = MMG5_InvMat_key(pim,pm->ref);
138 if( !MMG5_InvMat_check(pim,key) ) {
139 MMG5_InvMat_error(pim,pm->ref,k);
140 }
141 pim->lookup[key] = MMG5_InvMat_code(k,pm->dospl);
142
150 if( pm->dospl ) {
151 key = MMG5_InvMat_key(pim,pm->rin);
152 if( !MMG5_InvMat_check(pim,key) ) {
153 MMG5_InvMat_error(pim,pm->rin,k);
154 }
155 pim->lookup[key] = MMG5_InvMat_code(k,MG_MINUS);
156
157 key = MMG5_InvMat_key(pim,pm->rex);
158 if( !MMG5_InvMat_check(pim,key) ) {
159 MMG5_InvMat_error(pim,pm->rex,k);
160 }
161 pim->lookup[key] = MMG5_InvMat_code(k,MG_PLUS);
162 }
163
164 return 1;
165}
166
177static int MMG5_InvMat_getParent(MMG5_pMesh mesh,MMG5_pInvMat pim,MMG5_int ref,MMG5_int *pref) {
178 MMG5_pMat pm;
179 int k;
180
181 /* The parent index */
182 k = MMG5_InvMat_getIndex(pim,ref);
183
184 /* Material not found in the table */
185 if( k == -1 ) {
186 fprintf(stderr,"\n ## Warning: %s: material %" MMG5_PRId " not found in table.\n",
187 __func__,ref);
188 fprintf(stderr," Please ensure that you provide all mesh"
189 " references in the material map\n"
190 " (that is, the whole list of"
191 " surface materials in lssurf mode,\n"
192 " and the whole list of domain"
193 " materials in ls mode).\n" );
194 return 0;
195 }
196
197 /* Get the material in the lookup table and return the parent reference */
198 pm = &mesh->info.mat[k];
199 *pref = pm->ref;
200 return 1;
201}
202
213int MMG5_getStartRef(MMG5_pMesh mesh,MMG5_int ref,MMG5_int *pref) {
214 MMG5_pInvMat pim;
215
216 /* No multi-materials nor single material reference preservation */
217 if( !mesh->info.nmat ) {
218 *pref = 0;
219 return 1;
220 }
221
222 /* Get parent of material */
223 pim = &mesh->info.invmat;
224
225 /* Return 0 if the material does not exist, 1 otherwise */
226 if( !MMG5_InvMat_getParent(mesh,pim,ref,pref) )
227 return 0;
228 else
229 return 1;
230}
231
239 MMG5_int ref,pref;
240
241 /* Scan all references in the table limits, some may not exist */
242 for( ref = pim->offset; ref < pim->offset + pim->size; ref++ ) {
243 if( !MMG5_InvMat_getParent(mesh,pim,ref,&pref) ) continue;
244 printf("%" MMG5_PRId " (%" MMG5_PRId "): %" MMG5_PRId " %d\n",ref,
245 MMG5_InvMat_key(pim,ref),pref,
246 MMG5_InvMat_getAttrib(pim,ref));
247 }
248}
249
327 MMG5_pMat pm;
328 MMG5_pInvMat pim;
329 int k;
330 MMG5_int refmax,refmin;
331
332 /* Nothing to do if no multi-material option */
333 if( !mesh->info.nmat ) return 1;
334
335 /* Error if all the materials have not been set */
336 if( mesh->info.nmati < mesh->info.nmat ) {
337 fprintf(stderr,"\n ## Error: %s: Only %d materials out of %d have been set.\n",
338 __func__,mesh->info.nmati,mesh->info.nmat);
339 return 0;
340 }
341
342 /* Get pointer to the structure */
343 pim = &mesh->info.invmat;
344
345 /* Initialize the max and min reference */
346 refmax = 0;
347 refmin = INT_MAX;
348
349 /* Look for the max/min reference provided in material table */
350 for( k = 0; k < mesh->info.nmat; k++ ) {
351 pm = &mesh->info.mat[k];
352 /* Update max and min val for original ref */
353 if( pm->ref > refmax ) refmax = pm->ref;
354 if( pm->ref < refmin ) refmin = pm->ref;
355 if( !pm->dospl ) continue;
356 /* Update max and min val with interior ref */
357 if( pm->rin > refmax ) refmax = pm->rin;
358 if( pm->rin < refmin ) refmin = pm->rin;
359 /* Update max and min val with exterior ref */
360 if( pm->rex > refmax ) refmax = pm->rex;
361 if( pm->rex < refmin ) refmin = pm->rex;
362 }
363
364 /* Look for the max/min reference of tetra, triangles and edges provided
365 * inside the mesh (worst case to avoid memory error when checking the
366 * the inverse map). Looking at vertices is useless as
367 * we will never check for the mapping of reference of vertices */
368 for ( k=1; k<=mesh->ne; ++k ) {
369 if( mesh->tetra[k].ref > refmax ) refmax = mesh->tetra[k].ref;
370 if( mesh->tetra[k].ref < refmin ) refmin = mesh->tetra[k].ref;
371 }
372 for ( k=1; k<=mesh->nt; ++k ) {
373 if( mesh->tria[k].ref > refmax ) refmax = mesh->tria[k].ref;
374 if( mesh->tria[k].ref < refmin ) refmin = mesh->tria[k].ref;
375 }
376 for ( k=1; k<=mesh->na; ++k ) {
377 if( mesh->edge[k].ref > refmax ) refmax = mesh->edge[k].ref;
378 if( mesh->edge[k].ref < refmin ) refmin = mesh->edge[k].ref;
379 }
380
381 /* Get span of the lookup table */
382 pim->offset = refmin;
383 pim->size = refmax - refmin + 1;
384 assert( pim->size > 0 );
385
386 /* Allocate lookup table */
387 MMG5_ADD_MEM(mesh,pim->size*sizeof(int),"materials lookup table",return 0);
388 MMG5_SAFE_CALLOC(pim->lookup,pim->size,int,return 0);
389
390 /* Fill lookup table */
391 for( k = 0; k < mesh->info.nmat; k++ ) {
392 if( !MMG5_InvMat_set(mesh,pim,k) )
393 return 0;
394 }
395
396 // MMG5_InvMat_print(mesh,pim);
397 return 1;
398}
399
411int MMG5_isSplit(MMG5_pMesh mesh,MMG5_int ref,MMG5_int *refint,MMG5_int *refext) {
412 MMG5_pInvMat pim;
413 MMG5_pMat pm;
414 int k;
415
416 /* Default case: split with references MG_MINUS, MG_PLUS */
417 if( !mesh->info.nmat ) {
418 *refint = MG_MINUS;
419 *refext = MG_PLUS;
420 return 1;
421 }
422
423 /* Check in the info->mat table if reference ref is supplied by the user */
424 pim = &mesh->info.invmat;
425 k = MMG5_InvMat_getIndex(pim,ref);
426
427 assert( k != -1 );
428 pm = &mesh->info.mat[k];
429
430 if ( !pm->dospl ) {
431 return 0;
432 } else {
433 *refint = pm->rin;
434 *refext = pm->rex;
435 return 1;
436 }
437}
438
447int MMG5_isNotSplit(MMG5_pMesh mesh,MMG5_int ref) {
448 MMG5_pInvMat pim;
449
450 /* Split material by default if not in multi-material mode */
451 if( !mesh->info.nmat ) return 0;
452
453 /* Look in the table otherwise */
454 pim = &mesh->info.invmat;
455 if( !MMG5_InvMat_getAttrib(pim,ref) )
456 return 0;
457 else
458 return 1;
459
460}
461
471int MMG5_isLevelSet(MMG5_pMesh mesh,MMG5_int ref0,MMG5_int ref1) {
472 MMG5_pInvMat pim;
473 int8_t found0,found1;
474
475 /* Check whether multimaterial case or not */
476 if( mesh->info.nmat ) {
477 /* Retrieve levelset information from the lookup table */
478 pim = &mesh->info.invmat;
479 found0 = MMG5_InvMat_getAttrib(pim,ref0);
480 found1 = MMG5_InvMat_getAttrib(pim,ref1);
481
482 if( (found0+found1) == (MG_MINUS+MG_PLUS) ) return 1;
483 else return 0;
484
485 } else {
486 /* Single material, check references directly */
487 if( ( ref0 == MG_MINUS && ref1 == MG_PLUS ) ||
488 ( ref1 == MG_MINUS && ref0 == MG_PLUS ) ) return 1;
489 else return 0;
490 }
491}
492
503 MMG5_pTria pt,pt1;
504 MMG5_pPoint p0;
505 double v1,v2,*tmp;
506 MMG5_int k,kk,iel,ns,nc,ip,ip1,ip2,npl,nmn;
507 int ilist;
508 int8_t i,j,j1,j2;
509 MMG5_int list[MMG5_TRIA_LMAX+2];
510
511 /* Allocate memory for tmp */
512 MMG5_ADD_MEM(mesh,(mesh->npmax+1)*sizeof(double),"temporary table",
513 fprintf(stderr," Exit program.\n");
514 return 0);
515 MMG5_SAFE_CALLOC(tmp,mesh->npmax+1,double,return 0);
516
517 /* Reset point flags */
518 for (k=1; k<=mesh->np; k++)
519 mesh->point[k].flag = 0;
520
521 /* Snap values of sol that are close to 0 to 0 exactly */
522 ns = nc = 0;
523 for (k=1; k<=mesh->np; k++) {
524 p0 = &mesh->point[k];
525 if ( !MG_VOK(p0) ) continue;
526 if ( fabs(sol->m[k]) < MMG5_EPS ) {
527 tmp[k] = sol->m[k];
528 p0->flag = 1;
529 sol->m[k] = 0.0;
530 ns++;
531 }
532 }
533
534 /* Check that the snapping process has not led to a nonmanifold situation */
535 for (k=1; k<=mesh->nt; k++) {
536 pt = &mesh->tria[k];
537 if ( !MG_EOK(pt) ) continue;
538 for (i=0; i<3; i++) {
539 ip = pt->v[i];
540 ip1 = pt->v[MMG5_inxt2[i]];
541 ip2 = pt->v[MMG5_iprv2[i]];
542
543 p0 = &mesh->point[ip];
544 v1 = sol->m[ip1];
545 v2 = sol->m[ip2];
546
547 /* Catch a snapped point by a triangle where there is a sign change: use
548 * the same convention than in ismaniball to evaluate sign changes. If
549 * travelled in direct sense from a triangle, an edge is considered
550 * without sign change if first vertex is 0. It has a sign change if
551 * second vertex is 0 or if we have 2 vertices with different signs
552 * (otherwise a 0 vertex leads to count 2 sign changes instead of one). */
553 int smsgn = ((fabs(v2) < MMG5_EPS) || MG_SMSGN(v1,v2)) ? 1 : 0;
554 if ( p0->flag && !smsgn ) {
555 if ( !MMG5_ismaniball(mesh,sol,k,i) ) {
556 if ( tmp[ip] < 0.0 )
557 sol->m[ip] = -100.0*MMG5_EPS;
558 else
559 sol->m[ip] = 100.0*MMG5_EPS;
560 nc++;
561 }
562 p0->flag = 0;
563 }
564 }
565 }
566
567 /* Check that the ls function does not show isolated spots with 0 values (without sign changes) */
568 for (k=1; k<=mesh->nt; k++) {
569 pt = &mesh->tria[k];
570 if ( !MG_EOK(pt) ) continue;
571 for (i=0; i<3; i++) {
572 ip = pt->v[i];
573 if ( fabs(sol->m[ip]) >= MMG5_EPS ) continue;
574 npl = nmn = 0;
575 int8_t opn; //unused
576 ilist = MMG5_boulet(mesh,k,i,list,1,&opn);
577 for(kk=0; kk<ilist; kk++) {
578 iel = list[kk] / 3;
579 j = list[kk] % 3;
580 j1 = MMG5_inxt2[j];
581 j2 = MMG5_iprv2[i];
582 pt1 = &mesh->tria[iel];
583 ip1 = pt1->v[j1];
584 ip2 = pt1->v[j2];
585 if ( sol->m[ip1] >= MMG5_EPS ) npl = 1;
586 else if ( sol->m[ip1] <= -MMG5_EPS ) nmn = 1;
587
588 if ( sol->m[ip2] >= MMG5_EPS ) npl = 1;
589 else if ( sol->m[ip2] <= -MMG5_EPS ) nmn = 1;
590 }
591
592 if ( npl == 1 && nmn == 0 )
593 sol->m[ip] = 100.0*MMG5_EPS;
594 else if ( npl == 0 && nmn == 1 )
595 sol->m[ip] = -100.0*MMG5_EPS;
596 }
597 }
598
599 if ( (abs(mesh->info.imprim) > 5 || mesh->info.ddebug) && ns+nc > 0 )
600 fprintf(stdout," %8" MMG5_PRId " points snapped, %" MMG5_PRId " corrected\n",ns,nc);
601
602 /* memory free */
604
605 return 1;
606}
607
622int MMG5_ismaniball(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int start, int8_t istart) {
623 MMG5_pTria pt;
624 double v1, v2;
625 MMG5_int refstart,*adja,k,ip1,ip2,end1;
626 int8_t i,i1,smsgn;
627 static int8_t mmgWarn=0;
628
629 k = start;
630 refstart = mesh->tria[k].ref;
631 i = MMG5_inxt2[istart];
632
633 /* First loop: stop if an external boundary, or a change in signs (or a 0) is met
634 recall that MG_SMGSGN(a,b) = 1 provided a*b >0 */
635 do{
636 adja = &mesh->adja[3*(k-1)+1];
637 k = adja[i] / 3;
638 i1 = adja[i] % 3;
639 i = MMG5_iprv2[i1];
640
641 if ( k==0 ) break;
642
643 pt = &mesh->tria[k];
644
645 ip1 = pt->v[i1];
646 ip2 = pt->v[i];
647
648 v1 = sol->m[ip1];
649 v2 = sol->m[ip2];
650
651 if ( (fabs(v1) < MMG5_EPS) && (fabs(v2) < MMG5_EPS) ) {
652 /* Do not authorize a snap that leads to a triangle with only 0 vertices */
653 return 0;
654 }
655
656 /* Authorize change of references only provided the boundary reference is mesh->info.isoref */
657 if ( pt->ref != refstart && pt->edg[i1] != mesh->info.isoref ) {
658 smsgn = 0;
659 k = 0;
660 } else {
661 /* Evaluation of sign change using following convention: If
662 * travelled in direct sense from a triangle, an edge is considered
663 * without sign change if first vertex is 0. It has a sign change if
664 * second vertex is 0 or if we have 2 vertices with different signs
665 * (otherwise a 0 vertex leads to count 2 sign changes instead of one). */
666 smsgn = (fabs(v1) < MMG5_EPS) || ( (fabs(v2) > MMG5_EPS) && MG_SMSGN(v1,v2) ) ? 1 : 0;
667 }
668 }
669 while ( smsgn && (k != start) );
670
671 if ( k==start ) {
672 /* Complete ball has been travelled without crossing a boundary or finding a
673 * sign change: we are in the special case where v1 = v2 = v[istart] = 0 in
674 * tria start. In this case, test MG_SMSGN(v1,v2) returns 0 while smsgn is
675 * computed to 1, which is non consistent. */
676 assert ( smsgn );
677 return 0;
678 }
679
680 end1 = k;
681 k = start;
682 i = MMG5_iprv2[istart];
683
684 /* Second loop: same travel in the opposite sense */
685 do{
686 adja = &mesh->adja[3*(k-1)+1];
687 k = adja[i] / 3;
688 i1 = adja[i] % 3;
689 i = MMG5_inxt2[i1];
690
691 if ( k==0 ) break;
692
693 pt = &mesh->tria[k];
694 ip1 = pt->v[i1];
695 ip2 = pt->v[i];
696
697 v1 = sol->m[ip1];
698 v2 = sol->m[ip2];
699
700 if ( (fabs(v1) < MMG5_EPS) && (fabs(v2) < MMG5_EPS) ) {
701 /* Do not authorize a snap that leads to a triangle with only 0 vertices */
702 return 0;
703 }
704
705 if ( pt->ref != refstart && pt->edg[i1] != mesh->info.isoref ) {
706 smsgn = 0;
707 k = 0;
708 } else {
709 /* Evaluation of sign change using following convention: If
710 * travelled in undirect sense from a triangle, an edge is considered
711 * without sign change if second vertex is 0. It has a sign change if
712 * first vertex is 0 or if we have 2 vertices with different signs
713 * (it allows to evaluate the same splitted edges than the first loop). */
714 smsgn = (fabs(v2) < MMG5_EPS) || ( (fabs(v1) > MMG5_EPS) && MG_SMSGN(v1,v2) ) ? 1 : 0;
715 }
716 }
717 while ( smsgn && (k != start) );
718
719 assert ( k!=start );
720
721 /* If first stop was due to an external boundary, the second one must too
722 (k==end1==0); else, the final triangle for the first travel must be that of
723 the second one */
724 if ( k != end1 ) {
725 if ( !mmgWarn ) {
726 mmgWarn = 1;
727 fprintf(stderr,"\n ## Warning: %s: unsnap at least 1 point "
728 "(point %" MMG5_PRId " in tri %" MMG5_PRId ").\n",__func__,
729 MMG5_indPt(mesh,mesh->tria[start].v[istart]),MMG5_indElt(mesh,start));
730 }
731 return 0;
732 }
733 return 1;
734}
735
746static inline
747double MMG5_voltri(MMG5_pMesh mesh,MMG5_int ip0,MMG5_int ip1,MMG5_int ip2) {
748 MMG5_pPoint p0,p1,p2;
749 double vol;
750
751 p0 = &mesh->point[ip0];
752 p1 = &mesh->point[ip1];
753 p2 = &mesh->point[ip2];
754
755 vol = (p1->c[0]-p0->c[0])*(p2->c[1]-p0->c[1]) - (p1->c[1]-p0->c[1])*(p2->c[0]-p0->c[0]);
756 vol = 0.5*fabs(vol);
757
758 return vol;
759}
760
773static inline
774double MMG5_vfrac(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int k,int pm) {
775 MMG5_pTria pt;
776 MMG5_pPoint ppt[3];
777 double v[3],vfp,vfm,lam,area,eps,o1[2],o2[2];
778 MMG5_int ip[3],nplus,nminus,nzero;
779 int8_t i,i0,i1,i2,imin1,iplus1,iz;
780
781 eps = MMG5_EPS*MMG5_EPS;
782 pt = &mesh->tria[k];
783
784 ip[0] = pt->v[0];
785 ip[1] = pt->v[1];
786 ip[2] = pt->v[2];
787
788 ppt[0] = &mesh->point[ip[0]];
789 ppt[1] = &mesh->point[ip[1]];
790 ppt[2] = &mesh->point[ip[2]];
791
792 v[0] = sol->m[ip[0]];
793 v[1] = sol->m[ip[1]];
794 v[2] = sol->m[ip[2]];
795
796 /* Identify number of zero, positive and negative vertices, and corresponding indices */
797 nplus = nminus = nzero = 0;
798 imin1 = iplus1 = iz = -1;
799
800 for (i=0; i<3; i++) {
801 if ( fabs(v[i]) < eps ) {
802 nzero++;
803 if ( iz < 0 ) iz = i;
804 }
805 else if ( v[i] >= eps ) {
806 nplus++;
807 if ( iplus1 < 0 ) iplus1 = i;
808 }
809 else {
810 nminus++;
811 if ( imin1 < 0 ) imin1 = i;
812 }
813 }
814
815 /* Degenerate case */
816 if ( nzero == 3 ) return 0.0;
817
818 /* Whole triangle is positive */
819 if ( nminus == 0 ) {
820 vfp = (ppt[1]->c[0]-ppt[0]->c[0])*(ppt[2]->c[1]-ppt[0]->c[1]) - (ppt[1]->c[1]-ppt[0]->c[1])*(ppt[2]->c[0]-ppt[0]->c[0]);
821 vfp = 0.5*fabs(vfp);
822 if ( pm == 1 ) return vfp;
823 else return 0.0;
824 }
825
826 /* Whole triangle is negative */
827 if ( nplus == 0 ) {
828 vfm = (ppt[1]->c[0]-ppt[0]->c[0])*(ppt[2]->c[1]-ppt[0]->c[1]) - (ppt[1]->c[1]-ppt[0]->c[1])*(ppt[2]->c[0]-ppt[0]->c[0]);
829 vfm = 0.5*fabs(vfm);
830 if ( pm == -1 ) return vfm;
831 else return 0.0;
832 }
833
834 /* Exactly one vertex is negative */
835 if ( nminus == 1 ) {
836 i0 = imin1;
837 i1 = MMG5_inxt2[i0];
838 i2 = MMG5_iprv2[i0];
839
840 lam = v[i0] / (v[i0]-v[i1]);
841 o1[0] = ppt[i0]->c[0] + lam*(ppt[i1]->c[0]-ppt[i0]->c[0]);
842 o1[1] = ppt[i0]->c[1] + lam*(ppt[i1]->c[1]-ppt[i0]->c[1]);
843
844 lam = v[i0] / (v[i0]-v[i2]);
845 o2[0] = ppt[i0]->c[0] + lam*(ppt[i2]->c[0]-ppt[i0]->c[0]);
846 o2[1] = ppt[i0]->c[1] + lam*(ppt[i2]->c[1]-ppt[i0]->c[1]);
847
848 vfm = (o1[0]-ppt[i0]->c[0])*(o2[1]-ppt[i0]->c[1]) - (o1[1]-ppt[i0]->c[1])*(o2[0]-ppt[i0]->c[0]);
849 vfm = 0.5*fabs(vfm);
850
851 if ( pm == -1 ) return vfm;
852 else {
853 area = (ppt[1]->c[0]-ppt[0]->c[0])*(ppt[2]->c[1]-ppt[0]->c[1]) - (ppt[1]->c[1]-ppt[0]->c[1])*(ppt[2]->c[0]-ppt[0]->c[0]);
854 area = 0.5*fabs(area);
855 vfp = area-vfm;
856 return vfp;
857 }
858 }
859
860 /* Exactly one vertex is positive */
861 if ( nplus == 1 ) {
862 i0 = iplus1;
863 i1 = MMG5_inxt2[i0];
864 i2 = MMG5_iprv2[i0];
865
866 lam = v[i0] / (v[i0]-v[i1]);
867 o1[0] = ppt[i0]->c[0] + lam*(ppt[i1]->c[0]-ppt[i0]->c[0]);
868 o1[1] = ppt[i0]->c[1] + lam*(ppt[i1]->c[1]-ppt[i0]->c[1]);
869
870 lam = v[i0] / (v[i0]-v[i2]);
871 o2[0] = ppt[i0]->c[0] + lam*(ppt[i2]->c[0]-ppt[i0]->c[0]);
872 o2[1] = ppt[i0]->c[1] + lam*(ppt[i2]->c[1]-ppt[i0]->c[1]);
873
874 vfp = (o1[0]-ppt[i0]->c[0])*(o2[1]-ppt[i0]->c[1]) - (o1[1]-ppt[i0]->c[1])*(o2[0]-ppt[i0]->c[0]);
875 vfp = 0.5*fabs(vfp);
876
877 if ( pm == 1 ) return vfp;
878 else {
879 area = (ppt[1]->c[0]-ppt[0]->c[0])*(ppt[2]->c[1]-ppt[0]->c[1]) - (ppt[1]->c[1]-ppt[0]->c[1])*(ppt[2]->c[0]-ppt[0]->c[0]);
880 area = 0.5*fabs(area);
881 vfm = area-vfp;
882 return vfm;
883 }
884 }
885
886 /* Should not pass here */
887 return 0.0;
888}
889
891static inline
892int MMG5_isbr(MMG5_pMesh mesh,MMG5_int ref) {
893 MMG5_int k;
894
895 for(k=0; k<mesh->info.nbr; k++)
896 if ( ref == mesh->info.br[k] ) return 1;
897
898 return 0;
899}
900
912 MMG5_pTria pt,pt1,pt2;
913 double volc,voltot,v0,v1,v2;
914 MMG5_int k,kk,l,ll,ncp,ncm,ip0,ip1,ip2,cur,ipile,*pile,*adja,base;
915 int8_t i,i1,i2,onbr;
916
917 ncp = 0;
918 ncm = 0;
919
920 /* Erase triangle flags */
921 for (k=1; k<=mesh->nt; k++) mesh->tria[k].flag = 0;
922
923 /* Calculate volume of the total mesh */
924 voltot = 0.0;
925 for (k=1; k<=mesh->nt; k++) {
926 pt = &mesh->tria[k];
927 if ( !MG_EOK(pt) ) continue;
928 ip0 = pt->v[0];
929 ip1 = pt->v[1];
930 ip2 = pt->v[2];
931 voltot += MMG5_voltri(mesh,ip0,ip1,ip2);
932 }
933
934 /* Memory allocation for pile */
935 MMG5_ADD_MEM(mesh,(mesh->nt+1)*sizeof(MMG5_int),"temporary table",
936 printf(" Exit program.\n");
937 return 0);
938 MMG5_SAFE_CALLOC(pile,mesh->nt+1,MMG5_int,return 0);
939
940 /* Investigate only positive connected components */
941 base = ++mesh->base;
942
943 for (k=1; k<=mesh->nt; k++) {
944 ipile = 0;
945 volc = 0.0;
946 pt = &mesh->tria[k];
947 if ( !MG_EOK(pt) ) continue;
948 if ( pt->flag == base ) continue;
949
950 /* Checks signs of the LS function at the 3 vertices of pt */
951 ip0 = pt->v[0];
952 ip1 = pt->v[1];
953 ip2 = pt->v[2];
954
955 v0 = sol->m[ip0];
956 v1 = sol->m[ip1];
957 v2 = sol->m[ip2];
958
959 if ( v0 <= 0.0 && v1 <= 0.0 && v2 <= 0.0 ) continue;
960
961 /* Add triangle to pile if one vertex is > 0 */
962 pt->flag = base;
963 pile[ipile] = k;
964 ipile++;
965 if ( ipile > mesh->nt ) {
966 fprintf(stderr,"\n ## Problem in length of pile; function rmc.\n"
967 " Check that the level-set intersect the mesh.\n"
968 " Exit program.\n");
969
970 return 0;
971 }
972
973 /* Pile up all the positive connected component attached to the first triangle */
974 cur = 0;
975 do {
976 kk = pile[cur];
977 pt1 = &mesh->tria[kk];
978
979 /* Add local volume fraction of the positive subdomain to volc */
980 volc += MMG5_vfrac(mesh,sol,kk,1);
981
982 /* Add adjacent triangles to kk via positive vertices to the pile, if need be */
983 adja = &mesh->adja[3*(kk-1)+1];
984 for (i=0; i<3; i++) {
985 ip0 = pt1->v[i];
986 if ( sol->m[ip0] <= 0.0 ) continue;
987
988 i1 = MMG5_inxt2[i];
989 i2 = MMG5_inxt2[i1];
990
991 /* First neighbor of positive vertex i */
992 ll = adja[i1] / 3;
993 if ( ll ) {
994 pt2 = &mesh->tria[ll];
995 if ( pt2->flag != base ) {
996 pt2->flag = base;
997 pile[ipile] = ll;
998 ipile++;
999 if ( ipile > mesh->nt ) {
1000 fprintf(stderr,"\n ## Problem in length of pile; function rmc. Exit program.\n");
1001 return 0;
1002 }
1003 }
1004 }
1005
1006 /* Second neighbor of positive vertex i */
1007 ll = adja[i2] / 3;
1008 if ( ll ) {
1009 pt2 = &mesh->tria[ll];
1010 if ( pt2->flag != base ) {
1011 pt2->flag = base;
1012 pile[ipile] = ll;
1013 ipile++;
1014 if ( ipile > mesh->nt ) {
1015 fprintf(stderr,"\n ## Problem in length of pile; function rmc. Exit program.\n");
1016 return 0;
1017 }
1018 }
1019 }
1020 }
1021 }
1022 while ( ++cur < ipile );
1023
1024 /* Remove connected component if its volume is too small */
1025 if ( volc < mesh->info.rmc*voltot ) {
1026 for (l=0; l<ipile; l++) {
1027 pt1 = &mesh->tria[pile[l]];
1028 for (i=0; i<3; i++) {
1029 ip0 = pt1->v[i];
1030 if ( sol->m[ip0] > 0.0 ) sol->m[ip0] = -100*MMG5_EPS;
1031 }
1032 }
1033 ncp++;
1034 }
1035
1036 }
1037
1038 /* Investigate only negative connected components */
1039 base = ++mesh->base;
1040
1041 for (k=1; k<=mesh->nt; k++) {
1042 ipile = 0;
1043 volc = 0.0;
1044 pt = &mesh->tria[k];
1045 if ( !MG_EOK(pt) ) continue;
1046 if ( pt->flag == base ) continue;
1047
1048 /* Checks signs of the LS function at the 3 vertices of pt */
1049 ip0 = pt->v[0];
1050 ip1 = pt->v[1];
1051 ip2 = pt->v[2];
1052
1053 v0 = sol->m[ip0];
1054 v1 = sol->m[ip1];
1055 v2 = sol->m[ip2];
1056
1057 if ( v0 >= 0.0 && v1 >= 0.0 && v2 >= 0.0 ) continue;
1058
1059 /* Pile up all the negative connected component attached to the first triangle */
1060 pt->flag = base;
1061 pile[ipile] = k;
1062 ipile++;
1063 if ( ipile > mesh->nt ) {
1064 fprintf(stderr,"\n ## Problem in length of pile; function rmc. Exit program.\n");
1065 return 0;
1066 }
1067
1068 cur = 0;
1069 do {
1070 kk = pile[cur];
1071 pt1 = &mesh->tria[kk];
1072
1073 /* Add local volume fraction of the negative subdomain to volc */
1074 volc += MMG5_vfrac(mesh,sol,kk,-1);
1075
1076 /* Add adjacent triangles to kk via negative vertices to the pile, if need be */
1077 adja = &mesh->adja[3*(kk-1)+1];
1078 for (i=0; i<3; i++) {
1079 ip0 = pt1->v[i];
1080 if ( sol->m[ip0] >= 0.0 ) continue;
1081
1082 i1= MMG5_inxt2[i];
1083 i2 = MMG5_inxt2[i1];
1084
1085 /* First neighbor of negative vertex i */
1086 ll = adja[i1] / 3;
1087 if ( ll ) {
1088 pt2 = &mesh->tria[ll];
1089 if ( pt2->flag != base ) {
1090 pt2->flag = base;
1091 pile[ipile] = ll;
1092 ipile++;
1093 if ( ipile > mesh->nt ) {
1094 fprintf(stderr,"\n ## Problem in length of pile; function rmc. Exit program.\n");
1095 return 0;
1096 }
1097 }
1098 }
1099
1100 /* Second neighbor of negative vertex i */
1101 ll = adja[i2] / 3;
1102 if ( ll ) {
1103 pt2 = &mesh->tria[ll];
1104 if ( pt2->flag != base ) {
1105 pt2->flag = base;
1106 pile[ipile] = ll;
1107 ipile++;
1108 if ( ipile > mesh->nt ) {
1109 fprintf(stderr,"\n ## Problem in length of pile; function rmc. Exit program.\n");
1110 return 0;
1111 }
1112 }
1113 }
1114
1115 }
1116 }
1117 while ( ++cur < ipile );
1118
1119 /* Remove connected component if its volume is too small */
1120 if ( volc < mesh->info.rmc*voltot ) {
1121 for (l=0; l<ipile; l++) {
1122 pt1 = &mesh->tria[pile[l]];
1123 for (i=0; i<3; i++) {
1124 ip0 = pt1->v[i];
1125 if ( sol->m[ip0] < 0.0 ) sol->m[ip0] = 100*MMG5_EPS;
1126 }
1127 }
1128 ncm++;
1129 }
1130
1131 /* Remove connected component if it is not attached to one base reference */
1132 if ( mesh->info.nbr ) {
1133 onbr = 0;
1134 for (l=0; l<ipile; l++) {
1135 pt1 = &mesh->tria[pile[l]];
1136 for (i=0; i<3; i++) {
1137 if ( MMG5_isbr(mesh,pt1->edg[i]) ) {
1138 i1 = MMG5_inxt2[i];
1139 i2 = MMG5_inxt2[i1];
1140 ip1 = pt1->v[i1];
1141 if ( sol->m[ip1] < 0.0 ) {
1142 onbr = 1;
1143 break;
1144 }
1145 ip2 = pt1->v[i2];
1146 if ( sol->m[ip2] < 0.0 ) {
1147 onbr = 1;
1148 break;
1149 }
1150 }
1151 }
1152 if ( onbr ) break;
1153 }
1154
1155 if ( !onbr ) {
1156 for (l=0; l<ipile; l++) {
1157 pt1 = &mesh->tria[pile[l]];
1158 for (i=0; i<3; i++) {
1159 ip0 = pt1->v[i];
1160 if ( sol->m[ip0] < 0.0 ) sol->m[ip0] = 100*MMG5_EPS;
1161 }
1162 }
1163 ncm++;
1164 }
1165 }
1166
1167 }
1168
1169 /* Erase triangle flags */
1170 for (k=1; k<=mesh->nt; k++) mesh->tria[k].flag = 0;
1171
1172 /* Release memory */
1173 MMG5_DEL_MEM(mesh,pile);
1174
1175 if ( mesh->info.imprim > 0 || mesh->info.ddebug ) {
1176 printf("\n *** Removed %" MMG5_PRId " positive parasitic bubbles and %" MMG5_PRId " negative parasitic bubbles\n",ncp,ncm);
1177 }
1178
1179 return(1);
1180}
1181
1189 MMG5_pTria pt;
1190 MMG5_pPoint p0;
1191 MMG5_int ref,k;
1192 int8_t i;
1193
1194 for (k=1; k<=mesh->nt; k++) {
1195 pt = &mesh->tria[k];
1196 if ( !pt->v[0] ) continue;
1197
1198 for (i=0; i<3; i++) {
1199 p0 = &mesh->point[pt->v[i]];
1200 if ( pt->edg[i] == mesh->info.isoref ) pt->edg[i] = 0;
1201 if ( p0->ref == mesh->info.isoref ) p0->ref = 0;
1202 }
1203 }
1204
1205 /* Reset the triangle references to their initial distribution */
1206 for (k=1; k<=mesh->nt; k++) {
1207 pt = &mesh->tria[k];
1208 if ( !pt->v[0] ) continue;
1209 if( !MMG5_getStartRef(mesh,pt->ref,&ref) ) return 0;
1210 pt->ref = ref;
1211 }
1212
1213 return 1;
1214}
1215
1225 MMG5_pTria pt;
1226 double v,v1;
1227 int ier;
1228 MMG5_int k,ip,ip1,ref,refint,refext;
1229 int8_t i,i1,i2,nmn,npl,nz;
1230
1231 for (k=1; k<=mesh->nt; k++) {
1232 pt = &mesh->tria[k];
1233 if ( !MG_EOK(pt) ) continue;
1234
1235 ref = pt->ref;
1236 nmn = npl = nz = 0;
1237 for (i=0; i<3; i++) {
1238 ip = pt->v[i];
1239 v = sol->m[ip];
1240
1241 if ( v > 0.0 )
1242 npl++;
1243 else if ( v < 0.0 )
1244 nmn++;
1245 else
1246 nz++;
1247 }
1248
1249 assert(nz < 3);
1250
1251 /* Keep the initial triangle references of the mesh if iso==2, set
1252 * positive and negative ls refs otherwise */
1253 if ( mesh->info.iso != 2 ) {
1254
1255 /* find if current reference should be splitted and the new positive and negative refs */
1256 ier = MMG5_isSplit(mesh,ref,&refint,&refext);
1257 if ( ier ) {
1258 if ( npl ) {
1259 assert( !nmn );
1260 pt->ref = refext;
1261 }
1262 else {
1263 assert ( nmn );
1264 pt->ref = refint;
1265 }
1266 }
1267 }
1268
1269 /* Set mesh->info.isoref ref at ls edges and at the points of these edges */
1270 if ( nz == 2 ) {
1271 for (i=0; i<3; i++) {
1272 ip = pt->v[MMG5_inxt2[i]];
1273 ip1 = pt->v[MMG5_iprv2[i]];
1274 v = sol->m[ip];
1275 v1 = sol->m[ip1];
1276 if ( v == 0.0 && v1 == 0.0) {
1277 pt->edg[i] = mesh->info.isoref;
1278 pt->tag[i] |= MG_REF;
1279 i1 = MMG5_inxt2[i];
1280 i2 = MMG5_inxt2[i1];
1281 mesh->point[pt->v[i1]].ref = mesh->info.isoref;
1282 mesh->point[pt->v[i2]].ref = mesh->info.isoref;
1283 }
1284 }
1285 }
1286
1287 }
1288
1289 return 1;
1290}
1291
1303int MMG5_chkmaniball(MMG5_pMesh mesh, MMG5_int start, int8_t istart) {
1304 MMG5_int refstart,*adja,k;
1305 int8_t i,i1;
1306
1307 k = start;
1308 i = istart;
1309
1310 i1 = MMG5_iprv2[i];
1311
1312
1313 MMG5_pTria pt = &mesh->tria[start];
1314 assert( MG_EDG(pt->tag[i1]) && (pt->edg[i1]==mesh->info.isoref) );
1315
1317 refstart = pt->ref;
1318 do {
1319 adja = &mesh->adja[3*(k-1)+1];
1320 i1 = MMG5_inxt2[i];
1321
1322 k = adja[i1] / 3;
1323 i = adja[i1] % 3;
1324
1325 if ( !k ) break;
1326
1327 if ( mesh->info.iso !=2 ) {
1329 if ( mesh->tria[k].ref != refstart) break;
1330 }
1331 else {
1334 if ( mesh->tria[k].edg[i]==mesh->info.isoref ) break;
1335 }
1336 i = MMG5_inxt2[i];
1337 }
1338 while ( k!=start );
1339
1340 assert(k!=start); //unexpected case
1341
1345 if ( k == 0 ) {
1346 k = start;
1347 i = istart;
1348
1349 adja = &mesh->adja[3*(k-1)+1];
1350 i1 = MMG5_iprv2[i];
1351 k = adja[i1] / 3;
1352 i = adja[i1] % 3;
1353 i = MMG5_iprv2[i];
1354
1356 if ( k == 0 ) return 1;
1357
1358 do {
1359 adja = &mesh->adja[3*(k-1)+1];
1360 i1 = MMG5_iprv2[i];
1361
1362 k = adja[i1] / 3;
1363 i = adja[i1] % 3;
1364
1365 if ( !k ) break;
1366
1367 if ( mesh->info.iso !=2 ) {
1368 /* Normal or multi-material mode: check for change in triangle references */
1369 if ( mesh->tria[k].ref == refstart) break;
1370 }
1371 else {
1372 /* Input reference preservation mode (mmgs --keep-ref option): Check if
1373 * we cross an isoref edge */
1374 if ( mesh->tria[k].edg[i]==mesh->info.isoref ) break;
1375 }
1376 i = MMG5_iprv2[i];
1377 }
1378 while ( k!=start );
1379
1380 assert(k!=start); //unexpected case
1381
1382 return !k;
1383 }
1384
1386 i = MMG5_inxt2[i];
1387 do {
1388 adja = &mesh->adja[3*(k-1)+1];
1389 i1 = MMG5_inxt2[i];
1390
1391 k = adja[i1] / 3;
1392 i = adja[i1] % 3;
1393
1394 if ( !k ) break;
1395
1396 if ( mesh->info.iso !=2 ) {
1397 /* Check tria ref change */
1398 if ( mesh->tria[k].ref == refstart) break;
1399 }
1400 else {
1401 /* Check if we cross an isoref edge */
1402 if ( mesh->tria[k].edg[i]==mesh->info.isoref ) break;
1403 }
1404
1405 i = MMG5_inxt2[i];
1406 }
1407 while ( k!=start );
1408
1410 if ( k != start )
1411 return 0;
1412
1413 return 1;
1414}
1415
1424 MMG5_pTria pt,pt1;
1425 MMG5_int *adja,k;
1426 MMG5_int cnt,iel;
1427 int8_t i,i1;
1428 static int8_t mmgWarn = 0;
1429
1431 for (k=1; k<=mesh->nt; k++) {
1432 pt = &mesh->tria[k];
1433 if ( !MG_EOK(pt) ) continue;
1434
1435 adja = &mesh->adja[3*(k-1)+1];
1436 cnt = 0;
1437 for (i=0; i<3; i++) {
1438 iel = adja[i] / 3;
1439
1440 if (!iel ) {
1441 cnt++;
1442 continue;
1443 }
1444 else {
1445 if ( mesh->info.iso !=2 ) {
1446 /* Multi-material mode may lead to have only 1 isoref edge around a
1447 point (due to nosplit option): check tria ref change */
1448 pt1 = &mesh->tria[iel];
1449 if ( pt1->ref != pt->ref ) cnt++;
1450 }
1451 else {
1452 /* keep-ref mode: check if isoref edge */
1453 if ( pt->edg[i] == mesh->info.isoref ) cnt++;
1454 }
1455 }
1456 }
1457 if( cnt == 3 ) {
1458 if ( !mmgWarn ) {
1459 mmgWarn = 1;
1460 fprintf(stderr,"\n ## Warning: %s: at least 1 triangle with 3 boundary"
1461 " edges.\n",__func__);
1462 }
1463 }
1464 }
1465
1469 for (k=1; k<=mesh->nt; k++) {
1470 pt = &mesh->tria[k];
1471 if ( !MG_EOK(pt) ) continue;
1472
1473 for (i=0; i<3; i++) {
1474 adja = &mesh->adja[3*(k-1)+1];
1475 iel = adja[i] / 3;
1476
1477 if (! iel ) continue;
1478
1479 if ( mesh->info.iso !=2 ) {
1480 /* Check change of tria ref */
1481 pt1 = &mesh->tria[iel];
1482 if ( pt->ref == pt1->ref || pt->edg[i]!= mesh->info.isoref ) continue;
1483 }
1484 else {
1485 /* Check isoref edge only */
1486 if ( pt->edg[i] != mesh->info.isoref ) continue;
1487 }
1488
1489 i1 = MMG5_inxt2[i];
1490 if ( !MMG5_chkmaniball(mesh,k,i1) ) {
1491 fprintf(stderr," *** Topological problem\n");
1492 fprintf(stderr," non manifold curve at point %" MMG5_PRId "\n",pt->v[i1]);
1493 fprintf(stderr," non manifold curve at tria %" MMG5_PRId " (ip %d)\n", MMG5_indElt(mesh,k),i1);
1494 return 0;
1495 }
1496 }
1497 }
1498
1499 if ( mesh->info.imprim > 0 || mesh->info.ddebug )
1500 fprintf(stdout," *** Manifold implicit surface.\n");
1501
1502 return 1;
1503}
int ier
tmp[*strlen0]
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
MMG5_Info info
int MMG5_boulet(MMG5_pMesh mesh, MMG5_int start, int ip, MMG5_int *list, int8_t s, int8_t *opn)
Definition: boulep.c:363
#define MMG5_EPS
#define MG_PLUS
Definition: libmmgtypes.h:71
#define MG_MINUS
Definition: libmmgtypes.h:76
static int MMG5_InvMat_code(int k, int attr)
Definition: mmg2.c:58
static void MMG5_InvMat_error(MMG5_pInvMat pim, int ref, int k)
Definition: mmg2.c:111
int MMG5_rmc(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2.c:911
static int MMG5_InvMat_check(MMG5_pInvMat pim, int key)
Definition: mmg2.c:98
int MMG5_isLevelSet(MMG5_pMesh mesh, MMG5_int ref0, MMG5_int ref1)
Definition: mmg2.c:471
int MMG5_isNotSplit(MMG5_pMesh mesh, MMG5_int ref)
Definition: mmg2.c:447
int MMG5_ismaniball(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int start, int8_t istart)
Definition: mmg2.c:622
static int MMG5_isbr(MMG5_pMesh mesh, MMG5_int ref)
Definition: mmg2.c:892
static int MMG5_InvMat_getParent(MMG5_pMesh mesh, MMG5_pInvMat pim, MMG5_int ref, MMG5_int *pref)
Definition: mmg2.c:177
static MMG5_int MMG5_InvMat_key(MMG5_pInvMat pim, int ref)
Definition: mmg2.c:46
static int MMG5_InvMat_getAttrib(MMG5_pInvMat pim, int ref)
Definition: mmg2.c:84
int MMG5_snpval_ls(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2.c:502
int MMG5_isSplit(MMG5_pMesh mesh, MMG5_int ref, MMG5_int *refint, MMG5_int *refext)
Definition: mmg2.c:411
static int MMG5_InvMat_set(MMG5_pMesh mesh, MMG5_pInvMat pim, int k)
Definition: mmg2.c:129
static void MMG5_InvMat_print(MMG5_pMesh mesh, MMG5_pInvMat pim)
Definition: mmg2.c:238
static double MMG5_voltri(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, MMG5_int ip2)
Definition: mmg2.c:747
int MMG5_MultiMat_init(MMG5_pMesh mesh)
Definition: mmg2.c:326
int MMG5_getStartRef(MMG5_pMesh mesh, MMG5_int ref, MMG5_int *pref)
Definition: mmg2.c:213
static double MMG5_vfrac(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int k, int pm)
Definition: mmg2.c:774
int MMG5_resetRef_ls(MMG5_pMesh mesh)
Definition: mmg2.c:1188
int MMG5_chkmaniball(MMG5_pMesh mesh, MMG5_int start, int8_t istart)
Definition: mmg2.c:1303
int MMG5_chkmanimesh(MMG5_pMesh mesh)
Definition: mmg2.c:1423
static int MMG5_InvMat_getIndex(MMG5_pInvMat pim, int ref)
Definition: mmg2.c:69
int MMG5_setref_ls(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2.c:1224
#define MMG5_SAFE_CALLOC(ptr, size, type, law)
#define MG_EOK(pt)
#define MMG5_ADD_MEM(mesh, size, message, law)
#define MG_EDG(tag)
static const uint8_t MMG5_iprv2[3]
#define MMG5_TRIA_LMAX
static const uint8_t MMG5_inxt2[6]
#define MG_VOK(ppt)
#define MG_SMSGN(a, b)
#define MG_REF
#define MMG5_DEL_MEM(mesh, ptr)
MMG5_int ref
Definition: libmmgtypes.h:307
int8_t iso
Definition: libmmgtypes.h:534
int8_t ddebug
Definition: libmmgtypes.h:532
MMG5_int * br
Definition: libmmgtypes.h:520
double rmc
Definition: libmmgtypes.h:519
MMG5_pMat mat
Definition: libmmgtypes.h:554
MMG5_int isoref
Definition: libmmgtypes.h:521
MMG5_InvMat invmat
Definition: libmmgtypes.h:555
To store lookup table for references in the mesh (useful in LS mode)
Definition: libmmgtypes.h:505
MMG5_int offset
Definition: libmmgtypes.h:506
MMG5_int size
Definition: libmmgtypes.h:507
int * lookup
Definition: libmmgtypes.h:508
To store user-defined references in the mesh (useful in LS mode)
Definition: libmmgtypes.h:495
MMG5_int ref
Definition: libmmgtypes.h:497
int8_t dospl
Definition: libmmgtypes.h:496
MMG5_int rex
Definition: libmmgtypes.h:497
MMG5_int rin
Definition: libmmgtypes.h:497
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_int npmax
Definition: libmmgtypes.h:612
MMG5_int base
Definition: libmmgtypes.h:616
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pEdge edge
Definition: libmmgtypes.h:649
MMG5_int na
Definition: libmmgtypes.h:612
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 ref
Definition: libmmgtypes.h:404
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 flag
Definition: libmmgtypes.h:341
MMG5_int v[3]
Definition: libmmgtypes.h:334