15 const std::vector<int>& faces,
16 const std::vector<Eigen::Vector3d>& vertices_ref,
17 const std::vector<Eigen::Vector3d>& vertices_cur) {
21 if (faces.size() % 3 != 0) {
22 LOG_ERROR <<
"Faces must be Nx3 (got " << faces.size() <<
" elements)";
26 size_t n_faces = faces.size() / 3;
29 result.
D1.resize(n_faces);
30 result.
D2.resize(n_faces);
31 result.
D3.resize(n_faces);
32 result.
d1.resize(n_faces);
33 result.
d2.resize(n_faces);
34 result.
d3.resize(n_faces);
35 result.
Drec1.resize(n_faces);
36 result.
Drec2.resize(n_faces);
37 result.
Dnorm.resize(n_faces);
38 result.
Fmat.resize(n_faces);
39 result.
Cmat.resize(n_faces);
40 result.
Lamda1.resize(n_faces);
41 result.
Lamda2.resize(n_faces);
42 result.
J.resize(n_faces);
43 result.
Emat.resize(n_faces);
44 result.
emat.resize(n_faces);
45 result.
Emgn.resize(n_faces);
46 result.
emgn.resize(n_faces);
47 result.
Epc1.resize(n_faces);
48 result.
Epc2.resize(n_faces);
53 result.
epc1.resize(n_faces);
54 result.
epc2.resize(n_faces);
65 result.
Eeq.resize(n_faces);
66 result.
eeq.resize(n_faces);
67 result.
Area.resize(n_faces);
70 for (
size_t itri = 0; itri < n_faces; ++itri) {
71 size_t idx = itri * 3;
73 int v1 = faces[idx + 1];
74 int v2 = faces[idx + 2];
77 if (v0 < 0 || v1 < 0 || v2 < 0 ||
78 static_cast<size_t>(v0) >= vertices_ref.size() ||
static_cast<size_t>(v1) >= vertices_ref.size() ||
static_cast<size_t>(v2) >= vertices_ref.size() ||
79 static_cast<size_t>(v0) >= vertices_cur.size() ||
static_cast<size_t>(v1) >= vertices_cur.size() ||
static_cast<size_t>(v2) >= vertices_cur.size()) {
81 LOG_WARN <<
"Invalid vertex index in triangle " << itri
82 <<
" (v0=" << v0 <<
" v1=" << v1 <<
" v2=" << v2
83 <<
", nRef=" << vertices_ref.size() <<
" nCur=" << vertices_cur.size() <<
")";
86 result.
Fmat[itri] = Eigen::Matrix3d::Constant(std::nan(
""));
91 result.
D1[itri] = vertices_ref[v1] - vertices_ref[v0];
92 result.
D2[itri] = vertices_ref[v2] - vertices_ref[v0];
93 Eigen::Vector3d cross_D = result.
D1[itri].cross(result.
D2[itri]);
94 double norm_D = cross_D.norm();
97 result.
D3[itri] = Eigen::Vector3d(0, 0, 1);
99 result.
D3[itri] = cross_D / norm_D;
103 result.
d1[itri] = vertices_cur[v1] - vertices_cur[v0];
104 result.
d2[itri] = vertices_cur[v2] - vertices_cur[v0];
105 Eigen::Vector3d cross_d = result.
d1[itri].cross(result.
d2[itri]);
106 double norm_d = cross_d.norm();
107 if (norm_d < 1e-12) {
108 result.
d3[itri] = Eigen::Vector3d(0, 0, 1);
110 result.
d3[itri] = cross_d / norm_d;
114 result.
Dnorm[itri] = cross_D.dot(result.
D3[itri]);
115 if (std::abs(result.
Dnorm[itri]) < 1e-12) {
117 result.
Fmat[itri] = Eigen::Matrix3d::Constant(std::nan(
""));
121 result.
Drec1[itri] = result.
D2[itri].cross(result.
D3[itri]) / result.
Dnorm[itri];
122 result.
Drec2[itri] = result.
D3[itri].cross(result.
D1[itri]) / result.
Dnorm[itri];
125 double dnorm_val = cross_d.dot(result.
d3[itri]);
126 result.
Area[itri] = 0.5 * dnorm_val;
129 result.
Fmat[itri] = Eigen::Matrix3d::Zero();
130 for (
int i = 0; i < 3; ++i) {
131 for (
int j = 0; j < 3; ++j) {
132 result.
Fmat[itri](i, j) =
133 result.
d1[itri](i) * result.
Drec1[itri](j) +
134 result.
d2[itri](i) * result.
Drec2[itri](j) +
135 result.
d3[itri](i) * result.
D3[itri](j);
140 if (result.
Fmat[itri].array().isNaN().any()) {
142 result.
Cmat[itri] = Eigen::Matrix3d::Constant(std::nan(
""));
143 result.
Lamda1[itri] = std::nan(
"");
144 result.
Lamda2[itri] = std::nan(
"");
145 result.
J[itri] = std::nan(
"");
146 result.
Emat[itri] = Eigen::Matrix3d::Constant(std::nan(
""));
147 result.
emat[itri] = Eigen::Matrix3d::Constant(std::nan(
""));
148 result.
Emgn[itri] = std::nan(
"");
149 result.
emgn[itri] = std::nan(
"");
150 result.
Epc1[itri] = std::nan(
"");
151 result.
Epc2[itri] = std::nan(
"");
152 result.
Epc1vec[itri] = Eigen::Vector3d::Constant(std::nan(
""));
153 result.
Epc2vec[itri] = Eigen::Vector3d::Constant(std::nan(
""));
154 result.
Epc1vecCur[itri] = Eigen::Vector3d::Constant(std::nan(
""));
155 result.
Epc2vecCur[itri] = Eigen::Vector3d::Constant(std::nan(
""));
156 result.
epc1[itri] = std::nan(
"");
157 result.
epc2[itri] = std::nan(
"");
158 result.
epc1vec[itri] = Eigen::Vector3d::Constant(std::nan(
""));
159 result.
epc2vec[itri] = Eigen::Vector3d::Constant(std::nan(
""));
162 result.
EShearMaxVec1[itri] = Eigen::Vector3d::Constant(std::nan(
""));
163 result.
EShearMaxVec2[itri] = Eigen::Vector3d::Constant(std::nan(
""));
166 result.
eShearMaxVec1[itri] = Eigen::Vector3d::Constant(std::nan(
""));
167 result.
eShearMaxVec2[itri] = Eigen::Vector3d::Constant(std::nan(
""));
168 result.
Eeq[itri] = std::nan(
"");
169 result.
eeq[itri] = std::nan(
"");
174 result.
Cmat[itri] = result.
Fmat[itri].transpose() * result.
Fmat[itri];
177 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigC(result.
Cmat[itri]);
178 Eigen::Vector3d eigvals_C = eigC.eigenvalues();
179 Eigen::Vector3d lamdas = eigvals_C.array().sqrt();
183 double min_diff = std::abs(lamdas(0) - 1.0);
184 for (
int i = 1; i < 3; ++i) {
185 double diff = std::abs(lamdas(i) - 1.0);
186 if (diff < min_diff) {
192 std::vector<double> lamda_vec;
193 for (
int i = 0; i < 3; ++i) {
194 if (i != min_idx) lamda_vec.push_back(lamdas(i));
196 result.
Lamda1[itri] = lamda_vec[0];
197 result.
Lamda2[itri] = lamda_vec[1];
200 result.
J[itri] = result.
Fmat[itri].determinant();
203 result.
Emat[itri] = 0.5 * (result.
Fmat[itri].transpose() * result.
Fmat[itri] - Eigen::Matrix3d::Identity());
206 Eigen::Matrix3d FFT = result.
Fmat[itri] * result.
Fmat[itri].transpose();
207 result.
emat[itri] = 0.5 * (Eigen::Matrix3d::Identity() - FFT.inverse());
210 result.
Emgn[itri] = result.
Emat[itri].norm();
211 result.
emgn[itri] = result.
emat[itri].norm();
214 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigE(result.
Emat[itri]);
215 Eigen::Vector3d eigvals_E = eigE.eigenvalues();
216 Eigen::Matrix3d eigvecs_E = eigE.eigenvectors();
220 double max_dot = std::abs(eigvecs_E.col(0).dot(result.
D3[itri]));
221 for (
int i = 1; i < 3; ++i) {
222 double dot_val = std::abs(eigvecs_E.col(i).dot(result.
D3[itri]));
223 if (dot_val > max_dot) {
230 std::vector<int> plan_idx;
231 for (
int i = 0; i < 3; ++i) {
232 if (i != D3_idx) plan_idx.push_back(i);
236 double E_plan1 = eigvals_E(plan_idx[0]);
237 double E_plan2 = eigvals_E(plan_idx[1]);
239 if (E_plan1 < E_plan2) {
240 result.
Epc1[itri] = E_plan1;
241 result.
Epc2[itri] = E_plan2;
242 result.
Epc1vec[itri] = eigvecs_E.col(plan_idx[0]);
243 result.
Epc2vec[itri] = eigvecs_E.col(plan_idx[1]);
245 result.
Epc1[itri] = E_plan2;
246 result.
Epc2[itri] = E_plan1;
247 result.
Epc1vec[itri] = eigvecs_E.col(plan_idx[1]);
248 result.
Epc2vec[itri] = eigvecs_E.col(plan_idx[0]);
258 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eige(result.
emat[itri]);
259 Eigen::Vector3d eigvals_e = eige.eigenvalues();
260 Eigen::Matrix3d eigvecs_e = eige.eigenvectors();
264 max_dot = std::abs(eigvecs_e.col(0).dot(result.
d3[itri]));
265 for (
int i = 1; i < 3; ++i) {
266 double dot_val = std::abs(eigvecs_e.col(i).dot(result.
d3[itri]));
267 if (dot_val > max_dot) {
274 for (
int i = 0; i < 3; ++i) {
275 if (i != d3_idx) plan_idx.push_back(i);
278 double e_plan1 = eigvals_e(plan_idx[0]);
279 double e_plan2 = eigvals_e(plan_idx[1]);
281 if (e_plan1 < e_plan2) {
282 result.
epc1[itri] = e_plan1;
283 result.
epc2[itri] = e_plan2;
284 result.
epc1vec[itri] = eigvecs_e.col(plan_idx[0]);
285 result.
epc2vec[itri] = eigvecs_e.col(plan_idx[1]);
287 result.
epc1[itri] = e_plan2;
288 result.
epc2[itri] = e_plan1;
289 result.
epc1vec[itri] = eigvecs_e.col(plan_idx[1]);
290 result.
epc2vec[itri] = eigvecs_e.col(plan_idx[0]);
294 const double inv_sqrt2 = 1.0 / std::sqrt(2.0);
309 Eigen::Matrix3d Edev = result.
Emat[itri] - (result.
Emat[itri].trace() / 3.0) * Eigen::Matrix3d::Identity();
310 result.
Eeq[itri] = std::sqrt((2.0 / 3.0) * (Edev.array() * Edev.array()).sum());
312 Eigen::Matrix3d edev = result.
emat[itri] - (result.
emat[itri].trace() / 3.0) * Eigen::Matrix3d::Identity();
313 result.
eeq[itri] = std::sqrt((2.0 / 3.0) * (edev.array() * edev.array()).sum());