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 return 1;
599 }
600 else if ( MG_SIN(p0->tag) ) {
601 memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
602 memcpy(n0,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
603 }
604 else if ( MG_SIN(p1->tag) ) {
605 memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
606 memcpy(n1,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
607 }
608 else {
609 memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double));
610 memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double));
611 }
612
613 /* Check for internal non manifold edge */
614 intnom = ( mesh->xpoint[p0->xp].nnor ) || ( mesh->xpoint[p1->xp].nnor );
615
616 /* Normal interpolation */
617 if ( !intnom ) {
618 ps = ux*(n0[0] + n1[0]) + uy*(n0[1] + n1[1]) + uz*(n0[2] + n1[2]);
619 ps = 2.0*ps/ll;
620
621 bn[0] = n0[0] + n1[0] -ps*ux;
622 bn[1] = n0[1] + n1[1] -ps*uy;
623 bn[2] = n0[2] + n1[2] -ps*uz;
624
625 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
626 if ( dd > MMG5_EPSD ) {
627 dd = 1.0 / sqrt(dd);
628 bn[0] *= dd;
629 bn[1] *= dd;
630 bn[2] *= dd;
631 }
632 no[0] = (1.0-s)*(1.0-s)*n0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n1[0];
633 no[1] = (1.0-s)*(1.0-s)*n0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n1[1];
634 no[2] = (1.0-s)*(1.0-s)*n0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n1[2];
635
636 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
637 if ( dd > MMG5_EPSD2 ) {
638 dd = 1.0/sqrt(dd);
639 no[0] *= dd;
640 no[1] *= dd;
641 no[2] *= dd;
642 }
643 }
644
645 /* Tangent interpolation : possibly flip (back) t1 */
646 ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2];
647 if ( ps < 0.0 ) {
648 t1[0] *= -1.0;
649 t1[1] *= -1.0;
650 t1[2] *= -1.0;
651 }
652 to[0] = (1.0-s)*t0[0] + s*t1[0];
653 to[1] = (1.0-s)*t0[1] + s*t1[1];
654 to[2] = (1.0-s)*t0[2] + s*t1[2];
655
656 /* Projection of the tangent in the tangent plane defined by no */
657 if ( !intnom ) {
658 ps = to[0]*no[0] + to[1]*no[1] + to[2]*no[2];
659 to[0] = to[0] -ps*no[0];
660 to[1] = to[1] -ps*no[1];
661 to[2] = to[2] -ps*no[2];
662 }
663
664 dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2];
665 if ( dd > MMG5_EPSD2) {
666 dd = 1.0 / sqrt(dd);
667 to[0] *= dd;
668 to[1] *= dd;
669 to[2] *= dd;
670 }
671
672 return 1;
673}
674
675
694inline int MMG5_BezierReg(MMG5_pMesh mesh,MMG5_int ip0, MMG5_int ip1, double s, double v[3], double *o, double *no){
695 MMG5_pPoint p0,p1;
696 double b0[3],b1[3],bn[3],t0[3],t1[3],np0[3],np1[3],alpha,ux,uy,uz,ps1,ps2,ll;
697 double il,dd,*n1,*n2;
698
699 p0 = &mesh->point[ip0];
700 p1 = &mesh->point[ip1];
701
702 ux = p1->c[0] - p0->c[0];
703 uy = p1->c[1] - p0->c[1];
704 uz = p1->c[2] - p0->c[2];
705
706 ll = ux*ux + uy*uy + uz*uz;
707
708 np0[0] = np0[1] = np0[2] = 0;
709 np1[0] = np1[1] = np1[2] = 0;
710
711 /* Pathological case : don't move in that case ! */
712 if ( (MG_SIN_OR_NOM(p0->tag) && MG_SIN_OR_NOM(p1->tag)) || (ll<MMG5_EPSD) ){
713 o[0] = 0.5*( p0->c[0] + p1->c[0] );
714 o[1] = 0.5*( p0->c[1] + p1->c[1] );
715 o[2] = 0.5*( p0->c[2] + p1->c[2] );
716
717 memcpy(no,v,3*sizeof(double));
718 return 1;
719 }
720
721 il = 1.0 /sqrt(ll);
722
723 /* Coordinates of the new tangent and normal */
724 if ( MG_SIN_OR_NOM(p0->tag) ) {
725 if(p1->tag & MG_GEO){
726 n1 = &mesh->xpoint[p1->xp].n1[0];
727 n2 = &mesh->xpoint[p1->xp].n2[0];
728 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
729 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
730
731 if(fabs(ps1) < fabs(ps2)){
732 memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double));
733 }
734 else{
735 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
736 }
737 }
738 else{
739 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
740 }
741 memcpy(np0,np1,3*sizeof(double));
742 }
743 else if ( MG_SIN_OR_NOM(p1->tag) ) {
744 if(p0->tag & MG_GEO){
745 n1 = &mesh->xpoint[p0->xp].n1[0];
746 n2 = &mesh->xpoint[p0->xp].n2[0];
747 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
748 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
749
750 if(fabs(ps1) < fabs(ps2)){
751 memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double));
752 }
753 else{
754 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
755 }
756 }
757 else{
758 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
759 }
760 memcpy(np1,np0,3*sizeof(double));
761 }
762 else{
763 if(p0->tag & MG_GEO){
764 n1 = &mesh->xpoint[p0->xp].n1[0];
765 n2 = &mesh->xpoint[p0->xp].n2[0];
766 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
767 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
768
769 if(fabs(ps1) < fabs(ps2)){
770 memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double));
771 }
772 else{
773 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
774 }
775 }
776 else{
777 memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double));
778 }
779
780 if(p1->tag & MG_GEO){
781 n1 = &mesh->xpoint[p1->xp].n1[0];
782 n2 = &mesh->xpoint[p1->xp].n2[0];
783 ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2];
784 ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2];
785
786 if(fabs(ps1) < fabs(ps2)){
787 memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double));
788 }
789 else{
790 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
791 }
792 }
793 else{
794 memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double));
795 }
796 }
797
798 /* Normal interpolation */
799 ps1 = ux*(np0[0] + np1[0]) + uy*(np0[1] + np1[1]) + uz*(np0[2] + np1[2]);
800 ps1 = 2.0*ps1/ll;
801
802 bn[0] = np0[0] + np1[0] -ps1*ux;
803 bn[1] = np0[1] + np1[1] -ps1*uy;
804 bn[2] = np0[2] + np1[2] -ps1*uz;
805
806 dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
807 if(dd > MMG5_EPSD){
808 dd = 1.0/sqrt(dd);
809 bn[0] *= dd;
810 bn[1] *= dd;
811 bn[2] *= dd;
812 }
813
814 no[0] = (1.0-s)*(1.0-s)*np0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*np1[0];
815 no[1] = (1.0-s)*(1.0-s)*np0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*np1[1];
816 no[2] = (1.0-s)*(1.0-s)*np0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*np1[2];
817
818 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
819 if(dd > MMG5_EPSD){
820 dd = 1.0/sqrt(dd);
821 no[0] *= dd;
822 no[1] *= dd;
823 no[2] *= dd;
824 }
825
826 /* vertex position interpolation */
827 if(!MMG5_BezierTgt(p0->c,p1->c,np0,np1,t0,t1)){
828 t0[0] = ux * il;
829 t0[1] = uy * il;
830 t0[2] = uz * il;
831
832 t1[0] = - ux * il;
833 t1[1] = - uy * il;
834 t1[2] = - uz * il;
835 }
836
837 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
838
839 b0[0] = p0->c[0] + alpha * t0[0];
840 b0[1] = p0->c[1] + alpha * t0[1];
841 b0[2] = p0->c[2] + alpha * t0[2];
842
843 b1[0] = p1->c[0] + alpha * t1[0];
844 b1[1] = p1->c[1] + alpha * t1[1];
845 b1[2] = p1->c[2] + alpha * t1[2];
846
847 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] + \
848 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0];
849
850 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] + \
851 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1];
852
853 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] + \
854 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2];
855
856 return 1;
857}
858
860MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel) {
861 MMG5_pTetra pt;
862 MMG5_int ne, k;
863
864#ifndef USE_SCOTCH
865 ne = mesh->ne+1;
866 k = 1;
867
868 assert ( MG_EOK(&mesh->tetra[kel]) );
869
870 do {
871 pt = &mesh->tetra[k];
872
873 if ( !MG_EOK(pt) ) {
874 --ne;
875 pt = &mesh->tetra[ne];
876 assert( pt );
877
878 /* Search last used tetra */
879 while ( !MG_EOK(pt) && k < ne ) {
880 --ne;
881 pt = &mesh->tetra[ne];
882 }
883
884 /* Found elt */
885 if ( ne == kel ) {
886 return k;
887 }
888 }
889 else {
890 /* Found elt */
891 if ( k==kel ) {
892 return k;
893 }
894 }
895 /* All elts have been treated end of loop */
896 if ( k==ne ) {
897 break;
898 }
899 }
900 while ( ++k < ne );
901
902#else
903 ne = 0;
904 for (k=1; k<=mesh->ne; k++) {
905 pt = &mesh->tetra[k];
906 if ( MG_EOK(pt) ) {
907 ne++;
908 if ( k == kel ) return ne;
909 }
910 }
911#endif
912 return 0;
913}
914
916MMG5_int MMG3D_indPt(MMG5_pMesh mesh, MMG5_int kp) {
917 MMG5_pPoint ppt;
918 MMG5_int np, k;
919
920#ifndef USE_SCOTCH
921 np = mesh->np+1;
922 k = 1;
923
924 assert ( MG_VOK(&mesh->point[kp]) );
925
926 do {
927 ppt = &mesh->point[k];
928 if ( !MG_VOK(ppt) ) {
929 --np;
930 ppt = &mesh->point[np];
931 assert ( ppt );
932
933 /* Search the last used point */
934 while ( !MG_VOK(ppt) && k < np ) {
935 --np;
936 ppt = &mesh->point[np];
937 }
938
939 /* Found pt */
940 if ( np == kp ) {
941 return k;
942 }
943 }
944 else {
945 /* Found pt */
946 if ( k==kp ) {
947 return k;
948 }
949 }
950
951 /* All points have been treated end of loop */
952 if ( k==np ) {
953 break;
954 }
955 }
956 while ( ++k < np );
957
958#else
959 np = 0;
960 for (k=1; k<=mesh->np; k++) {
961 ppt = &mesh->point[k];
962 if ( MG_VOK(ppt) ) {
963 np++;
964 if ( k == kp ) return np;
965 }
966 }
967#endif
968
969 return 0;
970}
971
973void MMG5_printTetra(MMG5_pMesh mesh,char* fileName) {
974 MMG5_pTetra pt;
975 MMG5_pxTetra pxt;
976 MMG5_int k;
977 FILE *inm;
978
979 inm = fopen(fileName,"w");
980
981 fprintf(inm,"----------> %" MMG5_PRId " MMG5_TETRAHEDRAS <----------\n",mesh->ne);
982 for(k=1; k<=mesh->ne; k++) {
983 pt = &mesh->tetra[k];
984 fprintf(inm,"num %" MMG5_PRId " -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",k,pt->v[0],pt->v[1],
985 pt->v[2],pt->v[3]);
986 fprintf(inm,"ref,tag,xt -> %" MMG5_PRId " %d %" MMG5_PRId "\n",pt->ref,pt->tag,pt->xt);
987 if ( pt->xt ) {
988 pxt = &mesh->xtetra[pt->xt];
989 fprintf(inm,"tag -> %d %d %d %d %d %d\n",pxt->tag[0],pxt->tag[1],
990 pxt->tag[2],pxt->tag[3],pxt->tag[4],pxt->tag[5]);
991 fprintf(inm,"edg -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",pxt->edg[0],pxt->edg[1],
992 pxt->edg[2],pxt->edg[3],pxt->edg[4],pxt->edg[5]);
993 fprintf(inm,"ftag -> %d %d %d %d\n",pxt->ftag[0],pxt->ftag[1],
994 pxt->ftag[2],pxt->ftag[3]);
995 fprintf(inm,"ref -> %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId " %" MMG5_PRId "\n",pxt->ref[0],pxt->ref[1],
996 pxt->ref[2],pxt->ref[3]);
997 fprintf(inm,"ori -> %d \n",pxt->ori);
998 }
999 fprintf(inm,"\n");
1000 }
1001 fprintf(inm,"---------> END MMG5_TETRAHEDRAS <--------\n");
1002 fclose(inm);
1003}
1004
1005
1023int MMG3D_localParamReg(MMG5_pMesh mesh,MMG5_int ip,int64_t *listv,int ilistv,
1024 MMG5_int *lists,int ilists,
1025 double* hausd_ip,double *hmin_ip,double *hmax_ip) {
1026
1027 MMG5_pTetra pt;
1028 MMG5_pPar par;
1029 double hausd, hmin, hmax;
1030 int l,k,isloc,ifac1;
1031
1032 hausd = mesh->info.hausd;
1033 hmin = mesh->info.hmin;
1034 hmax = mesh->info.hmax;
1035 isloc = 0;
1036
1037 /* travel across the ball of ip to find the minimal local params imposed on
1038 * tetras */
1039 if ( mesh->info.parTyp & MG_Tetra ) {
1040 l = 0;
1041 do
1042 {
1043 if ( isloc ) break;
1044
1045 par = &mesh->info.par[l];
1046 if ( par->elt != MMG5_Tetrahedron ) continue;
1047
1048 for ( k=0; k<ilistv; ++k ) {
1049 pt = &mesh->tetra[listv[k]/4];
1050 if ( par->ref == pt->ref ) {
1051 hausd = par->hausd;
1052 hmin = par->hmin;
1053 hmax = par->hmax;
1054 isloc = 1;
1055 break;
1056 }
1057 }
1058 } while ( ++l<mesh->info.npar );
1059
1060 for ( ; l<mesh->info.npar; ++l ) {
1061 par = &mesh->info.par[l];
1062 if ( par->elt != MMG5_Tetrahedron ) continue;
1063
1064 for ( k=0; k<ilistv; ++k ) {
1065 pt = &mesh->tetra[listv[k]/4];
1066 if ( par->ref == pt->ref ) {
1067 hausd = MG_MIN(hausd,par->hausd);
1068 hmin = MG_MAX(hmin,par->hmin);
1069 hmax = MG_MIN(hmax,par->hmax);
1070 break;
1071 }
1072 }
1073 }
1074 }
1075 /* travel across the surface ball of ip to find the minimal local params
1076 * imposed on trias */
1077 if ( mesh->info.parTyp & MG_Tria ) {
1078 l = 0;
1079 do
1080 {
1081 if ( isloc ) break;
1082
1083 par = &mesh->info.par[l];
1084 if ( par->elt != MMG5_Triangle ) continue;
1085
1086 for ( k=0; k<ilists; ++k ) {
1087 pt = &mesh->tetra[lists[k]/4];
1088 ifac1 = lists[k] % 4;
1089 assert(pt->xt && (mesh->xtetra[pt->xt].ftag[ifac1] & MG_BDY) );
1090
1091 if ( par->ref == mesh->xtetra[pt->xt].ref[ifac1] ) {
1092 hausd = par->hausd;
1093 hmin = par->hmin;
1094 hmax = par->hmax;
1095 isloc = 1;
1096 break;
1097 }
1098 }
1099 } while ( ++l<mesh->info.npar );
1100
1101 for ( ; l<mesh->info.npar; ++l ) {
1102 par = &mesh->info.par[l];
1103 if ( par->elt != MMG5_Triangle ) continue;
1104
1105 for ( k=0; k<ilists; ++k ) {
1106 pt = &mesh->tetra[lists[k]/4];
1107 ifac1 = lists[k] % 4;
1108 assert(pt->xt && (mesh->xtetra[pt->xt].ftag[ifac1] & MG_BDY) );
1109
1110 if ( par->ref == mesh->xtetra[pt->xt].ref[ifac1] ) {
1111 hausd = MG_MIN(hausd,par->hausd);
1112 hmin = MG_MAX(hmin,par->hmin);
1113 hmax = MG_MIN(hmax,par->hmax);
1114 break;
1115 }
1116 }
1117 }
1118 }
1119
1120 /* Return the wanted values */
1121 if ( hausd_ip ) *hausd_ip = hausd;
1122 if ( hmin_ip ) *hmin_ip = hmin;
1123 if ( hmax_ip ) *hmax_ip = hmax;
1124
1125 return 1;
1126}
1127
1143int MMG3D_localParamNm(MMG5_pMesh mesh,MMG5_int iel,int iface,int ia,
1144 double* hausd_ip,double *hmin_ip,double *hmax_ip) {
1145
1146 MMG5_pTetra pt;
1147 MMG5_pxTetra pxt;
1148 MMG5_pPar par;
1149 double hausd, hmin, hmax;
1150 int l,k,isloc;
1151 int ilistv;
1152 int64_t listv[MMG3D_LMAX+2];
1153 MMG5_int ifac1,ifac2;
1154 static int8_t mmgWarn0;
1155
1156
1157 hausd = mesh->info.hausd;
1158 hmin = mesh->info.hmin;
1159 hmax = mesh->info.hmax;
1160 isloc = 0;
1161
1162 pt = &mesh->tetra[iel];
1163 pxt = &mesh->xtetra[pt->xt];
1164
1165 /* Warning : rough eval of the local param at triangles if coquilface
1166 * fails because we have more than 2 boundaries in the edge shell
1167 * (non-manifold domain). In this case, we just take into account 2
1168 * boundaries of the shell */
1169
1170 if ( pxt->tag[ia] & MG_OPNBDY ) {
1171 ilistv = 1;
1172 ifac1 = ifac2 = 4*iel + iface;
1173 }
1174 else {
1175 ilistv = MMG5_coquilface( mesh,iel,iface, ia,listv,&ifac1,&ifac2,1);
1176 }
1177 if ( ilistv < 0 )
1178 {
1179 if ( mesh->info.ddebug || mesh->info.imprim>5 ) {
1180 if ( !mmgWarn0 ) {
1181 mmgWarn0 = 1;
1182 fprintf(stderr, " ## Warning: %s: unable to take into account local"
1183 " parameters at at least 1 vertex.\n",__func__ );
1184 }
1185 }
1186
1187 if ( mesh->info.parTyp & MG_Tria ) {
1188 for ( l=0; l<mesh->info.npar; ++l) {
1189 par = &mesh->info.par[l];
1190 if ( par->elt != MMG5_Triangle ) continue;
1191
1192 if ( pxt->ref[iface]!=par->ref ) continue;
1193
1194 if ( isloc ) {
1195 hausd = MG_MIN(hausd,par->hausd);
1196 hmin = MG_MAX(hmin,par->hmin);
1197 hmax = MG_MIN(hmax,par->hmax);
1198 }
1199 else {
1200 hausd = par->hausd;
1201 hmin = par->hmin;
1202 hmax = par->hmax;
1203 isloc = 1;
1204 }
1205 }
1206 }
1207
1208 }
1209 else {
1210
1211 /* Local params at triangles containing the edge (not optimal) */
1212 if ( mesh->info.parTyp & MG_Tria ) {
1213 for ( l=0; l<mesh->info.npar; ++l) {
1214 par = &mesh->info.par[l];
1215 if ( par->elt != MMG5_Triangle ) continue;
1216
1217 if ( mesh->xtetra[mesh->tetra[ifac1/4].xt].ref[ifac1%4]!=par->ref &&
1218 mesh->xtetra[mesh->tetra[ifac2/4].xt].ref[ifac2%4]!=par->ref )
1219 continue;
1220
1221 if ( isloc ) {
1222 hausd = MG_MIN(hausd,par->hausd);
1223 hmin = MG_MAX(hmin,par->hmin);
1224 hmax = MG_MIN(hmax,par->hmax);
1225 }
1226 else {
1227 hausd = par->hausd;
1228 hmin = par->hmin;
1229 hmax = par->hmax;
1230 isloc = 1;
1231 }
1232 }
1233 }
1234 }
1235
1236 /* Local params at tetra of the edge shell */
1237 if ( mesh->info.parTyp & MG_Tetra ) {
1238 ilistv/=2;
1239 l = 0;
1240 do
1241 {
1242 if ( isloc ) break;
1243
1244 par = &mesh->info.par[l];
1245 if ( par->elt != MMG5_Tetrahedron ) continue;
1246
1247 for ( k=0; k<ilistv; ++k ) {
1248 pt = &mesh->tetra[listv[k]/6];
1249 if ( par->ref != pt->ref ) continue;
1250
1251 hausd = par->hausd;
1252 hmin = par->hmin;
1253 hmax = par->hmax;
1254 isloc = 1;
1255 }
1256 } while ( ++l<mesh->info.npar );
1257
1258 for ( ; l<mesh->info.npar; ++l ) {
1259 par = &mesh->info.par[l];
1260 if ( par->elt != MMG5_Tetrahedron ) continue;
1261
1262 for ( k=0; k<ilistv; ++k ) {
1263 pt = &mesh->tetra[listv[k]/6];
1264 if ( par->ref != pt->ref ) continue;
1265
1266 hausd = MG_MIN(hausd,par->hausd);
1267 hmin = MG_MAX(hmin,par->hmin);
1268 hmax = MG_MIN(hmax,par->hmax);
1269 break;
1270 }
1271 }
1272 }
1273 /* Return the wanted values */
1274 if ( hausd_ip ) *hausd_ip = hausd;
1275 if ( hmin_ip ) *hmin_ip = hmin;
1276 if ( hmax_ip ) *hmax_ip = hmax;
1277
1278 return 1;
1279}
1280
1288static inline
1290 MMG5_pTetra pt;
1291 MMG5_pPrism pq;
1292 MMG5_pPoint ppt;
1293 int i;
1294 MMG5_int k;
1295
1296 /* Preserve isolated required points */
1297 for ( k=1; k<=mesh->np; k++ ) {
1298 ppt = &mesh->point[k];
1299 if ( ppt->flag || !(ppt->tag & MG_REQ) ) {
1300 continue;
1301 }
1302 ppt->tag &= ~MG_NUL;
1303 }
1304
1305 /* Mark points used by the connectivity */
1306 for ( k=1; k<=mesh->ne; k++ ) {
1307 pt = &mesh->tetra[k];
1308 if ( !MG_EOK(pt) ) continue;
1309
1310 for (i=0; i<4; i++) {
1311 ppt = &mesh->point[ pt->v[i] ];
1312 ppt->tag &= ~MG_NUL;
1313 }
1314 }
1315
1316 for ( k=1; k<=mesh->nprism; k++ ) {
1317 pq = &mesh->prism[k];
1318 if ( !MG_EOK(pq) ) continue;
1319
1320 for (i=0; i<6; i++) {
1321 ppt = &mesh->point[ pq->v[i] ];
1322 ppt->tag &= ~MG_NUL;
1323 }
1324 }
1325
1326 /* Finally, clean point array */
1327 while ( (!MG_VOK(&mesh->point[mesh->np])) && mesh->np ) {
1329 }
1330
1331 return;
1332}
1333
1341static
1343 MMG5_pTetra pt;
1344 int i,iv;
1345 MMG5_int k,*adja,iadr,iadrv;
1346 int nfac = 4; // number of faces per elt
1347
1348 for ( k=1 ; k <= mesh->ne ; k++) {
1349 pt = &mesh->tetra[k];
1350
1351 if ( !MG_EOK(pt) ) continue;
1352
1353 /* Mark tetra vertices as seen to be able to detect isolated points */
1354 mesh->point[pt->v[0]].flag = 1;
1355 mesh->point[pt->v[1]].flag = 1;
1356 mesh->point[pt->v[2]].flag = 1;
1357 mesh->point[pt->v[3]].flag = 1;
1358
1359 if ( pt->ref == nsd ) continue;
1360
1361 /* Update adjacency relationship: we will delete elt k so k adjacent will
1362 * not be adjacent to k anymore */
1363 if ( mesh->adja ) {
1364 iadr = nfac*(k-1) + 1;
1365 adja = &mesh->adja[iadr];
1366 for ( i=0; i<nfac; ++i ) {
1367 iadrv = adja[i];
1368 if ( !iadrv ) {
1369 continue;
1370 }
1371 iv = iadrv%nfac;
1372 iadrv /= nfac;
1373 mesh->adja[nfac*(iadrv-1)+1+iv] = 0;
1374 }
1375 }
1376
1377 /* Delete element */
1378 MMG3D_delElt(mesh,k);
1379 }
1380
1381 return;
1382}
1383
1392
1393 if ( !nsd ) {
1394 return;
1395 }
1396
1397 if ( mesh->info.imprim > 4 || mesh->info.ddebug ) {
1398 fprintf(stdout,"\n -- ONLY KEEP DOMAIN OF REF %d\n",nsd );
1399 }
1400
1402
1404
1406
1407 return;
1408}
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:1843
#define MMG5_EPSD
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
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:227
@ MMG5_Triangle
Definition: libmmgtypes.h:226
#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:541
int8_t ddebug
Definition: libmmgtypes.h:532
MMG5_int * br
Definition: libmmgtypes.h:520
double hmin
Definition: libmmgtypes.h:518
double hmax
Definition: libmmgtypes.h:518
MMG5_pPar par
Definition: libmmgtypes.h:517
double hausd
Definition: libmmgtypes.h:518
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_pPrism prism
Definition: libmmgtypes.h:645
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
MMG5_int nprism
Definition: libmmgtypes.h:613
double hmin
Definition: libmmgtypes.h:258
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 xp
Definition: libmmgtypes.h:279
MMG5_int flag
Definition: libmmgtypes.h:282
MMG5_int v[6]
Definition: libmmgtypes.h:463
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int ref
Definition: libmmgtypes.h:404
int16_t tag
Definition: libmmgtypes.h:410
int8_t nnor
Definition: libmmgtypes.h:297
double n2[3]
Definition: libmmgtypes.h:295
double n1[3]
Definition: libmmgtypes.h:295
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
int8_t ori
Definition: libmmgtypes.h:427
MMG5_int edg[6]
Definition: libmmgtypes.h:421
MMG5_int ref[4]
Definition: libmmgtypes.h:419
static void MMG3D_keep_subdomainElts(MMG5_pMesh mesh, int nsd)
Definition: tools_3d.c:1342
static void MMG3D_mark_usedVertices(MMG5_pMesh mesh)
Definition: tools_3d.c:1289
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:1391
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:694
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:1143
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:916
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:973
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:1023
MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel)
Definition: tools_3d.c:860