28 SVector3 &vec, std::vector<SVector3> &grad)
31 const double n = vec.
normalize(), invN = 1 / n;
32 grad[0] = invN * vec[0] * vec;
34 grad[1] = invN * vec[1] * vec;
36 grad[2] = invN * vec[2] * vec;
44 NCJAndGrad2D(
const SVector3 &v01,
const std::vector<SVector3> &dv01dp0,
45 const std::vector<SVector3> &dv01dp1,
const SVector3 &v02,
46 const std::vector<SVector3> &dv02dp0,
47 const std::vector<SVector3> &dv02dp2,
const SVector3 &normal,
48 double &NCJ, std::vector<double> &dNCJ)
73 NCJ =
dot(vn, normal);
74 dNCJ[0] =
dot(dvndx0, normal);
75 dNCJ[1] =
dot(dvndy0, normal);
76 dNCJ[2] =
dot(dvndz0, normal);
77 dNCJ[3] =
dot(dvndx1, normal);
78 dNCJ[4] =
dot(dvndy1, normal);
79 dNCJ[5] =
dot(dvndz1, normal);
80 dNCJ[6] =
dot(dvndx2, normal);
81 dNCJ[7] =
dot(dvndy2, normal);
82 dNCJ[8] =
dot(dvndz2, normal);
96 template <
int iV,
int nV,
int i0,
int i1,
int i2>
97 inline void scatterNCJGrad(
const std::vector<double> &dNCJi,
98 std::vector<double> &dNCJ)
100 dNCJ[(iV * nV + i0) * 3] = dNCJi[0];
101 dNCJ[(iV * nV + i0) * 3 + 1] = dNCJi[1];
102 dNCJ[(iV * nV + i0) * 3 + 2] = dNCJi[2];
103 dNCJ[(iV * nV + i1) * 3] = dNCJi[3];
104 dNCJ[(iV * nV + i1) * 3 + 1] = dNCJi[4];
105 dNCJ[(iV * nV + i1) * 3 + 2] = dNCJi[5];
106 dNCJ[(iV * nV + i2) * 3] = dNCJi[6];
107 dNCJ[(iV * nV + i2) * 3 + 1] = dNCJi[7];
108 dNCJ[(iV * nV + i2) * 3 + 2] = dNCJi[8];
113 template <
int iV,
int nV,
int i0,
int i1,
int i2,
int i3>
114 inline void scatterNCJGrad(
const std::vector<double> &dNCJi,
115 std::vector<double> &dNCJ)
117 dNCJ[iV * nV + i0 * 3] = dNCJi[0];
118 dNCJ[iV * nV + i0 * 3 + 1] = dNCJi[1];
119 dNCJ[iV * nV + i0 * 3 + 2] = dNCJi[2];
120 dNCJ[iV * nV + i1 * 3] = dNCJi[3];
121 dNCJ[iV * nV + i1 * 3 + 1] = dNCJi[4];
122 dNCJ[iV * nV + i1 * 3 + 2] = dNCJi[5];
123 dNCJ[iV * nV + i2 * 3] = dNCJi[6];
124 dNCJ[iV * nV + i2 * 3 + 1] = dNCJi[7];
125 dNCJ[iV * nV + i2 * 3 + 2] = dNCJi[8];
126 dNCJ[iV * nV + i2 * 3] = dNCJi[9];
127 dNCJ[iV * nV + i2 * 3 + 1] = dNCJi[10];
128 dNCJ[iV * nV + i2 * 3 + 2] = dNCJi[11];
136 return gamma(p1->
X, p1->
Y, p1->
Z, p2->
X, p2->
Y, p2->
Z, p3->
X, p3->
Y, p3->
Z);
143 return gamma(n[0], n[1], n[2]);
154 return gamma(v1->
x(), v1->
y(), v1->
z(), v2->
x(), v2->
y(), v2->
z(), v3->
x(),
161 const double &xb,
const double &yb,
const double &zb,
162 const double &xc,
const double &yc,
const double &zc)
165 double a[3] = {xc - xb, yc - yb, zc - zb};
166 double b[3] = {xa - xc, ya - yc, za - zc};
167 double c[3] = {xb - xa, yb - ya, zb - za};
173 const double sina =
norm3(pva);
176 const double sinb =
norm3(pvb);
179 const double sinc =
norm3(pvc);
181 if(sina == 0.0 && sinb == 0.0 && sinc == 0.0)
184 return 2 * (2 * sina * sinb * sinc / (sina + sinb + sinc));
195 double amin = std::min(std::min(
a1,
a2), a3);
196 double angle = std::abs(60. - amin);
197 return 1. -
angle / 60;
203 double worst_quality = std::numeric_limits<double>::max();
206 double den = atan(a * (M_PI / 9)) + atan(a * (M_PI / 9));
224 const double u = i == 1 ? 1 : 0;
225 const double v = i == 2 ? 1 : 0;
229 for(std::size_t j = 0; j < i; j++) {
231 memcpy(mat, tmp,
sizeof(mat));
234 double v1[3] = {mat[0][0], mat[0][1], mat[0][2]};
235 double v2[3] = {mat[1][0], mat[1][1], mat[1][2]};
236 double v3[3] = {mat2[0][0], mat2[0][1], mat2[0][2]};
237 double v4[3] = {mat2[1][0], mat2[1][1], mat2[1][2]};
242 double v12[3], v34[3];
247 double const orientation =
prosca(v12, v34);
250 if(orientation < 0)
return -std::numeric_limits<double>::max();
252 double const c =
prosca(v1, v2);
253 double x = std::acos(
c) - M_PI / 3;
256 (std::atan(a * (x + M_PI / 9)) + std::atan(a * (M_PI / 9 - x))) / den;
257 worst_quality = std::min(worst_quality, quality);
266 return worst_quality;
275 primNodesXYZ(i, 0) = v->
x();
276 primNodesXYZ(i, 1) = v->
y();
277 primNodesXYZ(i, 2) = v->
z();
281 SVector3 normal(nM(0, 0), nM(0, 1), nM(0, 2));
283 std::vector<double> ncj(3);
286 valMin = *std::min_element(ncj.begin(), ncj.end());
287 valMax = *std::max_element(ncj.begin(), ncj.end());
291 const SVector3 &normal, std::vector<double> &NCJ)
294 SVector3 v01n(p0, p1), v12n(p1, p2), v20n(p2, p0);
312 std::vector<double> &NCJ,
313 std::vector<double> &dNCJ)
316 static const double fact = 2. / sqrt(3.);
320 std::vector<SVector3> dv01ndp0(3), dv01ndp1(3);
321 unitVecAndGrad(p0, p1, v01n, dv01ndp0);
323 for(
int i = 0; i < 3; i++) dv01ndp1[i] = -dv01ndp0[i];
324 const std::vector<SVector3> &dv10ndp1 = dv01ndp0, &dv10ndp0 = dv01ndp1;
328 std::vector<SVector3> dv12ndp1(3), dv12ndp2(3);
329 unitVecAndGrad(p1, p2, v12n, dv12ndp1);
331 for(
int i = 0; i < 3; i++) dv12ndp2[i] = -dv12ndp1[i];
332 const std::vector<SVector3> &dv21ndp2 = dv12ndp1, &dv21ndp1 = dv12ndp2;
336 std::vector<SVector3> dv20ndp2(3), dv20ndp0(3);
337 unitVecAndGrad(p2, p0, v20n, dv20ndp2);
339 for(
int i = 0; i < 3; i++) dv20ndp0[i] = -dv20ndp2[i];
340 const std::vector<SVector3> &dv02ndp0 = dv20ndp2, &dv02ndp2 = dv20ndp0;
344 std::vector<double> dNCJ0(9);
345 NCJAndGrad2D(v01n, dv01ndp0, dv01ndp1, v02n, dv02ndp0, dv02ndp2, normal,
350 scatterNCJGrad<0, 3, 0, 1, 2>(dNCJ0, dNCJ);
354 std::vector<double> dNCJ1(9);
355 NCJAndGrad2D(v12n, dv12ndp1, dv12ndp2, v10n, dv10ndp1, dv10ndp0, normal,
360 scatterNCJGrad<1, 3, 1, 2, 0>(dNCJ1, dNCJ);
365 std::vector<double> dNCJ2(9);
366 NCJAndGrad2D(v20n, dv20ndp2, dv20ndp0, v21n, dv21ndp2, dv21ndp1, normal,
371 scatterNCJGrad<2, 3, 2, 0, 1>(dNCJ2, dNCJ);
373 for(
int i = 0; i < 3; i++)
NCJ[i] *= fact;
374 for(
int i = 0; i < 27; i++) dNCJ[i] *= fact;
399 SVector3 v01(_v[1]->x() - _v[0]->x(), _v[1]->y() - _v[0]->y(),
400 _v[1]->
z() - _v[0]->
z());
401 SVector3 v12(_v[2]->x() - _v[1]->x(), _v[2]->y() - _v[1]->y(),
402 _v[2]->
z() - _v[1]->
z());
403 SVector3 v23(_v[3]->x() - _v[2]->x(), _v[3]->y() - _v[2]->y(),
404 _v[3]->
z() - _v[2]->
z());
405 SVector3 v30(_v[0]->x() - _v[3]->x(), _v[0]->y() - _v[3]->y(),
406 _v[0]->
z() - _v[3]->
z());
414 if(
dot(a, b) < 0 ||
dot(a,
c) < 0 ||
dot(a, d) < 0) sign = -1;
423 a1 = std::min(180.,
a1);
424 a2 = std::min(180.,
a2);
425 a3 = std::min(180., a3);
426 a4 = std::min(180.,
a4);
432 return sign * (1. -
angle / 90) * AR;
438 double worst_quality = std::numeric_limits<double>::max();
441 double den = atan(a * (M_PI / 4)) + atan(a * (2 * M_PI / 4 - (M_PI / 4)));
451 const double u[9] = {-1, -1, 1, 1, 0, 0, 1, -1, 0};
452 const double v[9] = {-1, 1, 1, -1, -1, 1, 0, 0, 0};
454 for(
int i = 0; i < 9; i++) {
463 double v1[3] = {mat[0][0], mat[0][1], mat[0][2]};
464 double v2[3] = {mat[1][0], mat[1][1], mat[1][2]};
465 double v3[3] = {mat2[0][0], mat2[0][1], mat2[0][2]};
466 double v4[3] = {mat2[1][0], mat2[1][1], mat2[1][2]};
471 double v12[3], v34[3];
482 double const c =
prosca(v1, v2);
483 double const x = std::abs(std::acos(
c)) - M_PI / 2;
485 double const quality = (std::atan(a * (x + M_PI / 4)) +
486 std::atan(a * (2 * M_PI / 4 - (x + M_PI / 4)))) /
488 worst_quality = std::min(worst_quality, quality);
490 return worst_quality;
500 primNodesXYZ(i, 0) = v->
x();
501 primNodesXYZ(i, 1) = v->
y();
502 primNodesXYZ(i, 2) = v->
z();
506 SVector3 normal(nM(0, 0), nM(0, 1), nM(0, 2));
508 std::vector<double> ncj(4);
511 valMin = *std::min_element(ncj.begin(), ncj.end());
512 valMax = *std::max_element(ncj.begin(), ncj.end());
517 std::vector<double> &ncj)
520 SVector3 v01n(p0, p1), v12n(p1, p2), v23n(p2, p3), v30n(p3, p0);
537 std::vector<double> &NCJ,
538 std::vector<double> &dNCJ)
542 std::vector<SVector3> dv01ndp0(3), dv01ndp1(3);
543 unitVecAndGrad(p0, p1, v01n, dv01ndp0);
545 for(
int i = 0; i < 3; i++) dv01ndp1[i] = -dv01ndp0[i];
546 const std::vector<SVector3> &dv10ndp1 = dv01ndp0, &dv10ndp0 = dv01ndp1;
550 std::vector<SVector3> dv12ndp1(3), dv12ndp2(3);
551 unitVecAndGrad(p1, p2, v12n, dv12ndp1);
553 for(
int i = 0; i < 3; i++) dv12ndp2[i] = -dv12ndp1[i];
554 const std::vector<SVector3> &dv21ndp2 = dv12ndp1, &dv21ndp1 = dv12ndp2;
558 std::vector<SVector3> dv23ndp2(3), dv23ndp3(3);
559 unitVecAndGrad(p2, p3, v23n, dv23ndp2);
561 for(
int i = 0; i < 3; i++) dv23ndp3[i] = -dv23ndp2[i];
562 const std::vector<SVector3> &dv32ndp3 = dv23ndp2, &dv32ndp2 = dv23ndp3;
566 std::vector<SVector3> dv30ndp3(3), dv30ndp0(3);
567 unitVecAndGrad(p3, p0, v30n, dv30ndp3);
569 for(
int i = 0; i < 3; i++) dv30ndp0[i] = -dv30ndp3[i];
570 const std::vector<SVector3> &dv03ndp0 = dv30ndp3, &dv03ndp3 = dv30ndp0;
574 std::vector<double> dNCJ0(9);
575 NCJAndGrad2D(v01n, dv01ndp0, dv01ndp1, v03n, dv03ndp0, dv03ndp3, normal,
577 scatterNCJGrad<0, 4, 0, 1, 3>(dNCJ0, dNCJ);
581 std::vector<double> dNCJ1(9);
582 NCJAndGrad2D(v12n, dv12ndp1, dv12ndp2, v10n, dv10ndp1, dv10ndp0, normal,
584 scatterNCJGrad<1, 4, 1, 2, 0>(dNCJ1, dNCJ);
588 std::vector<double> dNCJ2(9);
589 NCJAndGrad2D(v23n, dv23ndp2, dv23ndp3, v21n, dv21ndp2, dv21ndp1, normal,
591 scatterNCJGrad<2, 4, 2, 3, 1>(dNCJ2, dNCJ);
595 std::vector<double> dNCJ3(9);
596 NCJAndGrad2D(v30n, dv30ndp3, dv30ndp0, v32n, dv32ndp3, dv32ndp2, normal,
598 scatterNCJGrad<3, 4, 3, 0, 2>(dNCJ3, dNCJ);
626 return qm(v1->
x(), v1->
y(), v1->
z(), v2->
x(), v2->
y(), v2->
z(), v3->
x(),
627 v3->
y(), v3->
z(), v4->
x(), v4->
y(), v4->
z(), cr, volume);
631 const double &x2,
const double &y2,
const double &z2,
632 const double &x3,
const double &y3,
const double &z3,
633 const double &x4,
const double &y4,
const double &z4,
639 return eta(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, volume);
641 double G =
gamma(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, volume);
642 *volume = fabs(*volume);
646 return cond(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, volume);
647 default:
Msg::Error(
"Unknown quality measure");
return 0.;
652 const double &x2,
const double &y2,
const double &z2,
653 const double &x3,
const double &y3,
const double &z3,
654 const double &x4,
const double &y4,
const double &z4,
657 double p0[3] = {x1, y1, z1};
658 double p1[3] = {x2, y2, z2};
659 double p2[3] = {x3, y3, z3};
660 double p3[3] = {x4, y4, z4};
665 ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
666 l += ((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1) + (z3 - z1) * (z3 - z1));
667 l += ((x4 - x1) * (x4 - x1) + (y4 - y1) * (y4 - y1) + (z4 - z1) * (z4 - z1));
668 l += ((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) + (z3 - z2) * (z3 - z2));
669 l += ((x4 - x2) * (x4 - x2) + (y4 - y2) * (y4 - y2) + (z4 - z2) * (z4 - z2));
670 l += ((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4) + (z3 - z4) * (z3 - z4));
671 return 12. * pow(3 * fabs(*volume), 2. / 3.) / l;
675 const double &z1,
const double &x2,
676 const double &y2,
const double &z2,
677 const double &x3,
const double &y3,
678 const double &z3,
const double &x4,
679 const double &y4,
const double &z4,
double *volume)
683 double p0[3] = {x1, y1, z1};
684 double p1[3] = {x2, y2, z2};
685 double p2[3] = {x3, y3, z3};
686 double p3[3] = {x4, y4, z4};
690 if(fabs(*volume) == 0)
return 0;
693 (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1);
695 (x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1) + (z3 - z1) * (z3 - z1);
697 (x4 - x1) * (x4 - x1) + (y4 - y1) * (y4 - y1) + (z4 - z1) * (z4 - z1);
699 (x4 - x3) * (x4 - x3) + (y4 - y3) * (y4 - y3) + (z4 - z3) * (z4 - z3);
701 (x4 - x2) * (x4 - x2) + (y4 - y2) * (y4 - y2) + (z4 - z2) * (z4 - z2);
703 (x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) + (z3 - z2) * (z3 - z2);
705 double lalA = std::sqrt(la * lA);
706 double lblB = std::sqrt(lb * lB);
707 double lclC = std::sqrt(lc * lC);
709 double insideSqrt = (lalA + lblB + lclC) * (lalA + lblB - lclC) *
710 (lalA - lblB + lclC) * (-lalA + lblB + lclC);
714 if(insideSqrt <= 0)
return 0;
716 double R = std::sqrt(insideSqrt) / 24 / *volume;
722 double rho = 3 * 3 * *volume / (s1 + s2 + s3 + s4);
728 const double &x2,
const double &y2,
const double &z2,
729 const double &x3,
const double &y3,
const double &z3,
730 const double &x4,
const double &y4,
const double &z4,
734 double INVW[3][3] = {{1, -1. / sqrt(3.), -1. / sqrt(6.)},
735 {0, 2 / sqrt(3.), -1. / sqrt(6.)},
737 double A[3][3] = {{x2 - x1, y2 - y1, z2 - z1},
738 {x3 - x1, y3 - y1, z3 - z1},
739 {x4 - x1, y4 - y1, z4 - z1}};
740 double S[3][3], INVS[3][3];
742 *volume =
inv3x3(
S, INVS) * 0.70710678118654762;
744 double normINVS =
norm2(INVS);
745 return normS * normINVS;
752 static const double fact = 2. / sqrt(3.);
761 const double l1 = vec1.
norm();
762 const double l2 =
vec2.norm();
763 const double l3 =
vec3.norm();
766 return fact * fabs(val) / (l1 * l2 * l3);
778 const double result = *std::min_element(j, j + 6);
807 double angleMax = 0.0;
808 double angleMin = M_PI;
811 std::vector<MVertex *> vv;
820 for(
int j = 0; j < 4; j++) {
821 SVector3 a(vv[(j + 2) % 4]->x() - vv[(j + 1) % 4]->x(),
822 vv[(j + 2) % 4]->y() - vv[(j + 1) % 4]->y(),
823 vv[(j + 2) % 4]->
z() - vv[(j + 1) % 4]->
z());
824 SVector3 b(vv[(j + 1) % 4]->x() - vv[(j) % 4]->x(),
825 vv[(j + 1) % 4]->y() - vv[(j) % 4]->y(),
826 vv[(j + 1) % 4]->
z() - vv[(j) % 4]->
z());
828 angleMax = std::max(angleMax,
angle);
829 angleMin = std::min(angleMin,
angle);
833 zeta = 1. - std::max((angleMax - 0.5 * M_PI) / (0.5 * M_PI),
834 (0.5 * M_PI - angleMin) / (0.5 * M_PI));