Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
intmet.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 "mmgcommon_private.h"
36#include "mmgexterns_private.h"
37
50int MMG5_mmgIntmet33_ani(double *m,double *n,double *mr,double s) {
51 int order;
52 double lambda[3],vp[3][3],mu[3],is[6],isnis[6],mt[9],P[9],dd;
53 int8_t i;
54 static int8_t mmgWarn=0;
55
56 /* Compute inverse of square root of matrix M : is =
57 * P*diag(1/sqrt(lambda))*{^t}P */
58 order = MMG5_eigenv3d(1,m,lambda,vp);
59 if ( !order ) {
60 if ( !mmgWarn ) {
61 fprintf(stderr,"\n ## Warning: %s: unable to diagonalize at least"
62 " 1 metric.\n",__func__);
63 mmgWarn = 1;
64 }
65 return 0;
66 }
67
68 for (i=0; i<3; i++) {
69 if ( lambda[i] < MMG5_EPSD ) return 0;
70 lambda[i] = sqrt(lambda[i]);
71 lambda[i] = 1.0 / lambda[i];
72 }
73
74 is[0] = lambda[0]*vp[0][0]*vp[0][0] + lambda[1]*vp[1][0]*vp[1][0]
75 + lambda[2]*vp[2][0]*vp[2][0];
76 is[1] = lambda[0]*vp[0][0]*vp[0][1] + lambda[1]*vp[1][0]*vp[1][1]
77 + lambda[2]*vp[2][0]*vp[2][1];
78 is[2] = lambda[0]*vp[0][0]*vp[0][2] + lambda[1]*vp[1][0]*vp[1][2]
79 + lambda[2]*vp[2][0]*vp[2][2];
80 is[3] = lambda[0]*vp[0][1]*vp[0][1] + lambda[1]*vp[1][1]*vp[1][1]
81 + lambda[2]*vp[2][1]*vp[2][1];
82 is[4] = lambda[0]*vp[0][1]*vp[0][2] + lambda[1]*vp[1][1]*vp[1][2]
83 + lambda[2]*vp[2][1]*vp[2][2];
84 is[5] = lambda[0]*vp[0][2]*vp[0][2] + lambda[1]*vp[1][2]*vp[1][2]
85 + lambda[2]*vp[2][2]*vp[2][2];
86
87 mt[0] = n[0]*is[0] + n[1]*is[1] + n[2]*is[2];
88 mt[1] = n[0]*is[1] + n[1]*is[3] + n[2]*is[4];
89 mt[2] = n[0]*is[2] + n[1]*is[4] + n[2]*is[5];
90 mt[3] = n[1]*is[0] + n[3]*is[1] + n[4]*is[2];
91 mt[4] = n[1]*is[1] + n[3]*is[3] + n[4]*is[4];
92 mt[5] = n[1]*is[2] + n[3]*is[4] + n[4]*is[5];
93 mt[6] = n[2]*is[0] + n[4]*is[1] + n[5]*is[2];
94 mt[7] = n[2]*is[1] + n[4]*is[3] + n[5]*is[4];
95 mt[8] = n[2]*is[2] + n[4]*is[4] + n[5]*is[5];
96
97 isnis[0] = is[0]*mt[0] + is[1]*mt[3] + is[2]*mt[6];
98 isnis[1] = is[0]*mt[1] + is[1]*mt[4] + is[2]*mt[7];
99 isnis[2] = is[0]*mt[2] + is[1]*mt[5] + is[2]*mt[8];
100 isnis[3] = is[1]*mt[1] + is[3]*mt[4] + is[4]*mt[7];
101 isnis[4] = is[1]*mt[2] + is[3]*mt[5] + is[4]*mt[8];
102 isnis[5] = is[2]*mt[2] + is[4]*mt[5] + is[5]*mt[8];
103
104 order = MMG5_eigenv3d(1,isnis,lambda,vp);
105 if ( !order ) {
106 if ( !mmgWarn ) {
107 fprintf(stderr,"\n ## Warning: %s: unable to diagonalize at least"
108 " 1 metric.\n",__func__);
109 mmgWarn = 1;
110 }
111 return 0;
112 }
113
114 /* P = is * (vp) */
115 P[0] = is[0]*vp[0][0] + is[1]*vp[0][1] + is[2]*vp[0][2];
116 P[1] = is[0]*vp[1][0] + is[1]*vp[1][1] + is[2]*vp[1][2];
117 P[2] = is[0]*vp[2][0] + is[1]*vp[2][1] + is[2]*vp[2][2];
118 P[3] = is[1]*vp[0][0] + is[3]*vp[0][1] + is[4]*vp[0][2];
119 P[4] = is[1]*vp[1][0] + is[3]*vp[1][1] + is[4]*vp[1][2];
120 P[5] = is[1]*vp[2][0] + is[3]*vp[2][1] + is[4]*vp[2][2];
121 P[6] = is[2]*vp[0][0] + is[4]*vp[0][1] + is[5]*vp[0][2];
122 P[7] = is[2]*vp[1][0] + is[4]*vp[1][1] + is[5]*vp[1][2];
123 P[8] = is[2]*vp[2][0] + is[4]*vp[2][1] + is[5]*vp[2][2];
124
125 /* At this point, theory states that ^tPMP = I, {^t}PNP=\Lambda */
126 /* Linear interpolation between sizes */
127 for(i=0; i<3; i++) {
128 if ( lambda[i] < 0.0 ) return 0;
129 dd = s*sqrt(lambda[i]) + (1.0-s);
130 dd = dd*dd;
131 if ( dd < MMG5_EPSD ) return 0;
132 mu[i] = lambda[i]/dd;
133 }
134
135 if ( !MMG5_invmatg(P,mt) ) return 0;
136
137 /* Resulting matrix = ^tP^{-1} diag(mu) P^{-1} */
138 mr[0] = mu[0]*mt[0]*mt[0] + mu[1]*mt[3]*mt[3] + mu[2]*mt[6]*mt[6];
139 mr[1] = mu[0]*mt[0]*mt[1] + mu[1]*mt[3]*mt[4] + mu[2]*mt[6]*mt[7];
140 mr[2] = mu[0]*mt[0]*mt[2] + mu[1]*mt[3]*mt[5] + mu[2]*mt[6]*mt[8];
141 mr[3] = mu[0]*mt[1]*mt[1] + mu[1]*mt[4]*mt[4] + mu[2]*mt[7]*mt[7];
142 mr[4] = mu[0]*mt[1]*mt[2] + mu[1]*mt[4]*mt[5] + mu[2]*mt[7]*mt[8];
143 mr[5] = mu[0]*mt[2]*mt[2] + mu[1]*mt[5]*mt[5] + mu[2]*mt[8]*mt[8];
144
145 return 1;
146}
147
163int MMG5_intridmet(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int ip1, MMG5_int ip2,double s,
164 double v[3],double mr[6]) {
165 MMG5_pxPoint go1,go2;
166 MMG5_pPoint p1,p2;
167 double *m1,*m2,*n11,*n12,*n21,*n22,ps11,ps12,dd;
168 double hu1,hu2,hn1,hn2;
169
170 p1 = &mesh->point[ip1];
171 p2 = &mesh->point[ip2];
172 m1 = &met->m[6*ip1];
173 m2 = &met->m[6*ip2];
174
175 /* Case when both endpoints are singular */
176 if ( (MG_SIN(p1->tag) || (p1->tag & MG_NOM)) &&
177 (MG_SIN(p2->tag) || (p2->tag & MG_NOM)) ) {
178 /* m1 and m2 are isotropic metrics */
179 /* Remark (Algiane): Perspective of improvement can be:
180 - 1. to not force isotropy at singular point
181 - 2. to not force the metric to be along tangent and normal dir at ridge point
182 */
183
184 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[0]);
185 dd *= dd;
186 if ( dd < MMG5_EPSD ) {
187 if ( s < 0.5 ) {
188 mr[0] = m1[0];
189 mr[1] = m1[0];
190 mr[2] = m1[0];
191 mr[3] = m1[0];
192 mr[4] = m1[0];
193 }
194 else {
195 mr[0] = m2[0];
196 mr[1] = m2[0];
197 mr[2] = m2[0];
198 mr[3] = m2[0];
199 mr[4] = m2[0];
200 }
201 }
202 else {
203 mr[0] = m1[0]*m2[0] / dd;
204 mr[1] = mr[0];
205 mr[2] = mr[0];
206 mr[3] = mr[0];
207 mr[4] = mr[0];
208 }
209 }
210 /* vertex p1 is singular, p2 is regular */
211 else if ( (MG_SIN(p1->tag) || (p1->tag & MG_NOM)) &&
212 !(MG_SIN(p2->tag) || (p2->tag & MG_NOM)) ) {
213 /* m1 is an isotropic metric and m2 is a "ridge" metric that respect our
214 * storage convention. */
215 go2 = &mesh->xpoint[p2->xp];
216 n21 = &go2->n1[0];
217 n22 = &go2->n2[0];
218
219 /* Interpolation of the eigenvalue associated to tangent vector */
220 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[0]);
221 dd *= dd;
222 if ( dd < MMG5_EPSD ) {
223 mr[0] = s < 0.5 ? m1[0] : m2[0];
224 }
225 else {
226 mr[0] = m1[0]*m2[0] / dd;
227 }
228
229 /* Interpolation of the two other eigenvalues for each configuration. */
230 /* 1. For the surface ruled by n1. */
231 dd = (1-s)*sqrt(m2[1]) + s*sqrt(m1[0]);
232 dd *= dd;
233 if ( dd < MMG5_EPSD ) {
234 hu1 = s < 0.5 ? m1[0] : m2[1];
235 }
236 else {
237 hu1 = m1[0]*m2[1] / dd;
238 }
239 dd = (1-s)*sqrt(m2[3]) + s*sqrt(m1[0]);
240 dd *= dd;
241 if ( dd < MMG5_EPSD ) {
242 hn1 = s < 0.5 ? m1[0] : m2[3];
243 }
244 else {
245 hn1 = m1[0]*m2[3] / dd;
246 }
247
248 /* 2. For the surface ruled by n2. */
249 dd = (1-s)*sqrt(m2[2]) + s*sqrt(m1[0]);
250 dd *= dd;
251 if ( dd < MMG5_EPSD ) {
252 hu2 = s < 0.5 ? m1[0] : m2[2];
253 }
254 else {
255 hu2 = m1[0]*m2[2] / dd;
256 }
257 dd = (1-s)*sqrt(m2[4]) + s*sqrt(m1[0]);
258 dd *= dd;
259 if ( dd < MMG5_EPSD ) {
260 hn2 = s < 0.5 ? m1[0] : m2[4];
261 }
262 else {
263 hn2 = m1[0]*m2[4] / dd;
264 }
265
266 /* Decision of the ordering of hu1 and hu2 */
267 ps11 = n21[0]*v[0] + n21[1]*v[1] + n21[2]*v[2];
268 ps12 = n22[0]*v[0] + n22[1]*v[1] + n22[2]*v[2];
269 if ( fabs(ps11) > fabs(ps12) ) {
270 mr[1] = hu1;
271 mr[2] = hu2;
272 mr[3] = hn1;
273 mr[4] = hn2;
274 }
275 else {
276 mr[1] = hu2;
277 mr[2] = hu1;
278 mr[3] = hn2;
279 mr[4] = hn1;
280 }
281 }
282 /* vertex p2 is singular, p1 is regular */
283 else if ( ( MG_SIN(p2->tag) || (p2->tag & MG_NOM)) &&
284 !(MG_SIN(p1->tag) || (p1->tag & MG_NOM)) ) {
285 /* m2 is an isotropic metric and m1 is a "ridge" metric that respect our
286 * storage convention. */
287 go1 = &mesh->xpoint[p1->xp];
288 n11 = &go1->n1[0];
289 n12 = &go1->n2[0];
290
291 /* Interpolation of the eigenvalue associated to tangent vector */
292 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[0]);
293 dd *= dd;
294 if ( dd < MMG5_EPSD ) {
295 mr[0] = s < 0.5 ? m1[0] : m2[0];
296 }
297 else {
298 mr[0] = m1[0]*m2[0] / dd;
299 }
300 /* Interpolation of the two other eigenvalues for each configuration. */
301 /* 1. For the surface ruled by n1. */
302 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[1]);
303 dd *= dd;
304 if ( dd < MMG5_EPSD ) {
305 hu1 = s < 0.5 ? m1[1] : m2[0];
306 }
307 else {
308 hu1 = m1[1]*m2[0] / dd;
309 }
310 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[3]);
311 dd *= dd;
312 if ( dd < MMG5_EPSD ) {
313 hn1 = s < 0.5 ? m1[3] : m2[0];
314 }
315 else {
316 hn1 = m1[3]*m2[0] / dd;
317 }
318
319 /* 2. For the surface ruled by n2. */
320 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[2]);
321 dd *= dd;
322 if ( dd < MMG5_EPSD ) {
323 hu2 = s < 0.5 ? m1[2] : m2[0];
324 }
325 else {
326 hu2 = m1[2]*m2[0] / dd;
327 }
328 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[4]);
329 dd *= dd;
330 if ( dd < MMG5_EPSD ) {
331 hn2 = s < 0.5 ? m1[4] : m2[0];
332 }
333 else {
334 hn2 = m1[4]*m2[0] / dd;
335 }
336
337 /* Decision of the ordering of hu1 and hu2 */
338 ps11 = n11[0]*v[0] + n11[1]*v[1] + n11[2]*v[2];
339 ps12 = n12[0]*v[0] + n12[1]*v[1] + n12[2]*v[2];
340 if ( fabs(ps11) > fabs(ps12) ) {
341 mr[1] = hu1;
342 mr[2] = hu2;
343 mr[3] = hn1;
344 mr[4] = hn2;
345 }
346 else {
347 mr[1] = hu2;
348 mr[2] = hu1;
349 mr[3] = hn2;
350 mr[4] = hn1;
351 }
352 }
353 /* p1,p2 : nonsingular vertices */
354 else {
355 go1 = &mesh->xpoint[p1->xp];
356 go2 = &mesh->xpoint[p2->xp];
357
358 /* Interpolation of the eigenvalue associated to tangent vector */
359 dd = (1-s)*sqrt(m2[0]) + s*sqrt(m1[0]);
360 dd *= dd;
361 if ( dd < MMG5_EPSD ) {
362 mr[0] = s < 0.5 ? m1[0] : m2[0];
363 }
364 else {
365 mr[0] = m1[0]*m2[0] / dd;
366 }
367
368 /* Pairing of normal vectors at p1 and p2 */
369 n11 = &go1->n1[0];
370 n12 = &go1->n2[0];
371 n21 = &go2->n1[0];
372 n22 = &go2->n2[0];
373 ps11 = n11[0]*n21[0] + n11[1]*n21[1] + n11[2]*n21[2];
374 ps12 = n11[0]*n22[0] + n11[1]*n22[1] + n11[2]*n22[2];
375 if ( fabs(ps11) > fabs(ps12) ) { //n11 and n21 go together
376 /* 1. For the surface ruled by n1. */
377 dd = (1-s)*sqrt(m2[1]) + s*sqrt(m1[1]);
378 dd *= dd;
379 if ( dd < MMG5_EPSD ) {
380 hu1 = s < 0.5 ? m1[1] : m2[1];
381 }
382 else {
383 hu1 = m1[1]*m2[1] / dd;
384 }
385 dd = (1-s)*sqrt(m2[3]) + s*sqrt(m1[3]);
386 dd *= dd;
387 if ( dd < MMG5_EPSD ) {
388 hn1 = s < 0.5 ? m1[3] : m2[3];
389 }
390 else {
391 hn1 = m1[3]*m2[3] / dd;
392 }
393 /* 2. For the surface ruled by n2. */
394 dd = (1-s)*sqrt(m2[2]) + s*sqrt(m1[2]);
395 dd *= dd;
396 if ( dd < MMG5_EPSD ) {
397 hu2 = s < 0.5 ? m1[2] : m2[2];
398 }
399 else {
400 hu2 = m1[2]*m2[2] / dd;
401 }
402 dd = (1-s)*sqrt(m2[4]) + s*sqrt(m1[4]);
403 dd *= dd;
404 if ( dd < MMG5_EPSD ) {
405 hn2 = s < 0.5 ? m1[4] : m2[4];
406 }
407 else {
408 hn2 = m1[4]*m2[4] / dd;
409 }
410
411 }
412 else {
413 /* 1. */
414 dd = (1-s)*sqrt(m2[2]) + s*sqrt(m1[1]);
415 dd *= dd;
416 if ( dd < MMG5_EPSD ) {
417 hu1 = s < 0.5 ? m1[1] : m2[2];
418 }
419 else {
420 hu1 = m1[1]*m2[2] / dd;
421 }
422 dd = (1-s)*sqrt(m2[4]) + s*sqrt(m1[3]);
423 dd *= dd;
424 if ( dd < MMG5_EPSD ) {
425 hn1 = s < 0.5 ? m1[3] : m2[4];
426 }
427 else {
428 hn1 = m1[3]*m2[4] / dd;
429 }
430
431 /* 2. */
432 dd = (1-s)*sqrt(m2[1]) + s*sqrt(m1[2]);
433 dd *= dd;
434 if ( dd < MMG5_EPSD ) {
435 hu2 = s < 0.5 ? m1[2] : m2[1];
436 }
437 else {
438 hu2 = m1[2]*m2[1] / dd;
439 }
440 dd = (1-s)*sqrt(m2[3]) + s*sqrt(m1[4]);
441 dd *= dd;
442 if ( dd < MMG5_EPSD ) {
443 hn2 = s < 0.5 ? m1[4] : m2[3];
444 }
445 else {
446 hn2 = m1[4]*m2[3] / dd;
447 }
448 }
449
450 /* Now, hu1 is the eigenvalue associated to the direction at interpolated
451 point, closest to n11 (hu2 -> n12) ; one may need a different
452 orientation, and put eigenvalue of direction closest to v (= interpolated
453 normal) first */
454 ps11 = n11[0]*v[0] + n11[1]*v[1] + n11[2]*v[2];
455 ps12 = n12[0]*v[0] + n12[1]*v[1] + n12[2]*v[2];
456 if ( fabs(ps11) > fabs(ps12) ) {
457 mr[1] = hu1;
458 mr[2] = hu2;
459 mr[3] = hn1;
460 mr[4] = hn2;
461 }
462 else {
463 mr[1] = hu2;
464 mr[2] = hu1;
465 mr[3] = hn2;
466 mr[4] = hn1;
467 }
468 }
469 mr[5] = 0.0;
470
471 return 1;
472}
473
484int MMG5_interp_iso(double *ma,double *mb,double *mp,double t) {
485
486 *mp = (1.0-t)*(*ma) + t*(*mb);
487
488 return 1;
489
490}
491
505 double s,double mr[6]) {
506 MMG5_pPoint p1,p2;
507 MMG5_Bezier b;
508 double b1[3],b2[3],bn[3],c[3],nt[3],cold[3],nold[3],n[3];
509 double m1old[6],m2old[6],m1[6],m2[6],rbasis[3][3];
510 double *n1,*n2,step,u,r[3][3],dd,ddbn;
511 int nstep,l;
512 MMG5_int ip1,ip2;
513 int8_t i1,i2;
514 static int warn=0,warnnorm=0;
515
516 /* Number of steps for parallel transport */
517 nstep = 4;
518 i1 = MMG5_inxt2[i];
519 i2 = MMG5_iprv2[i];
520 ip1 = pt->v[i1];
521 ip2 = pt->v[i2];
522 p1 = &mesh->point[ip1];
523 p2 = &mesh->point[ip2];
524
525 if ( !MMG5_bezierCP(mesh,pt,&b,1) ) return 0;
526
527 n1 = &b.n[i1][0];
528 n2 = &b.n[i2][0];
529 memcpy(bn,&b.n[i+3][0],3*sizeof(double));
530 memcpy(b1,&b.b[2*i+3][0],3*sizeof(double));
531 memcpy(b2,&b.b[2*i+4][0],3*sizeof(double));
532
533 ddbn = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2];
534
535 /* Parallel transport of metric at p1 to point p(s) */
536 step = s / nstep;
537 cold[0] = p1->c[0];
538 cold[1] = p1->c[1];
539 cold[2] = p1->c[2];
540
541 nold[0] = n1[0];
542 nold[1] = n1[1];
543 nold[2] = n1[2];
544
545 if ( MG_SIN(p1->tag) || (p1->tag & MG_NOM) || (ddbn < MMG5_EPSD) ) {
546 memcpy(m1,&met->m[6*ip1],6*sizeof(double));
547 }
548 else {
549 if ( MG_GEO & p1->tag ) {
550 MMG5_nortri(mesh,pt,nt);
551 if ( !MMG5_buildridmetnor(mesh,met,pt->v[i1],nt,m1,rbasis) ) return 0;
552 }
553 else {
554 memcpy(m1,&met->m[6*ip1],6*sizeof(double));
555 }
556 memcpy(m1old,m1,6*sizeof(double));
557
558 /* Go from point (l-1)step, to point l step */
559 for (l=1; l<=nstep; l++) {
560 u = l*step;
561 c[0] = p1->c[0]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[0]\
562 + 3.0*u*u*(1.0-u)*b2[0] + u*u*u*p2->c[0];
563 c[1] = p1->c[1]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[1]\
564 + 3.0*u*u*(1.0-u)*b2[1] + u*u*u*p2->c[1];
565 c[2] = p1->c[2]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[2]\
566 + 3.0*u*u*(1.0-u)*b2[2] + u*u*u*p2->c[2];
567
568 n[0] = (1.0-u)*(1.0-u)*n1[0] + 2.0*u*(1.0-u)*bn[0] + u*u*n2[0];
569 n[1] = (1.0-u)*(1.0-u)*n1[1] + 2.0*u*(1.0-u)*bn[1] + u*u*n2[1];
570 n[2] = (1.0-u)*(1.0-u)*n1[2] + 2.0*u*(1.0-u)*bn[2] + u*u*n2[2];
571 dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
572 if ( dd < MMG5_EPSD ) return 0;
573 dd = 1.0 / sqrt(dd);
574 n[0] *= dd;
575 n[1] *= dd;
576 n[2] *= dd;
577
578 if ( !MMG5_paratmet(cold,nold,m1old,c,n,m1) ) return 0;
579
580 memcpy(cold,c,3*sizeof(double));
581 memcpy(nold,n,3*sizeof(double));
582 memcpy(m1old,m1,6*sizeof(double));
583 }
584 }
585
586 /* Parallel transport of metric at p2 to point p(s) */
587 step = (1.0-s) / nstep;
588 cold[0] = p2->c[0];
589 cold[1] = p2->c[1];
590 cold[2] = p2->c[2];
591
592 nold[0] = n2[0];
593 nold[1] = n2[1];
594 nold[2] = n2[2];
595
596 if ( MG_SIN(p2->tag) || (p2->tag & MG_NOM) || (ddbn < MMG5_EPSD) ) {
597 memcpy(m2,&met->m[6*ip2],6*sizeof(double));
598
599 /* In this pathological case, n is empty */
600 if ( MG_SIN(p1->tag) || (p1->tag & MG_NOM) ) {
601 memcpy(n,n2,3*sizeof(double));
602 assert( MMG5_EPSD < (n2[0]*n2[0]+n2[1]*n2[1]+n2[2]*n2[2]) && "normal at p2 is 0" );
603 }
604 else if (ddbn < MMG5_EPSD) {
605 /* Other case where n is empty: bezier normal is 0 */
606 if ( !warnnorm ) {
607 fprintf(stderr," ## Warning: %s: %d: unexpected case (null normal),"
608 " impossible interpolation.\n",__func__,__LINE__);
609 warnnorm = 1;
610 }
611 return 0;
612 }
613 }
614 else {
615 if ( p2->tag & MG_GEO ) {
616 MMG5_nortri(mesh,pt,nt);
617 if ( !MMG5_buildridmetnor(mesh,met,pt->v[i2],nt,m2,rbasis)) return 0;
618 }
619 else {
620 memcpy(m2,&met->m[6*ip2],6*sizeof(double));
621 }
622 memcpy(m2old,m2,6*sizeof(double));
623
624 /* Go from point (l-1)step, to point l step */
625 for (l=1; l<=nstep; l++) {
626 u = 1.0 - l*step;
627 c[0] = p1->c[0]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[0]\
628 + 3.0*u*u*(1.0-u)*b2[0] + u*u*u*p2->c[0];
629 c[1] = p1->c[1]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[1]\
630 + 3.0*u*u*(1.0-u)*b2[1] + u*u*u*p2->c[1];
631 c[2] = p1->c[2]*(1.0-u)*(1.0-u)*(1.0-u) + 3.0*(1.0-u)*(1.0-u)*u*b1[2]\
632 + 3.0*u*u*(1.0-u)*b2[2] + u*u*u*p2->c[2];
633
634 n[0] = (1.0-u)*(1.0-u)*n1[0] + 2.0*u*(1.0-u)*bn[0] + u*u*n2[0];
635 n[1] = (1.0-u)*(1.0-u)*n1[1] + 2.0*u*(1.0-u)*bn[1] + u*u*n2[1];
636 n[2] = (1.0-u)*(1.0-u)*n1[2] + 2.0*u*(1.0-u)*bn[2] + u*u*n2[2];
637 dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
638 if ( dd < MMG5_EPSD ) return 0;
639 dd = 1.0 / sqrt(dd);
640 n[0] *= dd;
641 n[1] *= dd;
642 n[2] *= dd;
643
644 if ( !MMG5_paratmet(cold,nold,m2old,c,n,m2) ) return 0;
645
646 memcpy(cold,c,3*sizeof(double));
647 memcpy(nold,n,3*sizeof(double));
648 memcpy(m2old,m2,6*sizeof(double));
649 }
650 }
651 /* At this point, c is point p(s), n is the normal at p(s), m1 and m2 are the 3*3
652 transported metric tensors from p1 and p2 to p(s) */
653
654 /* Rotate both matrices to the tangent plane */
655 if ( !MMG5_rotmatrix(n,r) ) return 0;
656 MMG5_rmtr(r,m1,m1old);
657 MMG5_rmtr(r,m2,m2old);
658
659 /* Interpolate both metrics expressed in the same tangent plane. */
660 if ( !MMG5_mmgIntmet33_ani(m1old,m2old,mr,s) ) {
661 if ( !warn ) {
662 ++warn;
663 fprintf(stderr,"\n ## Warning: %s: at least 1 impossible metric"
664 " interpolation.\n", __func__);
665
666 if ( mesh->info.ddebug ) {
667 fprintf(stderr," points: %"MMG5_PRId": %e %e %e (tag %s)\n",MMG5_indPt(mesh,ip1),
668 mesh->point[ip1].c[0],mesh->point[ip1].c[1],mesh->point[ip1].c[2],
670 fprintf(stderr," %"MMG5_PRId": %e %e %e (tag %s)\n",MMG5_indPt(mesh,ip2),
671 mesh->point[ip1].c[0],mesh->point[ip1].c[1],mesh->point[ip1].c[2],
673
674 fprintf(stderr,"\n BEFORE ROTATION:\n");
675 fprintf(stderr,"\n metric %e %e %e %e %e %e\n",
676 m1old[0],m1old[1],m1old[2],m1old[3],m1old[4],m1old[5]);
677 fprintf(stderr," %e %e %e %e %e %e\n",
678 m2old[0],m2old[1],m2old[2],m2old[3],m2old[4],m2old[5]);
679
680 fprintf(stderr,"\n AFTER ROTATION (to %e %e %e):\n",n[0],n[1],n[2]);
681 fprintf(stderr,"\n metric %e %e %e %e %e %e\n",
682 m1[0],m1[1],m1[2],m1[3],m1[4],m1[5]);
683 fprintf(stderr," %e %e %e %e %e %e\n",
684 m2[0],m2[1],m2[2],m2[3],m2[4],m2[5]);
685 }
686 }
687 return 0;
688 }
689
690 /* End rotating back tangent metric into canonical basis of R^3 : mr =
691 {^t}R*mr*R m1old serve for nothing, let it be the temporary resulting
692 matrix. */
693 m1old[0] = mr[0]*r[0][0]*r[0][0] + mr[3]*r[1][0]*r[1][0] + mr[5]*r[2][0]*r[2][0]
694 + 2.*( mr[1]*r[0][0]*r[1][0] + mr[2]*r[0][0]*r[2][0] + mr[4]*r[1][0]*r[2][0] );
695 m1old[3] = mr[0]*r[0][1]*r[0][1] + mr[3]*r[1][1]*r[1][1] + mr[5]*r[2][1]*r[2][1]
696 + 2.*( mr[1]*r[0][1]*r[1][1] + mr[2]*r[0][1]*r[2][1] + mr[4]*r[1][1]*r[2][1] );
697 m1old[5] = mr[0]*r[0][2]*r[0][2] + mr[3]*r[1][2]*r[1][2] + mr[5]*r[2][2]*r[2][2]
698 + 2.*( mr[1]*r[0][2]*r[1][2] + mr[2]*r[0][2]*r[2][2] + mr[4]*r[1][2]*r[2][2] );
699
700 m1old[1] = mr[0]*r[0][0]*r[0][1] + mr[1]*r[0][0]*r[1][1] + mr[2]*r[0][0]*r[2][1]
701 + mr[1]*r[1][0]*r[0][1] + mr[3]*r[1][0]*r[1][1] + mr[4]*r[1][0]*r[2][1]
702 + mr[2]*r[2][0]*r[0][1] + mr[4]*r[2][0]*r[1][1] + mr[5]*r[2][0]*r[2][1];
703 m1old[2] = mr[0]*r[0][0]*r[0][2] + mr[1]*r[0][0]*r[1][2] + mr[2]*r[0][0]*r[2][2]
704 + mr[1]*r[1][0]*r[0][2] + mr[3]*r[1][0]*r[1][2] + mr[4]*r[1][0]*r[2][2]
705 + mr[2]*r[2][0]*r[0][2] + mr[4]*r[2][0]*r[1][2] + mr[5]*r[2][0]*r[2][2];
706 m1old[4] = mr[0]*r[0][1]*r[0][2] + mr[1]*r[0][1]*r[1][2] + mr[2]*r[0][1]*r[2][2]
707 + mr[1]*r[1][1]*r[0][2] + mr[3]*r[1][1]*r[1][2] + mr[4]*r[1][1]*r[2][2]
708 + mr[2]*r[2][1]*r[0][2] + mr[4]*r[2][1]*r[1][2] + mr[5]*r[2][1]*r[2][2];
709
710 memcpy(mr,m1old,6*sizeof(double));
711
712 return 1;
713
714}
const char * MMG5_Get_tagName(int tag)
MMG5_pMesh * mesh
int MMG5_eigenv3d(int symmat, double *mat, double lambda[3], double v[3][3])
Find eigenvalues and vectors of a 3x3 matrix.
Definition: eigenv.c:385
#define MMG5_EPSD
int MMG5_interp_iso(double *ma, double *mb, double *mp, double t)
Definition: intmet.c:484
int MMG5_mmgIntmet33_ani(double *m, double *n, double *mr, double s)
Definition: intmet.c:50
int MMG5_interpreg_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria pt, int8_t i, double s, double mr[6])
Definition: intmet.c:504
int MMG5_intridmet(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip1, MMG5_int ip2, double s, double v[3], double mr[6])
Definition: intmet.c:163
int MMG5_buildridmetnor(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int np0, double nt[3], double mr[6], double r[3][3])
Definition: mettools.c:751
int MMG5_paratmet(double c0[3], double n0[3], double m[6], double c1[3], double n1[3], double mt[6])
Definition: mettools.c:1390
#define MG_GEO
static const uint8_t MMG5_iprv2[3]
#define MG_SIN(tag)
int MMG5_rmtr(double r[3][3], double m[6], double mr[6])
Definition: tools.c:405
static const uint8_t MMG5_inxt2[6]
int MMG5_nortri(MMG5_pMesh mesh, MMG5_pTria pt, double *n)
Definition: tools.c:209
int MMG5_rotmatrix(double n[3], double r[3][3])
Definition: tools.c:467
int MMG5_invmatg(double m[9], double mi[9])
Definition: tools.c:613
#define MG_NOM
double b[10][3]
double n[6][3]
int8_t ddebug
Definition: libmmgtypes.h:532
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
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
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
MMG5_int xp
Definition: libmmgtypes.h:279
double * m
Definition: libmmgtypes.h:671
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