4#include "isosurface/mesh_defects_finder.h"
5#include "isosurface/dense_undirected_graph.h"
6#include "geometry/point3d.h"
7#include <unordered_map>
10 mesh_defects_finder::mesh_defects_finder(
const vertices_type& vertices,
const faces_type& faces)
11 : vertices_(vertices), faces_(faces), vf_map_(vertices_.rows()) {
12 auto n_faces = faces.rows();
13 for (index_t fi = 0; fi < n_faces; fi++) {
14 auto f = faces.row(fi);
15 vf_map_.at(f(0)).push_back(fi);
16 vf_map_.at(f(1)).push_back(fi);
17 vf_map_.at(f(2)).push_back(fi);
22 std::unordered_set<index_t> mesh_defects_finder::intersecting_faces()
const {
23 std::unordered_set<index_t> result;
25 auto n_vertices = vertices_.rows();
26#pragma omp parallel for schedule(guided, 32)
27 for (index_t vi = 0; vi < n_vertices; vi++) {
28 const auto& fis = vf_map_.at(vi);
30 auto n_faces =
static_cast<index_t
>(fis.size());
31 for (index_t i = 0; i < n_faces - 1; i++) {
33 auto a = next_vertex(fi, vi);
34 auto b = prev_vertex(fi, vi);
35 for (index_t j = i + 1; j < n_faces; j++) {
37 auto c = next_vertex(fj, vi);
38 auto d = prev_vertex(fj, vi);
40 if (b == c || a == d) {
46 if (segment_triangle_intersect(a, b, fj) || segment_triangle_intersect(c, d, fi)) {
60 std::unordered_set<index_t> mesh_defects_finder::singular_vertices()
const {
61 std::unordered_set<index_t> result;
63 auto n_vertices = vertices_.rows();
64#pragma omp parallel for schedule(guided, 32)
65 for (index_t vi = 0; vi < n_vertices; vi++) {
66 const auto& fis = vf_map_.at(vi);
73 std::unordered_map<index_t, index_t> to_local_vi;
75 to_local_vi.emplace(next_vertex(fi, vi), to_local_vi.size());
76 to_local_vi.emplace(prev_vertex(fi, vi), to_local_vi.size());
79 auto order =
static_cast<index_t
>(to_local_vi.size());
82 dense_undirected_graph g(order);
85 auto i = to_local_vi.at(next_vertex(fi, vi));
86 auto j = to_local_vi.at(prev_vertex(fi, vi));
92 if (!(g.is_simple() && g.is_connected() && g.max_degree() <= 2)) {
101 index_t mesh_defects_finder::next_vertex(index_t fi, index_t vi)
const {
102 auto f = faces_.row(fi);
112 index_t mesh_defects_finder::prev_vertex(index_t fi, index_t vi)
const {
113 auto f = faces_.row(fi);
123 double orient2d_inexact(
const geometry::point2d& a,
const geometry::point2d& b,
124 const geometry::point2d& c) {
126 m << a(0) - c(0), a(1) - c(1), b(0) - c(0), b(1) - c(1);
127 return m.determinant();
130 double orient3d_inexact(
const geometry::point3d& a,
const geometry::point3d& b,
131 const geometry::point3d& c,
const geometry::point3d& d) {
133 m << a(0) - d(0), a(1) - d(1), a(2) - d(2), b(0) - d(0), b(1) - d(1), b(2) - d(2), c(0) - d(0),
134 c(1) - d(1), c(2) - d(2);
135 return m.determinant();
138 double coplanar_orientation(
const geometry::point3d& a,
const geometry::point3d& b,
139 const geometry::point3d& c) {
140 geometry::point2d a_xy(a(0), a(1));
141 geometry::point2d b_xy(b(0), b(1));
142 geometry::point2d c_xy(c(0), c(1));
143 auto abc_xy = orient2d_inexact(a_xy, b_xy, c_xy);
148 geometry::point2d a_yz(a(1), a(2));
149 geometry::point2d b_yz(b(1), b(2));
150 geometry::point2d c_yz(c(1), c(2));
151 auto abc_yz = orient2d_inexact(a_yz, b_yz, c_yz);
156 geometry::point2d a_zx(a(2), a(0));
157 geometry::point2d b_zx(b(2), b(0));
158 geometry::point2d c_zx(c(2), c(0));
159 auto abc_zx = orient2d_inexact(a_zx, b_zx, c_zx);
163 bool mesh_defects_finder::segment_triangle_intersect(index_t vi, index_t vj, index_t fi)
const {
164 auto f = faces_.row(fi);
166 auto a = vertices_.row(f(0));
167 auto b = vertices_.row(f(1));
168 auto c = vertices_.row(f(2));
169 auto p = vertices_.row(vi);
170 auto q = vertices_.row(vj);
172 auto abcp = orient3d_inexact(a, b, c, p);
173 auto abcq = orient3d_inexact(a, b, c, q);
175 if ((abcp > 0.0 && abcq > 0.0) || (abcp < 0.0 && abcq < 0.0)) {
179 if (abcp == 0.0 && abcq == 0.0) {
180 auto pqa = coplanar_orientation(p, q, a);
181 auto pqb = coplanar_orientation(p, q, b);
182 auto pqc = coplanar_orientation(p, q, c);
185 return !((pqa > 0.0 && pqb > 0.0 && pqc > 0.0) || (pqa < 0.0 && pqb < 0.0 && pqc < 0.0));
188 auto pqab = orient3d_inexact(p, q, a, b);
189 auto pqbc = orient3d_inexact(p, q, b, c);
190 auto pqca = orient3d_inexact(p, q, c, a);
192 return (pqab >= 0.0 && pqbc >= 0.0 && pqca >= 0.0) || (pqab <= 0.0 && pqbc <= 0.0 && pqca <= 0.0);