You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.5 KiB
126 lines
4.5 KiB
2 years ago
|
#include "background_mesh.h"
|
||
|
|
||
|
#include <igl/in_element.h>
|
||
|
#include <igl/signed_distance.h>
|
||
|
#include <oneapi/tbb.h>
|
||
|
#include <Eigen/Eigen>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace da::sha {
|
||
|
NestedBackgroundMesh::NestedBackgroundMesh(const std::vector<NestedCell> &nested_cells)
|
||
|
: nested_cells_(nested_cells) {}
|
||
|
|
||
|
auto NestedBackgroundMesh::GetPointLocation(const Eigen::Vector3d &p) -> std::pair<int, int> const {
|
||
|
int found_cell_idx = -1;
|
||
|
int found_tet_idx = -1;
|
||
|
|
||
|
const int num_macro_cells = nested_cells_.size();
|
||
|
|
||
|
for (index_t cell_idx = 0; cell_idx < num_macro_cells; ++cell_idx) {
|
||
|
auto &cell_surface = nested_cells_.at(cell_idx).macro_mesh;
|
||
|
auto &cell = nested_cells_.at(cell_idx).tetrahedrons;
|
||
|
Eigen::MatrixXd P(1, 3);
|
||
|
Eigen::VectorXd S;
|
||
|
Eigen::MatrixXi I;
|
||
|
Eigen::MatrixXd C;
|
||
|
Eigen::MatrixXd N;
|
||
|
P.row(0) = p.transpose();
|
||
|
igl::signed_distance(P, cell_surface.mat_coordinates, cell_surface.mat_faces,
|
||
|
igl::SIGNED_DISTANCE_TYPE_DEFAULT, S, I, C, N);
|
||
|
if (S(0, 0) > 0) continue;
|
||
|
found_cell_idx = cell_idx;
|
||
|
|
||
|
igl::AABB<Eigen::MatrixXd, 3> tree;
|
||
|
tree.init(cell.mat_coordinates, cell.mat_tetrahedrons);
|
||
|
Eigen::VectorXi tet_indices;
|
||
|
igl::in_element(cell.mat_coordinates, cell.mat_tetrahedrons, P, tree, tet_indices);
|
||
|
found_tet_idx = tet_indices(0);
|
||
|
break;
|
||
|
}
|
||
|
return std::make_pair(found_cell_idx, found_tet_idx);
|
||
|
}
|
||
|
|
||
|
auto NestedBackgroundMesh::GetPointLocationAlternative(const Eigen::Vector3d &p, const double tol_macro, const double tol_micro)
|
||
|
-> std::pair<int, int> {
|
||
|
int found_cell_idx = -1;
|
||
|
int found_tet_idx = -1;
|
||
|
|
||
|
const int num_macro_cells = nested_cells_.size();
|
||
|
|
||
|
for (index_t cell_idx = 0; cell_idx < num_macro_cells; ++cell_idx) {
|
||
|
auto &cell_surface = nested_cells_.at(cell_idx).macro_mesh;
|
||
|
auto &cell = nested_cells_.at(cell_idx).tetrahedrons;
|
||
|
Eigen::MatrixXd P(1, 3);
|
||
|
Eigen::VectorXd S;
|
||
|
Eigen::MatrixXi I;
|
||
|
Eigen::MatrixXd C;
|
||
|
Eigen::MatrixXd N;
|
||
|
P.row(0) = p.transpose();
|
||
|
igl::signed_distance(P, cell_surface.mat_coordinates, cell_surface.mat_faces,
|
||
|
igl::SIGNED_DISTANCE_TYPE_DEFAULT, S, I, C, N);
|
||
|
if (S(0, 0) > tol_macro) continue;
|
||
|
found_cell_idx = cell_idx;
|
||
|
|
||
|
const auto &tetVs = cell.mat_coordinates;
|
||
|
const auto &tetCells = cell.mat_tetrahedrons;
|
||
|
|
||
|
for (int tid = 0; tid < tetCells.rows(); ++tid) {
|
||
|
Eigen::Matrix4d D0;
|
||
|
D0.leftCols<3>() = tetVs(tetCells.row(tid), Eigen::all);
|
||
|
D0.col(3).setOnes();
|
||
|
bool flag = true;
|
||
|
for (int i = 0; i < 4; ++i) {
|
||
|
Eigen::MatrixXd Di = D0;
|
||
|
Di(i, {0, 1, 2}) = p;
|
||
|
if (Di.determinant() > tol_micro) {
|
||
|
flag = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (flag) {
|
||
|
found_tet_idx = tid;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return std::make_pair(found_cell_idx, found_tet_idx);
|
||
|
}
|
||
|
|
||
|
double NestedBackgroundMesh::ComputeAverageMicroTetEdgeLength() const {
|
||
|
double total_micro_tet_edge_length = 0.0;
|
||
|
const int num_macro_cells = nested_cells_.size();
|
||
|
|
||
|
for (index_t macro_cell_idx = 0; macro_cell_idx < num_macro_cells; ++macro_cell_idx) {
|
||
|
const auto ¯o_cell = nested_cells_.at(macro_cell_idx);
|
||
|
const Eigen::MatrixXd &micV_ = macro_cell.tetrahedrons.mat_coordinates;
|
||
|
const Eigen::MatrixXi &micT_ = macro_cell.tetrahedrons.mat_tetrahedrons;
|
||
|
const int num_tetrahedrons = macro_cell.tetrahedrons.NumTetrahedrons();
|
||
|
|
||
|
Eigen::MatrixXd t = micV_(micT_.col(0), Eigen::all) - micV_(micT_.col(1), Eigen::all);
|
||
|
Eigen::VectorXd len(num_tetrahedrons);
|
||
|
oneapi::tbb::parallel_for(0, num_tetrahedrons, 1,
|
||
|
[&](int micI) { len(micI) = t.row(micI).norm(); });
|
||
|
total_micro_tet_edge_length += len.mean();
|
||
|
}
|
||
|
return total_micro_tet_edge_length / num_macro_cells;
|
||
|
}
|
||
|
|
||
|
double NestedBackgroundMesh::ComputeMinMicroTetEdgeLength() const {
|
||
|
const size_t num_macro_cells = nested_cells_.size();
|
||
|
double min_micro_tet_edge_length = std::numeric_limits<double>::max();
|
||
|
for (index_t cell_idx = 0; cell_idx < num_macro_cells; ++cell_idx) {
|
||
|
auto &TV = nested_cells_.at(cell_idx).tetrahedrons.mat_coordinates;
|
||
|
auto &TT = nested_cells_.at(cell_idx).tetrahedrons.mat_tetrahedrons;
|
||
|
for (int i = 0; i < TT.rows(); ++i) {
|
||
|
for (int a = 0; a < 4; ++a) {
|
||
|
for (int b = a + 1; b < 4; ++b) {
|
||
|
min_micro_tet_edge_length =
|
||
|
std::min((TV.row(TT(i, a)) - TV.row(TT(i, b))).norm(), min_micro_tet_edge_length);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return min_micro_tet_edge_length;
|
||
|
}
|
||
|
} // namespace da
|