CPPxDIC
C++ Digital Image Correlation library for fingertip 3D reconstruction
Loading...
Searching...
No Matches
face_isotropy.cpp
Go to the documentation of this file.
1
6#include "face_isotropy.h"
7#include <cmath>
8#include <limits>
9
10namespace cppxdic {
11
13 const Eigen::Vector3d& v0,
14 const Eigen::Vector3d& v1,
15 const Eigen::Vector3d& v2
16) {
17 // Check for NaN in any vertex
18 if (!v0.allFinite() || !v1.allFinite() || !v2.allFinite()) {
19 return std::numeric_limits<double>::quiet_NaN();
20 }
21
22 // Compute centroid
23 Eigen::Vector3d centroid = (v0 + v1 + v2) / 3.0;
24
25 // Cluster position model: X = [x1-xa, x2-xa, x3-xa]
26 Eigen::Matrix3d X;
27 X.col(0) = v0 - centroid;
28 X.col(1) = v1 - centroid;
29 X.col(2) = v2 - centroid;
30
31 // Compute K = X * X' / 3
32 Eigen::Matrix3d K = (X * X.transpose()) / 3.0;
33
34 // Compute eigenvalues
35 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(K);
36 if (eigensolver.info() != Eigen::Success) {
37 return std::numeric_limits<double>::quiet_NaN();
38 }
39
40 Eigen::Vector3d eigenvalues = eigensolver.eigenvalues();
41
42 // Sort eigenvalues (they should already be sorted by Eigen, but let's be sure)
43 std::sort(eigenvalues.data(), eigenvalues.data() + 3);
44
45 // Isotropy index = 2*λ2 / (λ2 + λ3)
46 // where λ1 ≤ λ2 ≤ λ3 are sorted eigenvalues
47 double lambda2 = eigenvalues(1);
48 double lambda3 = eigenvalues(2);
49
50 // Avoid division by zero
51 double denominator = lambda2 + lambda3;
52 if (std::abs(denominator) < 1e-12) {
53 return 0.0; // Degenerate case
54 }
55
56 double isotropy = 2.0 * lambda2 / denominator;
57
58 // Clamp to [0, 1] due to numerical precision
59 isotropy = std::max(0.0, std::min(1.0, isotropy));
60
61 return isotropy;
62}
63
64std::vector<double> computeFaceIsotropyIndex(
65 const std::vector<int>& faces,
66 const std::vector<Eigen::Vector3d>& vertices
67) {
68 size_t nFaces = faces.size() / 3;
69 std::vector<double> isotropy(nFaces);
70
71 for (size_t iface = 0; iface < nFaces; ++iface) {
72 int i0 = faces[iface * 3 + 0];
73 int i1 = faces[iface * 3 + 1];
74 int i2 = faces[iface * 3 + 2];
75
76 // Bounds check
77 if (i0 < 0 || i0 >= static_cast<int>(vertices.size()) ||
78 i1 < 0 || i1 >= static_cast<int>(vertices.size()) ||
79 i2 < 0 || i2 >= static_cast<int>(vertices.size())) {
80 isotropy[iface] = std::numeric_limits<double>::quiet_NaN();
81 continue;
82 }
83
84 const Eigen::Vector3d& v0 = vertices[i0];
85 const Eigen::Vector3d& v1 = vertices[i1];
86 const Eigen::Vector3d& v2 = vertices[i2];
87
88 isotropy[iface] = computeSingleFaceIsotropyIndex(v0, v1, v2);
89 }
90
91 return isotropy;
92}
93
94} // namespace cppxdic
DataSerializer - Abstract base class for format-agnostic DIC data I/O.
double computeSingleFaceIsotropyIndex(const Eigen::Vector3d &v0, const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Compute isotropy index for a single triangle.
std::vector< double > computeFaceIsotropyIndex(const std::vector< int > &faces, const std::vector< Eigen::Vector3d > &vertices)
Compute isotropy index for triangular faces.
CGAL::Exact_predicates_inexact_constructions_kernel K