59 m_is_3d = (V.cols() == 3);
62 V_3d.resize(V.rows(), 3);
64 V_3d.block(0, 0, V.rows(), V.cols()) = V;
68 assert(V_3d.rows() == V.rows());
69 assert(V_3d.cols() == 3);
72 std::vector<Vector3i> faces;
73 for (
int i = 0; i < F.rows(); i++) {
74 faces.push_back(F.row(i));
78 if (m_is_3d && T.rows() > 0) {
79 for (
int i = 0; i < T.rows(); i++) {
84 faces.emplace_back(a, c, b);
85 faces.emplace_back(a, b, d);
86 faces.emplace_back(b, c, d);
87 faces.emplace_back(a, d, c);
94 m_tet_aabb_tree.init(m_V_T, m_T_T);
99 MatrixXi F_combo(faces.size(), 3);
100 for (
size_t i = 0; i < faces.size(); i++) {
101 F_combo.row(i) = faces[i];
103 m_tri_bvh.init(V_3d, F_combo, 1e-6);
107 std::vector<Eigen::Vector2i> edges;
108 for (
int i = 0; i < E.rows(); i++) {
109 edges.push_back(E.row(i));
111 for (
int i = 0; i < P.rows(); i++) {
112 edges.emplace_back(P(i), P(i));
115 if (!edges.empty()) {
116 MatrixXi E_combo(edges.size(), 2);
117 for (
size_t i = 0; i < edges.size(); i++) {
118 E_combo.row(i) = edges[i];
120 m_edge_bvh.init(V_3d, E_combo, 1e-6);
129 m_v2.reserve(
size_t(V.rows()));
130 for (
int i = 0; i < V.rows(); i++) {
131 m_v2.emplace_back(V(i, 0), V(i, 1));
133 m_e2.assign(edges.begin(), edges.end());
159 double min_sq_dist = std::numeric_limits<double>::max();
164 p3 << p(0), p(1), 0.0;
180 m_tri_bvh.nearest_facet(p3, closest_p, min_sq_dist);
184 m_edge_bvh.nearest_facet(p3, closest_p, tmp_sq_dist);
185 if (tmp_sq_dist < min_sq_dist) {
186 min_sq_dist = tmp_sq_dist;
205 p3 << p(0), p(1), 0.0;
210 Vector3d best_p = p3;
211 double best_sq_dist = std::numeric_limits<double>::max();
216 m_tri_bvh.nearest_facet(p3, closest_p, tmp_sq_dist);
217 if (tmp_sq_dist < best_sq_dist) {
218 best_sq_dist = tmp_sq_dist;
223 m_edge_bvh.nearest_facet(p3, closest_p, tmp_sq_dist);
224 if (tmp_sq_dist < best_sq_dist) {
225 best_sq_dist = tmp_sq_dist;
245 const Eigen::Vector2d& p,
246 Eigen::Vector2d& result,
248 Eigen::Vector2d& seg_normal,
249 int& feature_id)
const
254 if (m_is_3d || !m_has_edges ||
m_v2.empty() || m_e2.empty()) {
256 "SimplicialComplexBVH::nearest_point_feature: 2D {} | edges {} | copies {}/{}",
263 const Eigen::Vector3d p3(p[0], p[1], 0.0);
264 Eigen::Vector3d nearest;
266 m_edge_bvh.nearest_facet(p3, nearest, sq_dist);
268 std::vector<unsigned int> candidates;
269 const double pad = 1e-9 + 1e-9 * std::sqrt(sq_dist);
271 const Eigen::Vector3d lo(nearest[0] - pad, nearest[1] - pad, -pad);
272 const Eigen::Vector3d hi(nearest[0] + pad, nearest[1] + pad, pad);
273 m_edge_bvh.intersect_box(lo, hi, candidates);
274 if (candidates.empty()) {
276 "SimplicialComplexBVH::nearest_point_feature: no box candidate at the foot "
277 "point -- the BVH and the input copies disagree");
280 double best = std::numeric_limits<double>::max();
281 for (
const unsigned int fid : candidates) {
282 if (fid >= m_e2.size()) {
284 "SimplicialComplexBVH::nearest_point_feature: candidate id {} out of range "
289 const Eigen::Vector2d a =
m_v2[size_t(m_e2[fid][0])];
290 const Eigen::Vector2d b =
m_v2[size_t(m_e2[fid][1])];
291 const Eigen::Vector2d ab = b - a;
292 const double len2 = ab.squaredNorm();
293 const double t = len2 > 0 ? (p - a).dot(ab) / len2 : 0.0;
294 Eigen::Vector2d foot;
297 if (len2 <= 0 || t <= 0) {
310 const double d2 = (p - foot).squaredNorm();
317 seg_normal = Eigen::Vector2d(-ab[1], ab[0]) / std::sqrt(len2);