26 T
angle(
const T *vA0,
const T *vA1,
const T *vB0,
const T *vB1);
29 T
angle2D(
const T *vA0,
const T *vA1,
const T *vB0,
const T *vB1);
34 double angle = angle2D<T>(vA, vB, vA, vC);
56 std::array<T, 3> *coefficients =
nullptr,
57 const T *tolerance = NULL);
78 std::array<T, 2> &baryCentrics,
79 const int &dimension = 3);
95 std::array<T, 3> &baryCentrics);
109 template <
typename T>
126 template <
typename T>
130 std::array<T, 3> &angles);
138 template <
typename T>
150 template <
typename T>
159 template <
typename T>
170 template <
typename T>
182 template <
typename T>
190 template <
typename T>
191 T
distance(
const T *p0,
const T *p1,
const int &dimension = 3);
196 template <
typename T>
197 T
distance(
const std::vector<T> &p0,
const std::vector<T> &p1);
199 template <
typename T>
202 T di0 = (p0[0] - p1[0]);
203 T di1 = (p0[1] - p1[1]);
204 if(std::is_same<T, float>::value) {
219 template <
typename T>
221 const std::vector<std::vector<T>> &p1);
227 template <
typename T>
229 const std::vector<std::vector<T>> &p1);
237 template <
typename T>
238 T
dotProduct(
const T *vA0,
const T *vA1,
const T *vB0,
const T *vB1);
246 template <
typename T>
247 T
dotProduct(
const T *vA,
const T *vB,
const int &dimension = 3);
253 template <
typename T>
254 T
dotProduct(
const std::vector<T> &vA,
const std::vector<T> &vB);
260 template <
typename T>
262 const std::vector<std::vector<T>> &vB);
272 template <
typename T,
typename Container,
size_t dim>
274 std::array<std::pair<T, T>, dim> &bBox) {
279 for(
size_t i = 0; i < points.size(); i++) {
282 for(
size_t j = 0; j < dim; j++) {
283 bBox[j].first = points[i][j];
284 bBox[j].second = points[i][j];
287 for(
size_t j = 0; j < dim; j++) {
288 if(points[i][j] < bBox[j].first) {
289 bBox[j].first = points[i][j];
291 if(points[i][j] > bBox[j].second) {
292 bBox[j].second = points[i][j];
307 template <
typename T>
319 template <
typename T>
335 template <
typename T>
339 const int &dimension = 3);
347 template <
typename T>
351 const T *tolerance =
nullptr);
358 template <
typename T>
359 T
magnitude(
const T *v,
const int &dimension = 3);
364 template <
typename T>
371 template <
typename T>
377 template <
typename T>
382 template <
typename T>
383 inline T
powInt(
const T val,
const int n) {
385 return 1.0 /
powInt(val, -n);
393 return val * val * val;
396 for(
int i = 0; i < n - 1; ++i) {
404 template <
typename T =
double>
406 return powInt(
static_cast<T
>(10), n);
430#define TTK_POW_LAMBDA(CALLEXPR, TYPE, EXPN, ...) \
432 const auto one = [](const TYPE ttkNotUsed(a)) { return TYPE{1}; }; \
433 const auto id = [](const TYPE a) { return a; }; \
434 const auto square = [](const TYPE a) { return a * a; }; \
435 const auto cube = [](const TYPE a) { return a * a * a; }; \
437 = [EXPN](const TYPE a) { return Geometry::powInt(a, EXPN); }; \
440 CALLEXPR(__VA_ARGS__, one); \
441 } else if(EXPN == 1) { \
442 CALLEXPR(__VA_ARGS__, id); \
443 } else if(EXPN == 2) { \
444 CALLEXPR(__VA_ARGS__, square); \
445 } else if(EXPN == 3) { \
446 CALLEXPR(__VA_ARGS__, cube); \
448 CALLEXPR(__VA_ARGS__, powInt); \
455 template <
typename T1,
typename T2>
456 inline T1
pow(
const T1 val,
const T2 n) {
458 std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value,
459 "pow can only be applied on arithmetic values");
461 if(std::is_integral<T2>::value) {
463 }
else if(std::is_floating_point<T2>::value) {
464 return std::pow(val, n);
480 template <
typename T>
493 template <
typename T>
494 void projectOnEdge(
const T *p,
const T *a,
const T *b, T *out);
505 template <
typename T>
516 template <
typename T,
typename triangulationType>
518 std::vector<T> &dists,
519 const triangulationType &triangulation) {
520 for(
SimplexId i = 0; i < triangulation.getNumberOfVertices(); ++i) {
521 std::array<T, 3> pv{};
522 triangulation.getVertexPoint(i, pv[0], pv[1], pv[2]);
525 return std::min_element(dists.begin(), dists.end()) - dists.begin();
535 template <
typename T>
537 subtractVectors(
const T *a,
const T *b, T *out,
const int &dimension = 3);
544 template <
typename T>
546 const std::vector<T> &b,
547 std::vector<T> &out);
556 template <
typename T>
557 int addVectors(
const T *a,
const T *b, T *out,
const int &dimension = 3);
564 template <
typename T>
566 const std::vector<T> &b,
567 std::vector<T> &out);
573 template <
typename T>
575 const std::vector<std::vector<T>> &b,
576 std::vector<std::vector<T>> &out);
583 template <
typename T>
586 const std::vector<std::vector<std::vector<T>>> &b,
587 std::vector<std::vector<T>> &out);
596 template <
typename T>
598 scaleVector(
const T *a,
const T factor, T *out,
const int &dimension = 3);
605 template <
typename T>
607 scaleVector(
const std::vector<T> &a,
const T factor, std::vector<T> &out);
616 template <
typename T>
620 const int &dimension = 3);
627 template <
typename T>
629 const std::vector<T> &b,
630 std::vector<T> &out);
637 template <
typename T>
639 const std::vector<T> &b,
640 std::vector<T> &a_out,
641 std::vector<T> &b_out);
648 template <
typename T>
649 void gramSchmidt(
const std::vector<std::vector<T>> &a,
650 std::vector<std::vector<T>> &out);
655 template <
typename T>
661 template <
typename T>
668 template <
typename T>
676 template <
typename T>
678 std::vector<T> &out);
684 template <
typename T>
686 const std::vector<std::vector<std::vector<T>>> &a,
687 std::vector<std::vector<T>> &out);
696 template <
typename T>
698 std::vector<std::vector<T>> &out,
699 const int &no_columns = 2);
705 template <
typename T>
707 const std::vector<std::vector<T>> &b,
708 std::vector<std::vector<T>> &out);
715 template <
typename T>
717 const std::vector<std::vector<T>> &b,
718 std::vector<std::vector<T>> &out);
724 template <
typename T>
725 void addMatrices(
const std::vector<std::vector<T>> &a,
726 const std::vector<std::vector<T>> &b,
727 std::vector<std::vector<T>> &out);
733 template <
typename T>
734 void scaleMatrix(
const std::vector<std::vector<T>> &a,
736 std::vector<std::vector<T>> &out);
741 template <
typename T>
743 std::vector<std::vector<T>> &out);
752 template <
typename triangulationType>
755 const triangulationType &triangulation) {
757 std::array<float, 3> res{};
760 std::vector<std::array<SimplexId, 2>> edges{};
762 const auto nStar{triangulation.getVertexStarNumber(a)};
764 if(triangulation.getCellVertexNumber(0) == 3) {
768 triangulation.getVertexStar(a, i, c);
770 triangulation.getCellVertex(c, 0, v0);
772 triangulation.getCellVertex(c, 1, v0);
774 triangulation.getCellVertex(c, 1, v1);
776 triangulation.getCellVertex(c, 2, v1);
779 edges.emplace_back(std::array<SimplexId, 2>{v0, v1});
781 }
else if(triangulation.getCellVertexNumber(0) == 4) {
785 triangulation.getVertexStar(a, i, c);
786 std::array<SimplexId, 4> q{};
787 triangulation.getCellVertex(c, 0, q[0]);
788 triangulation.getCellVertex(c, 1, q[1]);
789 triangulation.getCellVertex(c, 2, q[2]);
790 triangulation.getCellVertex(c, 3, q[3]);
792 edges.emplace_back(std::array<SimplexId, 2>{
796 }
else if(q[1] == a) {
797 edges.emplace_back(std::array<SimplexId, 2>{
801 }
else if(q[2] == a) {
802 edges.emplace_back(std::array<SimplexId, 2>{
806 }
else if(q[3] == a) {
807 edges.emplace_back(std::array<SimplexId, 2>{
816 std::array<float, 3> pa{};
817 triangulation.getVertexPoint(a, pa[0], pa[1], pa[2]);
820 std::vector<std::array<float, 3>> normals{};
821 normals.reserve(nStar);
823 for(
auto &e : edges) {
824 std::array<float, 3> pb{}, pc{};
825 triangulation.getVertexPoint(e[0], pb[0], pb[1], pb[2]);
826 triangulation.getVertexPoint(e[1], pc[0], pc[1], pc[2]);
828 std::array<float, 3> normal{};
831 if(normal[0] != -1.0F && normal[1] != -1.0F && normal[2] != -1.0F) {
833 normals.emplace_back(normal);
837 if(!normals.empty()) {
840 for(
size_t i = 1; i < normals.size(); ++i) {
841 const auto dotProd =
dotProduct(normals[0].data(), normals[i].data());
843 scaleVector(normals[i].data(), -1.0F, normals[i].data());
848 for(
unsigned int i = 0; i < normals.size(); ++i)
849 addVectors(res.data(), normals[i].data(), res.data());
850 scaleVector(res.data(),
static_cast<float>(normals.size()), res.data());
866 std::array<float, 3>
pt;
884 std::array<float, 3> &
pt;
889 template <
typename triangulationType0,
typename triangulationType1>
893 std::vector<float> &dists,
894 std::stack<SimplexId> &trianglesToTest,
895 const bool reverseProjection,
896 const triangulationType0 &triangulationToSmooth,
897 const triangulationType1 &triangulation) {
901 std::array<float, 3> surfaceNormal{};
902 if(reverseProjection) {
905 res.reverseProjection = !std::isnan(surfaceNormal[0]);
909 while(!trianglesToTest.empty()) {
910 trianglesToTest.pop();
914 if(triangulation.getVertexTriangleNumber(res.nearestVertex) > 0) {
916 triangulation.getVertexTriangle(res.nearestVertex, 0, next);
917 trianglesToTest.push(next);
920 while(!trianglesToTest.empty()) {
922 const auto curr = trianglesToTest.top();
923 trianglesToTest.pop();
931 std::array<SimplexId, 3> tverts{};
932 triangulation.getTriangleVertex(curr, 0, tverts[0]);
933 triangulation.getTriangleVertex(curr, 1, tverts[1]);
934 triangulation.getTriangleVertex(curr, 2, tverts[2]);
937 std::array<std::array<float, 3>, 3>
939 triangulation.getVertexPoint(
940 tverts[0], mno[0][0], mno[0][1], mno[0][2]);
941 triangulation.getVertexPoint(
942 tverts[1], mno[1][0], mno[1][1], mno[1][2]);
943 triangulation.getVertexPoint(
944 tverts[2], mno[2][0], mno[2][1], mno[2][2]);
946 std::array<float, 3> normTri{};
948 mno[0].data(), mno[1].data(), mno[2].data(), normTri.data());
950 static const float PREC_FLT{powf(10, -FLT_DIG)};
952 if(res.reverseProjection) {
954 const auto denom =
dotProduct(surfaceNormal.data(), normTri.data());
957 if(std::abs(denom) < PREC_FLT) {
959 for(
auto &vert : tverts) {
960 auto ntr = triangulation.getVertexTriangleNumber(vert);
963 triangulation.getVertexTriangle(vert, j, tid);
965 trianglesToTest.push(tid);
974 std::array<float, 3> tmp{};
976 auto alpha =
dotProduct(tmp.data(), normTri.data()) / denom;
977 std::array<float, 3> surfaceNormalScaled{};
978 scaleVector(surfaceNormal.data(), alpha, surfaceNormalScaled.data());
979 addVectors(pi.
pt.data(), surfaceNormalScaled.data(), res.pt.data());
983 pi.
pt.data(), mno[0].data(), normTri.data(), res.pt.data());
987 std::array<float, 3> baryCoords{};
989 mno[2].data(), res.pt.data(), baryCoords);
992 bool inTriangle =
true;
994 for(
auto &coord : baryCoords) {
995 if(coord < -PREC_FLT) {
998 if(coord > 1 + PREC_FLT) {
1004 trianglesTested.
insert(curr);
1005 res.trianglesChecked++;
1008 res.projSuccess =
true;
1015 = std::minmax_element(baryCoords.begin(), baryCoords.end());
1019 std::array<SimplexId, 2> vid{
1020 static_cast<SimplexId>(extrema.second - baryCoords.begin()), 0};
1021 for(
size_t j = 0; j < baryCoords.size(); j++) {
1022 if(j !=
static_cast<size_t>(extrema.first - baryCoords.begin())
1023 && j !=
static_cast<size_t>(extrema.second - baryCoords.begin())) {
1030 res.nearestVertex = tverts[vid[0]];
1031 const auto secondNearVert{tverts[vid[1]]};
1035 const auto nEdges{triangulation.getVertexEdgeNumber(res.nearestVertex)};
1037 triangulation.getVertexEdge(res.nearestVertex, i, edge);
1039 triangulation.getEdgeVertex(edge, 0, v);
1040 if(v == res.nearestVertex) {
1041 triangulation.getEdgeVertex(edge, 1, v);
1043 if(v == secondNearVert) {
1050 const auto nTri{triangulation.getEdgeTriangleNumber(edge)};
1052 triangulation.getEdgeTriangle(edge, i, next);
1058 const auto nVisited{trianglesTested.
visitedIds_.size()};
1059 if(nVisited > 1 && next == trianglesTested.
visitedIds_[nVisited - 2]) {
1066 res.pt.data(), mno[vid[0]].data(), mno[vid[1]].data());
1067 if(!res.projSuccess) {
1069 triangulation.getVertexPoint(
1070 tverts[vid[0]], res.pt[0], res.pt[1], res.pt[2]);
1071 res.projSuccess =
true;
1077 trianglesToTest.push(next);
1081 const size_t maxTrChecked = 100;
1083 if(res.projSuccess && res.trianglesChecked > maxTrChecked) {
1084 res.projSuccess =
false;
1087 std::array<float, 3> nearestCoords{};
1088 triangulation.getVertexPoint(
1089 pi.
nearestVertex, nearestCoords[0], nearestCoords[1], nearestCoords[2]);
1092 res.projSuccess =
false;
1093 if(triangulationToSmooth.getDimensionality() == 2
1094 && !reverseProjection) {
1100 return findProjection(pi, trianglesTested, dists, trianglesToTest,
1101 true, triangulationToSmooth, triangulation);
1105 if(!res.projSuccess) {
1108 pi.
pt.data(), dists, triangulation);
1109 triangulation.getVertexPoint(
1110 res.nearestVertex, res.pt[0], res.pt[1], res.pt[2]);
int scaleVector(const T *a, const T factor, T *out, const int &dimension=3)
bool areVectorsColinear(const T *vA0, const T *vA1, const T *vB0, const T *vB1, std::array< T, 3 > *coefficients=nullptr, const T *tolerance=NULL)
int computeTriangleArea(const T *p0, const T *p1, const T *p2, T &area)
double angle2DUndirected(const T *vA, const T *vB, const T *vC)
int addVectors(const T *a, const T *b, T *out, const int &dimension=3)
void projectOnEdge(const T *p, const T *a, const T *b, T *out)
Compute euclidean projection on a 3D segment.
T dotProductFlatten(const std::vector< std::vector< T > > &vA, const std::vector< std::vector< T > > &vB)
int multiFlattenMultiDimensionalVector(const std::vector< std::vector< std::vector< T > > > &a, std::vector< std::vector< T > > &out)
void subtractMatrices(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
bool isTriangleColinear2D(const T *pptA, const T *pptB, const T *pptC, const T tolerance)
T dotProduct(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
void matrixMultiplication(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
bool isVectorNullFlatten(const std::vector< std::vector< T > > &a)
bool isPointOnSegment(const T &x, const T &y, const T &xA, const T &yA, const T &xB, const T &yB)
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)
int computeBarycentricCoordinates(const T *p0, const T *p1, const T *p, std::array< T, 2 > &baryCentrics, const int &dimension=3)
void projectOnTrianglePlane(const T *p, const T *a, const T *normTri, T *out)
Compute euclidean projection in a triangle plane.
void addMatrices(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
void gramSchmidt(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
void scaleMatrix(const std::vector< std::vector< T > > &a, const T factor, std::vector< std::vector< T > > &out)
int multiAddVectors(const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b, std::vector< std::vector< T > > &out)
SimplexId getNearestSurfaceVertex(const T *pa, std::vector< T > &dists, const triangulationType &triangulation)
Find nearest vertex on the surface.
int flattenMultiDimensionalVector(const std::vector< std::vector< T > > &a, std::vector< T > &out)
bool isVectorUniform(const std::vector< T > &a)
int subtractVectors(const T *a, const T *b, T *out, const int &dimension=3)
int computeTriangleAreaFromSides(const T s0, const T s1, const T s2, T &area)
T magnitudeFlatten(const std::vector< std::vector< T > > &v)
bool isVectorNull(const std::vector< T > &a)
void computeTriangleNormal(const T *a, const T *b, const T *c, T *out)
Compute normal vector to triangle.
T1 pow(const T1 val, const T2 n)
T distance2D(const T *p0, const T *p1)
bool isTriangleColinear(const T *p0, const T *p1, const T *p2, const T *tolerance=nullptr)
int getBoundingBox(const Container &points, std::array< std::pair< T, T >, dim > &bBox)
T angle(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
void addVectorsProjection(const std::vector< T > &a, const std::vector< T > &b, std::vector< T > &a_out, std::vector< T > &b_out)
T powIntTen(const int n)
Compute the nth power of ten.
T powInt(const T val, const int n)
int computeTriangleAngles(const T *p0, const T *p1, const T *p2, std::array< T, 3 > &angles)
int computeTriangleAngleFromSides(const T s0, const T s1, const T s2, T &angle)
int vectorProjection(const T *a, const T *b, T *out, const int &dimension=3)
int crossProduct(const T *vA0, const T *vA1, const T *vB0, const T *vB1, std::array< T, 3 > &crossProduct)
void transposeMatrix(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
std::array< float, 3 > computeSurfaceNormalAtPoint(const SimplexId a, const triangulationType &triangulation)
Compute (mean) surface normal at given surface vertex.
int unflattenMultiDimensionalVector(const std::vector< T > &a, std::vector< std::vector< T > > &out, const int &no_columns=2)
T magnitude(const T *v, const int &dimension=3)
T distance(const T *p0, const T *p1, const int &dimension=3)
T angle2D(const T *vA0, const T *vA1, const T *vB0, const T *vB1)
ProjectionResult findProjection(const ProjectionInput &pi, VisitedMask &trianglesTested, std::vector< float > &dists, std::stack< SimplexId > &trianglesToTest, const bool reverseProjection, const triangulationType0 &triangulationToSmooth, const triangulationType1 &triangulation)
T distanceFlatten(const std::vector< std::vector< T > > &p0, const std::vector< std::vector< T > > &p1)
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)
bool isPointInTriangle(const T *p0, const T *p1, const T *p2, const T *p)
int SimplexId
Identifier type for simplices of any dimension.
Stores the findProjection() result.
std::array< float, 3 > pt
Auto-cleaning re-usable graph propagations data structure.
std::vector< bool > & isVisited_
void insert(const SimplexId id)
std::vector< SimplexId > & visitedIds_