-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
cgalutils-hybrid.cc
151 lines (126 loc) · 4.96 KB
/
cgalutils-hybrid.cc
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
#include "cgalutils.h"
#include "CGALHybridPolyhedron.h"
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/convex_hull_3.h>
#include "CGAL_Nef_polyhedron.h"
#include "PolySetUtils.h"
#if ENABLE_MANIFOLD
#include "ManifoldGeometry.h"
#endif
namespace CGALUtils {
template <typename K>
std::shared_ptr<CGALHybridPolyhedron> createHybridPolyhedronFromPolyhedron(const CGAL::Polyhedron_3<K>& poly)
{
CGAL::Surface_mesh<CGAL::Point_3<K>> mesh;
CGAL::copy_face_graph(poly, mesh);
auto hybrid_mesh = std::make_shared<CGAL_HybridMesh>();
copyMesh(mesh, *hybrid_mesh);
CGALUtils::triangulateFaces(*hybrid_mesh);
return std::make_shared<CGALHybridPolyhedron>(hybrid_mesh);
}
template std::shared_ptr<CGALHybridPolyhedron> createHybridPolyhedronFromPolyhedron(const CGAL::Polyhedron_3<CGAL::Epick>& poly);
bool hasOnlyTriangles(const PolySet& ps) {
for (auto& p : ps.indices) {
if (p.size() != 3) {
return false;
}
}
return true;
}
std::shared_ptr<CGALHybridPolyhedron> createHybridPolyhedronFromPolySet(const PolySet& ps)
{
// Since is_convex doesn't work well with non-planar faces,
// we tessellate the polyset before checking.
PolySet psq(ps);
std::vector<Vector3d> points3d;
psq.quantizeVertices(&points3d);
auto ps_tri = PolySetUtils::tessellate_faces(psq);
if (ps_tri->isConvex()) {
using K = CGAL::Epick;
// Collect point cloud
std::vector<K::Point_3> points(points3d.size());
for (size_t i = 0, n = points3d.size(); i < n; i++) {
points[i] = vector_convert<K::Point_3>(points3d[i]);
}
if (points.size() <= 3) return std::make_shared<CGALHybridPolyhedron>();
// Apply hull
CGAL::Surface_mesh<CGAL::Point_3<K>> r;
CGAL::convex_hull_3(points.begin(), points.end(), r);
auto r_exact = std::make_shared<CGAL_HybridMesh>();
copyMesh(r, *r_exact);
return std::make_shared<CGALHybridPolyhedron>(r_exact);
}
auto mesh = std::make_shared<CGAL_HybridMesh>();
if (createMeshFromPolySet(*ps_tri, *mesh)) {
assert(false && "Error from createMeshFromPolySet");
}
if (!ps_tri->isConvex()) {
if (isClosed(*mesh)) {
// Note: PMP::orient can corrupt models and cause cataclysmic memory leaks
// (try testdata/scad/3D/issues/issue1105d.scad for instance), but
// PMP::orient_to_bound_a_volume seems just fine.
orientToBoundAVolume(*mesh);
} else {
LOG(message_group::Warning, "Warning: mesh is not closed!");
}
}
return std::make_shared<CGALHybridPolyhedron>(mesh);
}
std::shared_ptr<CGALHybridPolyhedron> createHybridPolyhedronFromNefPolyhedron(const CGAL_Nef_polyhedron& nef)
{
assert(nef.p3);
auto mesh = std::make_shared<CGAL_HybridMesh>();
CGAL::Surface_mesh<CGAL::Point_3<CGAL_Kernel3>> alien_mesh;
convertNefPolyhedronToTriangleMesh(*nef.p3, alien_mesh);
copyMesh(alien_mesh, *mesh);
return std::make_shared<CGALHybridPolyhedron>(mesh);
}
std::shared_ptr<CGALHybridPolyhedron> createMutableHybridPolyhedronFromGeometry(const std::shared_ptr<const Geometry>& geom)
{
if (auto poly = std::dynamic_pointer_cast<const CGALHybridPolyhedron>(geom)) {
return std::make_shared<CGALHybridPolyhedron>(*poly);
} else if (auto ps = std::dynamic_pointer_cast<const PolySet>(geom)) {
return createHybridPolyhedronFromPolySet(*ps);
} else if (auto nef = std::dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom)) {
return createHybridPolyhedronFromNefPolyhedron(*nef);
#if ENABLE_MANIFOLD
} else if (auto mani = std::dynamic_pointer_cast<const ManifoldGeometry>(geom)) {
return createHybridPolyhedronFromPolySet(*mani->toPolySet());
#endif
} else {
LOG(message_group::Warning, "Unsupported geometry format.");
return nullptr;
}
}
std::shared_ptr<const CGALHybridPolyhedron> getHybridPolyhedronFromGeometry(const std::shared_ptr<const Geometry>& geom)
{
if (auto poly = std::dynamic_pointer_cast<const CGALHybridPolyhedron>(geom)) {
return poly;
} else {
return createMutableHybridPolyhedronFromGeometry(geom);
}
}
std::shared_ptr<CGAL_Nef_polyhedron> createNefPolyhedronFromHybrid(const CGALHybridPolyhedron& hybrid)
{
using CGAL_SurfaceMesh = CGAL::Surface_mesh<CGAL::Point_3<CGAL_Kernel3>>;
if (auto mesh = hybrid.getMesh()) {
CGAL_SurfaceMesh alien_mesh;
copyMesh(*mesh, alien_mesh);
return std::make_shared<CGAL_Nef_polyhedron>(std::make_shared<CGAL_Nef_polyhedron3>(alien_mesh));
}
if (auto nef = hybrid.getNefPolyhedron()) {
CGAL_HybridMesh mesh;
CGALUtils::convertNefPolyhedronToTriangleMesh(*nef, mesh);
CGAL_SurfaceMesh alien_mesh;
copyMesh(mesh, alien_mesh);
return std::make_shared<CGAL_Nef_polyhedron>(std::make_shared<CGAL_Nef_polyhedron3>(alien_mesh));
} else {
assert(!"Invalid hybrid polyhedron state");
return nullptr;
}
}
} // namespace CGALUtils