Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
bezier_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*/
23#include "libmmg2d_private.h"
24
25// extern int8_t ddb;
26
27/* Check if triangle k should be split based on geometric and rough edge length considerations */
28int MMG2D_chkedg(MMG5_pMesh mesh, MMG5_int k) {
29 MMG5_pTria pt;
30 MMG5_pPoint p1,p2;
31 MMG5_pPar par;
32 double hausd[3],hmax[3],ps,cosn,ux,uy,ll,li,t1[2],t2[2];
33 int l;
34 int8_t i,i1,i2,fill;
35
36 pt = &mesh->tria[k];
37 hausd[0] = hausd[1] = hausd[2] = mesh->info.hausd;
38 hmax[0] = hmax[1] = hmax[2] = mesh->info.hmax;
39
40 /* Local parameters for pt and k */
41 int8_t isloc = 0;
42
43 if ( mesh->info.parTyp & MG_Tria ) {
44 for ( l=0; l<mesh->info.npar; ++l ) {
45 par = &mesh->info.par[l];
46
47 if ( par->elt != MMG5_Triangle ) continue;
48 if ( par->ref != pt->ref ) continue;
49
50 hmax[0] = hmax[1] = hmax[2] = par->hmax;
51 hausd[0] = hausd[1] = hausd[2] = par->hausd;
52 isloc = 1;
53 break;
54 }
55 }
56
57 fill = 0;
58 if ( mesh->info.parTyp & MG_Edge ) {
59 if ( isloc ) {
60 for ( l=0; l<mesh->info.npar; ++l ) {
61 par = &mesh->info.par[l];
62
63 if ( par->elt != MMG5_Edg ) continue;
64
65 for (i=0; i<3; i++) {
66 if ( par->ref != pt->edg[i] ) continue;
67
68 hmax[i] = MG_MIN(hmax[i],par->hmax);
69 hausd[i] = MG_MIN(hausd[i],par->hausd);
70
71 MG_SET(fill,i);
72 }
73
74 /* Stop the loop over local parameters if all edges have been found */
75 if ( fill == 7 ) {
76 break;
77 }
78
79 }
80 }
81 else {
82 for ( l=0; l<mesh->info.npar; ++l ) {
83 par = &mesh->info.par[l];
84
85 if ( par->elt != MMG5_Edg ) continue;
86
87 for (i=0; i<3; i++) {
88 if ( par->ref != pt->edg[i] ) continue;
89
90 hmax[i] = par->hmax;
91 hausd[i] = par->hausd;
92
93 MG_SET(fill,i);
94 }
95
96 /* Stop the loop over local parameters if all edges have been found */
97 if ( fill == 7 ) {
98 break;
99 }
100 }
101 }
102 }
103
104
105 /* Analyze the three edges of k */
106 for (i=0; i<3; i++) {
107 i1 = MMG5_inxt2[i];
108 i2 = MMG5_iprv2[i];
109
110 p1 = &mesh->point[pt->v[i1]];
111 p2 = &mesh->point[pt->v[i2]];
112
113 /* Check the lengths of the edges */
114 ux = p2->c[0] - p1->c[0];
115 uy = p2->c[1] - p1->c[1];
116 ll = ux*ux + uy*uy;
117
118 /* Long edges should be split */
119 if ( ll > hmax[i]*hmax[i] ) {
120 MG_SET(pt->flag,i);
121 continue;
122 }
123 /* Do not split very short edges */
124 else if ( ll < MMG5_EPSD ) continue;
125
126 /* Split non geometric edges connecting two parts of the border */
127 else if ( mesh->info.fem &&
128 ( (!MG_EDG(pt->tag[i])) && (p1->tag > MG_NOTAG) && (p2->tag > MG_NOTAG)) ) {
129 MG_SET(pt->flag,i);
130 continue;
131 }
132
133 /* Test the distance with respect to the continuous support in the case of a geometric edge */
134 if ( !MG_EDG(pt->tag[i]) ) continue;
135
136 /* Collect tangent vectors at both endpoints; remark t1 and t2 need not be oriented in the same fashion */
137 if ( (MG_CRN & p1->tag) || (p1->tag & MG_NOM) ) {
138 li = 1.0 / sqrt(ll);
139 t1[0] = li*ux;
140 t1[1] = li*uy;
141 }
142 else {
143 t1[0] = -p1->n[1];
144 t1[1] = p1->n[0];
145 }
146
147 if ( (MG_CRN & p2->tag) || (p2->tag & MG_NOM) ) {
148 li = 1.0 / sqrt(ll);
149 t2[0] = li*ux;
150 t2[1] = li*uy;
151 }
152 else {
153 t2[0] = -p2->n[1];
154 t2[1] = p2->n[0];
155 }
156
157 /* Evaluate Hausdorff distance with respect to the geometric support */
158 ps = t1[0]*ux + t1[1]*uy;
159 ps *= ps;
160 cosn = ps/ll ;
161 cosn *= (1.0-cosn);
162 cosn *= ll;
163 if ( cosn > 9.0*hausd[i]*hausd[i] ) { // Not so sure about that 9.0
164 MG_SET(pt->flag,i);
165 continue;
166 }
167
168 ps = -(t2[0]*ux + t2[1]*uy);
169 ps *= ps;
170 cosn = ps/ll ;
171 cosn *= (1.0-cosn);
172 cosn *= ll;
173 if ( cosn > 9.0*hausd[i]*hausd[i] ) {
174 MG_SET(pt->flag,i);
175 continue;
176 }
177 }
178
179 return pt->flag;
180}
181
182
183/* Calculate coordinates o[2] and interpolated normal vector no[2] of a new point
184 situated at parametric distance s from i1 = inxt2[i] */
185int MMG2D_bezierCurv(MMG5_pMesh mesh,MMG5_int k,int8_t i,double s,double *o,double *no) {
186 MMG5_pTria pt;
187 MMG5_pPoint p1,p2;
188 double b1[2],b2[2],t1[2],t2[2],n1[2],n2[2],bn[2],ux,uy,ll,li,ps;
189 int8_t i1,i2;
190
191 pt = &mesh->tria[k];
192 if ( !MG_EOK(pt) ) return 0;
193
194 i1 = MMG5_inxt2[i];
195 i2 = MMG5_iprv2[i];
196 p1 = &mesh->point[pt->v[i1]];
197 p2 = &mesh->point[pt->v[i2]];
198
199 /* When the edge is not geometric, simply take the midpoint */
200 if ( !MG_EDG(pt->tag[i]) ) {
201 o[0] = (1-s)*p1->c[0]+s*p2->c[0];
202 o[1] = (1-s)*p1->c[1]+s*p2->c[1];
203 memset(no,0,2*sizeof(double));
204 return 1;
205 }
206
207 ux = p2->c[0] - p1->c[0];
208 uy = p2->c[1] - p1->c[1];
209 ll = ux*ux + uy*uy;
210
211 if ( ll < MMG5_EPSD ) return 0;
212
213 /* Recover normal and tangent vectors */
214 if ( (MG_CRN & p1->tag) || (p1->tag & MG_NOM) ) {
215 li = 1.0 / sqrt(ll);
216 t1[0] = li*ux;
217 t1[1] = li*uy;
218
219 n1[0] = t1[1];
220 n1[1] = - t1[0];
221 }
222 else {
223 n1[0] = p1->n[0];
224 n1[1] = p1->n[1];
225
226 t1[0] = -p1->n[1];
227 t1[1] = p1->n[0];
228 }
229
230 if ( (MG_CRN & p2->tag) || (p2->tag & MG_NOM) ) {
231 li = 1.0 / sqrt(ll);
232 t2[0] = li*ux;
233 t2[1] = li*uy;
234
235 n2[0] = t2[1];
236 n2[1] = - t2[0];
237 }
238 else {
239 n2[0] = p2->n[0];
240 n2[1] = p2->n[1];
241
242 t2[0] = -p2->n[1];
243 t2[1] = p2->n[0];
244 }
245
246 /* When either p1 or p2 is singular, make orientation of both normal vectors consistent
247 (otherwise, it is already the case) */
248 if ( (MG_CRN & p1->tag) || (p1->tag & MG_NOM) ){
249 ps = n1[0]*n2[0] + n1[1]*n2[1];
250 if ( ps < 0.0 ) {
251 n1[0] *= -1.0;
252 n1[1] *= -1.0;
253 }
254 }
255 else if ( (MG_CRN & p2->tag) || (p2->tag & MG_NOM) ) {
256 ps = n1[0]*n2[0] + n1[1]*n2[1];
257 if ( ps < 0.0 ) {
258 n2[0] *= -1.0;
259 n2[1] *= -1.0;
260 }
261 }
262
263 /* Calculation of control points */
264 ps = ux*t1[0]+uy*t1[1];
265 b1[0] = p1->c[0] + MMG5_ATHIRD*ps*t1[0];
266 b1[1] = p1->c[1] + MMG5_ATHIRD*ps*t1[1];
267
268 ps = ux*t2[0]+uy*t2[1];
269 b2[0] = p2->c[0] - MMG5_ATHIRD*ps*t2[0];
270 b2[1] = p2->c[1] - MMG5_ATHIRD*ps*t2[1];
271
272 ps = ux*(n1[0]+n2[0]) + uy*(n1[1]+n2[1]);
273 ps = 2.0*ps/ll;
274
275 bn[0] = n1[0]+n2[0] - ps*ux;
276 bn[1] = n1[1]+n2[1] - ps*uy;
277 ps = bn[0]*bn[0] + bn[1]*bn[1];
278 if ( ps > MMG5_EPSD2 ) {
279 ps = 1.0 / sqrt(ps);
280 bn[0] *= ps;
281 bn[1] *= ps;
282 }
283
284 /* Interpolation of the position and normal vector */
285 o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p1->c[0] + 3.0*(1.0-s)*(1.0-s)*s*b1[0] + 3.0*(1.0-s)*s*s*b2[0] + s*s*s*p2->c[0];
286 o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p1->c[1] + 3.0*(1.0-s)*(1.0-s)*s*b1[1] + 3.0*(1.0-s)*s*s*b2[1] + s*s*s*p2->c[1];
287
288 no[0] = (1.0-s)*(1.0-s)*n1[0] + 2*(1.0-s)*s*bn[0] + s*s*n2[0];
289 no[1] = (1.0-s)*(1.0-s)*n1[1] + 2*(1.0-s)*s*bn[1] + s*s*n2[1];
290
291 return 1;
292}
MMG5_pMesh * mesh
int MMG2D_bezierCurv(MMG5_pMesh mesh, MMG5_int k, int8_t i, double s, double *o, double *no)
Definition: bezier_2d.c:185
int MMG2D_chkedg(MMG5_pMesh mesh, MMG5_int k)
Definition: bezier_2d.c:28
#define MMG5_EPSD
@ MMG5_Edg
Definition: libmmgtypes.h:225
@ MMG5_Triangle
Definition: libmmgtypes.h:226
#define MG_Tria
#define MG_Edge
#define MG_EOK(pt)
#define MG_MIN(a, b)
#define MG_EDG(tag)
#define MG_NOTAG
static const uint8_t MMG5_iprv2[3]
#define MMG5_ATHIRD
static const uint8_t MMG5_inxt2[6]
#define MG_CRN
#define MG_NOM
#define MMG5_EPSD2
#define MG_SET(flag, bit)
int8_t parTyp
Definition: libmmgtypes.h:541
double hmax
Definition: libmmgtypes.h:518
MMG5_pPar par
Definition: libmmgtypes.h:517
double hausd
Definition: libmmgtypes.h:518
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_pTria tria
Definition: libmmgtypes.h:647
double hmax
Definition: libmmgtypes.h:259
double hausd
Definition: libmmgtypes.h:260
MMG5_int ref
Definition: libmmgtypes.h:261
int8_t elt
Definition: libmmgtypes.h:262
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double n[3]
Definition: libmmgtypes.h:272
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
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