8 changed files with 222 additions and 25 deletions
Binary file not shown.
@ -0,0 +1,8 @@ |
|||||
|
//
|
||||
|
// Created by cflin on 4/24/23.
|
||||
|
//
|
||||
|
|
||||
|
#include "IrregularMesh.h" |
||||
|
|
||||
|
namespace top { |
||||
|
} // top
|
@ -0,0 +1,137 @@ |
|||||
|
//
|
||||
|
// Created by cflin on 4/24/23.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef TOP3D_IRREGULARMESH_H |
||||
|
#define TOP3D_IRREGULARMESH_H |
||||
|
|
||||
|
#include "Mesh.h" |
||||
|
|
||||
|
namespace top { |
||||
|
struct ModelMesh { |
||||
|
Eigen::MatrixX3d points; |
||||
|
Eigen::MatrixXi surfaces; |
||||
|
}; |
||||
|
|
||||
|
class IrregularMesh : public Mesh { |
||||
|
public: |
||||
|
IrregularMesh(const ModelMesh &arbitrary_mesh) : Mesh() { |
||||
|
// get num_pixels
|
||||
|
min_point_box_ = arbitrary_mesh.points.colwise().minCoeff(); |
||||
|
Eigen::Vector3d box_max_point = arbitrary_mesh.points.colwise().maxCoeff(); |
||||
|
Eigen::Vector3d box_len = box_max_point - min_point_box_; |
||||
|
const double percentage_of_min_len = 0.20; |
||||
|
len_pixel_ = box_len.minCoeff() * percentage_of_min_len; |
||||
|
Eigen::Vector3d d_num_pixels = box_len / len_pixel_; |
||||
|
Eigen::Vector3i num_pixels(std::ceil(d_num_pixels(0)), std::ceil(d_num_pixels(1)), |
||||
|
std::ceil(d_num_pixels(2))); |
||||
|
|
||||
|
lx_ = num_pixels(0); |
||||
|
ly_ = num_pixels(1); |
||||
|
lz_ = num_pixels(2); |
||||
|
num_node_ = (lx_ + 1) * (ly_ + 1) * (lz_ + 1); |
||||
|
num_ele_ = lx_ * ly_ * lz_; |
||||
|
|
||||
|
ten_ele_coord2ele_id = Tensor3i(lx_, ly_, lz_); |
||||
|
ten_node_coord2node_id.setConstant(-1); |
||||
|
ten_node_coord2node_id = Tensor3i(lx_ + 1, ly_ + 1, lz_ + 1); |
||||
|
ten_node_coord2node_id.setConstant(-1); |
||||
|
|
||||
|
auto EvaluateSDF = [](const Eigen::Vector3d point) { |
||||
|
Eigen::Vector3d center(1, 1, 1); |
||||
|
double r = 5; |
||||
|
return r - (point - center).norm(); |
||||
|
}; |
||||
|
auto GetWorldCoordByElementIdx = [&](const Eigen::Vector3i &ele_idx) { |
||||
|
Eigen::Vector3d local_coord = ele_idx.cast<double>(); |
||||
|
Eigen::Vector3d world_coord = ((local_coord.array() + 0.5) * len_pixel_).matrix() + min_point_box_; |
||||
|
return world_coord; |
||||
|
}; |
||||
|
auto Is_in_model = [&](const Eigen::Vector3i &ele_idx) { |
||||
|
return EvaluateSDF(GetWorldCoordByElementIdx(ele_idx)) >= 0; |
||||
|
}; |
||||
|
|
||||
|
static const Eigen::MatrixXi delta_coord = (Eigen::MatrixXi(8, 3) << |
||||
|
0, 0, 0, |
||||
|
1, 0, 0, |
||||
|
1, 1, 0, |
||||
|
0, 1, 0, |
||||
|
0, 0, 1, |
||||
|
1, 0, 1, |
||||
|
1, 1, 1, |
||||
|
0, 1, 1 |
||||
|
).finished(); |
||||
|
// get num_pixel_ && fill pixel id
|
||||
|
int cnt_pixel = 0; |
||||
|
for (int k = 0; k < lz_; ++k) { |
||||
|
for (int j = 0; j < ly_; ++j) { |
||||
|
for (int i = 0; i < lx_; ++i) { |
||||
|
if (Is_in_model({i, j, k})) { |
||||
|
ten_ele_coord2ele_id(i, j, k) = cnt_pixel++; |
||||
|
for (int di = 0; di < delta_coord.rows(); ++di) { |
||||
|
Eigen::Vector3i cur_delta_coord = delta_coord.row(di); |
||||
|
ten_node_coord2node_id(i + cur_delta_coord(0), j + cur_delta_coord(1), |
||||
|
k + cur_delta_coord(2)) = 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
num_pixel_ = cnt_pixel; |
||||
|
// get_num_node_pixel && fill node_id
|
||||
|
int cnt_node_pixel = 0; |
||||
|
for (int k = 0; k < lz_ + 1; ++k) { |
||||
|
for (int j = 0; j < ly_ + 1; ++j) { |
||||
|
for (int i = 0; i < lx_ + 1; ++i) { |
||||
|
if (ten_node_coord2node_id(i, j, k) == 1) { |
||||
|
ten_node_coord2node_id(i, j, k) = cnt_node_pixel++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
num_node_pixel_ = cnt_node_pixel; |
||||
|
// fill mat_ele_id2dofs_
|
||||
|
mat_ele_id2dofs_.resize(num_pixel_, NUM_NODES_EACH_ELE * 3); |
||||
|
for (int k = 0; k < lz_; ++k) { |
||||
|
for (int j = 0; j < ly_; ++j) { |
||||
|
for (int i = 0; i < lx_; ++i) { |
||||
|
int cur_ele_id = ten_ele_coord2ele_id(i, j, k); |
||||
|
if (cur_ele_id == -1) { |
||||
|
continue; |
||||
|
} |
||||
|
Eigen::MatrixXi world_node_coords = delta_coord.rowwise() + Eigen::RowVector3i(i, j, k); |
||||
|
assert(world_node_coords.rows() == 8 && world_node_coords.cols() == 3); |
||||
|
Eigen::Vector<int, 8> node_ids = ten_node_coord2node_id(world_node_coords); |
||||
|
for (int nodi = 0; nodi < 8; ++nodi) { |
||||
|
mat_ele_id2dofs_(cur_ele_id, {3 * nodi, 3 * nodi + 1, 3 * nodi + 2}) = Eigen::Vector3i( |
||||
|
3 * node_ids(nodi), 3 * node_ids(nodi) + 1, 3 * node_ids(nodi) + 2); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int GetNumDofs() const override { |
||||
|
return num_node_pixel_ * 3; |
||||
|
} |
||||
|
|
||||
|
int GetNumEles() const override { |
||||
|
return num_pixel_; |
||||
|
} |
||||
|
|
||||
|
int GetNumNodes() const override { |
||||
|
return num_node_pixel_; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
double len_pixel_; |
||||
|
double num_pixel_; |
||||
|
double num_node_pixel_; |
||||
|
Eigen::Vector3d min_point_box_; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
} // top
|
||||
|
|
||||
|
#endif //TOP3D_IRREGULARMESH_H
|
Loading…
Reference in new issue