23
#include "PreCompiled.h"
34
#define M_PI 3.14159265358979323846f
37
#include <Eigen/SparseCholesky>
39
#include "MeshFlatteningLscmRelax.h"
50
using trip = Eigen::Triplet<double>;
51
using spMat = Eigen::SparseMatrix<double>;
55
ColMat<double, 2> map_to_2D(ColMat<double, 3> points)
57
ColMat<double, 4> mat(points.size(), 4);
58
mat << points, ColMat<double, 1>::Ones(points.size());
59
Eigen::JacobiSVD<Eigen::MatrixXd> svd(mat, Eigen::ComputeThinU | Eigen::ComputeThinV);
60
Vector3 n = svd.matrixV().row(2);
64
if ((n - y).norm() < 0.0001)
66
Vector3 x = n.cross(y);
69
Eigen::Matrix<double, 3, 2> transform;
72
return points * transform;
76
unsigned int get_max_distance(Vector3 point, RowMat<double, 3> vertices, double & max_dist)
80
unsigned long max_dist_index = 0;
82
for (j=0; j < vertices.cols(); j++)
85
dist = (point - vertices.col(j)).norm();
92
return max_dist_index;
97
RowMat<double, 3> vertices,
98
RowMat<long, 3> triangles,
99
std::vector<long> fixed_pins)
101
this->vertices = vertices;
102
this->triangles = triangles;
103
this->flat_vertices.resize(2, this->vertices.cols());
104
this->fixed_pins = fixed_pins;
107
this->set_fixed_pins();
110
unsigned int fixed_count = 0;
111
for (long i=0; i < this->vertices.cols(); i++)
113
if (fixed_count < this->fixed_pins.size())
115
if (i == this->fixed_pins[fixed_count])
118
this->old_order.push_back(i);
121
this->old_order.push_back(i);
124
for (auto fixed_index: this->fixed_pins)
125
this->old_order.push_back(fixed_index);
128
this->new_order.resize(this->old_order.size());
130
for (auto index: this->old_order)
132
this->new_order[index] = j;
137
this->C << 1, nue, 0,
140
this->C *= elasticity / (1 - nue * nue);
148
void LscmRelax::relax(double weight)
150
ColMat<double, 3> d_q_l_g = this->q_l_m - this->q_l_g;
152
Eigen::Matrix<double, 3, 6> B;
153
Eigen::Matrix<double, 2, 2> T;
154
Eigen::Matrix<double, 6, 6> K_m;
155
Eigen::Matrix<double, 6, 1> u_m, rhs_m;
156
Eigen::VectorXd rhs(this->vertices.cols() * 2 + 3);
157
if (this->sol.size() == 0)
158
this->sol.Zero(this->vertices.cols() * 2 + 3);
159
spMat K_g(this->vertices.cols() * 2 + 3, this->vertices.cols() * 2 + 3);
160
std::vector<trip> K_g_triplets;
161
Vector2 v1, v2, v3, v12, v23, v31;
162
long row_pos, col_pos;
167
for (long i=0; i<this->triangles.cols(); i++)
170
v1 = this->flat_vertices.col(this->triangles(0, i));
171
v2 = this->flat_vertices.col(this->triangles(1, i));
172
v3 = this->flat_vertices.col(this->triangles(2, i));
176
B << -v23.y(), 0, -v31.y(), 0, -v12.y(), 0,
177
0, v23.x(), 0, v31.x(), 0, v12.x(),
178
-v23.x(), v23.y(), -v31.x(), v31.y(), -v12.x(), v12.y();
179
T << v12.x(), -v12.y(),
182
A = std::abs(this->q_l_m(i, 0) * this->q_l_m(i, 2) / 2);
186
u_m << Vector2(0, 0), T * Vector2(d_q_l_g(i, 0), 0), T * Vector2(d_q_l_g(i, 1), d_q_l_g(i, 2));
190
rhs_m = B.transpose() * this->C * B * u_m * A;
191
K_m = B.transpose() * this->C * B * A;
194
for (int j=0; j < 3; j++)
196
row_pos = this->triangles(j, i);
197
rhs[row_pos * 2] += rhs_m[j * 2];
198
rhs[row_pos * 2 + 1] += rhs_m[j * 2 +1];
199
for (int k=0; k < 3; k++)
201
col_pos = this->triangles(k, i);
202
K_g_triplets.emplace_back(trip(row_pos * 2, col_pos * 2, K_m(j * 2, k * 2)));
203
K_g_triplets.emplace_back(trip(row_pos * 2 + 1, col_pos * 2, K_m(j * 2 + 1, k * 2)));
204
K_g_triplets.emplace_back(trip(row_pos * 2 + 1, col_pos * 2 + 1, K_m(j * 2 + 1, k * 2 + 1)));
205
K_g_triplets.emplace_back(trip(row_pos * 2, col_pos * 2 + 1, K_m(j * 2, k * 2 + 1)));
254
for (long i=0; i < this->flat_vertices.cols() ; i++)
257
K_g_triplets.emplace_back(trip(i * 2, this->flat_vertices.cols() * 2, 1));
258
K_g_triplets.emplace_back(trip(this->flat_vertices.cols() * 2, i * 2, 1));
260
K_g_triplets.emplace_back(trip(i * 2 + 1, this->flat_vertices.cols() * 2 + 1, 1));
261
K_g_triplets.emplace_back(trip(this->flat_vertices.cols() * 2 + 1, i * 2 + 1, 1));
263
K_g_triplets.emplace_back(trip(i * 2, this->flat_vertices.cols() * 2 + 2, - this->flat_vertices(1, i)));
264
K_g_triplets.emplace_back(trip(this->flat_vertices.cols() * 2 + 2, i * 2, - this->flat_vertices(1, i)));
265
K_g_triplets.emplace_back(trip(i * 2 + 1, this->flat_vertices.cols() * 2 + 2, this->flat_vertices(0, i)));
266
K_g_triplets.emplace_back(trip(this->flat_vertices.cols() * 2 + 2, i * 2 + 1, this->flat_vertices(0, i)));
285
K_g.setFromTriplets(K_g_triplets.begin(), K_g_triplets.end());
289
Eigen::SimplicialLDLT<spMat, Eigen::Lower> solver;
291
this->sol = solver.solve(-rhs);
292
this->set_shift(this->sol.head(this->vertices.cols() * 2) * weight);
297
void LscmRelax::area_relax(double weight)
300
if (this->sol.size() == 0)
301
this->sol.Zero(this->vertices.cols());
302
std::vector<trip> K_g_triplets;
303
spMat K_g(this->vertices.cols() * 2, this->vertices.cols() * 2);
304
spMat K_g_lsq(this->triangles.cols(), this->vertices.cols() * 2);
305
Eigen::VectorXd rhs_lsq(this->triangles.cols());
306
Eigen::VectorXd rhs(this->vertices.cols() * 2);
309
Eigen::Matrix<double, 1, 6> B;
311
Vector2 v1, v2, v3, v12, v23, v31;
314
for (long i=0; i<this->triangles.cols(); i++)
317
v1 = this->flat_vertices.col(this->triangles(0, i));
318
v2 = this->flat_vertices.col(this->triangles(1, i));
319
v3 = this->flat_vertices.col(this->triangles(2, i));
323
B << -v23.y(), v23.x(), -v31.y(), v31.x(), -v12.y(), v12.x();
324
delta_a = fabs(this->q_l_g(i, 0) * this->q_l_g(i, 2)) -
325
fabs(this->q_l_m(i, 0) * this->q_l_m(i, 2));
326
rhs_lsq[i] = delta_a * 0.1;
328
std::array<int, 6> range_6 {{0, 1, 2, 3, 4, 5}};
329
std::array<long, 6> indices;
330
for (int index=0; index<3; index++)
332
indices[index * 2] = this->triangles(index, i) * 2;
333
indices[index * 2 + 1] = this->triangles(index, i) * 2 + 1;
336
for(auto col: range_6)
338
K_g_triplets.emplace_back(trip(i, indices[col], (double) B[col]));
341
K_g_lsq.setFromTriplets(K_g_triplets.begin(), K_g_triplets.end());
342
K_g_triplets.clear();
344
K_g.setFromTriplets(K_g_triplets.begin(), K_g_triplets.end());
345
Eigen::ConjugateGradient<spMat> solver;
347
this->sol = solver.solve(-rhs);
348
this->set_shift(this->sol * weight);
352
void LscmRelax::edge_relax(double weight)
355
std::set<std::array<long, 2>> edges;
356
std::array<long, 2> edge;
357
for(long i=0; i<this->triangles.cols(); i++)
359
for(int j=0; j<3; j++)
364
if (this->triangles(j, i) < this->triangles(k, i))
365
edge = std::array<long, 2>{{this->triangles(j, i), this->triangles(k, i)}};
367
edge = std::array<long, 2>{{this->triangles(k, i), this->triangles(j, i)}};
373
if (this->sol.size() == 0)
374
this->sol.Zero(this->vertices.cols());
376
std::vector<trip> K_g_triplets;
377
spMat K_g(this->vertices.cols() * 2, this->vertices.cols() * 2);
378
Eigen::VectorXd rhs(this->vertices.cols() * 2);
380
for(auto edge : edges)
383
Vector3 v1_g = this->vertices.col(edge[0]);
384
Vector3 v2_g = this->vertices.col(edge[1]);
385
Vector2 v1_l = this->flat_vertices.col(edge[0]);
386
Vector2 v2_l = this->flat_vertices.col(edge[1]);
387
std::vector<int> range_4 {0, 1, 2, 3};
388
std::vector<long> indices {edge[0] * 2, edge[0] * 2 + 1, edge[1] * 2, edge[1] * 2 + 1};
389
double l_g = (v2_g - v1_g).norm();
390
double l_l = (v2_l - v1_l).norm();
391
Vector2 t = (v2_l - v1_l);
394
Eigen::Matrix<double, 1, 4> B;
395
Eigen::Matrix<double, 4, 4> K;
396
Eigen::Matrix<double, 4, 1> rhs_m;
398
B << -t.x(), -t.y(), t.x(), t.y();
399
K = 1. / l_g * B.transpose() * B;
400
rhs_m = - B.transpose() * (l_g - l_l);
403
for(auto row: range_4)
405
for (auto col: range_4)
407
K_g_triplets.emplace_back(trip(indices[row], indices[col], (double) K(row, col)));
409
rhs(indices[row]) += rhs_m[row];
413
K_g.setFromTriplets(K_g_triplets.begin(), K_g_triplets.end());
414
Eigen::ConjugateGradient<spMat,Eigen::Lower, NullSpaceProjector> solver;
415
solver.preconditioner().setNullSpace(this->get_nullspace());
417
this->sol = solver.solve(-rhs);
418
this->set_shift(this->sol * weight);
425
void LscmRelax::lscm()
428
std::vector<trip> triple_list;
430
double x21, x31, y31, x32;
433
for(i=0; i<this->triangles.cols(); i++)
435
x21 = this->q_l_g(i, 0);
436
x31 = this->q_l_g(i, 1);
437
y31 = this->q_l_g(i, 2);
440
triple_list.emplace_back(trip(2 * i, this->new_order[this->triangles(0, i)] * 2, x32));
441
triple_list.emplace_back(trip(2 * i, this->new_order[this->triangles(0, i)] * 2 + 1, -y31));
442
triple_list.emplace_back(trip(2 * i, this->new_order[this->triangles(1, i)] * 2, -x31));
443
triple_list.emplace_back(trip(2 * i, this->new_order[this->triangles(1, i)] * 2 + 1, y31));
444
triple_list.emplace_back(trip(2 * i, this->new_order[this->triangles(2, i)] * 2, x21));
446
triple_list.emplace_back(trip(2 * i + 1, this->new_order[this->triangles(0, i)] * 2, y31));
447
triple_list.emplace_back(trip(2 * i + 1, this->new_order[this->triangles(0, i)] * 2 + 1, x32));
448
triple_list.emplace_back(trip(2 * i + 1, this->new_order[this->triangles(1, i)] * 2, -y31));
449
triple_list.emplace_back(trip(2 * i + 1, this->new_order[this->triangles(1, i)] * 2 + 1, -x31));
450
triple_list.emplace_back(trip(2 * i + 1, this->new_order[this->triangles(2, i)] * 2 + 1, x21));
454
std::vector<trip> rhs_triplets;
455
std::vector<trip> mat_triplets;
456
for (auto triplet: triple_list)
458
if (triplet.col() > static_cast<int>((this->vertices.cols() - this->fixed_pins.size()) * 2 - 1))
459
rhs_triplets.push_back(triplet);
461
mat_triplets.push_back(triplet);
465
Eigen::VectorXd rhs_pos(this->vertices.cols() * 2);
467
for (auto index: this->fixed_pins)
469
rhs_pos[this->new_order[index] * 2] = this->flat_vertices(0, index);
470
rhs_pos[this->new_order[index] * 2 + 1] = this->flat_vertices(1, index);
474
Eigen::VectorXd rhs(this->triangles.cols() * 2);
475
spMat B(this->triangles.cols() * 2, this->vertices.cols() * 2);
476
B.setFromTriplets(rhs_triplets.begin(), rhs_triplets.end());
480
spMat A(this->triangles.cols() * 2, (this->vertices.cols() - this->fixed_pins.size()) * 2);
481
A.setFromTriplets(mat_triplets.begin(), mat_triplets.end());
485
Eigen::LeastSquaresConjugateGradient<spMat > solver;
486
Eigen::VectorXd sol(this->vertices.size() * 2);
488
sol = solver.solve(-rhs);
491
this->set_position(sol);
493
this->transform(true);
499
void LscmRelax::set_q_l_g()
504
this->q_l_g.resize(this->triangles.cols(), 3);
505
for (long i = 0; i < this->triangles.cols(); i++)
507
Vector3 r1 = this->vertices.col(this->triangles(0, i));
508
Vector3 r2 = this->vertices.col(this->triangles(1, i));
509
Vector3 r3 = this->vertices.col(this->triangles(2, i));
510
Vector3 r21 = r2 - r1;
511
Vector3 r31 = r3 - r1;
512
double r21_norm = r21.norm();
515
this->q_l_g.row(i) << r21_norm, r31.dot(r21), r31.cross(r21).norm();
519
void LscmRelax::set_q_l_m()
524
this->q_l_m.resize(this->triangles.cols(), 3);
525
for (long i = 0; i < this->triangles.cols(); i++)
527
Vector2 r1 = this->flat_vertices.col(this->triangles(0, i));
528
Vector2 r2 = this->flat_vertices.col(this->triangles(1, i));
529
Vector2 r3 = this->flat_vertices.col(this->triangles(2, i));
530
Vector2 r21 = r2 - r1;
531
Vector2 r31 = r3 - r1;
532
double r21_norm = r21.norm();
535
this->q_l_m.row(i) << r21_norm, r31.dot(r21), -(r31.x() * r21.y() - r31.y() * r21.x());
539
void LscmRelax::set_fixed_pins()
544
if (this->fixed_pins.size() == 0)
545
this->fixed_pins.push_back(0);
546
if (this->fixed_pins.size() == 1)
550
this->fixed_pins.push_back(get_max_distance(this->vertices.col(this->fixed_pins[0]), this->vertices, dist));
551
this->flat_vertices.col(this->fixed_pins[0]) = Vector2(0, 0);
552
this->flat_vertices.col(this->fixed_pins[1]) = Vector2(dist, 0);
554
std::sort(this->fixed_pins.begin(), this->fixed_pins.end());
572
ColMat<double, 3> LscmRelax::get_flat_vertices_3D()
574
ColMat<double, 2> mat = this->flat_vertices.transpose();
575
ColMat<double, 3> mat3d(mat.rows(), 3);
576
mat3d << mat, ColMat<double, 1>::Zero(mat.rows());
580
void LscmRelax::set_position(Eigen::VectorXd sol)
582
for (long i=0; i < this->vertices.size(); i++)
584
if (sol.size() > i * 2 + 1)
585
this->flat_vertices.col(this->old_order[i]) << sol[i * 2], sol[i * 2 + 1];
589
void LscmRelax::set_shift(Eigen::VectorXd sol)
591
for (long i=0; i < this->vertices.size(); i++)
593
if (sol.size() > i * 2 + 1)
594
this->flat_vertices.col(i) += Vector2(sol[i * 2], sol[i * 2 + 1]);
598
double LscmRelax::get_area()
601
for(long i = 0; i < this->triangles.cols(); i++)
603
area += this->q_l_g(i, 0) * this->q_l_g(i, 2);
608
double LscmRelax::get_flat_area()
611
for(long i = 0; i < this->triangles.cols(); i++)
613
area += this->q_l_m(i, 0) * this->q_l_m(i, 2);
618
void LscmRelax::transform(bool scale)
621
Vector2 weighted_center, center;
622
weighted_center.setZero();
623
double flat_area = 0;
624
double global_area = 0;
626
for(long i = 0; i < this->triangles.cols(); i++)
628
global_area += this->q_l_g(i, 0) * this->q_l_g(i, 2) / 2;
629
element_area = this->q_l_m(i, 0) * this->q_l_m(i, 2) / 2;
630
for (int j=0; j < 3; j++)
631
weighted_center += this->flat_vertices.col(this->triangles(j, i)) * element_area / 3;
632
flat_area += element_area;
634
center = weighted_center / flat_area;
635
for (long i = 0; i < this->flat_vertices.cols(); i++)
636
this->flat_vertices.col(i) -= center;
638
this->flat_vertices *= std::pow(global_area / flat_area, 0.5);
642
void LscmRelax::rotate_by_min_bound_area()
648
bool x_dominant = false;
650
for (int i = 0; i < n + 1; i++ )
653
Eigen::VectorXd x_proj = this->flat_vertices.transpose() * Vector2(std::cos(phi), std::sin(phi));
654
Eigen::VectorXd y_proj = this->flat_vertices.transpose() * Vector2(-std::sin(phi), std::cos(phi));
655
double x_distance = x_proj.maxCoeff() - x_proj.minCoeff();
656
double y_distance = y_proj.maxCoeff() - y_proj.minCoeff();
657
double area = x_distance * y_distance;
658
if (min_area == 0 || area < min_area)
662
x_dominant = x_distance > y_distance;
665
Eigen::Matrix<double, 2, 2> rot;
666
min_phi += x_dominant * M_PI / 2;
667
rot << std::cos(min_phi), std::sin(min_phi), -std::sin(min_phi), std::cos(min_phi);
668
this->flat_vertices = rot * this->flat_vertices;
671
std::vector<long> LscmRelax::get_fem_fixed_pins()
673
long min_x_index = 0;
674
double min_x = this->vertices(0, 0);
675
for (long i=0; i<this->flat_vertices.cols(); i++)
678
if (this->flat_vertices(0, i) < min_x)
680
min_x = this->flat_vertices(0, i);
684
double min_y = this->flat_vertices(1, min_x_index);
685
long max_x_index = 0;
687
for (long i=0; i<this->flat_vertices.cols(); i++)
690
double d_x = (this->flat_vertices(0, i) - min_x);
691
double d_y = (this->flat_vertices(1, i) - min_y);
692
if (d_x * d_x - d_y * d_y > max_x)
694
max_x = d_x * d_x - d_y * d_y;
698
return std::vector<long>{min_x_index * 2, min_x_index * 2 + 1, max_x_index * 2 + 1};
701
Eigen::MatrixXd LscmRelax::get_nullspace()
703
Eigen::MatrixXd null_space;
704
null_space.setZero(this->flat_vertices.size() * 2, 3);
706
for (int i=0; i<this->flat_vertices.cols(); i++)
708
null_space(i * 2, 0) = 1;
709
null_space(i * 2 + 1, 1) = 1;
710
null_space(i * 2, 2) = - this->flat_vertices(1, i);
711
null_space(i * 2 + 1, 2) = this->flat_vertices(0, i);