Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
tools_3d.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 "libmmg3d.h"
37#include "libmmg3d_private.h"
38
39extern int8_t ddb;
40
42int MMG5_isbr(MMG5_pMesh mesh,MMG5_int ref) {
43 int k;
44
45 for(k=0; k<mesh->info.nbr; k++)
46 if ( ref == mesh->info.br[k] ) return(1);
47
48 return(0);
49}
50
52int MMG5_norface(MMG5_pMesh mesh,MMG5_int k,int iface,double n[3]) {
53 MMG5_pTetra pt;
54
55 pt = &mesh->tetra[k];
56
57 return MMG5_norpts(mesh,
58 pt->v[MMG5_idir[iface][0]],
59 pt->v[MMG5_idir[iface][1]],
60 pt->v[MMG5_idir[iface][2]],n);
61}
62
66inline int MMG5_directsurfball(MMG5_pMesh mesh, MMG5_int ip, MMG5_int *list, int ilist, double n[3]){
67 int j;
68 MMG5_int iel,aux;
69 double nt[3],ps;
70 uint8_t iface;
71
72 iel = list[0] / 4;
73 iface = list[0] % 4;
74
75 if ( !MMG5_norface(mesh,iel,iface,nt) ) return 0;
76 ps = nt[0]*n[0] + nt[1]*n[1] + nt[2]*n[2];
77 if ( ps > 0.0 ) return 1;
78
79 for (j=1; j<=(ilist-1)/2; j++) {
80 aux = list[j];
81 list[j] = list[ilist -j];
82 list[ilist -j] = aux;
83 }
84
85 return 2;
86}
87
91int MMG5_startedgsurfball(MMG5_pMesh mesh,MMG5_int nump,MMG5_int numq,MMG5_int *list,int ilist) {
92 MMG5_pTetra pt;
93 int l;
94 MMG5_int tmp,iel;
95 uint8_t iface,ip,ipt;
96
97 iel = list[0]/4;
98 iface = list[0]%4;
99 pt = &mesh->tetra[iel];
100
101 for(ip=0;ip<4;ip++){
102 if(pt->v[ip] == nump) break;
103 }
104 assert(ip<4);
105
106 ipt = MMG5_idirinv[iface][ip]; // index of ip in face iface
107 ipt = MMG5_inxt2[ipt]; // next index in this face
108 ipt = MMG5_idir[iface][ipt]; // index of this point in local num of tetra
109
110 if(pt->v[ipt] == numq) return 1;
111
112 else{
113 ipt = MMG5_idir[iface][MMG5_iprv2[MMG5_idirinv[iface][ip]]];
114 assert(pt->v[ipt] == numq);
115
116 tmp = list[0];
117 for(l=0;l<ilist-1;l++){
118 list[l] = list[l+1];
119 }
120 list[ilist-1] = tmp;
121 }
122
123 return 2;
124}
125
145inline int MMG5_BezierRidge ( MMG5_pMesh mesh,MMG5_int ip0,MMG5_int ip1,double s,double *o,
146 double *no1,double *no2,double *to ) {
147 MMG5_pPoint p0,p1;
148 double ux,uy,uz,n01[3],n02[3],n11[3],n12[3],t0[3],t1[3];
149 double ps,ps2,b0[3],b1[3],bn[3],ll,il,ntemp[3],dd,alpha;
150
151 p0 = &mesh->point[ip0]; /* Ref point, from which step is counted */
152 p1 = &mesh->point[ip1];
153 if ( !(MG_GEO & p0->tag) || !(MG_GEO & p1->tag) ) {
154 return 0;
155 }
156
157 ux = p1->c[0] - p0->c[0];
158 uy = p1->c[1] - p0->c[1];
159 uz = p1->c[2] - p0->c[2];
160 ll = ux*ux + uy*uy + uz*uz;
161 if ( ll < MMG5_EPSD2 ) {
162 return 0;
163 }
164 il = 1.0 / sqrt(ll);
165
166 if ( MG_SIN(p0->tag) ) {
167 t0[0] = ux * il;
168 t0[1] = uy * il;
169 t0[2] = uz * il;
170 }
171 else {
172 /* It is ok to pass here for nm points because they have always a tangent */
173 memcpy(t0,&(p0->n[0]),3*sizeof(double));
174 ps = t0[0]*ux + t0[1]*uy + t0[2]*uz;
175 if ( ps < 0.0 ) {
176 t0[0] *= -1.0;
177 t0[1] *= -1.0;
178 t0[2] *= -1.0;
179 }
180 }
181
182 if ( MG_SIN(p1->tag) ) {
183 t1[0] = -ux * il;
184 t1[1] = -uy * il;
185 t1[2] = -uz * il;
186 }
187 else {
188 /* It is ok to pass here for nm points because they have always a tangent */
189 memcpy(t1,&(p1->n[0]),3*sizeof(double));
190 ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz );
191 if ( ps < 0.0 ) {
192 t1[0] *= -1.0;
193 t1[1] *= -1.0;
194 t1[2] *= -1.0;
195 }
196 }
197 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
198
199 b0[0] = p0->c[0] + alpha * t0[0];
200 b0[1] = p0->c[1] + alpha * t0[1];
201 b0[2] = p0->c[2] + alpha * t0[2];
202
203 b1[0] = p1->c[0] + alpha * t1[0];
204 b1[1] = p1->c[1] + alpha * t1[1];
205 b1[2] = p1->c[2] + alpha * t1[2];
206
207 o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \
208 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0];
209
210 o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \
211 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1];
212
213 o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \
214 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2];
215
216 if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) {
217 /* In this case, the tangent orientation depends on the triangle from
218 * which we see the ridge */
219 memcpy(to,t0,3*sizeof(double));
220 return 1;
221 }
222 else if ( MG_SIN(p0->tag) ) {
223 memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
224 memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
225 memcpy(n01,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
226 memcpy(n02,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
227 }
228 else if ( MG_SIN(p1->tag) ) {
229 memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
230 memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
231 memcpy(n11,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
232 memcpy(n12,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
233 }
234 else {
235 memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
236 memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
237 memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
238 memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
239
240 /* Switch normals of p1 for pairing */
241 ps = n01[0] * n11[0] + n01[1] * n11[1] + n01[2] * n11[2];
242 ps2 = n01[0] * n12[0] + n01[1] * n12[1] + n01[2] * n12[2];
243 if ( ps2 > ps ) {
244 memcpy(ntemp,n11,3*sizeof(double));
245 memcpy(n11,n12,3*sizeof(double));
246 memcpy(n12,ntemp,3*sizeof(double));
247 }
248 }
249
250 /* Normal n1 interpolation */
251 ps = ux*(n01[0] + n11[0]) + uy*(n01[1] + n11[1]) + uz*(n01[2] + n11[2]);
252 ps = 2.0*ps / ll;
253
254 bn[0] = n01[0] + n11[0] -ps*ux;
255 bn[1] = n01[1] + n11[1] -ps*uy;
256 bn[2] = n01[2] + n11[2] -ps*uz;
257
258 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
259 if ( dd > MMG5_EPSD2 ) {
260 dd = 1.0 / sqrt(dd);
261 bn[0] *= dd;
262 bn[1] *= dd;
263 bn[2] *= dd;
264 }
265 no1[0] = (1.0-s)*(1.0-s)*n01[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n11[0];
266 no1[1] = (1.0-s)*(1.0-s)*n01[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n11[1];
267 no1[2] = (1.0-s)*(1.0-s)*n01[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n11[2];
268 dd = no1[0]*no1[0] + no1[1]*no1[1] + no1[2]*no1[2];
269 if ( dd > MMG5_EPSD2 ) {
270 dd = 1.0 / sqrt(dd);
271 no1[0] *= dd;
272 no1[1] *= dd;
273 no1[2] *= dd;
274 }
275
276 /* Normal n2 interpolation */
277 ps = ux*(n02[0] + n12[0]) + uy*(n02[1] + n12[1]) + uz*(n02[2] + n12[2]);
278 ps = 2.0*ps/ll;
279
280 bn[0] = n02[0] + n12[0] -ps*ux;
281 bn[1] = n02[1] + n12[1] -ps*uy;
282 bn[2] = n02[2] + n12[2] -ps*uz;
283
284 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
285 if ( dd > MMG5_EPSD2 ) {
286 dd = 1.0 / sqrt(dd);
287 bn[0] *= dd;
288 bn[1] *= dd;
289 bn[2] *= dd;
290 }
291 no2[0] = (1.0-s)*(1.0-s)*n02[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n12[0];
292 no2[1] = (1.0-s)*(1.0-s)*n02[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n12[1];
293 no2[2] = (1.0-s)*(1.0-s)*n02[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n12[2];
294 dd = no2[0]*no2[0] + no2[1]*no2[1] + no2[2]*no2[2];
295 if ( dd > MMG5_EPSD2 ) {
296 dd = 1.0 / sqrt(dd);
297 no2[0] *= dd;
298 no2[1] *= dd;
299 no2[2] *= dd;
300
301 to[0] = no1[1]*no2[2] - no1[2]*no2[1];
302 to[1] = no1[2]*no2[0] - no1[0]*no2[2];
303 to[2] = no1[0]*no2[1] - no1[1]*no2[0];
304 }
305 else {
306 /* Open boundary: tangent interpolation (possibly flip (back) t1) */
307 ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2];
308 if ( ps < 0.0 ) {
309 t1[0] *= -1.0;
310 t1[1] *= -1.0;
311 t1[2] *= -1.0;
312 }
313 to[0] = (1.0-s)*t0[0] + s*t1[0];
314 to[1] = (1.0-s)*t0[1] + s*t1[1];
315 to[2] = (1.0-s)*t0[2] + s*t1[2];
316
317 /* Projection of the tangent in the tangent plane defined by no */
318 ps = to[0]*no1[0] + to[1]*no1[1] + to[2]*no1[2];
319 to[0] = to[0] -ps*no1[0];
320 to[1] = to[1] -ps*no1[1];
321 to[2] = to[2] -ps*no1[2];
322 }
323
324 dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2];
325 if ( dd > MMG5_EPSD2 ) {
326 dd = 1.0/sqrt(dd);
327 to[0] *= dd;
328 to[1] *= dd;
329 to[2] *= dd;
330 }
331
332 return 1;
333}
334
352inline int MMG5_BezierRef ( MMG5_pMesh mesh,MMG5_int ip0,MMG5_int ip1,double s,double *o,
353 double *no,double *to) {
354 MMG5_pPoint p0,p1;
355 double ux,uy,uz,n01[3],n02[3],n11[3],n12[3],ntemp[3],t0[3],t1[3];
356 double ps,b0[3],b1[3],bn[3],ll,il,dd,alpha,ps2;
357
358 p0 = &mesh->point[ip0]; /* Ref point, from which step is counted */
359 p1 = &mesh->point[ip1];
360
361 ux = p1->c[0] - p0->c[0];
362 uy = p1->c[1] - p0->c[1];
363 uz = p1->c[2] - p0->c[2];
364 ll = ux*ux + uy*uy + uz*uz;
365 if ( ll < MMG5_EPSD2 ) {
366 return 0;
367 }
368 il = 1.0 / sqrt(ll);
369 assert( (MG_REF & p0->tag) && (MG_REF & p1->tag) );
370
371 /* Coordinates of the new point */
372 if ( MG_SIN(p0->tag) ) {
373 t0[0] = ux * il;
374 t0[1] = uy * il;
375 t0[2] = uz * il;
376 }
377 else {
378 /* nm points have a tangent so its ok to get it here */
379 memcpy(t0,&(p0->n[0]),3*sizeof(double));
380 ps = t0[0]*ux + t0[1]*uy + t0[2]*uz;
381 if ( ps < 0.0 ) {
382 t0[0] *= -1.0;
383 t0[1] *= -1.0;
384 t0[2] *= -1.0;
385 }
386 }
387 if ( MG_SIN(p1->tag) ) {
388 t1[0] = -ux * il;
389 t1[1] = -uy * il;
390 t1[2] = -uz * il;
391 }
392 else {
393 /* nm points have a tangent so its ok to get it here */
394 memcpy(t1,&(p1->n[0]),3*sizeof(double));
395 ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz );
396 if ( ps < 0.0 ) {
397 t1[0] *= -1.0;
398 t1[1] *= -1.0;
399 t1[2] *= -1.0;
400 }
401 }
402
403 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
404
405 b0[0] = p0->c[0] + alpha * t0[0];
406 b0[1] = p0->c[1] + alpha * t0[1];
407 b0[2] = p0->c[2] + alpha * t0[2];
408
409 b1[0] = p1->c[0] + alpha * t1[0];
410 b1[1] = p1->c[1] + alpha * t1[1];
411 b1[2] = p1->c[2] + alpha * t1[2];
412
413 o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \
414 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0];
415
416 o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \
417 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1];
418
419 o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \
420 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2];
421
422 /* Coordinates of the new tangent and normal */
423 if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) {
424 memcpy(to,t0,3*sizeof(double));
425 return 1;
426 }
427 else if ( MG_SIN(p0->tag) ) {
428 memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
429 memcpy(n01,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
430 memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
431 memcpy(n02,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
432 }
433 else if ( MG_SIN(p1->tag) ) {
434 memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
435 memcpy(n11,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
436 memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
437 memcpy(n12,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
438 }
439 else {
440 memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
441 memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
442 memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double));
443 memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double));
444 }
445
446 /* Switch normals of p1 for pairing */
447 ps = n01[0] * n11[0] + n01[1] * n11[1] + n01[2] * n11[2];
448 ps2 = n01[0] * n12[0] + n01[1] * n12[1] + n01[2] * n12[2];
449 if ( ps2 > ps ) {
450 memcpy(ntemp,n11,3*sizeof(double));
451 memcpy(n11,n12,3*sizeof(double));
452 memcpy(n12,ntemp,3*sizeof(double));
453 }
454
455 /* Normal interpolation */
456 ps = ux*(n01[0] + n11[0]) + uy*(n01[1] + n11[1]) + uz*(n01[2] + n11[2]);
457 ps = 2.0*ps/ll;
458
459 bn[0] = n01[0] + n11[0] -ps*ux;
460 bn[1] = n01[1] + n11[1] -ps*uy;
461 bn[2] = n01[2] + n11[2] -ps*uz;
462
463 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
464 if ( dd > MMG5_EPSD ) {
465 dd = 1.0 / sqrt(dd);
466 bn[0] *= dd;
467 bn[1] *= dd;
468 bn[2] *= dd;
469 }
470 no[0] = (1.0-s)*(1.0-s)*n01[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n11[0];
471 no[1] = (1.0-s)*(1.0-s)*n01[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n11[1];
472 no[2] = (1.0-s)*(1.0-s)*n01[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n11[2];
473
474 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
475 if ( dd > MMG5_EPSD2 ) {
476 dd = 1.0/sqrt(dd);
477 no[0] *= dd;
478 no[1] *= dd;
479 no[2] *= dd;
480 }
481
482 /* Tangent interpolation : possibly flip (back) t1 */
483 ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2];
484 if ( ps < 0.0 ) {
485 t1[0] *= -1.0;
486 t1[1] *= -1.0;
487 t1[2] *= -1.0;
488 }
489 to[0] = (1.0-s)*t0[0] + s*t1[0];
490 to[1] = (1.0-s)*t0[1] + s*t1[1];
491 to[2] = (1.0-s)*t0[2] + s*t1[2];
492
493 /* Projection of the tangent in the tangent plane defined by no */
494 ps = to[0]*no[0] + to[1]*no[1] + to[2]*no[2];
495 to[0] = to[0] -ps*no[0];
496 to[1] = to[1] -ps*no[1];
497 to[2] = to[2] -ps*no[2];
498
499 dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2];
500 if ( dd > MMG5_EPSD2) {
501 dd = 1.0 / sqrt(dd);
502 to[0] *= dd;
503 to[1] *= dd;
504 to[2] *= dd;
505 }
506
507 return 1;
508}
509
527inline int MMG5_BezierNom(MMG5_pMesh mesh,MMG5_int ip0,MMG5_int ip1,double s,double *o,double *no,double *to) {
528 MMG5_pPoint p0,p1;
529 double ux,uy,uz,il,ll,ps,alpha,dd;
530 double t0[3],t1[3],b0[3],b1[3],n0[3],n1[3],bn[3];
531 int8_t intnom;
532
533 p0 = &mesh->point[ip0];
534 p1 = &mesh->point[ip1];
535
536 ux = p1->c[0] - p0->c[0];
537 uy = p1->c[1] - p0->c[1];
538 uz = p1->c[2] - p0->c[2];
539 ll = ux*ux + uy*uy + uz*uz;
540
541 if(ll < MMG5_EPSD2) return 0;
542 il = 1.0 / sqrt(ll);
543
544 assert(( p0->tag & MG_NOM ) && ( p1->tag & MG_NOM ));
545
546 /* Coordinates of the new point */
547 if ( MG_SIN(p0->tag) ) {
548 t0[0] = ux * il;
549 t0[1] = uy * il;
550 t0[2] = uz * il;
551 }
552 else {
553 memcpy(t0,&(p0->n[0]),3*sizeof(double));
554 ps = t0[0]*ux + t0[1]*uy + t0[2]*uz;
555 if ( ps < 0.0 ) {
556 t0[0] *= -1.0;
557 t0[1] *= -1.0;
558 t0[2] *= -1.0;
559 }
560 }
561 if ( MG_SIN(p1->tag) ) {
562 t1[0] = -ux * il;
563 t1[1] = -uy * il;
564 t1[2] = -uz * il;
565 }
566 else {
567 memcpy(t1,&(p1->n[0]),3*sizeof(double));
568 ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz );
569 if ( ps < 0.0 ) {
570 t1[0] *= -1.0;
571 t1[1] *= -1.0;
572 t1[2] *= -1.0;
573 }
574 }
575
576 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
577
578 b0[0] = p0->c[0] + alpha * t0[0];
579 b0[1] = p0->c[1] + alpha * t0[1];
580 b0[2] = p0->c[2] + alpha * t0[2];
581
582 b1[0] = p1->c[0] + alpha * t1[0];
583 b1[1] = p1->c[1] + alpha * t1[1];
584 b1[2] = p1->c[2] + alpha * t1[2];
585
586 o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \
587 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0];
588
589 o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \
590 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1];
591
592 o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \
593 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2];
594
595 /* Coordinates of the new tangent and normal */
596 if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { // function should not be used in that case
597 memcpy(to,t0,3*sizeof(double));
598 /* returning 1 here may create memory error afterward because no (that
599 * is not filled) will be used */
600 return 0;
601 }
602 else if ( MG_SIN(p0->tag) ) {
603 memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
604 memcpy(n0,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
605 }
606 else if ( MG_SIN(p1->tag) ) {
607 memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
608 memcpy(n1,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
609 }
610 else {
611 memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
612 memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
613 }
614
615 /* Check for internal non manifold edge */
616 intnom = ( mesh->xpoint[p0->xp].nnor ) || ( mesh->xpoint[p1->xp].nnor );
617
618 /* Normal interpolation */
619 if ( !intnom ) {
620 ps = ux*(n0[0] + n1[0]) + uy*(n0[1] + n1[1]) + uz*(n0[2] + n1[2]);
621 ps = 2.0*ps/ll;
622
623 bn[0] = n0[0] + n1[0] -ps*ux;
624 bn[1] = n0[1] + n1[1] -ps*uy;
625 bn[2] = n0[2] + n1[2] -ps*uz;
626
627 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
628 if ( dd > MMG5_EPSD ) {
629 dd = 1.0 / sqrt(dd);
630 bn[0] *= dd;
631 bn[1] *= dd;
632 bn[2] *= dd;
633 }
634 no[0] = (1.0-s)*(1.0-s)*n0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n1[0];
635 no[1] = (1.0-s)*(1.0-s)*n0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n1[1];
636 no[2] = (1.0-s)*(1.0-s)*n0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n1[2];
637
638 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
639 if ( dd > MMG5_EPSD2 ) {
640 dd = 1.0/sqrt(dd);
641 no[0] *= dd;
642 no[1] *= dd;
643 no[2] *= dd;
644 }
645 }
646
647 /* Tangent interpolation : possibly flip (back) t1 */
648 ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2];
649 if ( ps < 0.0 ) {
650 t1[0] *= -1.0;
651 t1[1] *= -1.0;
652 t1[2] *= -1.0;
653 }
654 to[0] = (1.0-s)*t0[0] + s*t1[0];
655 to[1] = (1.0-s)*t0[1] + s*t1[1];
656 to[2] = (1.0-s)*t0[2] + s*t1[2];
657
658 /* Projection of the tangent in the tangent plane defined by no */
659 if ( !intnom ) {
660 ps = to[0]*no[0] + to[1]*no[1] + to[2]*no[2];
661 to[0] = to[0] -ps*no[0];
662 to[1] = to[1] -ps*no[1];
663 to[2] = to[2] -ps*no[2];
664 }
665
666 dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2];
667 if ( dd > MMG5_EPSD2) {
668 dd = 1.0 / sqrt(dd);
669 to[0] *= dd;
670 to[1] *= dd;
671 to[2] *= dd;
672 }
673
674 return 1;
675}
676
677
696inline int MMG5_BezierReg(MMG5_pMesh mesh,MMG5_int ip0, MMG5_int ip1, double s, double v[3], double *o, double *no){
697 MMG5_pPoint p0,p1;
698 double b0[3],b1[3],bn[3],t0[3],t1[3],np0[3],np1[3],alpha,ux,uy,uz,ps1,ps2,ll;
699 double il,dd,*n1,*n2;
700
701 p0 = &mesh->point[ip0];
702 p1 = &mesh->point[ip1];
703
704 ux = p1->c[0] - p0->c[0];
705 uy = p1->c[1] - p0->c[1];
706 uz = p1->c[2] - p0->c[2];
707
708 ll = ux*ux + uy*uy + uz*uz;
709
710 np0[0] = np0[1] = np0[2] = 0;
711 np1[0] = np1[1] = np1[2] = 0;
712
713 /* Pathological case : don't move in that case ! */
714 if ( (MG_SIN_OR_NOM(p0->tag) && MG_SIN_OR_NOM(p1->tag)) || (ll<MMG5_EPSD) ){
715 o[0] = 0.5*( p0->c[0] + p1->c[0] );
716 o[1] = 0.5*( p0->c[1] + p1->c[1] );
717 o[2] = 0.5*( p0->c[2] + p1->c[2] );
718
719 memcpy(no,v,3*sizeof(double));
720 return 1;
721 }
722
723 il = 1.0 /sqrt(ll);
724
725 /* Coordinates of the new tangent and normal */
726 if ( MG_SIN_OR_NOM(p0->tag) ) {
727 if(p1->tag & MG_GEO){
728 n1 = &mesh->xpoint[p1->xp].n1[0];
729 n2 = &mesh->xpoint[p1->xp].n2[0];
730 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
731 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
732
733 if(fabs(ps1) < fabs(ps2)){
734 memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double));
735 }
736 else{
737 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
738 }
739 }
740 else{
741 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
742 }
743 memcpy(np0,np1,3*sizeof(double));
744 }
745 else if ( MG_SIN_OR_NOM(p1->tag) ) {
746 if(p0->tag & MG_GEO){
747 n1 = &mesh->xpoint[p0->xp].n1[0];
748 n2 = &mesh->xpoint[p0->xp].n2[0];
749 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
750 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
751
752 if(fabs(ps1) < fabs(ps2)){
753 memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double));
754 }
755 else{
756 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
757 }
758 }
759 else{
760 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
761 }
762 memcpy(np1,np0,3*sizeof(double));
763 }
764 else{
765 if(p0->tag & MG_GEO){
766 n1 = &mesh->xpoint[p0->xp].n1[0];
767 n2 = &mesh->xpoint[p0->xp].n2[0];
768 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
769 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
770
771 if(fabs(ps1) < fabs(ps2)){
772 memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double));
773 }
774 else{
775 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
776 }
777 }
778 else{
779 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
780 }
781
782 if(p1->tag & MG_GEO){
783 n1 = &mesh->xpoint[p1->xp].n1[0];
784 n2 = &mesh->xpoint[p1->xp].n2[0];
785 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
786 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
787
788 if(fabs(ps1) < fabs(ps2)){
789 memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double));
790 }
791 else{
792 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
793 }
794 }
795 else{
796 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
797 }
798 }
799
800 /* Normal interpolation */
801 ps1 = ux*(np0[0] + np1[0]) + uy*(np0[1] + np1[1]) + uz*(np0[2] + np1[2]);
802 ps1 = 2.0*ps1/ll;
803
804 bn[0] = np0[0] + np1[0] -ps1*ux;
805 bn[1] = np0[1] + np1[1] -ps1*uy;
806 bn[2] = np0[2] + np1[2] -ps1*uz;
807
808 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
809 if(dd > MMG5_EPSD){
810 dd = 1.0/sqrt(dd);
811 bn[0] *= dd;
812 bn[1] *= dd;
813 bn[2] *= dd;
814 }
815
816 no[0] = (1.0-s)*(1.0-s)*np0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*np1[0];
817 no[1] = (1.0-s)*(1.0-s)*np0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*np1[1];
818 no[2] = (1.0-s)*(1.0-s)*np0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*np1[2];
819
820 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
821 if(dd > MMG5_EPSD){
822 dd = 1.0/sqrt(dd);
823 no[0] *= dd;
824 no[1] *= dd;
825 no[2] *= dd;
826 }
827
828 /* vertex position interpolation */
829 if(!MMG5_BezierTgt(p0->c,p1->c,np0,np1,t0,t1)){
830 t0[0] = ux * il;
831 t0[1] = uy * il;
832 t0[2] = uz * il;
833
834 t1[0] = - ux * il;
835 t1[1] = - uy * il;
836 t1[2] = - uz * il;
837 }
838
839 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
840
841 b0[0] = p0->c[0] + alpha * t0[0];
842 b0[1] = p0->c[1] + alpha * t0[1];
843 b0[2] = p0->c[2] + alpha * t0[2];
844
845 b1[0] = p1->c[0] + alpha * t1[0];
846 b1[1] = p1->c[1] + alpha * t1[1];
847 b1[2] = p1->c[2] + alpha * t1[2];
848
849 o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \
850 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0];
851
852 o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \
853 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1];
854
855 o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \
856 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2];
857
858 return 1;
859}
860
862MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel) {
863 MMG5_pTetra pt;
864 MMG5_int ne, k;
865
866#ifndef USE_SCOTCH
867 ne = mesh->ne+1;
868 k = 1;
869
870 assert ( MG_EOK(&mesh->tetra[kel]) );
871
872 do {
873 pt = &mesh->tetra[k];
874
875 if ( !MG_EOK(pt) ) {
876 --ne;
877 pt = &mesh->tetra[ne];
878 assert( pt );
879
880 /* Search last used tetra */
881 while ( !MG_EOK(pt) && k < ne ) {
882 --ne;
883 pt = &mesh->tetra[ne];
884 }
885
886 /* Found elt */
887 if ( ne == kel ) {
888 return k;
889 }
890 }
891 else {
892 /* Found elt */
893 if ( k==kel ) {
894 return k;
895 }
896 }
897 /* All elts have been treated end of loop */
898 if ( k==ne ) {
899 break;
900 }
901 }
902 while ( ++k < ne );
903
904#else
905 ne = 0;
906 for (k=1; k<=mesh->ne; k++) {
907 pt = &mesh->tetra[k];
908 if ( MG_EOK(pt) ) {
909 ne++;
910 if ( k == kel ) return ne;
911 }
912 }
913#endif
914 return 0;
915}
916
918MMG5_int MMG3D_indPt(MMG5_pMesh mesh, MMG5_int kp) {
919 MMG5_pPoint ppt;
920 MMG5_int np, k;
921
922#ifndef USE_SCOTCH
923 np = mesh->np+1;
924 k = 1;
925
926 assert ( MG_VOK(&mesh->point[kp]) );
927
928 do {
929 ppt = &mesh->point[k];
930 if ( !MG_VOK(ppt) ) {
931 --np;
932 ppt = &mesh->point[np];
933 assert ( ppt );
934
935 /* Search the last used point */
936 while ( !MG_VOK(ppt) && k < np ) {
937 --np;
938 ppt = &mesh->point[np];
939 }
940
941 /* Found pt */
942 if ( np == kp ) {
943 return k;
944 }
945 }
946 else {
947 /* Found pt */
948 if ( k==kp ) {
949 return k;
950 }
951 }
952
953 /* All points have been treated end of loop */
954 if ( k==np ) {
955 break;
956 }
957 }
958 while ( ++k < np );
959
960#else
961 np = 0;
962 for (k=1; k<=mesh->np; k++) {
963 ppt = &mesh->point[k];
964 if ( MG_VOK(ppt) ) {
965 np++;
966 if ( k == kp ) return np;
967 }
968 }
969#endif
970
971 return 0;
972}
973
975void MMG5_printTetra(MMG5_pMesh mesh,char* fileName) {
976 MMG5_pTetra pt;
977 MMG5_pxTetra pxt;
978 MMG5_int k;
979 FILE *inm;
980
981 inm = fopen(fileName,"w");
982
983 fprintf(inm,"----------> %" MMG5_PRId " MMG5_TETRAHEDRAS <----------\n",mesh->ne);
984 for(k=1; k<=mesh->ne; k++) {
985 pt = &mesh->tetra[k];
986 fprintf(inm,"num %" MMG5_PRId " -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",k,pt->v[0],pt->v[1],
987 pt->v[2],pt->v[3]);
988 fprintf(inm,"ref,tag,xt -> %" MMG5_PRId " %d %" MMG5_PRId "\n",pt->ref,pt->tag,pt->xt);
989 if ( pt->xt ) {
990 pxt = &mesh->xtetra[pt->xt];
991 fprintf(inm,"tag -> %d %d %d %d %d %d\n",pxt->tag[0],pxt->tag[1],
992 pxt->tag[2],pxt->tag[3],pxt->tag[4],pxt->tag[5]);
993 fprintf(inm,"edg -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",pxt->edg[0],pxt->edg[1],
994 pxt->edg[2],pxt->edg[3],pxt->edg[4],pxt->edg[5]);
995 fprintf(inm,"ftag -> %d %d %d %d\n",pxt->ftag[0],pxt->ftag[1],
996 pxt->ftag[2],pxt->ftag[3]);
997 fprintf(inm,"ref -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",pxt->ref[0],pxt->ref[1],
998 pxt->ref[2],pxt->ref[3]);
999 fprintf(inm,"ori -> %d \n",pxt->ori);
1000 }
1001 fprintf(inm,"\n");
1002 }
1003 fprintf(inm,"---------> END MMG5_TETRAHEDRAS <--------\n");
1004 fclose(inm);
1005}
1006
1007
1025int MMG3D_localParamReg(MMG5_pMesh mesh,MMG5_int ip,int64_t *listv,int ilistv,
1026 MMG5_int *lists,int ilists,
1027 double* hausd_ip,double *hmin_ip,double *hmax_ip) {
1028
1029 MMG5_pTetra pt;
1030 MMG5_pPar par;
1031 double hausd, hmin, hmax;
1032 int l,k,isloc,ifac1;
1033
1034 hausd = mesh->info.hausd;
1035 hmin = mesh->info.hmin;
1036 hmax = mesh->info.hmax;
1037 isloc = 0;
1038
1039 /* travel across the ball of ip to find the minimal local params imposed on
1040 * tetras */
1041 if ( mesh->info.parTyp & MG_Tetra ) {
1042 l = 0;
1043 do
1044 {
1045 if ( isloc ) break;
1046
1047 par = &mesh->info.par[l];
1048 if ( par->elt != MMG5_Tetrahedron ) continue;
1049
1050 for ( k=0; k<ilistv; ++k ) {
1051 pt = &mesh->tetra[listv[k]/4];
1052 if ( par->ref == pt->ref ) {
1053 hausd = par->hausd;
1054 hmin = par->hmin;
1055 hmax = par->hmax;
1056 isloc = 1;
1057 break;
1058 }
1059 }
1060 } while ( ++l<mesh->info.npar );
1061
1062 for ( ; l<mesh->info.npar; ++l ) {
1063 par = &mesh->info.par[l];
1064 if ( par->elt != MMG5_Tetrahedron ) continue;
1065
1066 for ( k=0; k<ilistv; ++k ) {
1067 pt = &mesh->tetra[listv[k]/4];
1068 if ( par->ref == pt->ref ) {
1069 hausd = MG_MIN(hausd,par->hausd);
1070 hmin = MG_MAX(hmin,par->hmin);
1071 hmax = MG_MIN(hmax,par->hmax);
1072 break;
1073 }
1074 }
1075 }
1076 }
1077 /* travel across the surface ball of ip to find the minimal local params
1078 * imposed on trias */
1079 if ( mesh->info.parTyp & MG_Tria ) {
1080 l = 0;
1081 do
1082 {
1083 if ( isloc ) break;
1084
1085 par = &mesh->info.par[l];
1086 if ( par->elt != MMG5_Triangle ) continue;
1087
1088 for ( k=0; k<ilists; ++k ) {
1089 pt = &mesh->tetra[lists[k]/4];
1090 ifac1 = lists[k] % 4;
1091 assert(pt->xt && (mesh->xtetra[pt->xt].ftag[ifac1] & MG_BDY) );
1092
1093 if ( par->ref == mesh->xtetra[pt->xt].ref[ifac1] ) {
1094 hausd = par->hausd;
1095 hmin = par->hmin;
1096 hmax = par->hmax;
1097 isloc = 1;
1098 break;
1099 }
1100 }
1101 } while ( ++l<mesh->info.npar );
1102
1103 for ( ; l<mesh->info.npar; ++l ) {
1104 par = &mesh->info.par[l];
1105 if ( par->elt != MMG5_Triangle ) continue;
1106
1107 for ( k=0; k<ilists; ++k ) {
1108 pt = &mesh->tetra[lists[k]/4];
1109 ifac1 = lists[k] % 4;
1110 assert(pt->xt && (mesh->xtetra[pt->xt].ftag[ifac1] & MG_BDY) );
1111
1112 if ( par->ref == mesh->xtetra[pt->xt].ref[ifac1] ) {
1113 hausd = MG_MIN(hausd,par->hausd);
1114 hmin = MG_MAX(hmin,par->hmin);
1115 hmax = MG_MIN(hmax,par->hmax);
1116 break;
1117 }
1118 }
1119 }
1120 }
1121
1122 /* Return the wanted values */
1123 if ( hausd_ip ) *hausd_ip = hausd;
1124 if ( hmin_ip ) *hmin_ip = hmin;
1125 if ( hmax_ip ) *hmax_ip = hmax;
1126
1127 return 1;
1128}
1129
1145int MMG3D_localParamNm(MMG5_pMesh mesh,MMG5_int iel,int iface,int ia,
1146 double* hausd_ip,double *hmin_ip,double *hmax_ip) {
1147
1148 MMG5_pTetra pt;
1149 MMG5_pxTetra pxt;
1150 MMG5_pPar par;
1151 double hausd, hmin, hmax;
1152 int l,k,isloc;
1153 int ilistv;
1154 int64_t listv[MMG3D_LMAX+2];
1155 MMG5_int ifac1,ifac2;
1156 static int8_t mmgWarn0;
1157
1158
1159 hausd = mesh->info.hausd;
1160 hmin = mesh->info.hmin;
1161 hmax = mesh->info.hmax;
1162 isloc = 0;
1163
1164 pt = &mesh->tetra[iel];
1165 pxt = &mesh->xtetra[pt->xt];
1166
1167 /* Warning : rough eval of the local param at triangles if coquilface
1168 * fails because we have more than 2 boundaries in the edge shell
1169 * (non-manifold domain). In this case, we just take into account 2
1170 * boundaries of the shell */
1171
1172 if ( pxt->tag[ia] & MG_OPNBDY ) {
1173 ilistv = 1;
1174 ifac1 = ifac2 = 4*iel + iface;
1175 }
1176 else {
1177 ilistv = MMG5_coquilface( mesh,iel,iface, ia,listv,&ifac1,&ifac2,1);
1178 }
1179 if ( ilistv < 0 )
1180 {
1181 if ( mesh->info.ddebug || mesh->info.imprim>5 ) {
1182 if ( !mmgWarn0 ) {
1183 mmgWarn0 = 1;
1184 fprintf(stderr, " ## Warning: %s: unable to take into account local"
1185 " parameters at at least 1 vertex.\n",__func__ );
1186 }
1187 }
1188
1189 if ( mesh->info.parTyp & MG_Tria ) {
1190 for ( l=0; l<mesh->info.npar; ++l) {
1191 par = &mesh->info.par[l];
1192 if ( par->elt != MMG5_Triangle ) continue;
1193
1194 if ( pxt->ref[iface]!=par->ref ) continue;
1195
1196 if ( isloc ) {
1197 hausd = MG_MIN(hausd,par->hausd);
1198 hmin = MG_MAX(hmin,par->hmin);
1199 hmax = MG_MIN(hmax,par->hmax);
1200 }
1201 else {
1202 hausd = par->hausd;
1203 hmin = par->hmin;
1204 hmax = par->hmax;
1205 isloc = 1;
1206 }
1207 }
1208 }
1209
1210 }
1211 else {
1212
1213 /* Local params at triangles containing the edge (not optimal) */
1214 if ( mesh->info.parTyp & MG_Tria ) {
1215 for ( l=0; l<mesh->info.npar; ++l) {
1216 par = &mesh->info.par[l];
1217 if ( par->elt != MMG5_Triangle ) continue;
1218
1219 if ( mesh->xtetra[mesh->tetra[ifac1/4].xt].ref[ifac1%4]!=par->ref &&
1220 mesh->xtetra[mesh->tetra[ifac2/4].xt].ref[ifac2%4]!=par->ref )
1221 continue;
1222
1223 if ( isloc ) {
1224 hausd = MG_MIN(hausd,par->hausd);
1225 hmin = MG_MAX(hmin,par->hmin);
1226 hmax = MG_MIN(hmax,par->hmax);
1227 }
1228 else {
1229 hausd = par->hausd;
1230 hmin = par->hmin;
1231 hmax = par->hmax;
1232 isloc = 1;
1233 }
1234 }
1235 }
1236 }
1237
1238 /* Local params at tetra of the edge shell */
1239 if ( mesh->info.parTyp & MG_Tetra ) {
1240 ilistv/=2;
1241 l = 0;
1242 do
1243 {
1244 if ( isloc ) break;
1245
1246 par = &mesh->info.par[l];
1247 if ( par->elt != MMG5_Tetrahedron ) continue;
1248
1249 for ( k=0; k<ilistv; ++k ) {
1250 pt = &mesh->tetra[listv[k]/6];
1251 if ( par->ref != pt->ref ) continue;
1252
1253 hausd = par->hausd;
1254 hmin = par->hmin;
1255 hmax = par->hmax;
1256 isloc = 1;
1257 }
1258 } while ( ++l<mesh->info.npar );
1259
1260 for ( ; l<mesh->info.npar; ++l ) {
1261 par = &mesh->info.par[l];
1262 if ( par->elt != MMG5_Tetrahedron ) continue;
1263
1264 for ( k=0; k<ilistv; ++k ) {
1265 pt = &mesh->tetra[listv[k]/6];
1266 if ( par->ref != pt->ref ) continue;
1267
1268 hausd = MG_MIN(hausd,par->hausd);
1269 hmin = MG_MAX(hmin,par->hmin);
1270 hmax = MG_MIN(hmax,par->hmax);
1271 break;
1272 }
1273 }
1274 }
1275 /* Return the wanted values */
1276 if ( hausd_ip ) *hausd_ip = hausd;
1277 if ( hmin_ip ) *hmin_ip = hmin;
1278 if ( hmax_ip ) *hmax_ip = hmax;
1279
1280 return 1;
1281}
1282
1290static inline
1292 MMG5_pTetra pt;
1293 MMG5_pPrism pq;
1294 MMG5_pPoint ppt;
1295 int i;
1296 MMG5_int k;
1297
1298 /* Preserve isolated required points */
1299 for ( k=1; k<=mesh->np; k++ ) {
1300 ppt = &mesh->point[k];
1301 if ( ppt->flag || !(ppt->tag & MG_REQ) ) {
1302 continue;
1303 }
1304 ppt->tag &= ~MG_NUL;
1305 }
1306
1307 /* Mark points used by the connectivity */
1308 for ( k=1; k<=mesh->ne; k++ ) {
1309 pt = &mesh->tetra[k];
1310 if ( !MG_EOK(pt) ) continue;
1311
1312 for (i=0; i<4; i++) {
1313 ppt = &mesh->point[ pt->v[i] ];
1314 ppt->tag &= ~MG_NUL;
1315 }
1316 }
1317
1318 for ( k=1; k<=mesh->nprism; k++ ) {
1319 pq = &mesh->prism[k];
1320 if ( !MG_EOK(pq) ) continue;
1321
1322 for (i=0; i<6; i++) {
1323 ppt = &mesh->point[ pq->v[i] ];
1324 ppt->tag &= ~MG_NUL;
1325 }
1326 }
1327
1328 /* Finally, clean point array */
1329 while ( (!MG_VOK(&mesh->point[mesh->np])) && mesh->np ) {
1331 }
1332
1333 return;
1334}
1335
1343static
1345 MMG5_pTetra pt;
1346 int i,iv;
1347 MMG5_int k,*adja,iadr,iadrv;
1348 int nfac = 4; // number of faces per elt
1349
1350 for ( k=1 ; k <= mesh->ne ; k++) {
1351 pt = &mesh->tetra[k];
1352
1353 if ( !MG_EOK(pt) ) continue;
1354
1355 /* Mark tetra vertices as seen to be able to detect isolated points */
1356 mesh->point[pt->v[0]].flag = 1;
1357 mesh->point[pt->v[1]].flag = 1;
1358 mesh->point[pt->v[2]].flag = 1;
1359 mesh->point[pt->v[3]].flag = 1;
1360
1361 if ( pt->ref == nsd ) continue;
1362
1363 /* Update adjacency relationship: we will delete elt k so k adjacent will
1364 * not be adjacent to k anymore */
1365 if ( mesh->adja ) {
1366 iadr = nfac*(k-1) + 1;
1367 adja = &mesh->adja[iadr];
1368 for ( i=0; i<nfac; ++i ) {
1369 iadrv = adja[i];
1370 if ( !iadrv ) {
1371 continue;
1372 }
1373 iv = iadrv%nfac;
1374 iadrv /= nfac;
1375 mesh->adja[nfac*(iadrv-1)+1+iv] = 0;
1376 }
1377 }
1378
1379 /* Delete element */
1380 MMG3D_delElt(mesh,k);
1381 }
1382
1383 return;
1384}
1385
1394
1395 if ( !nsd ) {
1396 return;
1397 }
1398
1399 if ( mesh->info.imprim > 4 || mesh->info.ddebug ) {
1400 fprintf(stdout,"\n -- ONLY KEEP DOMAIN OF REF %d\n",nsd );
1401 }
1402
1404
1406
1408
1409 return;
1410}
tmp[*strlen0]
MMG5_pMesh * mesh
int MMG5_BezierTgt(double c1[3], double c2[3], double n1[3], double n2[3], double t1[3], double t2[3])
Definition: bezier_3d.c:53
double MMG5_BezierGeod(double c1[3], double c2[3], double t1[3], double t2[3])
Definition: bezier_3d.c:111
MMG5_Info info
int MMG5_coquilface(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int ia, int64_t *list, MMG5_int *it1, MMG5_int *it2, int silent)
Definition: boulep_3d.c:1846
#define MMG5_EPSD
API headers and documentation for the mmg3d library, for volumetric meshes in 3D.
#define MMG3D_LMAX
Definition: libmmg3d.h:130
static const int8_t MMG5_idirinv[4][4]
void MMG3D_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_3d.c:80
int MMG3D_delElt(MMG5_pMesh mesh, MMG5_int iel)
Definition: zaldy_3d.c:122
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
@ MMG5_Tetrahedron
Definition: libmmgtypes.h:233
@ MMG5_Triangle
Definition: libmmgtypes.h:232
#define MG_Tria
#define MG_REQ
#define MG_GEO
#define MG_EOK(pt)
#define MG_OPNBDY
#define MG_MIN(a, b)
#define MG_MAX(a, b)
static const uint8_t MMG5_iprv2[3]
#define MG_SIN(tag)
#define MG_Tetra
static const uint8_t MMG5_inxt2[6]
void MMG5_mark_verticesAsUnused(MMG5_pMesh mesh)
Definition: tools.c:994
#define MG_VOK(ppt)
#define MG_BDY
#define MG_NOM
#define MG_SIN_OR_NOM(tag)
int MMG5_norpts(MMG5_pMesh, MMG5_int, MMG5_int, MMG5_int, double *)
Definition: tools.c:183
#define MMG5_EPSD2
#define MG_REF
int8_t parTyp
Definition: libmmgtypes.h:548
int8_t ddebug
Definition: libmmgtypes.h:539
MMG5_int * br
Definition: libmmgtypes.h:527
double hmin
Definition: libmmgtypes.h:525
double hmax
Definition: libmmgtypes.h:525
MMG5_pPar par
Definition: libmmgtypes.h:524
double hausd
Definition: libmmgtypes.h:525
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_int ne
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_pPrism prism
Definition: libmmgtypes.h:653
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:650
MMG5_pTetra tetra
Definition: libmmgtypes.h:651
MMG5_int np
Definition: libmmgtypes.h:620
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:652
MMG5_int nprism
Definition: libmmgtypes.h:621
Local parameters for a specific entity and reference.
Definition: libmmgtypes.h:263
double hmin
Definition: libmmgtypes.h:264
double hmax
Definition: libmmgtypes.h:265
double hausd
Definition: libmmgtypes.h:266
MMG5_int ref
Definition: libmmgtypes.h:267
int8_t elt
Definition: libmmgtypes.h:268
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double n[3]
Definition: libmmgtypes.h:278
double c[3]
Definition: libmmgtypes.h:277
uint16_t tag
Definition: libmmgtypes.h:290
MMG5_int xp
Definition: libmmgtypes.h:285
MMG5_int flag
Definition: libmmgtypes.h:288
Structure to store prsim of a MMG mesh.
Definition: libmmgtypes.h:469
MMG5_int v[6]
Definition: libmmgtypes.h:470
Structure to store tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:407
MMG5_int v[4]
Definition: libmmgtypes.h:409
MMG5_int xt
Definition: libmmgtypes.h:413
MMG5_int ref
Definition: libmmgtypes.h:410
uint16_t tag
Definition: libmmgtypes.h:417
int8_t nnor
Definition: libmmgtypes.h:303
double n2[3]
Definition: libmmgtypes.h:301
double n1[3]
Definition: libmmgtypes.h:301
Structure to store additional information for the surface tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:425
uint16_t tag[6]
Definition: libmmgtypes.h:432
int8_t ori
Definition: libmmgtypes.h:434
MMG5_int edg[6]
Definition: libmmgtypes.h:428
MMG5_int ref[4]
Definition: libmmgtypes.h:426
uint16_t ftag[4]
Definition: libmmgtypes.h:430
static void MMG3D_keep_subdomainElts(MMG5_pMesh mesh, int nsd)
Definition: tools_3d.c:1344
static void MMG3D_mark_usedVertices(MMG5_pMesh mesh)
Definition: tools_3d.c:1291
int MMG5_norface(MMG5_pMesh mesh, MMG5_int k, int iface, double n[3])
Definition: tools_3d.c:52
void MMG3D_keep_only1Subdomain(MMG5_pMesh mesh, int nsd)
Definition: tools_3d.c:1393
int MMG5_BezierReg(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double s, double v[3], double *o, double *no)
Definition: tools_3d.c:696
int MMG3D_localParamNm(MMG5_pMesh mesh, MMG5_int iel, int iface, int ia, double *hausd_ip, double *hmin_ip, double *hmax_ip)
Definition: tools_3d.c:1145
int MMG5_startedgsurfball(MMG5_pMesh mesh, MMG5_int nump, MMG5_int numq, MMG5_int *list, int ilist)
Definition: tools_3d.c:91
MMG5_int MMG3D_indPt(MMG5_pMesh mesh, MMG5_int kp)
Definition: tools_3d.c:918
int MMG5_BezierRidge(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double s, double *o, double *no1, double *no2, double *to)
Definition: tools_3d.c:145
int MMG5_isbr(MMG5_pMesh mesh, MMG5_int ref)
Definition: tools_3d.c:42
void MMG5_printTetra(MMG5_pMesh mesh, char *fileName)
Definition: tools_3d.c:975
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG5_BezierRef(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double s, double *o, double *no, double *to)
Definition: tools_3d.c:352
int MMG5_directsurfball(MMG5_pMesh mesh, MMG5_int ip, MMG5_int *list, int ilist, double n[3])
Definition: tools_3d.c:66
int MMG5_BezierNom(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double s, double *o, double *no, double *to)
Definition: tools_3d.c:527
int MMG3D_localParamReg(MMG5_pMesh mesh, MMG5_int ip, int64_t *listv, int ilistv, MMG5_int *lists, int ilists, double *hausd_ip, double *hmin_ip, double *hmax_ip)
Definition: tools_3d.c:1025
MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel)
Definition: tools_3d.c:862