11 #define tolerance 0.1e-20
17 inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] +
18 m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
19 inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] -
20 m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
21 inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] +
22 m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
23 inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] -
24 m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
25 inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] -
26 m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
27 inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] +
28 m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
29 inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] -
30 m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
31 inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] +
32 m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
33 inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] +
34 m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
35 inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] -
36 m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
37 inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] +
38 m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
39 inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] -
40 m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
41 inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] -
42 m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
43 inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] +
44 m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
45 inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] -
46 m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
47 inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] +
48 m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
50 *det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
52 if(*det == 0)
return false;
54 double invDet = 1.0 / *det;
56 for(i = 0; i < 16; i++) inv[i] *= invDet;
61 static void solveEig(
double A,
double B,
double C,
double D,
double *lambda1,
62 double *v1x,
double *v1y,
double *lambda2,
double *v2x,
76 double det = A *
D - B * C;
77 double S = sqrt((tr * tr / 4) - det);
78 *lambda1 = tr / 2 +
S;
79 *lambda2 = tr / 2 -
S;
81 double temp = ((A -
D) * (A -
D) / 4) + B * C;
83 double SS = sqrt(temp > 0 ? temp : 0.0);
86 *v1y = -(A -
D) / 2 + SS;
87 *v2x = +(A -
D) / 2 - SS;
92 *v2y = -(A -
D) / 2 - SS;
93 *v1x = +(A -
D) / 2 + SS;
97 double n1 = sqrt((*v1x) * (*v1x) + (*v1y) * (*v1y));
100 double n2 = sqrt((*v2x) * (*v2x) + (*v2y) * (*v2y));
107 const std::size_t *e0 = (
const std::size_t *)p0;
108 const std::size_t *e1 = (
const std::size_t *)p1;
110 if(e0[0] < e1[0])
return -1;
111 if(e0[0] > e1[0])
return 1;
117 double d = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
126 static inline void makevector(
const double *a,
const double *b,
double *ba)
133 static inline double dotprod(
double *a,
double *b)
135 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
138 static inline void crossprod(
double *a,
double *b,
double *n)
140 n[0] = a[1] * b[2] - a[2] * b[1];
141 n[1] = -(a[0] * b[2] - a[2] * b[0]);
142 n[2] = a[0] * b[1] - a[1] * b[0];
146 const double *x3,
double *n,
double *s)
148 double a[3] = {x2[0] - x1[0], x2[1] - x1[1], x2[2] - x1[2]};
149 double b[3] = {x3[0] - x1[0], x3[1] - x1[1], x3[2] - x1[2]};
157 if(fabs(n[0]) > fabs(n[1]) && fabs(n[0]) > fabs(n[2])) {
173 const std::vector<int> &triangles,
const std::vector<SPoint3> &nodes,
174 std::vector<std::pair<SVector3, SVector3> > &nodalCurvatures)
176 std::size_t nTriangles = triangles.size() / 3;
177 std::size_t nVertices = nodes.size();
179 nodalCurvatures.resize(nVertices);
185 std::vector<std::size_t> node2tri(3 * 2 * nTriangles);
189 std::vector<double> nodeNormals(3 * nVertices, 0.);
190 std::size_t counter = 0;
193 for(std::size_t i = 0; i < nTriangles; i++) {
194 node2tri[counter++] = triangles[3 * i + 0];
195 node2tri[counter++] = i;
196 node2tri[counter++] = triangles[3 * i + 1];
197 node2tri[counter++] = i;
198 node2tri[counter++] = triangles[3 * i + 2];
199 node2tri[counter++] = i;
201 nodes[triangles[3 * i + 1]].data(),
202 nodes[triangles[3 * i + 2]].data(), n, &surf);
203 double *n0 = &nodeNormals[3 * triangles[3 * i + 0]];
204 double *n1 = &nodeNormals[3 * triangles[3 * i + 1]];
205 double *n2 = &nodeNormals[3 * triangles[3 * i + 2]];
206 for(std::size_t i1 = 0; i1 < 3; i1++) {
212 for(std::size_t i = 0; i < nVertices; i++)
normalize(&nodeNormals[3 * i]);
214 qsort(&node2tri[0], 3 * nTriangles, 2 *
sizeof(std::size_t),
219 std::vector<double> CURV(4 * nTriangles);
221 for(std::size_t i = 0; i < nTriangles; i++) {
222 double *n0 = &nodeNormals[3 * triangles[3 * i + 0]];
223 double *n1 = &nodeNormals[3 * triangles[3 * i + 1]];
224 double *n2 = &nodeNormals[3 * triangles[3 * i + 2]];
226 double e0[3], e1[3], e2[3];
227 makevector(nodes[triangles[3 * i + 2]].data(),
228 nodes[triangles[3 * i + 1]].data(), e0);
229 makevector(nodes[triangles[3 * i + 0]].data(),
230 nodes[triangles[3 * i + 2]].data(), e1);
231 makevector(nodes[triangles[3 * i + 1]].data(),
232 nodes[triangles[3 * i + 0]].data(), e2);
234 nodes[triangles[3 * i + 1]].data(),
235 nodes[triangles[3 * i + 2]].data(), n, &surf);
237 makevector(nodes[triangles[3 * i + 0]].data(),
238 nodes[triangles[3 * i + 1]].data(), u);
242 double sys[6][4], rhs[6], temp[3], invA[16], A[16], B[4];
243 sys[0][0] = sys[1][2] =
dotprod(e0, u);
244 sys[0][1] = sys[1][3] =
dotprod(e0, v);
245 sys[0][2] = sys[0][3] = sys[1][0] = sys[1][1] = 0;
250 sys[2][0] = sys[3][2] =
dotprod(e1, u);
251 sys[2][1] = sys[3][3] =
dotprod(e1, v);
252 sys[2][2] = sys[2][3] = sys[3][0] = sys[3][1] = 0;
257 sys[4][0] = sys[5][2] =
dotprod(e2, u);
258 sys[4][1] = sys[5][3] =
dotprod(e2, v);
259 sys[4][2] = sys[4][3] = sys[5][0] = sys[5][1] = 0;
264 for(std::size_t i1 = 0; i1 < 4; i1++) {
266 for(std::size_t i3 = 0; i3 < 6; i3++) { B[i1] += sys[i3][i1] * rhs[i3]; }
267 for(std::size_t i2 = 0; i2 < 4; i2++) {
268 A[i1 + 4 * i2] = 0.0;
269 for(std::size_t i3 = 0; i3 < 6; i3++) {
270 A[i1 + 4 * i2] += sys[i3][i2] * sys[i3][i1];
276 for(std::size_t i1 = 0; i1 < 4; i1++) {
277 CURV[4 * i + i1] = 0.0;
278 for(std::size_t i2 = 0; i2 < 4; i2++) {
279 CURV[4 * i + i1] += invA[i1 + 4 * i2] * B[i2];
282 CURV[4 * i + 1] = CURV[4 * i + 2] =
283 0.5 * (CURV[4 * i + 1] + CURV[4 * i + 2]);
287 double uP[3] = {0., 0., 0.}, vP[3] = {0., 0., 0.};
288 double A = 0., B = 0.,
D = 0.;
291 for(uint64_t iVert = 0; iVert < nVertices; ++iVert) {
296 while(node2tri[2 * ind + 0] == iVert) {
297 iTriangle = node2tri[2 * ind + 1];
301 nodes[triangles[3 * iTriangle + 1]].data(),
302 nodes[triangles[3 * iTriangle + 2]].data(), n, &surf);
304 makevector(nodes[triangles[3 * iTriangle + 0]].data(),
305 nodes[triangles[3 * iTriangle + 1]].data(), uF);
308 double *
c = &CURV[4 * iTriangle];
313 A += (UP[0] * UP[0] *
c[0] + 2 * UP[0] * UP[1] *
c[1] +
314 UP[1] * UP[1] *
c[3]);
315 D += (VP[0] * VP[0] *
c[0] + 2 * VP[0] * VP[1] *
c[1] +
316 VP[1] * VP[1] *
c[3]);
317 B += (VP[0] * UP[0] *
c[0] + (VP[1] * UP[0] + VP[0] * UP[1]) *
c[1] +
318 VP[1] * UP[1] *
c[3]);
321 if(ind >= 3 * nTriangles)
break;
327 double lambda1, lambda2, v1x, v1y, v2x, v2y;
328 solveEig(A, B, B,
D, &lambda1, &v1x, &v1y, &lambda2, &v2x, &v2y);
329 SVector3 cMax(fabs(lambda1) * (v1x * uP[0] + v1y * vP[0]),
330 fabs(lambda1) * (v1x * uP[1] + v1y * vP[1]),
331 fabs(lambda1) * (v1x * uP[2] + v1y * vP[2]));
332 SVector3 cMin(fabs(lambda2) * (v2x * uP[0] + v2y * vP[0]),
333 fabs(lambda2) * (v2x * uP[1] + v2y * vP[1]),
334 fabs(lambda2) * (v2x * uP[2] + v2y * vP[2]));
335 nodalCurvatures[iVert] = std::make_pair(cMax, cMin);
342 const std::vector<int> &triangles,
const std::vector<SPoint3> &nodes,
343 std::vector<std::pair<SVector3, SVector3> > &nodalCurvatures,
344 std::vector<double> &nodeNormals)
346 std::size_t nTriangles = triangles.size() / 3;
347 std::size_t nVertices = nodes.size();
349 nodalCurvatures.resize(nVertices);
355 std::vector<std::size_t> node2tri(3 * 2 * nTriangles);
360 std::size_t counter = 0;
363 for(std::size_t i = 0; i < nTriangles; i++) {
364 node2tri[counter++] = triangles[3 * i + 0];
365 node2tri[counter++] = i;
366 node2tri[counter++] = triangles[3 * i + 1];
367 node2tri[counter++] = i;
368 node2tri[counter++] = triangles[3 * i + 2];
369 node2tri[counter++] = i;
371 nodes[triangles[3 * i + 1]].data(),
372 nodes[triangles[3 * i + 2]].data(), n, &surf);
373 double *n0 = &nodeNormals[3 * triangles[3 * i + 0]];
374 double *n1 = &nodeNormals[3 * triangles[3 * i + 1]];
375 double *n2 = &nodeNormals[3 * triangles[3 * i + 2]];
376 for(std::size_t i1 = 0; i1 < 3; i1++) {
382 for(std::size_t i = 0; i < nVertices; i++)
normalize(&nodeNormals[3 * i]);
384 qsort(&node2tri[0], 3 * nTriangles, 2 *
sizeof(std::size_t),
389 std::vector<double> CURV(4 * nTriangles);
391 for(std::size_t i = 0; i < nTriangles; i++) {
392 double *n0 = &nodeNormals[3 * triangles[3 * i + 0]];
393 double *n1 = &nodeNormals[3 * triangles[3 * i + 1]];
394 double *n2 = &nodeNormals[3 * triangles[3 * i + 2]];
396 double e0[3], e1[3], e2[3];
397 makevector(nodes[triangles[3 * i + 2]].data(),
398 nodes[triangles[3 * i + 1]].data(), e0);
399 makevector(nodes[triangles[3 * i + 0]].data(),
400 nodes[triangles[3 * i + 2]].data(), e1);
401 makevector(nodes[triangles[3 * i + 1]].data(),
402 nodes[triangles[3 * i + 0]].data(), e2);
404 nodes[triangles[3 * i + 1]].data(),
405 nodes[triangles[3 * i + 2]].data(), n, &surf);
407 makevector(nodes[triangles[3 * i + 0]].data(),
408 nodes[triangles[3 * i + 1]].data(), u);
412 double sys[6][4], rhs[6], temp[3], invA[16], A[16], B[4];
413 sys[0][0] = sys[1][2] =
dotprod(e0, u);
414 sys[0][1] = sys[1][3] =
dotprod(e0, v);
415 sys[0][2] = sys[0][3] = sys[1][0] = sys[1][1] = 0;
420 sys[2][0] = sys[3][2] =
dotprod(e1, u);
421 sys[2][1] = sys[3][3] =
dotprod(e1, v);
422 sys[2][2] = sys[2][3] = sys[3][0] = sys[3][1] = 0;
427 sys[4][0] = sys[5][2] =
dotprod(e2, u);
428 sys[4][1] = sys[5][3] =
dotprod(e2, v);
429 sys[4][2] = sys[4][3] = sys[5][0] = sys[5][1] = 0;
434 for(std::size_t i1 = 0; i1 < 4; i1++) {
436 for(std::size_t i3 = 0; i3 < 6; i3++) { B[i1] += sys[i3][i1] * rhs[i3]; }
437 for(std::size_t i2 = 0; i2 < 4; i2++) {
438 A[i1 + 4 * i2] = 0.0;
439 for(std::size_t i3 = 0; i3 < 6; i3++) {
440 A[i1 + 4 * i2] += sys[i3][i2] * sys[i3][i1];
446 for(std::size_t i1 = 0; i1 < 4; i1++) {
447 CURV[4 * i + i1] = 0.0;
448 for(std::size_t i2 = 0; i2 < 4; i2++) {
449 CURV[4 * i + i1] += invA[i1 + 4 * i2] * B[i2];
452 CURV[4 * i + 1] = CURV[4 * i + 2] =
453 0.5 * (CURV[4 * i + 1] + CURV[4 * i + 2]);
457 double uP[3] = {0., 0., 0.}, vP[3] = {0., 0., 0.};
458 double A = 0., B = 0.,
D = 0.;
461 for(uint64_t iVert = 0; iVert < nVertices; ++iVert) {
466 while(node2tri[2 * ind + 0] == iVert) {
467 iTriangle = node2tri[2 * ind + 1];
471 nodes[triangles[3 * iTriangle + 1]].data(),
472 nodes[triangles[3 * iTriangle + 2]].data(), n, &surf);
474 makevector(nodes[triangles[3 * iTriangle + 0]].data(),
475 nodes[triangles[3 * iTriangle + 1]].data(), uF);
478 double *
c = &CURV[4 * iTriangle];
483 A += (UP[0] * UP[0] *
c[0] + 2 * UP[0] * UP[1] *
c[1] +
484 UP[1] * UP[1] *
c[3]);
485 D += (VP[0] * VP[0] *
c[0] + 2 * VP[0] * VP[1] *
c[1] +
486 VP[1] * VP[1] *
c[3]);
487 B += (VP[0] * UP[0] *
c[0] + (VP[1] * UP[0] + VP[0] * UP[1]) *
c[1] +
488 VP[1] * UP[1] *
c[3]);
491 if(ind >= 3 * nTriangles)
break;
497 double lambda1, lambda2, v1x, v1y, v2x, v2y;
498 solveEig(A, B, B,
D, &lambda1, &v1x, &v1y, &lambda2, &v2x, &v2y);
499 SVector3 cMax(fabs(lambda1) * (v1x * uP[0] + v1y * vP[0]),
500 fabs(lambda1) * (v1x * uP[1] + v1y * vP[1]),
501 fabs(lambda1) * (v1x * uP[2] + v1y * vP[2]));
502 SVector3 cMin(fabs(lambda2) * (v2x * uP[0] + v2y * vP[0]),
503 fabs(lambda2) * (v2x * uP[1] + v2y * vP[1]),
504 fabs(lambda2) * (v2x * uP[2] + v2y * vP[2]));
505 nodalCurvatures[iVert] = std::make_pair(cMax, cMin);