24 std::map<std::string, std::vector<int64_t>> names;
30 if (operating_axis[2]) {
31 wmtk::logger().warn(
"Fusion on Z axis is not supported for 2D mesh.");
46 Eigen::MatrixXd V_rescale(V.rows(), V.cols());
48 Eigen::VectorXd min_pos = V.colwise().minCoeff();
53 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
54 V_rescale.row(i) = V.row(i) - min_pos.transpose();
57 Eigen::VectorXd max_pos = V_rescale.colwise().maxCoeff();
58 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
59 V_rescale(i, 0) /= max_pos[0];
60 V_rescale(i, 1) /= max_pos[1];
68 std::map<int64_t, int64_t> vertex_map;
70 std::array<std::vector<std::pair<int64_t, Eigen::VectorXd>>, 2> vertices_on_zero;
71 std::array<std::vector<std::pair<int64_t, Eigen::VectorXd>>, 2> vertices_on_one;
78 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
79 const auto& pos = V_rescale.row(i);
81 if (
abs(pos[0] - 0.0) < eps) {
82 vertices_on_zero[0].emplace_back(std::make_pair(i, pos));
84 if (
abs(pos[1] - 0.0) < eps) {
85 vertices_on_zero[1].emplace_back(std::make_pair(i, pos));
87 if (
abs(pos[0] - 1.0) < eps) {
88 vertices_on_one[0].emplace_back(std::make_pair(i, pos));
90 if (
abs(pos[1] - 1.0) < eps) {
91 vertices_on_one[1].emplace_back(std::make_pair(i, pos));
95 if (
abs(pos[0] - 0.0) < eps &&
abs(pos[1] - 0.0) < eps) {
96 if (v00 != -1)
throw std::runtime_error(
"More than 1 vertices on corner 00.");
99 if (
abs(pos[0] - 0.0) < eps &&
abs(pos[1] - 1.0) < eps) {
100 if (v01 != -1)
throw std::runtime_error(
"More than 1 vertices on corner 01.");
103 if (
abs(pos[0] - 1.0) < eps &&
abs(pos[1] - 0.0) < eps) {
104 if (v10 != -1)
throw std::runtime_error(
"More than 1 vertices on corner 10.");
107 if (
abs(pos[0] - 1.0) < eps &&
abs(pos[1] - 1.0) < eps) {
108 if (v11 != -1)
throw std::runtime_error(
"More than 1 vertices on corner 11.");
114 for (
int axis = 0; axis < 2; ++axis) {
115 if (!operating_axis[axis])
continue;
117 if (vertices_on_zero[axis].size() != vertices_on_one[axis].size()) {
118 throw std::runtime_error(
"vertices size on the fusion axis does not match!");
121 auto cmp = [&](
const std::pair<int64_t, Eigen::VectorXd>& a,
122 const std::pair<int64_t, Eigen::VectorXd>& b) {
123 return a.second[1 - axis] < b.second[1 - axis];
126 std::sort(vertices_on_zero[axis].begin(), vertices_on_zero[axis].end(),
cmp);
127 std::sort(vertices_on_one[axis].begin(), vertices_on_one[axis].end(),
cmp);
129 for (int64_t i = 0; i < vertices_on_zero[axis].size(); ++i) {
131 abs(vertices_on_zero[axis][i].second[1 - axis] -
132 vertices_on_one[axis][i].second[1 - axis]) < eps);
134 vertex_map[vertices_on_one[axis][i].first] = vertices_on_zero[axis][i].first;
139 if (operating_axis[0] && operating_axis[1]) {
140 vertex_map[v00] = v00;
141 vertex_map[v01] = v00;
142 vertex_map[v10] = v00;
143 vertex_map[v11] = v00;
149 for (int64_t i = 0; i < FV.rows(); ++i) {
150 for (int64_t k = 0; k < 3; ++k) {
151 if (vertex_map.find(FV(i, k)) != vertex_map.end()) {
152 FV_new(i, k) = vertex_map[FV(i, k)];
154 FV_new(i, k) = FV(i, k);
159 Eigen::MatrixXd V_new_tmp(V.rows(), V.cols());
162 std::map<int64_t, int64_t> v_consolidate_map;
164 int64_t v_valid_cnt = 0;
165 for (int64_t i = 0; i < V.rows(); ++i) {
166 if (vertex_map.find(i) == vertex_map.end() || vertex_map[i] == i) {
167 for (
int k = 0; k < V_rescale.cols(); ++k) {
168 V_new_tmp(v_valid_cnt, k) = V(i, k);
170 v_consolidate_map[i] = v_valid_cnt++;
176 Eigen::MatrixXd V_new(v_valid_cnt, V.cols());
177 V_new = V_new_tmp.block(0, 0, v_valid_cnt, V.cols());
183 for (int64_t i = 0; i < FV_new.rows(); ++i) {
184 for (int64_t k = 0; k < FV_new.cols(); ++k) {
185 FV_new(i, k) = v_consolidate_map[FV_new(i, k)];
222 std::shared_ptr<TriMesh> child_ptr = std::make_shared<TriMesh>(std::move(position_mesh));
223 std::shared_ptr<TriMesh> parent_ptr = std::make_shared<TriMesh>(std::move(fusion_mesh));
226 parent_ptr->register_child_mesh(child_ptr, child_map);
246 Vector3d min_pos = V.colwise().minCoeff();
248 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
249 V_rescale.row(i) = V.row(i) - min_pos.transpose();
252 Vector3d max_pos = V_rescale.colwise().maxCoeff();
253 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
254 V_rescale(i, 0) /= max_pos[0];
255 V_rescale(i, 1) /= max_pos[1];
256 V_rescale(i, 2) /= max_pos[2];
259 std::map<int64_t, int64_t> vertex_map;
261 std::array<std::vector<std::pair<int64_t, Eigen::VectorXd>>, 3> vertices_on_zero;
262 std::array<std::vector<std::pair<int64_t, Eigen::VectorXd>>, 3> vertices_on_one;
264 for (int64_t i = 0; i < V_rescale.rows(); ++i) {
265 const auto& pos = V_rescale.row(i);
267 for (
int k = 0; k < 3; ++k) {
268 if (
abs(pos[k] - 0.0) < eps) {
269 vertices_on_zero[k].push_back(std::make_pair(i, pos));
271 if (
abs(pos[k] - 1.0) < eps) {
272 vertices_on_one[k].push_back(std::make_pair(i, pos));
278 for (
int axis = 0; axis < 3; ++axis) {
279 if (!operating_axis[axis])
continue;
281 if (vertices_on_zero[axis].size() != vertices_on_one[axis].size()) {
282 throw std::runtime_error(
"vertices size on the fusion axis does not match!");
285 auto cmp = [&](
const std::pair<int64_t, Eigen::VectorXd>& a,
286 const std::pair<int64_t, Eigen::VectorXd>& b) {
287 if (
abs(a.second[(axis + 2) % 3] - b.second[(axis + 2) % 3]) < eps) {
288 return a.second[(axis + 1) % 3] < b.second[(axis + 1) % 3];
290 return a.second[(axis + 2) % 3] < b.second[(axis + 2) % 3];
294 std::sort(vertices_on_zero[axis].begin(), vertices_on_zero[axis].end(),
cmp);
295 std::sort(vertices_on_one[axis].begin(), vertices_on_one[axis].end(),
cmp);
297 for (int64_t i = 0; i < vertices_on_zero[axis].size(); ++i) {
299 abs(vertices_on_zero[axis][i].second[(axis + 1) % 3] -
300 vertices_on_one[axis][i].second[(axis + 1) % 3]) < eps &&
301 abs(vertices_on_zero[axis][i].second[(axis + 2) % 3] -
302 vertices_on_one[axis][i].second[(axis + 2) % 3]) < eps);
304 vertex_map[vertices_on_one[axis][i].first] = vertices_on_zero[axis][i].first;
311 for (int64_t i = 0; i < TV.rows(); ++i) {
312 for (int64_t k = 0; k < 4; ++k) {
313 if (vertex_map.find(TV(i, k)) != vertex_map.end()) {
314 int64_t v_root = vertex_map[TV(i, k)];
315 while (vertex_map.find(v_root) != vertex_map.end() &&
316 vertex_map[v_root] != v_root) {
317 v_root = vertex_map[v_root];
319 TV_new(i, k) = v_root;
321 TV_new(i, k) = TV(i, k);
332 std::map<int64_t, int64_t> v_consolidate_map;
334 int64_t v_valid_cnt = 0;
335 for (int64_t i = 0; i < V.rows(); ++i) {
336 if (vertex_map.find(i) == vertex_map.end() || vertex_map[i] == i) {
337 V_new_tmp(v_valid_cnt, 0) = V(i, 0);
338 V_new_tmp(v_valid_cnt, 1) = V(i, 1);
339 V_new_tmp(v_valid_cnt, 2) = V(i, 2);
340 v_consolidate_map[i] = v_valid_cnt++;
347 V_new = V_new_tmp.block(0, 0, v_valid_cnt, 3);
353 for (int64_t i = 0; i < TV_new.rows(); ++i) {
354 for (int64_t k = 0; k < TV_new.cols(); ++k) {
355 TV_new(i, k) = v_consolidate_map[TV_new(i, k)];
374 std::shared_ptr<TetMesh> child_ptr = std::make_shared<TetMesh>(std::move(position_mesh));
375 std::shared_ptr<TetMesh> parent_ptr = std::make_shared<TetMesh>(std::move(fusion_mesh));
378 parent_ptr->register_child_mesh(child_ptr, child_map);
383 throw std::runtime_error(
"mesh dimension not supported");
void serialize(MeshWriter &writer, const Mesh *local_root=nullptr) const
std::vector< Tuple > get_all(PrimitiveType type) const
Generate a vector of Tuples from global vertex/edge/triangle/tetrahedron index.
int64_t top_cell_dimension() const
void initialize(Eigen::Ref< const RowVectors4l > TV, Eigen::Ref< const RowVectors6l > TE, Eigen::Ref< const RowVectors4l > TF, Eigen::Ref< const RowVectors4l > TT, Eigen::Ref< const VectorXl > VT, Eigen::Ref< const VectorXl > ET, Eigen::Ref< const VectorXl > FT)
void initialize(Eigen::Ref< const RowVectors3l > FV, Eigen::Ref< const RowVectors3l > FE, Eigen::Ref< const RowVectors3l > FF, Eigen::Ref< const VectorXl > VF, Eigen::Ref< const VectorXl > EF)
void get_position_matrix(MatrixX< double > &matrix)
void get_TV_matrix(MatrixX< int64_t > &matrix)
void get_FV_matrix(MatrixX< int64_t > &matrix)
std::shared_ptr< Mesh > axis_aligned_fusion(const Mesh &mesh, const std::vector< bool > &operating_axis, double eps)
attribute::MeshAttributeHandle set_matrix_attribute(const Mat &data, const std::string &name, const PrimitiveType &type, Mesh &mesh)
std::vector< std::array< Tuple, 2 > > same_simplex_dimension_bijection(const Mesh &parent, const Mesh &child)
int cmp(const Rational &r, const Rational &r1)
RowVectors< int64_t, 3 > RowVectors3l
Rational abs(const Rational &r0)
RowVectors< int64_t, 4 > RowVectors4l
spdlog::logger & logger()
Retrieves the current logger.
Vector< double, 3 > Vector3d
RowVectors< double, 3 > RowVectors3d
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > MatrixX