-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPolyhedron3Utils.cpp
120 lines (106 loc) · 3.98 KB
/
Polyhedron3Utils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "Polyhedron3Utils.hpp"
#include <vector>
#include <unordered_set>
#include <iterator>
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
#include <CGAL/Polygon_mesh_processing/connected_components.h>
namespace PMP = CGAL::Polygon_mesh_processing;
// Polyhedron Property Map for connected components
typedef boost::property_map<Polyhedron3, boost::face_index_t>::const_type P3_facet_index_map_t;
typedef boost::vector_property_map<size_t, P3_facet_index_map_t> P3_facet_int_map;
///////////////////////////////////////////////////////////////////////////////////////////////////
// These are utilities for Polyhedron3 objects. Many of the utilities are complex and take multiple
// lines.
///////////////////////////////////////////////////////////////////////////////////////////////////
Polygon2 facet_to_polygon2(Polyhedron3::Facet_const_handle f)
{
// Assumes the facet is planar
const Plane3 h = facet_to_plane3(f);
std::vector<Point2> pts;
FOR_VERTICES_AROUND_FACET(f, v) { pts.push_back(h.to_2d(v->point())); }
return Polygon2(pts.begin(), pts.end());
}
FilteredPolyhedron3* filter_faces(Polyhedron3* P, const P3FacetSet& facets)
{
return new FilteredPolyhedron3(*P, facets);
}
FilteredPolyhedron3* filter_vertices(Polyhedron3* P, const P3VertexSet& verts)
{
P3FacetSet facets, processed;
facets.reserve(verts.size()*2);
processed.reserve(verts.size()*2);
for (P3Vertex v : verts)
{
FOR_FACETS_AROUND_VERTEX(v, f)
{
if (processed.count(f)) { continue; } // facet already processed
processed.insert(f); // now mark it as processed
bool include = true;
FOR_VERTICES_AROUND_FACET(f, vf)
{
if (!verts.count(vf)) { include = false; break; } // do not include facet - not all vertices are present
}
// Include it
if (include) { facets.insert(f); }
}
}
return filter_faces(P, facets);
}
// Checks uniqueness of vertex points and if each face is a simple polygon
bool is_not_degenerate(const Polyhedron3* P)
{
// Check uniqueness of vertices
std::unordered_set<Point3, boost::hash<Point3>> points;
for (Polyhedron3::Point_const_iterator p = P->points_begin(), end = P->points_end(); p != end; ++p)
{
if (!points.insert(*p).second) { return false; }
}
// Check geometry of facets
for (Polyhedron3::Facet_const_iterator f = P->facets_begin(), end = P->facets_end(); f != end; ++f)
{
const auto &a = f->halfedge(), &b = a->next(), &c = b->next();
if (c->next() == a) // f->is_triangle()
{
// This is significantly more accurate and faster then the other method
if (CGAL::collinear(a->vertex()->point(), b->vertex()->point(), c->vertex()->point()))
{
return false;
}
}
else
{
const Polygon2& p = facet_to_polygon2(f);
if (!p.is_simple() || p.area() == 0)
{
return false;
}
}
}
return true;
}
// Check if a mesh has a single connected component
bool is_single_component(const Polyhedron3* P)
{
return PMP::connected_components(*P, P3_facet_int_map(get(boost::face_index, *P))) == 1;
}
// For triangulating holes (don't need the output)
struct null_output_iterator : std::iterator<std::output_iterator_tag, null_output_iterator>
{
template<typename T> void operator=(T const&) { }
null_output_iterator & operator++() { return *this; }
null_output_iterator operator++(int) { return *this; }
null_output_iterator & operator*() { return *this; }
};
// Triangulate all holes in the given polyhedron
void triangulate_holes(Polyhedron3* P)
{
for (auto he = P->halfedges_begin(), end = P->halfedges_end(); he != end; ++he)
{
if (he->is_border())
{
PMP::triangulate_hole(*P, he, null_output_iterator());
}
}
assert(P->is_closed());
CGAL::set_halfedgeds_items_id(*P);
}