Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
swapar_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*/
34#include "libmmg2d_private.h"
35
36/* Version of edge swapping specific to the boundary enforcement stage in Delaunay meshing;
37 the quality of the resulting criterion should be > crit.
38 list returns both modified triangles */
39int MMG2D_swapdelone(MMG5_pMesh mesh,MMG5_pSol sol,MMG5_int k,int8_t i,double crit,MMG5_int *list) {
40 MMG5_pTria pt,pt1,pt0;
41 double cal1,cal2,area1,area2,arean1,arean2;
42 MMG5_int *adja,*adja1,k1,k2,k3,vo2,vo3,num1,numa1;
43 int8_t i1,i2,j,j1,j2;
44
45 adja = &mesh->adja[3*(k-1)+1];
46 k1 = adja[i] / 3;
47 if ( !k1 ) return 0;
48
49 j = adja[i] % 3;
50 j1 = MMG5_inxt2[j];
51 j2 = MMG5_iprv2[j];
52 pt0 = &mesh->tria[0];
53 pt = &mesh->tria[k];
54 pt1 = &mesh->tria[k1];
55
56 if(pt->ref!=pt1->ref) {
57 return 0;
58 }
59
60 area1 = MMG2D_quickarea(mesh->point[pt->v[0]].c,mesh->point[pt->v[1]].c,mesh->point[pt->v[2]].c);
61 area2 = MMG2D_quickarea(mesh->point[pt1->v[0]].c,mesh->point[pt1->v[1]].c,mesh->point[pt1->v[2]].c);
62
63 /* Simulate the alternate configuration */
64 i1 = MMG5_inxt2[i];
65 i2 = MMG5_iprv2[i];
66
67 pt0->v[0] = pt->v[i];
68 pt0->v[1] = pt->v[i1];
69 pt0->v[2] = pt1->v[j];
70 cal1 = MMG2D_caltri_iso(mesh,sol,pt0);
71 arean1 = MMG2D_quickarea(mesh->point[pt0->v[0]].c,mesh->point[pt0->v[1]].c,mesh->point[pt0->v[2]].c);
72 if ( cal1 > crit ) return 0;
73
74 pt0->v[0] = pt->v[i];
75 pt0->v[1] = pt1->v[j];
76 pt0->v[2] = pt->v[i2];
77 cal2 = MMG2D_caltri_iso(mesh,sol,pt0);
78 arean2 = MMG2D_quickarea(mesh->point[pt0->v[0]].c,mesh->point[pt0->v[1]].c,mesh->point[pt0->v[2]].c);
79 if ( cal2 > crit ) return 0;
80
81 if ( arean1 < 0.0 || arean2 < 0.0 || fabs((area1+area2)-(arean1+arean2)) > MMG2D_EPSD ) {
82 if(mesh->info.ddebug) printf(" ## Warning: non convex configuration\n");
83 return 0;
84 }
85
86 /* Update vertices of both triangles */
87 k2 = adja[i1] / 3;
88 vo2 = adja[i1] % 3;
89 adja1 = &mesh->adja[3*(k1-1)+1];
90 k3 = adja1[j1] / 3;
91 vo3 = adja1[j1] % 3;
92
93 pt->v[i2] = pt1->v[j];
94 pt->qual = cal1;
95 list[1] = k;
96 pt1->v[j2] = pt->v[i];
97 pt1->qual = cal2;
98 list[2] = k1;
99
100 /* Update edge references */
101#ifndef NDEBUG
102 MMG5_int num = pt->edg[i];
103 assert ( !num );
104#endif
105 num1 = pt->edg[i1];
106 numa1 = pt1->edg[j1];
107
108 /* Update adjacencies */
109 mesh->adja[3*(k1-1)+1+j] = 3*k2+vo2;
110 pt1->edg[j] = num1;
111 if ( k2 )
112 mesh->adja[3*(k2-1)+1+vo2] = 3*k1+j;
113
114 mesh->adja[3*(k-1)+1+i] = 3*k3+vo3;
115 pt->edg[i] = numa1;
116 if ( k3 )
117 mesh->adja[3*(k3-1)+1+vo3] = 3*k+i;
118
119 mesh->adja[3*(k-1)+1+i1] = 3*k1+j1;
120 pt->edg[i1] = 0;
121 mesh->adja[3*(k1-1)+1+j1] = 3*k+i1;
122 pt1->edg[j1] = 0;
123
124 return 1;
125}
126
127/* Check whether swap of edge i in triangle k is valid, and suitable for the mesh */
128int MMG2D_chkswp(MMG5_pMesh mesh, MMG5_pSol met,MMG5_int k,int8_t i,int8_t typchk) {
129 MMG5_pTria pt,pt0,pt1;
130 double /*loni,lona,*/cal1,cal2,calnat,calchg;
131 MMG5_int *adja,ip,ip1,ip2,iq,kk;
132 uint8_t i1,i2,ii,ii1,ii2;
133
134 pt0 = &mesh->tria[0];
135 pt = &mesh->tria[k];
136 i1 = MMG5_inxt2[i];
137 i2 = MMG5_iprv2[i];
138 if ( MG_EDG(pt->tag[i]) || MG_SIN(pt->tag[i]) ) return 0;
139
140 ip = pt->v[i];
141 ip1 = pt->v[i1];
142 ip2 = pt->v[i2];
143
144 adja = &mesh->adja[3*(k-1)+1];
145 if ( !adja[i] ) return 0;
146
147 kk = adja[i] / 3;
148 ii = adja[i] % 3;
149 ii1 = MMG5_inxt2[ii];
150 ii2 = MMG5_iprv2[ii];
151
152 pt1 = &mesh->tria[kk];
153 iq = pt1->v[ii];
154
155 /* If mesh->info.fem : avoid creating a non BDY edge with BDY endpoints */
156 if ( mesh->info.fem ) {
157 if ( (mesh->point[ip].tag & MG_BDY) && (mesh->point[iq].tag & MG_BDY) ) return 0;
158 }
159
160 /* Check length in typchk = 2 mode ; prevent swap if the created edge is
161 longer than the swapped one, and than the maximum authorized edge length */
162 /* I believe this test is hindering the reach of good quality */
163 /* if ( typchk == 2 && met->m ) { */
164 /* loni = MMG2D_lencurv(mesh,met,ip1,ip2); */
165 /* lona = MMG2D_lencurv(mesh,met,ip,iq); */
166 /* if ( loni > 1.0 ) loni = MG_MIN(1.0 / loni,MMG2D_LSHRT); */
167 /* if ( lona > 1.0 ) lona = 1.0 / lona; */
168 /* if ( lona < loni ) return 0; */
169 /* } */
170
171 /* Check qualities: see possible bug in mmgs + correct for metric (use in anisotropic?) */
172 if ( typchk == 2 && met->m && met->size == 3 ) {
173 /* initial quality */
174 pt0->v[0]= ip; pt0->v[1]= ip1; pt0->v[2]= ip2;
175 pt0->tag[0] = pt->tag[i];
176 pt0->tag[1] = pt->tag[i1];
177 pt0->tag[2] = pt->tag[i2];
178 cal1 = MMG2D_caltri_ani(mesh,met,pt0);
179
180 pt0->v[0]= ip1; pt0->v[1]= iq; pt0->v[2]= ip2;
181 pt0->tag[0] = pt1->tag[ii2];
182 pt0->tag[1] = pt1->tag[ii];
183 pt0->tag[2] = pt1->tag[ii1];
184 cal2 = MMG2D_caltri_ani(mesh,met,pt0);
185
186 calnat = MG_MIN(cal1,cal2);
187 assert(calnat > 0.);
188
189 /* quality after swap */
190 pt0->v[0]= ip; pt0->v[1]= ip1; pt0->v[2]= iq;
191 pt0->tag[0] = pt1->tag[ii1];
192 pt0->tag[1] = MG_NUL;
193 pt0->tag[2] = pt->tag[i2];
194 cal1 = MMG2D_caltri_ani(mesh,met,pt0);
195
196 pt0->v[0]= ip; pt0->v[1]= iq; pt0->v[2]= ip2;
197 pt0->tag[0] = pt1->tag[ii2];
198 pt0->tag[1] = pt->tag[i1];
199 pt0->tag[2] = MG_NUL;
200 cal2 = MMG2D_caltri_ani(mesh,met,pt0);
201
202 calchg = MG_MIN(cal1,cal2);
203 }
204 else {
205 pt0->v[0]= ip; pt0->v[1]= ip1; pt0->v[2]= ip2;
206 cal1 = MMG2D_caltri_iso(mesh,NULL,pt0);
207 pt0->v[0]= ip1; pt0->v[1]= iq; pt0->v[2]= ip2;
208 cal2 = MMG2D_caltri_iso(mesh,NULL,pt0);
209 calnat = MG_MIN(cal1,cal2);
210 pt0->v[0]= ip; pt0->v[1]= ip1; pt0->v[2]= iq;
211 cal1 = MMG2D_caltri_iso(mesh,NULL,pt0);
212 pt0->v[0]= ip; pt0->v[1]= iq; pt0->v[2]= ip2;
213 cal2 = MMG2D_caltri_iso(mesh,NULL,pt0);
214 calchg = MG_MIN(cal1,cal2);
215 }
216
217 return calchg > 1.01 * calnat;
218}
219
220/* Effective swap of edge i in triangle k */
221int MMG2D_swapar(MMG5_pMesh mesh,MMG5_int k,int8_t i) {
222 MMG5_pTria pt,pt1;
223 MMG5_int *adja,adj,k11,k21;
224 int8_t i1,i2,j,jj,j2,v11,v21;
225
226 pt = &mesh->tria[k];
227 if ( MG_EDG(pt->tag[i]) || MG_SIN(pt->tag[i]) ) return 0;
228
229 adja = &mesh->adja[3*(k-1)+1];
230 assert(adja[i]);
231
232 adj = adja[i] / 3;
233 j = adja[i] % 3;
234 pt1 = &mesh->tria[adj];
235
236 i1 = MMG5_inxt2[i];
237 i2 = MMG5_iprv2[i];
238
239 /* update structure */
240 k11 = adja[i1] / 3;
241 v11 = adja[i1] % 3;
242 adja = &mesh->adja[3*(adj-1)+1];
243 jj = MMG5_inxt2[j];
244 j2 = MMG5_iprv2[j];
245 k21 = adja[jj] / 3;
246 v21 = adja[jj] % 3;
247
248 pt->v[i2] = pt1->v[j];
249 pt1->v[j2] = pt->v[i];
250
251 /* update info */
252 pt->tag[i] = pt1->tag[jj];
253 pt->edg[i] = pt1->edg[jj];
254 pt->base = mesh->base;
255 pt1->tag[j] = pt->tag[i1];
256 pt1->edg[j] = pt->edg[i1];
257 pt->tag[i1] = 0;
258 pt->edg[i1] = 0;
259 pt1->tag[jj] = 0;
260 pt1->edg[jj] = 0;
261 pt1->base = mesh->base;
262
263 /* update adjacent */
264 mesh->adja[3*(k-1)+1+i] = 3*k21+v21;
265 if ( k21 )
266 mesh->adja[3*(k21-1)+1+v21] = 3*k+i;
267 mesh->adja[3*(k-1)+1+i1] = 3*adj+jj;
268 mesh->adja[3*(adj-1)+1+jj] = 3*k+i1;
269 if ( k11 )
270 mesh->adja[3*(k11-1)+1+v11] = 3*adj+j;
271 mesh->adja[3*(adj-1)+1+j] = 3*k11+v11;
272
273 return 1;
274}
275
276
277
MMG5_pMesh MMG5_pSol * sol
MMG5_pMesh * mesh
double MMG2D_caltri_ani(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pTria)
Definition: quality_2d.c:121
double MMG2D_caltri_iso(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_pTria)
Definition: quality_2d.c:107
#define MMG2D_EPSD
double MMG2D_quickarea(double a[2], double b[2], double c[2])
Definition: tools.c:971
#define MG_NUL
#define MG_MIN(a, b)
#define MG_EDG(tag)
static const uint8_t MMG5_iprv2[3]
#define MG_SIN(tag)
static const uint8_t MMG5_inxt2[6]
#define MG_BDY
int8_t ddebug
Definition: libmmgtypes.h:532
int8_t fem
Definition: libmmgtypes.h:539
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 base
Definition: libmmgtypes.h:616
MMG5_pTria tria
Definition: libmmgtypes.h:647
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
double * m
Definition: libmmgtypes.h:671
MMG5_int edg[3]
Definition: libmmgtypes.h:339
int16_t tag[3]
Definition: libmmgtypes.h:342
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
int MMG2D_swapdelone(MMG5_pMesh mesh, MMG5_pSol sol, MMG5_int k, int8_t i, double crit, MMG5_int *list)
Definition: swapar_2d.c:39
int MMG2D_swapar(MMG5_pMesh mesh, MMG5_int k, int8_t i)
Definition: swapar_2d.c:221
int MMG2D_chkswp(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, int8_t typchk)
Definition: swapar_2d.c:128