TTK
Loading...
Searching...
No Matches
Geometry.cpp
Go to the documentation of this file.
1#include <Geometry.h>
2
3#include <algorithm>
4
5using namespace std;
6using namespace ttk;
7
8static const double PREC_DBL{Geometry::pow(10.0, -DBL_DIG)};
9static const float PREC_FLT{powf(10.0F, -FLT_DIG)};
10static const float PREC_FLT_1{powf(10.0F, -FLT_DIG + 1)};
11
12template <typename T>
13T Geometry::angle(const T *vA0, const T *vA1, const T *vB0, const T *vB1) {
14 return M_PI
15 - acos(dotProduct(vA0, vA1, vB0, vB1)
16 / (magnitude(vA0, vA1) * magnitude(vB0, vB1)));
17}
18
19template <typename T>
20T Geometry::angle2D(const T *vA0, const T *vA1, const T *vB0, const T *vB1) {
21 double vecA[2] = {vA1[0] - vA0[0], vA1[1] - vA0[1]};
22 double vecB[2] = {vB1[0] - vB0[0], vB1[1] - vB0[1]};
23 return atan2(vecB[1], vecB[0]) - atan2(vecA[1], vecA[0]);
24}
25
26template <typename T>
28 const T *vA1,
29 const T *vB0,
30 const T *vB1,
31 std::array<T, 3> *coefficients,
32 const T *tolerance) {
33
34 int aNullComponents = 0, bNullComponents = 0;
35 std::array<T, 3> a{}, b{};
36 for(int i = 0; i < 3; i++) {
37 a[i] = vA1[i] - vA0[i];
38 if(fabs(a[i]) < PREC_FLT) {
39 aNullComponents++;
40 }
41 b[i] = vB1[i] - vB0[i];
42 if(fabs(b[i]) < PREC_FLT) {
43 bNullComponents++;
44 }
45 }
46
47 if((aNullComponents == 3) || (bNullComponents == 3)) {
48 return true;
49 }
50
51 // check for axis aligned vectors
52 if((aNullComponents > 1) || (bNullComponents > 1)) {
53 if(aNullComponents == bNullComponents) {
54 // only one non-null component for both vectors
55 return true;
56 }
57 }
58
59 bool useDenominatorA = false;
60 T sumA = 0, sumB = 0;
61 for(int i = 0; i < 3; i++) {
62 sumA += fabs(a[i]);
63 sumB += fabs(b[i]);
64 }
65 if(sumA > sumB) {
66 useDenominatorA = true;
67 }
68
69 std::array<T, 3> k{};
70
71 T maxDenominator = 0;
72 int isNan = -1, maximizer = 0;
73 for(int i = 0; i < 3; i++) {
74 if(useDenominatorA) {
75 if(fabs(a[i]) > PREC_FLT) {
76 k[i] = b[i] / a[i];
77 } else {
78 isNan = i;
79 }
80 } else {
81 if(fabs(b[i]) > PREC_FLT) {
82 k[i] = a[i] / b[i];
83 } else {
84 isNan = i;
85 }
86 }
87
88 if(!i) {
89 maxDenominator = fabs(k[i]);
90 maximizer = i;
91 } else {
92 if(fabs(k[i]) > maxDenominator) {
93 maxDenominator = fabs(k[i]);
94 maximizer = i;
95 }
96 }
97 }
98
99 T colinearityThreshold;
100
101 colinearityThreshold = PREC_FLT;
102 if(tolerance) {
103 colinearityThreshold = *tolerance;
104 }
105
106 if(coefficients) {
107 (*coefficients) = k;
108 }
109
110 if(isNan == -1) {
111
112 if((fabs(1 - fabs(k[(maximizer + 1) % 3] / k[maximizer]))
113 < colinearityThreshold)
114 && (fabs(1 - fabs(k[(maximizer + 2) % 3] / k[maximizer]))
115 < colinearityThreshold)) {
116 return true;
117 }
118 } else {
119 if(fabs(1 - fabs(k[(isNan + 1) % 3] / k[(isNan + 2) % 3]))
120 < colinearityThreshold) {
121 return true;
122 }
123 }
124 k[0] = k[1] = k[2] = 0;
125
126 return false;
127}
128
129template <typename T>
131 const T *pptB,
132 const T *pptC,
133 const T tolerance) {
134 double ptA[2] = {pptA[0], pptA[1]}, ptB[2] = {pptB[0], pptB[1]},
135 ptC[2] = {pptC[0], pptC[1]};
136 return fabs(ptA[0] * (ptB[1] - ptC[1]) + ptB[0] * (ptC[1] - ptA[1])
137 + ptC[0] * (ptA[1] - ptB[1]))
138 <= tolerance;
139}
140
141template <typename T>
143 const T *p1,
144 const T *p,
145 std::array<T, 2> &baryCentrics,
146 const int &dimension) {
147
148 if(dimension > 3) {
149 return -1;
150 }
151
152 int bestI = 0;
153 T maxDenominator = 0;
154
155 for(int i = 0; i < dimension; i++) {
156
157 T denominator = fabs(p0[i] - p1[i]);
158 if(!i) {
159 maxDenominator = denominator;
160 bestI = i;
161 } else {
162 if(denominator > maxDenominator) {
163 maxDenominator = denominator;
164 bestI = i;
165 }
166 }
167 }
168
169 baryCentrics[0] = p0[bestI] - p1[bestI];
170 baryCentrics[0] = (p[bestI] - p1[bestI]) / baryCentrics[0];
171
172 baryCentrics[1] = 1 - baryCentrics[0];
173
174 // check if the point lies in the edge
175 std::array<T, 3> test{};
176 for(int i = 0; i < dimension; i++) {
177 test[i] = baryCentrics[0] * p0[i] + baryCentrics[1] * p1[i];
178 }
179
180 if((!((fabs(test[0] - p[0]) < PREC_FLT_1)
181 && (fabs(test[1] - p[1]) < PREC_FLT_1)))) {
182 for(int i = 0; i < 2; i++) {
183 baryCentrics[i] = -baryCentrics[i];
184 }
185 }
186
187 return 0;
188}
189template <typename T>
191 const T *p1,
192 const T *p2,
193 const T *p,
194 std::array<T, 3> &baryCentrics) {
195
196 // find the pair of coordinates that maximize the sum of the denominators
197 // (more stable computations)
198 int bestI = 0, bestJ = 1;
199 T maxDenominator = 0;
200
201 for(int i = 0; i < 2; i++) {
202 for(int j = i + 1; j < 3; j++) {
203
204 baryCentrics[0]
205 = (p1[j] - p2[j]) * (p0[i] - p2[i]) + (p2[i] - p1[i]) * (p0[j] - p2[j]);
206 baryCentrics[1]
207 = (p1[j] - p2[j]) * (p0[i] - p2[i]) + (p2[i] - p1[i]) * (p0[j] - p2[j]);
208
209 T denominator = fabs(baryCentrics[0]);
210
211 if(fabs(baryCentrics[1]) < denominator) {
212 denominator = fabs(baryCentrics[1]);
213 }
214
215 if((i == 0) && (j == 1)) {
216 maxDenominator = denominator;
217 } else {
218 if(denominator > maxDenominator) {
219 maxDenominator = denominator;
220 bestI = i;
221 bestJ = j;
222 }
223 }
224 }
225 }
226
227 baryCentrics[0] = (p1[bestJ] - p2[bestJ]) * (p0[bestI] - p2[bestI])
228 + (p2[bestI] - p1[bestI]) * (p0[bestJ] - p2[bestJ]);
229 // (y1 - y2)*(x - x2) + (x2 - x1)*(y - y2)
230 baryCentrics[0] = ((p1[bestJ] - p2[bestJ]) * (p[bestI] - p2[bestI])
231 + (p2[bestI] - p1[bestI]) * (p[bestJ] - p2[bestJ]))
232 / baryCentrics[0];
233
234 // (y1 - y2)*(x0 - x2) + (x2 - x1)*(y0 - y2)
235 baryCentrics[1] = (p1[bestJ] - p2[bestJ]) * (p0[bestI] - p2[bestI])
236 + (p2[bestI] - p1[bestI]) * (p0[bestJ] - p2[bestJ]);
237 // (y2 - y0)*(x - x2) + (x0 - x2)*(y - y2)
238 baryCentrics[1] = ((p2[bestJ] - p0[bestJ]) * (p[bestI] - p2[bestI])
239 + (p0[bestI] - p2[bestI]) * (p[bestJ] - p2[bestJ]))
240 / baryCentrics[1];
241
242 baryCentrics[2] = 1 - baryCentrics[0] - baryCentrics[1];
243
244 return 0;
245}
246
247template <typename T>
249 const T &yA,
250 const T &xB,
251 const T &yB,
252 const T &xC,
253 const T &yC,
254 const T &xD,
255 const T &yD,
256 T &x,
257 T &y) {
258
259 T d = (xA - xB) * (yC - yD) - (yA - yB) * (xC - xD);
260
261 if(fabs(d) < PREC_DBL) {
262 return false;
263 }
264
265 x = ((xC - xD) * (xA * yB - yA * xB) - (xA - xB) * (xC * yD - yC * xD)) / d;
266
267 y = ((yC - yD) * (xA * yB - yA * xB) - (yA - yB) * (xC * yD - yC * xD)) / d;
268
269 if((x < std::min(xA, xB) - PREC_FLT) || (x > std::max(xA, xB) + PREC_FLT)) {
270 return false;
271 }
272
273 if((x < std::min(xC, xD) - PREC_FLT) || (x > std::max(xC, xD) + PREC_FLT)) {
274 return false;
275 }
276
277 return true;
278}
279
280template <typename T>
282 const T *p1,
283 const T *p2,
284 T &area) {
285
286 std::array<T, 3> cross{};
287
288 crossProduct(p0, p1, p1, p2, cross);
289
290 area = 0.5 * magnitude(cross.data());
291
292 return 0;
293}
294
295template <typename T>
297 const T s1,
298 const T s2,
299 T &area) {
300
301 double const s = (s0 + s1 + s2) / 2.0;
302 area = std::sqrt(s * (s - s0) * (s - s1) * (s - s2));
303
304 return 0;
305}
306
307template <typename T>
309 const T *p1,
310 const T *p2,
311 std::array<T, 3> &angles) {
312
313 angles[0] = angle(p0, p1, p1, p2);
314 angles[1] = angle(p1, p2, p2, p0);
315 angles[2] = angle(p2, p0, p0, p1);
316
317 return 0;
318}
319
320template <typename T>
322 const T s1,
323 const T s2,
324 T &angle) {
325
326 angle = std::acos((s0 * s0 + s1 * s1 - s2 * s2) / (2.0 * s0 * s1));
327
328 return 0;
329}
330
331template <typename T>
332int Geometry::crossProduct(const T *vA0,
333 const T *vA1,
334 const T *vB0,
335 const T *vB1,
336 std::array<T, 3> &crossProduct) {
337
338 std::array<T, 3> a{}, b{};
339
340 for(int i = 0; i < 3; i++) {
341 a[i] = vA1[i] - vA0[i];
342 b[i] = vB1[i] - vB0[i];
343 }
344
345 for(int i = 0; i < 3; i++) {
346 crossProduct[i]
347 = a[(i + 1) % 3] * b[(i + 2) % 3] - a[(i + 2) % 3] * b[(i + 1) % 3];
348 }
349
350 return 0;
351}
352
353template <typename T>
354int Geometry::crossProduct(const T *vA, const T *vB, T *crossProduct) {
355 crossProduct[0] = vA[1] * vB[2] - vA[2] * vB[1];
356 crossProduct[1] = vA[2] * vB[0] - vA[0] * vB[2];
357 crossProduct[2] = vA[0] * vB[1] - vA[1] * vB[0];
358 return 0;
359}
360
361template <typename T>
362T Geometry::distance(const T *p0, const T *p1, const int &dimension) {
363
364 T distance = 0;
365
366 for(int i = 0; i < dimension; i++) {
367 distance += (p0[i] - p1[i]) * (p0[i] - p1[i]);
368 }
369
370 return sqrt(distance);
371}
372
373template <typename T>
374T Geometry::distance(const std::vector<T> &p0, const std::vector<T> &p1) {
375 return distance(p0.data(), p1.data(), p0.size());
376}
377
378template <typename T>
379T Geometry::distanceFlatten(const std::vector<std::vector<T>> &p0,
380 const std::vector<std::vector<T>> &p1) {
381 std::vector<T> p0_flatten, p1_flatten;
382 flattenMultiDimensionalVector(p0, p0_flatten);
383 flattenMultiDimensionalVector(p1, p1_flatten);
384 return distance(p0_flatten, p1_flatten);
385}
386
387template <typename T>
388T Geometry::dotProduct(const T *vA0, const T *vA1, const T *vB0, const T *vB1) {
389
390 T dotProduct = 0;
391 for(int i = 0; i < 3; i++) {
392 dotProduct += (vA1[i] - vA0[i]) * (vB1[i] - vB0[i]);
393 }
394
395 return dotProduct;
396}
397
398template <typename T>
399T Geometry::dotProduct(const T *vA, const T *vB, const int &dimension) {
400 T dotProduct = 0;
401 for(int i = 0; i < dimension; ++i)
402 dotProduct += vA[i] * vB[i];
403 return dotProduct;
404}
405
406template <typename T>
407T Geometry::dotProduct(const std::vector<T> &vA, const std::vector<T> &vB) {
408 return dotProduct(vA.data(), vB.data(), vA.size());
409}
410
411template <typename T>
412T Geometry::dotProductFlatten(const std::vector<std::vector<T>> &vA,
413 const std::vector<std::vector<T>> &vB) {
414 std::vector<T> vA_flatten, vB_flatten;
415 flattenMultiDimensionalVector(vA, vA_flatten);
416 flattenMultiDimensionalVector(vB, vB_flatten);
417 return dotProduct(vA_flatten, vB_flatten);
418}
419
420template <typename T>
422 const T *p1,
423 const T *p2,
424 const T *p) {
425
426 std::array<T, 3> barycentrics{};
427
428 Geometry::computeBarycentricCoordinates(p0, p1, p2, p, barycentrics);
429
430 for(int i = 0; i < static_cast<int>(barycentrics.size()); i++) {
431 if(barycentrics[i] < -PREC_DBL) {
432 return false;
433 }
434 if(barycentrics[i] > 1 + PREC_DBL) {
435 return false;
436 }
437 }
438
439 return true;
440}
441
442template <typename T>
444 const T &x, const T &y, const T &xA, const T &yA, const T &xB, const T &yB) {
445
446 std::array<T, 2> pA{xA, yA}, pB{xB, yB}, p{x, y};
447 return Geometry::isPointOnSegment(p.data(), pA.data(), pB.data(), 2);
448}
449
450template <typename T>
452 const T *pA,
453 const T *pB,
454 const int &dimension) {
455
456 std::array<T, 2> baryCentrics{};
457
458 Geometry::computeBarycentricCoordinates(pA, pB, p, baryCentrics, dimension);
459
460 return (
461 ((baryCentrics[0] > -PREC_DBL) && (baryCentrics[0] < 1 + PREC_DBL))
462 && ((baryCentrics[1] > -PREC_DBL) && (baryCentrics[1] < 1 + PREC_DBL)));
463}
464
465template <typename T>
467 const T *p1,
468 const T *p2,
469 const T *tolerance) {
470
471 bool maxDecision = false;
472 T maxCoefficient = 0;
473 std::array<T, 3> coefficients{};
474
475 bool decision = areVectorsColinear(p0, p1, p1, p2, &coefficients, tolerance);
476 maxDecision = decision;
477 for(int i = 0; i < 3; i++) {
478 if(!i) {
479 maxCoefficient = fabs(coefficients[i]);
480 maxDecision = decision;
481 } else {
482 if(fabs(coefficients[i]) > maxCoefficient) {
483 maxCoefficient = fabs(coefficients[i]);
484 maxDecision = decision;
485 }
486 }
487 }
488
489 decision = areVectorsColinear(p0, p2, p2, p1, &coefficients, tolerance);
490 for(int i = 0; i < 3; i++) {
491 if(fabs(coefficients[i]) > maxCoefficient) {
492 maxCoefficient = fabs(coefficients[i]);
493 maxDecision = decision;
494 }
495 }
496
497 decision = areVectorsColinear(p1, p0, p0, p2, &coefficients, tolerance);
498 for(int i = 0; i < 3; i++) {
499 if(fabs(coefficients[i]) > maxCoefficient) {
500 maxCoefficient = fabs(coefficients[i]);
501 maxDecision = decision;
502 }
503 }
504
505 return maxDecision;
506}
507
508template <typename T>
509T Geometry::magnitude(const T *v, const int &dimension) {
510 return sqrt(dotProduct(v, v, dimension));
511}
512
513template <typename T>
514T Geometry::magnitude(const std::vector<T> &v) {
515 return magnitude(v.data(), v.size());
516}
517
518template <typename T>
519T Geometry::magnitudeFlatten(const std::vector<std::vector<T>> &v) {
520 std::vector<T> v_flatten;
521 flattenMultiDimensionalVector(v, v_flatten);
522 return magnitude(v_flatten);
523}
524
525template <typename T>
526T Geometry::magnitude(const T *o, const T *d) {
527
528 T mag = 0;
529
530 for(int i = 0; i < 3; i++) {
531 mag += (o[i] - d[i]) * (o[i] - d[i]);
532 }
533
534 return sqrt(mag);
535}
536
537template <typename T>
539 const T *a,
540 const T *normTri,
541 T *out) {
542 std::array<T, 3> ap{};
543 subtractVectors(a, p, ap.data());
544 std::array<T, 3> normTriScaled{};
545 scaleVector(normTri, dotProduct(normTri, ap.data()), normTriScaled.data());
546 subtractVectors(normTriScaled.data(), p, out);
547}
548
549template <typename T>
550void Geometry::projectOnEdge(const T *p, const T *a, const T *b, T *out) {
551 std::array<T, 3> ab{};
552 subtractVectors(a, b, ab.data());
553 std::array<T, 3> ap{};
554 subtractVectors(a, p, ap.data());
555 std::array<T, 3> abScaled{};
557 ab.data(),
558 dotProduct(ap.data(), ab.data()) / dotProduct(ab.data(), ab.data()),
559 abScaled.data());
560 addVectors(a, abScaled.data(), out);
561}
562
563template <typename T>
565 const T *b,
566 const T *c,
567 T *out) {
568
569 // triangle normal: cross product of two edges
570 // ab, ac vectors
571 std::array<T, 3> ab{};
572 subtractVectors(a, b, ab.data());
573 std::array<T, 3> ac{};
574 subtractVectors(a, c, ac.data());
575 // compute ab ^ ac
576 crossProduct(ab.data(), ac.data(), out);
577 // magnitude
578 const auto mag = magnitude(out);
579
580 if(mag > powf(10, -FLT_DIG)) {
581 // unitary normal vector
582 scaleVector(out, 1 / mag, out);
583 return;
584 }
585
586 out[0] = -1.0F;
587 out[1] = -1.0F;
588 out[2] = -1.0F;
589}
590
591template <typename T>
593 const T *b,
594 T *out,
595 const int &dimension) {
596 for(int i = 0; i < dimension; ++i)
597 out[i] = b[i] - a[i];
598 return 0;
599}
600
601template <typename T>
602int Geometry::subtractVectors(const std::vector<T> &a,
603 const std::vector<T> &b,
604 std::vector<T> &out) {
605 out.resize(a.size());
606 return subtractVectors(a.data(), b.data(), out.data(), a.size());
607}
608
609template <typename T>
610int Geometry::addVectors(const T *a, const T *b, T *out, const int &dimension) {
611 for(int i = 0; i < dimension; ++i)
612 out[i] = b[i] + a[i];
613 return 0;
614}
615
616template <typename T>
617int Geometry::addVectors(const std::vector<T> &a,
618 const std::vector<T> &b,
619 std::vector<T> &out) {
620 out.resize(a.size());
621 return addVectors(a.data(), b.data(), out.data(), a.size());
622}
623
624template <typename T>
625int Geometry::multiAddVectors(const std::vector<std::vector<T>> &a,
626 const std::vector<std::vector<T>> &b,
627 std::vector<std::vector<T>> &out) {
628 out.resize(a.size());
629 for(unsigned int i = 0; i < a.size(); ++i)
630 addVectors(a[i], b[i], out[i]);
631 return 0;
632}
633
634template <typename T>
636 const std::vector<std::vector<std::vector<T>>> &a,
637 const std::vector<std::vector<std::vector<T>>> &b,
638 std::vector<std::vector<T>> &out) {
639 std::vector<std::vector<T>> a_flatten, b_flatten;
642 multiAddVectors(a_flatten, b_flatten, out);
643 return 0;
644}
645
646template <typename T>
648 const T factor,
649 T *out,
650 const int &dimension) {
651 for(int i = 0; i < dimension; ++i)
652 out[i] = a[i] * factor;
653 return 0;
654}
655
656template <typename T>
657int Geometry::scaleVector(const std::vector<T> &a,
658 const T factor,
659 std::vector<T> &out) {
660 out.resize(a.size());
661 return scaleVector(a.data(), factor, out.data(), a.size());
662}
663
664template <typename T>
666 const T *b,
667 T *out,
668 const int &dimension) {
669 T dotProdBB = dotProduct(b, b, dimension);
670 T dotProdAB;
671 if(dotProdBB > PREC_DBL) {
672 dotProdAB = dotProduct(a, b, dimension);
673 dotProdAB /= dotProdBB;
674 } else
675 dotProdAB = 0; // Gram-Schmidt convention
676 for(int i = 0; i < dimension; ++i)
677 out[i] = b[i] * dotProdAB;
678 return 0;
679}
680
681template <typename T>
682int Geometry::vectorProjection(const std::vector<T> &a,
683 const std::vector<T> &b,
684 std::vector<T> &out) {
685 out.resize(a.size(), 0.0);
686 return vectorProjection(a.data(), b.data(), out.data(), a.size());
687}
688
689template <typename T>
690void Geometry::addVectorsProjection(const std::vector<T> &a,
691 const std::vector<T> &b,
692 std::vector<T> &a_out,
693 std::vector<T> &b_out) {
694 std::vector<T> sumV;
695 addVectors(a, b, sumV);
696 vectorProjection(a, sumV, a_out);
697 vectorProjection(b, sumV, b_out);
698}
699
700template <typename T>
701void Geometry::gramSchmidt(const std::vector<std::vector<T>> &a,
702 std::vector<std::vector<T>> &out) {
703 out.resize(a.size());
704 out[0] = a[0];
705 for(unsigned int i = 1; i < a.size(); ++i) {
706 std::vector<T> projecSum;
707 vectorProjection(a[i], out[0], projecSum);
708 for(unsigned int j = 1; j < i; ++j) {
709 std::vector<T> projecTemp, projecSumTemp;
710 vectorProjection(a[i], out[j], projecTemp);
711 addVectors(projecSum, projecTemp, projecSumTemp);
712 projecSum = projecSumTemp;
713 }
714 subtractVectors(projecSum, a[i], out[i]);
715 }
716}
717
718template <typename T>
719bool Geometry::isVectorUniform(const std::vector<T> &a) {
720 for(unsigned int i = 0; i < a.size() - 1; ++i)
721 if(not(std::abs(a[i] - a[i + 1]) < PREC_DBL))
722 return false;
723 return true;
724}
725
726template <typename T>
727bool Geometry::isVectorNull(const std::vector<T> &a) {
728 for(unsigned int i = 0; i < a.size(); ++i)
729 if(not(std::abs(a[i]) < PREC_DBL))
730 return false;
731 return true;
732}
733
734template <typename T>
735bool Geometry::isVectorNullFlatten(const std::vector<std::vector<T>> &a) {
736 std::vector<T> a_flatten;
737 flattenMultiDimensionalVector(a, a_flatten);
738 return isVectorNull(a_flatten);
739}
740
741template <typename T>
743 const std::vector<std::vector<T>> &a, std::vector<T> &out) {
744 out.resize(a.size() * a[0].size());
745 for(unsigned int i = 0; i < a.size(); ++i)
746 for(unsigned int j = 0; j < a[0].size(); ++j)
747 out[i * a[0].size() + j] = a[i][j];
748 return 0;
749}
750
751template <typename T>
753 const std::vector<std::vector<std::vector<T>>> &a,
754 std::vector<std::vector<T>> &out) {
755 out.resize(a.size());
756 for(unsigned int i = 0; i < a.size(); ++i)
757 flattenMultiDimensionalVector(a[i], out[i]);
758 return 0;
759}
760
761template <typename T>
763 std::vector<std::vector<T>> &out,
764 const int &no_columns) {
765 if(a.size() % no_columns != 0)
766 return -1;
767 out.resize(a.size() / no_columns);
768 for(unsigned int i = 0; i < out.size(); ++i) {
769 out[i].resize(no_columns);
770 for(unsigned int j = 0; j < out[i].size(); ++j)
771 out[i][j] = a[i * no_columns + j];
772 }
773 return 0;
774}
775
776template <typename T>
777void Geometry::matrixMultiplication(const std::vector<std::vector<T>> &a,
778 const std::vector<std::vector<T>> &b,
779 std::vector<std::vector<T>> &out) {
780 out.resize(a.size(), std::vector<T>(b[0].size(), 0.0));
781 for(unsigned int i = 0; i < out.size(); ++i)
782 for(unsigned int j = 0; j < out[i].size(); ++j)
783 for(unsigned int k = 0; k < a[i].size(); ++k)
784 out[i][j] += a[i][k] * b[k][j];
785}
786
787template <typename T>
788void Geometry::subtractMatrices(const std::vector<std::vector<T>> &a,
789 const std::vector<std::vector<T>> &b,
790 std::vector<std::vector<T>> &out) {
791 out.resize(a.size(), std::vector<T>(a[0].size()));
792 for(unsigned int i = 0; i < out.size(); ++i)
793 for(unsigned int j = 0; j < out[0].size(); ++j)
794 out[i][j] = b[i][j] - a[i][j];
795}
796
797template <typename T>
798void Geometry::addMatrices(const std::vector<std::vector<T>> &a,
799 const std::vector<std::vector<T>> &b,
800 std::vector<std::vector<T>> &out) {
801 out.resize(a.size(), std::vector<T>(a[0].size()));
802 for(unsigned int i = 0; i < a.size(); ++i)
803 for(unsigned int j = 0; j < a[0].size(); ++j)
804 out[i][j] = a[i][j] + b[i][j];
805}
806
807template <typename T>
808void Geometry::scaleMatrix(const std::vector<std::vector<T>> &a,
809 const T factor,
810 std::vector<std::vector<T>> &out) {
811 out.resize(a.size(), std::vector<T>(a[0].size()));
812 for(unsigned int i = 0; i < out.size(); ++i)
813 for(unsigned int j = 0; j < out[i].size(); ++j)
814 out[i][j] = a[i][j] * factor;
815}
816
817template <typename T>
818void Geometry::transposeMatrix(const std::vector<std::vector<T>> &a,
819 std::vector<std::vector<T>> &out) {
820 out.resize(a[0].size(), std::vector<T>(a.size()));
821 for(unsigned int i = 0; i < a.size(); ++i)
822 for(unsigned int j = 0; j < a[0].size(); ++j)
823 out[j][i] = a[i][j];
824}
825
826#define GEOMETRY_SPECIALIZE(TYPE) \
827 template TYPE Geometry::angle<TYPE>( \
828 TYPE const *, TYPE const *, TYPE const *, TYPE const *); \
829 template TYPE Geometry::angle2D<TYPE>( \
830 TYPE const *, TYPE const *, TYPE const *, TYPE const *); \
831 template bool Geometry::areVectorsColinear<TYPE>( \
832 TYPE const *, TYPE const *, TYPE const *, TYPE const *, \
833 std::array<TYPE, 3> *, TYPE const *); \
834 template bool Geometry::isTriangleColinear2D<TYPE>( \
835 TYPE const *, TYPE const *, TYPE const *, TYPE const); \
836 template int Geometry::computeBarycentricCoordinates<TYPE>( \
837 TYPE const *, TYPE const *, TYPE const *, std::array<TYPE, 2> &, \
838 int const &); \
839 template int Geometry::computeBarycentricCoordinates<TYPE>( \
840 TYPE const *, TYPE const *, TYPE const *, TYPE const *, \
841 std::array<TYPE, 3> &); \
842 template bool Geometry::computeSegmentIntersection<TYPE>( \
843 TYPE const &, TYPE const &, TYPE const &, TYPE const &, TYPE const &, \
844 TYPE const &, TYPE const &, TYPE const &, TYPE &, TYPE &); \
845 template int Geometry::computeTriangleAngles<TYPE>( \
846 TYPE const *, TYPE const *, TYPE const *, std::array<TYPE, 3> &); \
847 template int Geometry::computeTriangleAngleFromSides<TYPE>( \
848 TYPE const, TYPE const, TYPE const, TYPE &); \
849 template int Geometry::computeTriangleArea<TYPE>( \
850 TYPE const *, TYPE const *, TYPE const *, TYPE &); \
851 template int Geometry::computeTriangleAreaFromSides<TYPE>( \
852 TYPE const, TYPE const, TYPE const, TYPE &); \
853 template int Geometry::crossProduct<TYPE>(TYPE const *, TYPE const *, \
854 TYPE const *, TYPE const *, \
855 std::array<TYPE, 3> &); \
856 template int Geometry::crossProduct<TYPE>( \
857 TYPE const *, TYPE const *, TYPE *); \
858 template TYPE Geometry::distance<TYPE>( \
859 TYPE const *, TYPE const *, int const &); \
860 template TYPE Geometry::distance<TYPE>( \
861 std::vector<TYPE> const &, std::vector<TYPE> const &); \
862 template TYPE Geometry::distanceFlatten<TYPE>( \
863 std::vector<std::vector<TYPE>> const &, \
864 std::vector<std::vector<TYPE>> const &); \
865 template TYPE Geometry::dotProduct<TYPE>( \
866 TYPE const *, TYPE const *, TYPE const *, TYPE const *); \
867 template TYPE Geometry::dotProduct<TYPE>( \
868 TYPE const *, TYPE const *, int const &); \
869 template TYPE Geometry::dotProduct<TYPE>( \
870 std::vector<TYPE> const &, std::vector<TYPE> const &); \
871 template TYPE Geometry::dotProductFlatten<TYPE>( \
872 std::vector<std::vector<TYPE>> const &, \
873 std::vector<std::vector<TYPE>> const &); \
874 template bool Geometry::isPointInTriangle<TYPE>( \
875 TYPE const *, TYPE const *, TYPE const *, TYPE const *); \
876 template bool Geometry::isPointOnSegment<TYPE>(TYPE const &, TYPE const &, \
877 TYPE const &, TYPE const &, \
878 TYPE const &, TYPE const &); \
879 template bool Geometry::isPointOnSegment<TYPE>( \
880 TYPE const *, TYPE const *, TYPE const *, int const &); \
881 template bool Geometry::isTriangleColinear<TYPE>( \
882 TYPE const *, TYPE const *, TYPE const *, TYPE const *); \
883 template TYPE Geometry::magnitude<TYPE>(TYPE const *, int const &); \
884 template TYPE Geometry::magnitude<TYPE>(std::vector<TYPE> const &); \
885 template TYPE Geometry::magnitudeFlatten<TYPE>( \
886 std::vector<std::vector<TYPE>> const &); \
887 template TYPE Geometry::magnitude<TYPE>(TYPE const *, TYPE const *); \
888 template void Geometry::projectOnTrianglePlane<TYPE>( \
889 TYPE const *, TYPE const *, TYPE const *, TYPE *); \
890 template void Geometry::projectOnEdge<TYPE>( \
891 TYPE const *, TYPE const *, TYPE const *, TYPE *); \
892 template void Geometry::computeTriangleNormal<TYPE>( \
893 TYPE const *, TYPE const *, TYPE const *, TYPE *); \
894 template int Geometry::subtractVectors<TYPE>( \
895 TYPE const *, TYPE const *, TYPE *, int const &); \
896 template int Geometry::subtractVectors<TYPE>(std::vector<TYPE> const &, \
897 std::vector<TYPE> const &, \
898 std::vector<TYPE> &); \
899 template int Geometry::addVectors<TYPE>( \
900 TYPE const *, TYPE const *, TYPE *, int const &); \
901 template int Geometry::addVectors<TYPE>(std::vector<TYPE> const &, \
902 std::vector<TYPE> const &, \
903 std::vector<TYPE> &); \
904 template int Geometry::multiAddVectors<TYPE>( \
905 std::vector<std::vector<TYPE>> const &, \
906 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &); \
907 template int Geometry::multiAddVectorsFlatten<TYPE>( \
908 std::vector<std::vector<std::vector<TYPE>>> const &, \
909 std::vector<std::vector<std::vector<TYPE>>> const &, \
910 std::vector<std::vector<TYPE>> &); \
911 template int Geometry::scaleVector<TYPE>( \
912 TYPE const *, TYPE const, TYPE *, int const &); \
913 template int Geometry::scaleVector<TYPE>( \
914 std::vector<TYPE> const &, TYPE const, std::vector<TYPE> &); \
915 template int Geometry::vectorProjection<TYPE>( \
916 TYPE const *, TYPE const *, TYPE *, int const &); \
917 template int Geometry::vectorProjection<TYPE>(std::vector<TYPE> const &, \
918 std::vector<TYPE> const &, \
919 std::vector<TYPE> &); \
920 template void Geometry::addVectorsProjection<TYPE>( \
921 std::vector<TYPE> const &, std::vector<TYPE> const &, std::vector<TYPE> &, \
922 std::vector<TYPE> &); \
923 template void Geometry::gramSchmidt<TYPE>( \
924 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &); \
925 template bool Geometry::isVectorUniform<TYPE>(std::vector<TYPE> const &); \
926 template bool Geometry::isVectorNull<TYPE>(std::vector<TYPE> const &); \
927 template bool Geometry::isVectorNullFlatten<TYPE>( \
928 std::vector<std::vector<TYPE>> const &); \
929 template int Geometry::flattenMultiDimensionalVector<TYPE>( \
930 std::vector<std::vector<TYPE>> const &, std::vector<TYPE> &); \
931 template int Geometry::multiFlattenMultiDimensionalVector<TYPE>( \
932 std::vector<std::vector<std::vector<TYPE>>> const &, \
933 std::vector<std::vector<TYPE>> &); \
934 template int Geometry::unflattenMultiDimensionalVector<TYPE>( \
935 std::vector<TYPE> const &, std::vector<std::vector<TYPE>> &, int const &); \
936 template void Geometry::matrixMultiplication<TYPE>( \
937 std::vector<std::vector<TYPE>> const &, \
938 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &); \
939 template void Geometry::subtractMatrices<TYPE>( \
940 std::vector<std::vector<TYPE>> const &, \
941 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &); \
942 template void Geometry::addMatrices<TYPE>( \
943 std::vector<std::vector<TYPE>> const &, \
944 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &); \
945 template void Geometry::scaleMatrix<TYPE>( \
946 std::vector<std::vector<TYPE>> const &, TYPE const, \
947 std::vector<std::vector<TYPE>> &); \
948 template void Geometry::transposeMatrix<TYPE>( \
949 std::vector<std::vector<TYPE>> const &, std::vector<std::vector<TYPE>> &);
950
951// explicit specializations for float and double
#define GEOMETRY_SPECIALIZE(TYPE)
Definition Geometry.cpp:826
#define M_PI
Definition Os.h:50
int scaleVector(const T *a, const T factor, T *out, const int &dimension=3)
Definition Geometry.cpp:647
bool areVectorsColinear(const T *vA0, const T *vA1, const T *vB0, const T *vB1, std::array< T, 3 > *coefficients=nullptr, const T *tolerance=NULL)
Definition Geometry.cpp:27
int computeTriangleArea(const T *p0, const T *p1, const T *p2, T &area)
Definition Geometry.cpp:281
int addVectors(const T *a, const T *b, T *out, const int &dimension=3)
Definition Geometry.cpp:610
void projectOnEdge(const T *p, const T *a, const T *b, T *out)
Compute euclidean projection on a 3D segment.
Definition Geometry.cpp:550
T dotProductFlatten(const std::vector< std::vector< T > > &vA, const std::vector< std::vector< T > > &vB)
Definition Geometry.cpp:412
int multiFlattenMultiDimensionalVector(const std::vector< std::vector< std::vector< T > > > &a, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:752
void subtractMatrices(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:788
bool isTriangleColinear2D(const T *pptA, const T *pptB, const T *pptC, const T tolerance)
Definition Geometry.cpp:130
T dotProduct(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
Definition Geometry.cpp:388
void matrixMultiplication(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:777
bool isVectorNullFlatten(const std::vector< std::vector< T > > &a)
Definition Geometry.cpp:735
bool isPointOnSegment(const T &x, const T &y, const T &xA, const T &yA, const T &xB, const T &yB)
Definition Geometry.cpp:443
bool computeSegmentIntersection(const T &xA, const T &yA, const T &xB, const T &yB, const T &xC, const T &yC, const T &xD, const T &yD, T &x, T &y)
Definition Geometry.cpp:248
int computeBarycentricCoordinates(const T *p0, const T *p1, const T *p, std::array< T, 2 > &baryCentrics, const int &dimension=3)
Definition Geometry.cpp:142
void projectOnTrianglePlane(const T *p, const T *a, const T *normTri, T *out)
Compute euclidean projection in a triangle plane.
Definition Geometry.cpp:538
void addMatrices(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:798
void gramSchmidt(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:701
void scaleMatrix(const std::vector< std::vector< T > > &a, const T factor, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:808
int multiAddVectors(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:625
int flattenMultiDimensionalVector(const std::vector< std::vector< T > > &a, std::vector< T > &out)
Definition Geometry.cpp:742
bool isVectorUniform(const std::vector< T > &a)
Definition Geometry.cpp:719
int subtractVectors(const T *a, const T *b, T *out, const int &dimension=3)
Definition Geometry.cpp:592
int computeTriangleAreaFromSides(const T s0, const T s1, const T s2, T &area)
Definition Geometry.cpp:296
T magnitudeFlatten(const std::vector< std::vector< T > > &v)
Definition Geometry.cpp:519
bool isVectorNull(const std::vector< T > &a)
Definition Geometry.cpp:727
void computeTriangleNormal(const T *a, const T *b, const T *c, T *out)
Compute normal vector to triangle.
Definition Geometry.cpp:564
T1 pow(const T1 val, const T2 n)
Definition Geometry.h:456
bool isTriangleColinear(const T *p0, const T *p1, const T *p2, const T *tolerance=nullptr)
Definition Geometry.cpp:466
T angle(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
Definition Geometry.cpp:13
void addVectorsProjection(const std::vector< T > &a, const std::vector< T > &b, std::vector< T > &a_out, std::vector< T > &b_out)
Definition Geometry.cpp:690
int computeTriangleAngles(const T *p0, const T *p1, const T *p2, std::array< T, 3 > &angles)
Definition Geometry.cpp:308
int computeTriangleAngleFromSides(const T s0, const T s1, const T s2, T &angle)
Definition Geometry.cpp:321
int vectorProjection(const T *a, const T *b, T *out, const int &dimension=3)
Definition Geometry.cpp:665
int crossProduct(const T *vA0, const T *vA1, const T *vB0, const T *vB1, std::array< T, 3 > &crossProduct)
Definition Geometry.cpp:332
void transposeMatrix(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:818
int unflattenMultiDimensionalVector(const std::vector< T > &a, std::vector< std::vector< T > > &out, const int &no_columns=2)
Definition Geometry.cpp:762
T magnitude(const T *v, const int &dimension=3)
Definition Geometry.cpp:509
T distance(const T *p0, const T *p1, const int &dimension=3)
Definition Geometry.cpp:362
T angle2D(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
Definition Geometry.cpp:20
T distanceFlatten(const std::vector< std::vector< T > > &p0, const std::vector< std::vector< T > > &p1)
Definition Geometry.cpp:379
int multiAddVectorsFlatten(const std::vector< std::vector< std::vector< T > > > &a, const std::vector< std::vector< std::vector< T > > > &b, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:635
bool isPointInTriangle(const T *p0, const T *p1, const T *p2, const T *p)
Definition Geometry.cpp:421
The Topology ToolKit.