Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmgs2.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
35#include "libmmgs_private.h"
36#include "mmgexterns_private.h"
37
49 MMG5_pTria pt;
50 MMG5_pPoint p0,p1;
51 MMG5_Hash hash;
52 double c[3],v0,v1,s;
53 MMG5_int vx[3],k,np,refint,refext;
54 MMG5_int ip0,ip1,ns,nt,ier,nb;
55 int8_t i;
56
57 /* Reset flag field for points */
58 for (k=1; k<=mesh->np; k++)
59 mesh->point[k].flag = 0;
60
61 /* Evaluate the number of intersected edges by the 0 level set */
62 nb = 0;
63 for (k=1; k<=mesh->nt; k++) {
64 pt = &mesh->tria[k];
65 if ( !MG_EOK(pt) ) continue;
66
67 for (i=0; i<3; i++) {
68 /* If only surface edges are discretized, skip non boundary entities: as
69 * mmgs doesn't add MG_BDY tags, we check if an edge is bdy from the
70 * MG_REF tag */
71 if ( mesh->info.isosurf && !(pt->tag[i] & MG_REF) ) continue;
72
73 ip0 = pt->v[MMG5_inxt2[i]];
74 ip1 = pt->v[MMG5_iprv2[i]];
75 p0 = &mesh->point[ip0];
76 p1 = &mesh->point[ip1];
77
78 if ( p0->flag && p1->flag ) continue;
79
80 v0 = sol->m[ip0];
81 v1 = sol->m[ip1];
82
83 if ( fabs(v0) > MMG5_EPSD2 && fabs(v1) > MMG5_EPSD2 && v0*v1 < 0.0 ) {
84 nb++;
85 if ( !p0->flag ) p0->flag = nb;
86 if ( !p1->flag ) p1->flag = nb;
87 }
88 }
89 }
90 if ( !nb ) return 1;
91
92 /* Create the intersection points between the edges in the mesh and the 0
93 * level set */
94 if ( !MMG5_hashNew(mesh,&hash,nb,2*nb) ) return 0;
95
96 for (k=1; k<=mesh->nt; k++) {
97 pt = &mesh->tria[k];
98 if ( !MG_EOK(pt) ) continue;
99
100 for (i=0; i<3; i++) {
101 if ( mesh->info.isosurf && !(pt->tag[i] & MG_REF) ) {
102 continue;
103 }
104
105 ip0 = pt->v[MMG5_inxt2[i]];
106 ip1 = pt->v[MMG5_iprv2[i]];
107
108 np = MMG5_hashGet(&hash,ip0,ip1);
109 if ( np ) continue;
110
111 /* Look either at the triangle ref or at the boundary one */
112 MMG5_int ref;
113 if ( mesh->info.isosurf ) {
114 ref = pt->edg[i];
115 }
116 else {
117 ref = pt->ref;
118 }
119
120 /* If user asks to keep input refs, ignore multi-mat mode */
121 if ( mesh->info.iso!=2 ) {
122 if ( !MMG5_isSplit(mesh,ref,&refint,&refext) ) continue;
123 }
124
125 v0 = sol->m[ip0];
126 v1 = sol->m[ip1];
127
128 p0 = &mesh->point[ip0];
129 p1 = &mesh->point[ip1];
130
131 if ( fabs(v0) < MMG5_EPSD2 || fabs(v1) < MMG5_EPSD2 ) continue;
132 else if ( MG_SMSGN(v0,v1) ) continue;
133 else if ( !p0->flag || !p1->flag ) continue;
134
135 /* Intersection point between edge p0p1 and the 0 level set */
136 s = v0 / (v0-v1);
137 s = MG_MAX(MG_MIN(s,1.0-MMG5_EPS),MMG5_EPS);
138
139 c[0] = p0->c[0] + s*(p1->c[0]-p0->c[0]);
140 c[1] = p0->c[1] + s*(p1->c[1]-p0->c[1]);
141 c[2] = p0->c[2] + s*(p1->c[2]-p0->c[2]);
142
143 np = MMGS_newPt(mesh,c,NULL);
144 if ( !np ) {
146 fprintf(stderr,"\n ## Error: %s: unable to"
147 " allocate a new point\n",__func__);
149 return 0
150 ,c,NULL);
151 }
152 sol->m[np] = 0.0;
153
154 /* If user provide a metric, interpolate it at the new point */
155 if ( met && met->m ) {
156 if ( met->size > 1 ) {
157 ier = MMGS_intmet33_ani(mesh,met,k,i,np,s);
158 }
159 else {
160 ier = intmet_iso(mesh,met,k,i,np,s);
161 }
162 if ( ier <= 0 ) {
163 // Unable to compute the metric
164 fprintf(stderr,"\n ## Error: %s: unable to"
165 " interpolate the metric during the level-set"
166 " discretization\n",__func__);
167 return 0;
168 }
169 }
170
171 MMG5_hashEdge(mesh,&hash,ip0,ip1,np);
172 }
173 }
174
175 /* Proceed to splitting by calling patterns */
176 nt = mesh->nt;
177 ns = 0;
178 ier = 1;
179 for (k=1; k<=nt; k++) {
180
181 pt = &mesh->tria[k];
182 if ( !MG_EOK(pt) ) continue;
183 pt->flag = 0;
184 memset(vx,0,3*sizeof(MMG5_int));
185 for (i=0; i<3; i++) {
186 vx[i] = MMG5_hashGet(&hash,pt->v[MMG5_inxt2[i]],pt->v[MMG5_iprv2[i]]);
187 if ( vx[i] ) {
188 MG_SET(pt->flag,i);
189 }
190 }
191 switch (pt->flag) {
192 case 1: /* 1 edge split */
193 ier = MMGS_split1(mesh,met,k,0,vx);
194 ns++;
195 break;
196
197 case 2: /* 1 edge split */
198 ier = MMGS_split1(mesh,met,k,1,vx);
199 ns++;
200 break;
201
202 case 4: /* 1 edge split */
203 ier = MMGS_split1(mesh,met,k,2,vx);
204 ns++;
205 break;
206
207 case 3: case 5: case 6: /* 2 edges split */
208 ier = MMGS_split2(mesh,met,k,vx);
209 ns++;
210 break;
211
212 default :
213 assert(pt->flag == 0);
214 break;
215 }
216 if ( !ier ) return 0;
217 }
218
219 if ( (mesh->info.ddebug || abs(mesh->info.imprim) > 5) && ns > 0 )
220 fprintf(stdout," %7" MMG5_PRId " splitted\n",ns);
221
222 /* reset point flags */
223 for (k=1; k<=mesh->np; k++)
224 mesh->point[k].flag = 0;
225
226 MMG5_DEL_MEM(mesh,hash.item);
227 return ns;
228
229}
230
242 char str[16]="";
243 MMG5_int k;
244
245 assert ( (mesh->info.iso || mesh->info.isosurf) && "level-set discretization mode not specified" );
246
247 assert ( (!(mesh->info.iso && mesh->info.isosurf)) && "unable to determine level-set discretization mode" );
248
249 /* Set function pointers */
250 if ( mesh->info.isosurf ) {
251 strcat(str,"(BOUNDARY PART)");
252
253 MMG5_snpval = MMG5_snpval_lssurf;
254 MMG5_resetRef = MMG5_resetRef_lssurf;
255 MMG5_setref = MMG5_setref_lssurf;
256 }
257 else {
258 MMG5_snpval = MMG5_snpval_ls;
259 MMG5_resetRef = MMG5_resetRef_ls;
260 MMG5_setref = MMG5_setref_ls;
261 }
262
263 if ( abs(mesh->info.imprim) > 3 ) {
264 fprintf(stdout," ** ISOSURFACE EXTRACTION %s\n",str);
265 }
266
267 /* Work only with the 0 level set */
268 for (k=1; k<= sol->np; k++)
269 sol->m[k] -= mesh->info.ls;
270
271 /* Transfer the boundary edge references to the triangles */
272 if ( !MMGS_assignEdge(mesh) ) {
273 fprintf(stderr,"\n ## Problem in setting boundary. Exit program.\n");
274 return 0;
275 }
276
277 /* Snap values of level set function if need be, then discretize it */
278 if ( !MMGS_hashTria(mesh) ) {
279 fprintf(stderr,"\n ## Error: %s: hashing problem (1). Exit program.\n",
280 __func__);
281 return 0;
282 }
283 /* identify connexity and reorient triangles (needed for manifoldness checks) */
284 if ( !MMGS_setadj(mesh) ) {
285 fprintf(stderr,"\n ## Topology problem. Exit program.\n");
286 return 0;
287 }
288
289 /* Snap values of the level set function which are very close to 0 to 0 exactly */
290 if ( !MMG5_snpval(mesh,sol) ) {
291 fprintf(stderr,"\n ## Problem with implicit function. Exit program.\n");
292 return 0;
293 }
294
295 if ( mesh->info.iso ) {
296 /* Removal of small parasitic components */
297 if ( mesh->info.rmc > 0. && !MMG5_rmc(mesh,sol) ) {
298 fprintf(stderr,"\n ## Error in removing small parasitic components. Exit program.\n");
299 return 0;
300 }
301 }
302 else {
303 /* RMC : on verra */
304 if ( mesh->info.rmc > 0 ) {
305 fprintf(stdout,"\n ## Warning: rmc option not implemented for boundary"
306 " isosurface extraction.\n");
307 }
308 }
309
311
312 if ( mesh->info.iso != 2 ) {
313 /* Reset the mesh->info.isoref field everywhere it appears */
314 if ( !MMG5_resetRef(mesh) ) {
315 fprintf(stderr,"\n ## Problem in resetting references. Exit program.\n");
316 return 0;
317 }
318 }
319
320 if ( !MMGS_cuttri(mesh,sol,met) ) {
321 fprintf(stderr,"\n ## Problem in discretizing implicit function. Exit program.\n");
322 return 0;
323 }
324
325 if ( !MMG5_setref(mesh,sol) ) {
326 fprintf(stderr,"\n ## Problem in setting references. Exit program.\n");
327 return 0;
328 }
329
330 /* Creation of adjacency relations in the mesh */
331 if ( !MMGS_hashTria(mesh) ) {
332 fprintf(stderr,"\n ## Hashing problem. Exit program.\n");
333 return 0;
334 }
335
336 if ( mesh->info.iso ) {
337 /* Check that the resulting mesh is manifold */
338 if ( !MMG5_chkmanimesh(mesh) ) {
339 fprintf(stderr,"\n ## No manifold resulting situation. Exit program.\n");
340 return 0;
341 }
342 }
343
344 /* Clean memory */
346 sol->np = 0;
347
349
350 return 1;
351}
int ier
MMG5_pMesh MMG5_pSol * sol
if(!ier) exit(EXIT_FAILURE)
MMG5_pMesh * mesh
int MMGS_setadj(MMG5_pMesh mesh)
Definition: analys_s.c:47
#define MMG5_EPS
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 MMGS_assignEdge(MMG5_pMesh mesh)
Definition: hash_s.c:113
int MMGS_hashTria(MMG5_pMesh mesh)
Definition: hash_s.c:77
int MMGS_intmet33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_s.c:144
int intmet_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_s.c:77
MMG5_int MMGS_newPt(MMG5_pMesh mesh, double c[3], double n[3])
Definition: zaldy_s.c:39
int MMGS_split1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int i, MMG5_int *vx)
Definition: split_s.c:109
#define MMGS_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag)
int MMGS_split2(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int *vx)
Definition: split_s.c:459
int MMG5_rmc(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2.c:911
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
int MMG5_resetRef_ls(MMG5_pMesh mesh)
Definition: mmg2.c:1188
int MMG5_chkmanimesh(MMG5_pMesh mesh)
Definition: mmg2.c:1423
int MMG5_setref_ls(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2.c:1224
int MMG5_resetRef_lssurf(MMG5_pMesh mesh)
Definition: mmg2s.c:129
int MMG5_snpval_lssurf(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2s.c:45
int MMG5_setref_lssurf(MMG5_pMesh mesh, MMG5_pSol sol)
Definition: mmg2s.c:160
#define MG_EOK(pt)
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MIN(a, b)
#define MG_MAX(a, b)
static const uint8_t MMG5_iprv2[3]
static const uint8_t MMG5_inxt2[6]
#define MG_SMSGN(a, b)
#define MMG5_EPSD2
#define MG_REF
#define MMG5_DEL_MEM(mesh, ptr)
#define MG_SET(flag, bit)
static int MMGS_cuttri(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: mmgs2.c:48
int MMGS_mmgs2(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: mmgs2.c:241
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 iso
Definition: libmmgtypes.h:534
int8_t ddebug
Definition: libmmgtypes.h:532
int8_t isosurf
Definition: libmmgtypes.h:535
double rmc
Definition: libmmgtypes.h:519
MMG5_pMat mat
Definition: libmmgtypes.h:554
double ls
Definition: libmmgtypes.h:519
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 nt
Definition: libmmgtypes.h:612
MMG5_pTria tria
Definition: libmmgtypes.h:647
MMG5_int np
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 flag
Definition: libmmgtypes.h:282
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 flag
Definition: libmmgtypes.h:341
MMG5_int v[3]
Definition: libmmgtypes.h:334