Wildmeshing Toolkit
Loading...
Searching...
No Matches
SimplicialComplexBVH.hpp
1#pragma once
2#include <igl/AABB.h>
3#include <igl/in_element.h>
4#include <Eigen/Dense>
5#include <SimpleBVH/BVH.hpp>
6
7
8namespace wmtk::components::topological_offset {
9
10
12{
13private:
14 // tet bvh
15 igl::AABB<MatrixXd, 3> m_tet_aabb_tree;
16 bool m_has_tets = false;
17
18 // triangle bvh
19 SimpleBVH::BVH m_tri_bvh;
20 bool m_has_tris = false;
21
22 // edge bvh
23 SimpleBVH::BVH m_edge_bvh;
24 bool m_has_edges = false;
25
26 bool m_is_3d;
27 MatrixXd m_V_T = MatrixXd(0, 3); // tet vertices
28 MatrixXi m_T_T = MatrixXi(0, 4); // tets w.r.t. V_T vertices
29 // igl::AABB<MatrixXd, 3> m_tet_aabb_tree;
30
31public:
41 void init(
42 const MatrixXd& V,
43 const MatrixXi& T,
44 const MatrixXi& F,
45 const MatrixXi& E,
46 const MatrixXi& P)
47 {
48 m_is_3d = (V.cols() == 3);
49 MatrixXd V_3d; // if V 2d, pad vertices to 3d (BVH needs this. should be fixed inside BVH)
50 if (!m_is_3d) {
51 V_3d.resize(V.rows(), 3);
52 V_3d.setZero();
53 V_3d.block(0, 0, V.rows(), V.cols()) = V;
54 } else {
55 V_3d = V;
56 }
57 assert(V_3d.rows() == V.rows());
58 assert(V_3d.cols() == 3);
59
60 // extract isolated faces
61 std::vector<Vector3i> faces;
62 for (int i = 0; i < F.rows(); i++) {
63 faces.push_back(F.row(i));
64 }
65
66 // complex is 3d and has tets
67 if (m_is_3d && T.rows() > 0) {
68 for (int i = 0; i < T.rows(); i++) {
69 int a = T(i, 0);
70 int b = T(i, 1);
71 int c = T(i, 2);
72 int d = T(i, 3);
73 faces.emplace_back(a, c, b);
74 faces.emplace_back(a, b, d);
75 faces.emplace_back(b, c, d);
76 faces.emplace_back(a, d, c);
77 }
78
79 m_V_T = V;
80 m_T_T = T;
81 // m_T_T.col(2).swap(m_T_T.col(3));
82 m_has_tets = true;
83 m_tet_aabb_tree.init(m_V_T, m_T_T);
84 }
85
86 // initialize triangle bvh
87 if (!faces.empty()) {
88 MatrixXi F_combo(faces.size(), 3);
89 for (size_t i = 0; i < faces.size(); i++) {
90 F_combo.row(i) = faces[i];
91 }
92 m_tri_bvh.init(V_3d, F_combo, 1e-6);
93 m_has_tris = true;
94 }
95
96 std::vector<Eigen::Vector2i> edges; // extract isolated edges
97 for (int i = 0; i < E.rows(); i++) { // actual edges
98 edges.push_back(E.row(i));
99 }
100 for (int i = 0; i < P.rows(); i++) { // pseudo edges
101 edges.emplace_back(P(i), P(i));
102 }
103
104 if (!edges.empty()) {
105 MatrixXi E_combo(edges.size(), 2);
106 for (size_t i = 0; i < edges.size(); i++) {
107 E_combo.row(i) = edges[i];
108 }
109 m_edge_bvh.init(V_3d, E_combo, 1e-6);
110 m_has_edges = true;
111 }
112 }
113
117 bool inside_any_tet(const Vector3d& p) const
118 {
119 // 2D or no tets
120 if (!m_has_tets) {
121 return false;
122 }
123
124 Eigen::MatrixXd Q(1, 3);
125 Q.row(0) = p;
126 Eigen::VectorXi I;
127 igl::in_element(m_V_T, m_T_T, Q, m_tet_aabb_tree, I);
128 return (I(0) != -1);
129 }
130
134 double squared_dist(const VectorXd& p) const
135 {
136 double min_sq_dist = std::numeric_limits<double>::max();
137
138 // pad to 3d if necessary
139 Vector3d p3;
140 if (p.size() == 2) {
141 p3 << p(0), p(1), 0.0;
142 } else {
143 p3 = p;
144 }
145
146 // inside tet check
147 if (m_has_tets) { // has any tets
148 if (inside_any_tet(p3)) {
149 return 0.0;
150 }
151 }
152
153 Vector3d closest_p;
154 double tmp_sq_dist;
155
156 if (m_has_tris) { // min dist to isolated triangles (and tet faces)
157 m_tri_bvh.nearest_facet(p3, closest_p, min_sq_dist);
158 }
159
160 if (m_has_edges) { // min dist to isolated edges (and 'pseudo'edges, ie isolated vertices)
161 m_edge_bvh.nearest_facet(p3, closest_p, tmp_sq_dist);
162 if (tmp_sq_dist < min_sq_dist) {
163 min_sq_dist = tmp_sq_dist;
164 }
165 }
166
167 return min_sq_dist;
168 }
169
170 double dist(const VectorXd& p) const { return sqrt(squared_dist(p)); }
171
172 void clear()
173 {
174 m_tri_bvh.clear();
175 m_has_tris = false;
176 m_edge_bvh.clear();
177 m_has_edges = false;
178 m_tet_aabb_tree = igl::AABB<MatrixXd, 3>(); // reset
179 m_has_tets = false;
180 m_V_T.resize(0, 3);
181 m_T_T.resize(0, 4);
182 }
183};
184
185
186} // namespace wmtk::components::topological_offset
bool inside_any_tet(const Vector3d &p) const
check if a point is inside any tet.
Definition SimplicialComplexBVH.hpp:117
double squared_dist(const VectorXd &p) const
compute distance to complex
Definition SimplicialComplexBVH.hpp:134
void init(const MatrixXd &V, const MatrixXi &T, const MatrixXi &F, const MatrixXi &E, const MatrixXi &P)
initialize BVH from "closed" simplicial complex
Definition SimplicialComplexBVH.hpp:41