Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
mmg2d6.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*/
33#include "libmmg2d_private.h"
34#include "mmgexterns_private.h"
36
49 MMG5_pTria pt;
50 MMG5_pPoint p0,p1;
51 MMG5_Hash hash;
52 double v0,v1,s,c[2];
53 MMG5_int k,ip0,ip1,nb,np,nt,ns,refint,refext,vx[3];
54 int8_t i,ier;
55
56 /* Reset flag field for points */
57 for (k=1; k<=mesh->np; k++)
58 mesh->point[k].flag = 0;
59
60 /* Estimate the number of intersected edges or surface edges by the 0 level set */
61 nb = 0;
62 for (k=1; k<=mesh->nt; k++) {
63 pt = &mesh->tria[k];
64 if ( !MG_EOK(pt) ) continue;
65
66 for (i=0; i<3; i++) {
67
68 /* If only surface edges are discretized, skip non boundary entities */
69 if ( mesh->info.isosurf && !(pt->tag[i] & MG_BDY) ) continue;
70
71 ip0 = pt->v[MMG5_inxt2[i]];
72 ip1 = pt->v[MMG5_iprv2[i]];
73 p0 = &mesh->point[ip0];
74 p1 = &mesh->point[ip1];
75
76 if ( p0->flag && p1->flag ) continue;
77
78 v0 = sol->m[ip0];
79 v1 = sol->m[ip1];
80
81 if ( fabs(v0) > MMG5_EPSD2 && fabs(v1) > MMG5_EPSD2 && v0*v1 < 0.0 ) {
82 nb++;
83 if ( !p0->flag ) p0->flag = nb;
84 if ( !p1->flag ) p1->flag = nb;
85 }
86 }
87 }
88 if ( !nb ) return 1;
89
90 /* Create the intersection points between the edges or surface edges
91 * in the mesh and the 0 level set */
92 if ( !MMG5_hashNew(mesh,&hash,nb,2*nb) ) return 0;
93
94 for (k=1; k<=mesh->nt; k++) {
95 pt = &mesh->tria[k];
96 if ( !MG_EOK(pt) ) continue;
97
98 for (i=0; i<3; i++) {
99 if ( mesh->info.isosurf && !(pt->tag[i] & MG_REF) ) {
100 continue;
101 }
102
103 ip0 = pt->v[MMG5_inxt2[i]];
104 ip1 = pt->v[MMG5_iprv2[i]];
105
106 np = MMG5_hashGet(&hash,ip0,ip1);
107 if ( np ) continue;
108
109 /* Look either at the triangle ref or at the boundary one */
110 MMG5_int ref;
111 if ( mesh->info.isosurf ) {
112 ref = pt->edg[i];
113 }
114 else {
115 ref = pt->ref;
116 }
117
118 if ( !MMG5_isSplit(mesh,ref,&refint,&refext) ) continue;
119
120 v0 = sol->m[ip0];
121 v1 = sol->m[ip1];
122
123 p0 = &mesh->point[ip0];
124 p1 = &mesh->point[ip1];
125
126 if ( fabs(v0) < MMG5_EPSD2 || fabs(v1) < MMG5_EPSD2 ) continue;
127 else if ( MG_SMSGN(v0,v1) ) continue;
128 else if ( !p0->flag || !p1->flag ) continue;
129
130 /* Intersection point between edge p0p1 and the 0 level set */
131 s = v0 / (v0-v1);
132 s = MG_MAX(MG_MIN(s,1.0-MMG5_EPS),MMG5_EPS);
133
134 c[0] = p0->c[0] + s*(p1->c[0]-p0->c[0]);
135 c[1] = p0->c[1] + s*(p1->c[1]-p0->c[1]);
136
137 np = MMG2D_newPt(mesh,c,0);
138 if ( !np ) {
139 /* reallocation of point table */
141 fprintf(stderr,"\n ## Error: %s: unable to"
142 " allocate a new point.\n",__func__);
144 return 0;,
145 c,0);
146 }
147 sol->m[np] = 0.0;
148 /* If there is a metric in the mesh, interpolate it at the new point */
149 if ( met && met->m )
150 MMG2D_intmet(mesh,met,k,i,np,s);
151
152 MMG5_hashEdge(mesh,&hash,ip0,ip1,np);
153 }
154 }
155
156 /* Proceed to splitting by calling patterns */
157 nt = mesh->nt;
158 ns = 0;
159 ier = 1;
160 for (k=1; k<=nt; k++) {
161
162 pt = &mesh->tria[k];
163 if ( !MG_EOK(pt) ) continue;
164 pt->flag = 0;
165
166 for (i=0; i<3; i++) {
167 ip0 = pt->v[MMG5_inxt2[i]];
168 ip1 = pt->v[MMG5_iprv2[i]];
169
170 vx[i] = MMG5_hashGet(&hash,ip0,ip1);
171
172 if ( vx[i] ) MG_SET(pt->flag,i);
173 }
174
175 switch( pt->flag ) {
176 /* 1 edge split -> 0-+ */
177 case 1: case 2: case 4:
178 ier = MMG2D_split1(mesh,met,k,vx);
179 ns++;
180 break;
181
182 /* 2 edge split -> +-- or -++ */
183 case 3: case 5: case 6:
184 ier = MMG2D_split2(mesh,met,k,vx);
185 ns++;
186 break;
187
188 default:
189 assert(pt->flag==0);
190 break;
191 }
192 if ( !ier ) return 0;
193 }
194
195 if ( (mesh->info.ddebug || abs(mesh->info.imprim) > 5) && ns > 0 )
196 fprintf(stdout," %7" MMG5_PRId " splitted\n",ns);
197
198 MMG5_DEL_MEM(mesh,hash.item);
199 return ns;
200
201}
202
203/* Main function of the -ls mode */
205 char str[16]="";
206 MMG5_int k;
207
208 assert ( (mesh->info.iso || mesh->info.isosurf) && "level-set discretization mode not specified" );
209
210 assert ( (!(mesh->info.iso && mesh->info.isosurf)) && "unable to determine level-set discretization mode" );
211
212 /* Set function pointers */
213 if ( mesh->info.isosurf ) {
214 strcat(str,"(BOUNDARY PART)");
215
216 MMG5_snpval = MMG5_snpval_lssurf;
217 MMG5_resetRef = MMG5_resetRef_lssurf;
218 MMG5_setref = MMG5_setref_lssurf;
219 }
220 else {
221 MMG5_snpval = MMG5_snpval_ls;
222 MMG5_resetRef = MMG5_resetRef_ls;
223 MMG5_setref = MMG5_setref_ls;
224 }
225
226 if ( abs(mesh->info.imprim) > 3 ) {
227 fprintf(stdout," ** ISOSURFACE EXTRACTION %s\n",str);
228 }
229
230 if ( mesh->nquad ) {
231 fprintf(stderr,"\n ## Error: Isosurface extraction not available with"
232 " hybrid meshes. Exit program.\n");
233 return 0;
234 }
235
236 /* Work only with the 0 level set */
237 for (k=1; k<= sol->np; k++)
238 sol->m[k] -= mesh->info.ls;
239
240 /* Transfer the boundary edge references to the triangles */
241 if ( !MMG2D_assignEdge(mesh) ) {
242 fprintf(stderr,"\n ## Problem in setting boundary. Exit program.\n");
243 return 0;
244 }
245
246 /* Processing of bdy infos for isosurface boundary discretization */
247 if ( mesh->info.isosurf ) {
248 /* Creation of tria adjacency relations in the mesh */
249 if ( !MMG2D_hashTria(mesh) ) {
250 fprintf(stderr,"\n ## Hashing problem. Exit program.\n");
251 return 0;
252 }
253
254 /* Set tags to triangles from geometric configuration */
255 if ( !MMG2D_setadj(mesh,0) ) {
256 fprintf(stderr,"\n ## Problem in function setadj. Exit program.\n");
257 return 0;
258 }
259 }
260
261 /* Snap values of the level set function which are very close to 0 to 0 exactly */
262 if ( !MMG5_snpval(mesh,sol) ) {
263 fprintf(stderr,"\n ## Wrong input implicit function. Exit program.\n");
264 return 0;
265 }
266
267 if ( mesh->info.iso ) {
268 /* Removal of small parasitic components */
269 if ( mesh->info.rmc > 0. && !MMG5_rmc(mesh,sol) ) {
270 fprintf(stderr,"\n ## Error in removing small parasitic components. Exit program.\n");
271 return 0;
272 }
273 }
274 else {
275 /* RMC : on verra */
276 if ( mesh->info.rmc > 0 ) {
277 fprintf(stdout,"\n ## Warning: rmc option not implemented for boundary"
278 " isosurface extraction.\n");
279 }
280 }
281
282 /* No need to keep adjacencies from now on */
284
285 /* Reset the mesh->info.isoref field everywhere it appears */
286 if ( !MMG5_resetRef(mesh) ) {
287 fprintf(stderr,"\n ## Problem in resetting references. Exit program.\n");
288 return 0;
289 }
290
291 /* Effective splitting of the crossed triangles */
292 if ( !MMG2D_cuttri(mesh,sol,met) ) {
293 fprintf(stderr,"\n ## Problem in cutting triangles. Exit program.\n");
294 return 0;
295 }
296
297 /* Set references on the interior / exterior triangles*/
298 if ( !MMG5_setref(mesh,sol) ) {
299 fprintf(stderr,"\n ## Problem in setting references. Exit program.\n");
300 return 0;
301 }
302
303 /* Creation of adjacency relations in the mesh */
304 if ( !MMG2D_hashTria(mesh) ) {
305 fprintf(stderr,"\n ## Hashing problem. Exit program.\n");
306 return 0;
307 }
308
309 if ( mesh->info.iso ) {
310 /* Check that the resulting mesh is manifold */
311 if ( !MMG5_chkmanimesh(mesh) ) {
312 fprintf(stderr,"\n ## No manifold resulting situation. Exit program.\n");
313 return 0;
314 }
315 }
316
317 /* Clean memory */
319 sol->np = 0;
320
322
323 return 1;
324}
int ier
MMG5_pMesh MMG5_pSol * sol
if(!ier) exit(EXIT_FAILURE)
MMG5_pMesh * mesh
int MMG2D_setadj(MMG5_pMesh mesh, int8_t init_cc)
Definition: analys_2d.c:50
#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 MMG2D_assignEdge(MMG5_pMesh mesh)
Definition: hash_2d.c:331
int MMG2D_hashTria(MMG5_pMesh mesh)
Definition: hash_2d.c:35
#define MMG2D_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag)
int MMG2D_split2(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_int vx[3])
Definition: split_2d.c:505
int MMG2D_split1(MMG5_pMesh, MMG5_pSol, MMG5_int, MMG5_int vx[3])
Definition: split_2d.c:390
MMG5_int MMG2D_newPt(MMG5_pMesh mesh, double c[2], int16_t tag)
Definition: zaldy_2d.c:38
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 MMG2D_mmg2d6(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: mmg2d6.c:204
int MMG2D_cuttri(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pSol met)
Definition: mmg2d6.c:48
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_BDY
#define MG_SMSGN(a, b)
#define MMG5_EPSD2
#define MG_REF
#define MMG5_DEL_MEM(mesh, ptr)
#define MG_SET(flag, bit)
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 nquad
Definition: libmmgtypes.h:613
double gap
Definition: libmmgtypes.h:608
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