Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
bezier_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
35#include "libmmg3d_private.h"
36
37extern int8_t ddb;
38
52inline int
53MMG5_BezierTgt(double c1[3],double c2[3],double n1[3],double n2[3],double t1[3],double t2[3]) {
54 double ux,uy,uz,b[3],n[3],dd;
55
56 ux = c2[0] - c1[0];
57 uy = c2[1] - c1[1];
58 uz = c2[2] - c1[2];
59
60 n[0] = 0.5*(n1[0]+n2[0]);
61 n[1] = 0.5*(n1[1]+n2[1]);
62 n[2] = 0.5*(n1[2]+n2[2]);
63
64 b[0] = uy*n[2] - uz*n[1];
65 b[1] = uz*n[0] - ux*n[2];
66 b[2] = ux*n[1] - uy*n[0];
67
68 t1[0] = n1[1]*b[2] - n1[2]*b[1];
69 t1[1] = n1[2]*b[0] - n1[0]*b[2];
70 t1[2] = n1[0]*b[1] - n1[1]*b[0];
71
72 t2[0] = -( n2[1]*b[2] - n2[2]*b[1] );
73 t2[1] = -( n2[2]*b[0] - n2[0]*b[2] );
74 t2[2] = -( n2[0]*b[1] - n2[1]*b[0] );
75
76 dd = t1[0]*t1[0] + t1[1]*t1[1] + t1[2]*t1[2];
77 if ( dd < MMG5_EPSD )
78 return 0;
79 else{
80 dd = 1.0 / sqrt(dd);
81 t1[0] *= dd;
82 t1[1] *= dd;
83 t1[2] *= dd;
84 }
85
86 dd = t2[0]*t2[0] + t2[1]*t2[1] + t2[2]*t2[2];
87 if ( dd < MMG5_EPSD )
88 return 0;
89 else{
90 dd = 1.0 / sqrt(dd);
91 t2[0] *= dd;
92 t2[1] *= dd;
93 t2[2] *= dd;
94 }
95
96 return 1;
97}
98
110inline double
111MMG5_BezierGeod(double c1[3],double c2[3],double t1[3],double t2[3]) {
112 double /*alpha,t[3],ps,*/ux,uy,uz,ll;
113
114 ux = c2[0] - c1[0];
115 uy = c2[1] - c1[1];
116 uz = c2[2] - c1[2];
117
118 ll = ux*ux + uy*uy + uz*uz;
119
120 /* tentative to do something...*/
121 /* t[0] = MMG5_ATHIRD*(t2[0]-t1[0]); */
122 /* t[1] = MMG5_ATHIRD*(t2[1]-t1[1]); */
123 /* t[2] = MMG5_ATHIRD*(t2[2]-t1[2]); */
124
125 /* nt2 = t[0]*t[0] + t[1]*t[1] + t[2]*t[2]; */
126 /* nt2 = 16.0 - nt2; */
127
128 /* ps = t[0]*ux + t[1]*uy + t[2]*uz; */
129
130 /* alpha = ps + sqrt(ps*ps + ll*nt2); */
131 /* alpha *= (6.0 / nt2); */
132
133 return MMG5_ATHIRD*sqrt(ll);
134}
135
151inline int
152MMG5_BezierEdge(MMG5_pMesh mesh,MMG5_int ip0,MMG5_int ip1,double b0[3],
153 double b1[3],int8_t ised, double v[3]) {
154 MMG5_pPoint p0,p1;
155 MMG5_pxPoint pxp0,pxp1;
156 double ux,uy,uz,ps,ps1,ps2,*n1,*n2,np0[3],np1[3],t0[3],t1[3],il,ll,alpha;
157
158 p0 = &mesh->point[ip0];
159 p1 = &mesh->point[ip1];
160 if ( !(p0->tag & MG_BDY) || !(p1->tag & MG_BDY) ) return 0;
161
162 np0[0] = np0[1] = np0[2] = 0;
163 np1[0] = np1[1] = np1[2] = 0;
164 n1 = n2 = NULL;
165
166 if ( !MG_SIN(p0->tag) ) {
167 assert(p0->xp);
168 pxp0 = &mesh->xpoint[p0->xp];
169 }
170 else
171 pxp0 = 0;
172
173 if ( !MG_SIN(p1->tag) ) {
174 /* Remark: all nom points have xpoints */
175 assert(p1->xp);
176 pxp1 = &mesh->xpoint[p1->xp];
177 }
178 else
179 pxp1 = 0;
180
181 ux = p1->c[0] - p0->c[0];
182 uy = p1->c[1] - p0->c[1];
183 uz = p1->c[2] - p0->c[2];
184
185 ll = ux*ux + uy*uy + uz*uz;
186 if ( ll < MMG5_EPSD2 ) {
187 b0[0] = p0->c[0] + MMG5_ATHIRD*ux;
188 b0[1] = p0->c[1] + MMG5_ATHIRD*uy;
189 b0[2] = p0->c[2] + MMG5_ATHIRD*uz;
190
191 b1[0] = p1->c[0] - MMG5_ATHIRD*ux;
192 b1[1] = p1->c[1] - MMG5_ATHIRD*uy;
193 b1[2] = p1->c[2] - MMG5_ATHIRD*uz;
194
195 return 1;
196 }
197 il = 1.0 / sqrt(ll);
198
199 if ( ised ) {
200 if ( MG_SIN(p0->tag) ) {
201 t0[0] = ux * il;
202 t0[1] = uy * il;
203 t0[2] = uz * il;
204 }
205 else {
206 memcpy(t0,&(p0->n[0]),3*sizeof(double));
207 ps = t0[0]*ux + t0[1]*uy + t0[2]*uz;
208 if ( ps < 0.0 ) {
209 t0[0] *= -1.0;
210 t0[1] *= -1.0;
211 t0[2] *= -1.0;
212 }
213 }
214 if ( MG_SIN(p1->tag) ) {
215 t1[0] = - ux * il;
216 t1[1] = - uy * il;
217 t1[2] = - uz * il;
218 }
219 else {
220 memcpy(t1,&(p1->n[0]),3*sizeof(double));
221 ps = -( t1[0]*ux + t1[1]*uy + t1[2]*uz );
222 if ( ps < 0.0 ) {
223 t1[0] *= -1.0;
224 t1[1] *= -1.0;
225 t1[2] *= -1.0;
226 }
227 }
228 }
229
230 else {
231 if ( ! MG_SIN_OR_NOM(p0->tag) ) {
232 if ( p0->tag & MG_GEO ) {
233 n1 = &(pxp0->n1[0]);
234 n2 = &(pxp0->n2[0]);
235 ps1 = v[0]*n1[0] + v[1]*n1[1] + v[2]*n1[2];
236 ps2 = v[0]*n2[0] + v[1]*n2[1] + v[2]*n2[2];
237 if ( fabs(ps2) > fabs(ps1) )
238 memcpy(np0,&(pxp0->n2[0]),3*sizeof(double));
239 else
240 memcpy(np0,&(pxp0->n1[0]),3*sizeof(double));
241 }
242 else
243 memcpy(np0,&(pxp0->n1[0]),3*sizeof(double));
244 }
245
246 if ( !MG_SIN_OR_NOM(p1->tag) ) {
247 if ( p1->tag & MG_GEO ) {
248 n1 = &(pxp1->n1[0]);
249 n2 = &(pxp1->n2[0]);
250 ps1 = -(v[0]*n1[0] + v[1]*n1[1] + v[2]*n1[2]);
251 ps2 = -(v[0]*n2[0] + v[1]*n2[1] + v[2]*n2[2]);
252 if ( fabs(ps2) > fabs(ps1) )
253 memcpy(np1,&(pxp1->n2[0]),3*sizeof(double));
254 else
255 memcpy(np1,&(pxp1->n1[0]),3*sizeof(double));
256 }
257 else
258 memcpy(np1,&(pxp1->n1[0]),3*sizeof(double));
259 }
260 if ( MG_SIN_OR_NOM(p0->tag) && MG_SIN_OR_NOM(p1->tag) ) {
261 t0[0] = ux * il;
262 t0[1] = uy * il;
263 t0[2] = uz * il;
264
265 t1[0] = -ux * il;
266 t1[1] = -uy * il;
267 t1[2] = -uz * il;
268 }
269 else if ( (!MG_SIN_OR_NOM(p0->tag)) && MG_SIN_OR_NOM(p1->tag) ) {
270 if ( !MMG5_BezierTgt(p0->c,p1->c,np0,np0,t0,t1) ) {
271 t0[0] = ux * il;
272 t0[1] = uy * il;
273 t0[2] = uz * il;
274 }
275 t1[0] = -ux * il;
276 t1[1] = -uy * il;
277 t1[2] = -uz * il;
278 }
279 else if ( MG_SIN_OR_NOM(p0->tag) && (!MG_SIN_OR_NOM(p1->tag)) ) {
280 if ( !MMG5_BezierTgt(p0->c,p1->c,np1,np1,t0,t1) ) {
281 t1[0] = - ux * il;
282 t1[1] = - uy * il;
283 t1[2] = - uz * il;
284 }
285 t0[0] = ux * il;
286 t0[1] = uy * il;
287 t0[2] = uz * il;
288 }
289 else {
290 if ( !MMG5_BezierTgt(p0->c,p1->c,np0,np1,t0,t1) ) {
291 t0[0] = ux * il;
292 t0[1] = uy * il;
293 t0[2] = uz * il;
294
295 t1[0] = - ux * il;
296 t1[1] = - uy * il;
297 t1[2] = - uz * il;
298 }
299 }
300 }
301
302 alpha = MMG5_BezierGeod(p0->c,p1->c,t0,t1);
303 b0[0] = p0->c[0] + alpha * t0[0];
304 b0[1] = p0->c[1] + alpha * t0[1];
305 b0[2] = p0->c[2] + alpha * t0[2];
306
307 b1[0] = p1->c[0] + alpha * t1[0];
308 b1[1] = p1->c[1] + alpha * t1[1];
309 b1[2] = p1->c[2] + alpha * t1[2];
310
311 return 1;
312}
313
327 MMG5_pPoint p[3];
328 MMG5_xPoint *pxp;
329 double *n1,*n2,nt[3],t1[3],t2[3],ps,ps2,dd,ux,uy,uz,l,ll,alpha;
330 MMG5_int ia,ib,ic;
331 int8_t i,i1,i2,im,isnm;
332
333 ia = pt->v[0];
334 ib = pt->v[1];
335 ic = pt->v[2];
336 p[0] = &mesh->point[ia];
337 p[1] = &mesh->point[ib];
338 p[2] = &mesh->point[ic];
339
340 memset(pb,0,sizeof(MMG5_Bezier));
341
342 /* first 3 CP = vertices, normals */
343 for (i=0; i<3; i++) {
344 memcpy(&pb->b[i],p[i]->c,3*sizeof(double));
345 pb->p[i] = p[i];
346
347 if ( MG_SIN(p[i]->tag) ) {
348 MMG5_nortri(mesh,pt,pb->n[i]);
349 if ( !ori ) {
350 pb->n[i][0] *= -1.0;
351 pb->n[i][1] *= -1.0;
352 pb->n[i][2] *= -1.0;
353 }
354 }
355 else if( p[i]->tag & MG_NOM){
356 /* Remark: external nom points have 1 normal, internal ones have no normals */
357 MMG5_nortri(mesh,pt,pb->n[i]);
358 if ( !ori ) {
359 pb->n[i][0] *= -1.0;
360 pb->n[i][1] *= -1.0;
361 pb->n[i][2] *= -1.0;
362 }
363 assert(p[i]->xp);
364 memcpy(&pb->t[i],p[i]->n,3*sizeof(double));
365 }
366 else {
367 assert(p[i]->xp);
368 pxp = &mesh->xpoint[p[i]->xp];
369 if ( MG_EDG(p[i]->tag) ) {
370 MMG5_nortri(mesh,pt,nt);
371 if ( !ori ) {
372 nt[0] *= -1.0;
373 nt[1] *= -1.0;
374 nt[2] *= -1.0;
375 }
376 /* Choose the closest normal to our surface to ensure smoothness */
377 ps = pxp->n1[0]*nt[0] + pxp->n1[1]*nt[1] + pxp->n1[2]*nt[2];
378 ps2 = pxp->n2[0]*nt[0] + pxp->n2[1]*nt[1] + pxp->n2[2]*nt[2];
379
393 assert ( ps > 0. || ps2 > 0. &&
394 "Negative projection of normal at tria onto normal at point: surface degeneracy");
395
396 /* As previous assert may fail in some cases, deal with both cases */
397 if ( (ps > 0.) || (ps2 >0.) ) {
398 /* Normal case */
399 if ( ps > ps2 ) {
400 memcpy(&pb->n[i],pxp->n1,3*sizeof(double));
401 }
402 else {
403 memcpy(&pb->n[i],pxp->n2,3*sizeof(double));
404 }
405 }
406 else {
407 /* I think that tis case is only possible when we face surface
408 * degeneracy: in this case we want to choose the normal whose
409 * projection over the normal at triangle is smallest as possible
410 * (otherwise we will worsen the degeneracy) */
411 if ( ps < ps2 ) {
412 memcpy(&pb->n[i],pxp->n1,3*sizeof(double));
413 }
414 else {
415 memcpy(&pb->n[i],pxp->n2,3*sizeof(double));
416 }
417 }
418 memcpy(&pb->t[i],p[i]->n,3*sizeof(double));
419
420 /* Normal should have suitable orientation */
421 ps = pb->n[i][0]*nt[0] + pb->n[i][1]*nt[1] + pb->n[i][2]*nt[2];
422 /* This assertion may fail if assertion on ps and ps2 positivity fails:
423 * I think that we don't want to reorient the tangent because we know
424 * that the negativity of projection is not normal */
425 assert ( ps > 0. );
426 }
427 else {
428 memcpy(&pb->n[i],pxp->n1,3*sizeof(double));
429 }
430 }
431 }
432
434 /* Detect non-manifold points */
435 im = -1;
436 isnm = 0;
437 for (i=0; i<3; i++) {
438 if ( p[i]->tag & MG_NOM )
439 isnm++;
440 else if ( im == -1 )
441 im = i;
442 }
443
444 /* Orientation of the normal */
445 if ( isnm ) {
446 /* with respect to the normal at manifold points if at least one manifold
447 * point is detected. */
448 if ( im != -1 ) {
449 for (i=0; i<3; i++) {
450 if ( p[i]->tag & MG_NOM ) {
451 ps = pb->n[i][0]*pb->n[im][0] + pb->n[i][1]*pb->n[im][1] + pb->n[i][2]*pb->n[im][2];
452 if ( ps < 0.0 ) {
453 pb->n[i][0] *= -1.0;
454 pb->n[i][1] *= -1.0;
455 pb->n[i][2] *= -1.0;
456 }
457 }
458 }
459 }
460 else {
461 /* with respect to the normal at point 0 in the other case (all vertices are
462 * non-manifold) */
463 for (i=1; i<3; i++) {
464 if ( p[i]->tag & MG_NOM ) {
465 ps = pb->n[i][0]*pb->n[0][0] + pb->n[i][1]*pb->n[0][1] + pb->n[i][2]*pb->n[0][2];
466 if ( ps < 0.0 ) {
467 pb->n[i][0] *= -1.0;
468 pb->n[i][1] *= -1.0;
469 pb->n[i][2] *= -1.0;
470 }
471 }
472 }
473 }
474 }
475
476 /* compute control points along edges of face */
477 for (i=0; i<3; i++) {
478 i1 = MMG5_inxt2[i];
479 i2 = MMG5_iprv2[i];
480
481 ux = p[i2]->c[0] - p[i1]->c[0];
482 uy = p[i2]->c[1] - p[i1]->c[1];
483 uz = p[i2]->c[2] - p[i1]->c[2];
484
485 ll = ux*ux + uy*uy + uz*uz;
486 l = sqrt(ll);
487
488 /* choose normals */
489 n1 = pb->n[i1];
490 n2 = pb->n[i2];
491
492 /* check for boundary curve */
493 if ( MG_EDG_OR_NOM(pt->tag[i]) ) {
494 if ( MG_SIN(p[i1]->tag) ) {
495 t1[0] = ux / l;
496 t1[1] = uy / l;
497 t1[2] = uz / l;
498 }
499 else {
500 /* Nom points have a tangent so its ok to pass here */
501 memcpy(t1,&pb->t[i1],3*sizeof(double));
502 ps = t1[0]*ux + t1[1]*uy + t1[2]*uz;
503 if(ps < 0.0){
504 t1[0] *= -1.0;
505 t1[1] *= -1.0;
506 t1[2] *= -1.0;
507 }
508 }
509 if ( MG_SIN(p[i2]->tag) ) {
510 t2[0] = - ux / l;
511 t2[1] = - uy / l;
512 t2[2] = - uz / l;
513 }
514 else {
515 /* Nom points have a tangent so its ok to pass here */
516 memcpy(t2,&pb->t[i2],3*sizeof(double));
517 ps = -(t2[0]*ux + t2[1]*uy + t2[2]*uz);
518 if(ps < 0.0){
519 t2[0] *= -1.0;
520 t2[1] *= -1.0;
521 t2[2] *= -1.0;
522 }
523 }
524
525 /* tangent evaluation using quadratic variation theory (cf Vlachos, Curve
526 * PN Triangles: 3.3): reflection of the mean tangent across the plane
527 * perpendicular to the edge */
528 ps = ux*(pb->t[i1][0]+pb->t[i2][0]) + uy*(pb->t[i1][1]+pb->t[i2][1]) + uz*(pb->t[i1][2]+pb->t[i2][2]);
529 ps = 2.0 * ps / ll;
530 pb->t[i+3][0] = pb->t[i1][0] + pb->t[i2][0] - ps*ux;
531 pb->t[i+3][1] = pb->t[i1][1] + pb->t[i2][1] - ps*uy;
532 pb->t[i+3][2] = pb->t[i1][2] + pb->t[i2][2] - ps*uz;
533 dd = pb->t[i+3][0]*pb->t[i+3][0] + pb->t[i+3][1]*pb->t[i+3][1] + pb->t[i+3][2]*pb->t[i+3][2];
534 if ( dd > MMG5_EPSD2 ) {
535 dd = 1.0 / sqrt(dd);
536 pb->t[i+3][0] *= dd;
537 pb->t[i+3][1] *= dd;
538 pb->t[i+3][2] *= dd;
539 }
540 }
541
542 else { /* internal edge */
543 if ( !MMG5_BezierTgt(p[i1]->c,p[i2]->c,n1,n2,t1,t2) ) {
544 t1[0] = ux / l;
545 t1[1] = uy / l;
546 t1[2] = uz / l;
547
548 t2[0] = - ux / l;
549 t2[1] = - uy / l;
550 t2[2] = - uz / l;
551 }
552 }
553
554 alpha = MMG5_BezierGeod(p[i1]->c,p[i2]->c,t1,t2);
555
556 pb->b[2*i+3][0] = p[i1]->c[0] + alpha * t1[0];
557 pb->b[2*i+3][1] = p[i1]->c[1] + alpha * t1[1];
558 pb->b[2*i+3][2] = p[i1]->c[2] + alpha * t1[2];
559
560 pb->b[2*i+4][0] = p[i2]->c[0] + alpha * t2[0];
561 pb->b[2*i+4][1] = p[i2]->c[1] + alpha * t2[1];
562 pb->b[2*i+4][2] = p[i2]->c[2] + alpha * t2[2];
563
564 /* normal evaluation using quadratic variation theory (cf Vlachos, Curve PN
565 * Triangles: 3.3): reflection of the mean normal across the plane
566 * perpendicular to the edge */
567 ps = ux*(n1[0]+n2[0]) + uy*(n1[1]+n2[1]) + uz*(n1[2]+n2[2]);
568 ps = 2.0*ps / ll;
569 pb->n[i+3][0] = n1[0] + n2[0] - ps*ux;
570 pb->n[i+3][1] = n1[1] + n2[1] - ps*uy;
571 pb->n[i+3][2] = n1[2] + n2[2] - ps*uz;
572 dd = pb->n[i+3][0]*pb->n[i+3][0] + pb->n[i+3][1]*pb->n[i+3][1] + pb->n[i+3][2]*pb->n[i+3][2];
573 if ( dd > MMG5_EPSD2 ) {
574 dd = 1.0 / sqrt(dd);
575 pb->n[i+3][0] *= dd;
576 pb->n[i+3][1] *= dd;
577 pb->n[i+3][2] *= dd;
578 }
579 }
580
581 /* Central Bezier coefficient */
582 for (i=0; i<3; i++) {
583 dd = 0.5 / 3.0;
584 pb->b[9][0] -= dd * pb->b[i][0];
585 pb->b[9][1] -= dd * pb->b[i][1];
586 pb->b[9][2] -= dd * pb->b[i][2];
587 }
588 for (i=0; i<3; i++) {
589 pb->b[9][0] += 0.25 * (pb->b[2*i+3][0] + pb->b[2*i+4][0]);
590 pb->b[9][1] += 0.25 * (pb->b[2*i+3][1] + pb->b[2*i+4][1]);
591 pb->b[9][2] += 0.25 * (pb->b[2*i+3][2] + pb->b[2*i+4][2]);
592 }
593
594 return 1;
595}
596
608int MMG3D_bezierInt(MMG5_pBezier pb,double uv[2],double o[3],double no[3],double to[3]) {
609 double dd,u,v,w,ps,ux,uy,uz;
610 int8_t i;
611
612 memset(to,0,3*sizeof(double));
613 u = uv[0];
614 v = uv[1];
615 w = 1 - u - v;
616
617 for (i=0; i<3; i++) {
618 o[i] = pb->b[0][i]*w*w*w + pb->b[1][i]*u*u*u + pb->b[2][i]*v*v*v \
619 + 3.0 * (pb->b[3][i]*u*u*v + pb->b[4][i]*u*v*v + pb->b[5][i]*w*v*v \
620 + pb->b[6][i]*w*w*v + pb->b[7][i]*w*w*u + pb->b[8][i]*w*u*u)\
621 + 6.0 * pb->b[9][i]*u*v*w;
622
623 /* quadratic interpolation of normals */
624 no[i] = pb->n[0][i]*w*w + pb->n[1][i]*u*u + pb->n[2][i]*v*v \
625 + 2.0 * (pb->n[3][i]*u*v + pb->n[4][i]*v*w + pb->n[5][i]*u*w);
626
627 /* linear interpolation, not used here
628 no[i] = pb->n[0][i]*w + pb->n[1][i]*u + pb->n[2][i]*v; */
629 }
630 assert ( no[0]*no[0] + no[1]*no[1] + no[2]*no[2] > 0. );
631
632 /* tangent */
633 if ( w < MMG5_EPSD2 ) {
634 ux = pb->b[2][0] - pb->b[1][0];
635 uy = pb->b[2][1] - pb->b[1][1];
636 uz = pb->b[2][2] - pb->b[1][2];
637 dd = ux*ux + uy*uy + uz*uz;
638 if ( dd > MMG5_EPSD2 ) {
639 dd = 1.0 / sqrt(dd);
640 ux *= dd;
641 uy *= dd;
642 uz *= dd;
643 }
644
645 /* corners and required points: no tangent */
646 if ( MG_SIN(pb->p[1]->tag) ) {
647 pb->t[1][0] = ux;
648 pb->t[1][1] = uy;
649 pb->t[1][2] = uz;
650 }
651 if ( MG_SIN(pb->p[2]->tag) ) {
652 pb->t[2][0] = ux;
653 pb->t[2][1] = uy;
654 pb->t[2][2] = uz;
655 }
656
657 ps = pb->t[1][0]* pb->t[2][0] + pb->t[1][1]* pb->t[2][1] + pb->t[1][2]* pb->t[2][2];
658 if ( ps > 0.0 ) {
659 to[0] = pb->t[1][0]*u + pb->t[2][0]*v;
660 to[1] = pb->t[1][1]*u + pb->t[2][1]*v;
661 to[2] = pb->t[1][2]*u + pb->t[2][2]*v;
662 }
663 else {
664 to[0] = -pb->t[1][0]*u + pb->t[2][0]*v;
665 to[1] = -pb->t[1][1]*u + pb->t[2][1]*v;
666 to[2] = -pb->t[1][2]*u + pb->t[2][2]*v;
667 }
668 }
669
670 if ( u < MMG5_EPSD2 ) {
671 ux = pb->b[2][0] - pb->b[0][0];
672 uy = pb->b[2][1] - pb->b[0][1];
673 uz = pb->b[2][2] - pb->b[0][2];
674 dd = ux*ux + uy*uy + uz*uz;
675 if ( dd > MMG5_EPSD2 ) {
676 dd = 1.0 / sqrt(dd);
677 ux *= dd;
678 uy *= dd;
679 uz *= dd;
680 }
681
682 /* corners and required points: no tangent */
683 if ( MG_SIN(pb->p[0]->tag) ) {
684 pb->t[0][0] = ux;
685 pb->t[0][1] = uy;
686 pb->t[0][2] = uz;
687 }
688 if ( MG_SIN(pb->p[2]->tag) ) {
689 pb->t[2][0] = ux;
690 pb->t[2][1] = uy;
691 pb->t[2][2] = uz;
692 }
693
694 ps = pb->t[0][0]* pb->t[2][0] + pb->t[0][1]* pb->t[2][1] + pb->t[0][2]* pb->t[2][2];
695 if ( ps > 0.0 ) {
696 to[0] = pb->t[0][0]*w + pb->t[2][0]*v;
697 to[1] = pb->t[0][1]*w + pb->t[2][1]*v;
698 to[2] = pb->t[0][2]*w + pb->t[2][2]*v;
699 }
700 else {
701 to[0] = -pb->t[0][0]*w + pb->t[2][0]*v;
702 to[1] = -pb->t[0][1]*w + pb->t[2][1]*v;
703 to[2] = -pb->t[0][2]*w + pb->t[2][2]*v;
704 }
705 }
706
707 if ( v < MMG5_EPSD2 ) {
708 ux = pb->b[1][0] - pb->b[0][0];
709 uy = pb->b[1][1] - pb->b[0][1];
710 uz = pb->b[1][2] - pb->b[0][2];
711 dd = ux*ux + uy*uy + uz*uz;
712 if ( dd > MMG5_EPSD2 ) {
713 dd = 1.0 / sqrt(dd);
714 ux *= dd;
715 uy *= dd;
716 uz *= dd;
717 }
718
719 /* corners */
720 if ( MG_SIN(pb->p[0]->tag) ) {
721 pb->t[0][0] = ux;
722 pb->t[0][1] = uy;
723 pb->t[0][2] = uz;
724 }
725 if ( MG_SIN(pb->p[1]->tag) ) {
726 pb->t[1][0] = ux;
727 pb->t[1][1] = uy;
728 pb->t[1][2] = uz;
729 }
730
731 ps = pb->t[0][0]* pb->t[1][0] + pb->t[0][1]* pb->t[1][1] + pb->t[0][2]* pb->t[1][2];
732 if ( ps > 0.0 ) {
733 to[0] = pb->t[0][0]*w + pb->t[1][0]*u;
734 to[1] = pb->t[0][1]*w + pb->t[1][1]*u;
735 to[2] = pb->t[0][2]*w + pb->t[1][2]*u;
736 }
737 else {
738 to[0] = -pb->t[0][0]*w + pb->t[1][0]*u;
739 to[1] = -pb->t[0][1]*w + pb->t[1][1]*u;
740 to[2] = -pb->t[0][2]*w + pb->t[1][2]*u;
741 }
742 }
743
744 dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2];
745 if ( dd > MMG5_EPSD2 ) {
746 dd = 1.0 / sqrt(dd);
747 no[0] *= dd;
748 no[1] *= dd;
749 no[2] *= dd;
750 }
751
752 dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2];
753 if ( dd > MMG5_EPSD2 ) {
754 dd = 1.0 / sqrt(dd);
755 to[0] *= dd;
756 to[1] *= dd;
757 to[2] *= dd;
758 }
759
760 return 1;
761}
MMG5_pMesh * mesh
int MMG5_BezierEdge(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double b0[3], double b1[3], int8_t ised, double v[3])
Definition: bezier_3d.c:152
int MMG3D_bezierInt(MMG5_pBezier pb, double uv[2], double o[3], double no[3], double to[3])
Definition: bezier_3d.c:608
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
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG5_mmg3dBezierCP(MMG5_pMesh mesh, MMG5_Tria *pt, MMG5_pBezier pb, int8_t ori)
Definition: bezier_3d.c:326
#define MMG5_EPSD
#define MG_GEO
#define MG_EDG(tag)
static const uint8_t MMG5_iprv2[3]
#define MMG5_ATHIRD
#define MG_EDG_OR_NOM(tag)
#define MG_SIN(tag)
static const uint8_t MMG5_inxt2[6]
int MMG5_nortri(MMG5_pMesh mesh, MMG5_pTria pt, double *n)
Definition: tools.c:209
#define MG_BDY
#define MG_NOM
#define MG_SIN_OR_NOM(tag)
#define MMG5_EPSD2
double b[10][3]
MMG5_pPoint p[3]
double n[6][3]
double t[6][3]
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
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
int16_t tag[3]
Definition: libmmgtypes.h:342
MMG5_int v[3]
Definition: libmmgtypes.h:334
Structure to store surface points of a MMG mesh.
Definition: libmmgtypes.h:294
double n2[3]
Definition: libmmgtypes.h:295
double n1[3]
Definition: libmmgtypes.h:295