-
Notifications
You must be signed in to change notification settings - Fork 0
/
Points2Spheres.cpp
104 lines (93 loc) · 3.3 KB
/
Points2Spheres.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
#include "Points2Spheres.hpp"
#include "GeometryUtils.hpp"
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <math.h>
typedef std::unordered_map<Point3, size_t, boost::hash<Point3>> pt2ind;
size_t ipow(int base, int exp)
{
size_t x = 1;
for (int i = 0; i < exp; ++i) { x *= base; }
return x;
}
template <class HDS>
class Build_sphere : public CGAL::Modifier_base<HDS>
{
typedef typename CGAL::Polyhedron_incremental_builder_3<HDS> Builder;
const Point3& pt;
const double r;
const size_t n;
public:
Build_sphere(const Point3& pt, const double r, const size_t n) : pt(pt), r(r), n(n) {}
void operator()(HDS& hds)
{
Builder B(hds, true);
B.begin_surface(2+2*ipow(4, n), ipow(4, n+1), 6*ipow(4, n));
// Build a refined tetrahedron
Point3 a(0, 0, -1), b(0, 0.9428, 1.0/3), c(-0.8165, -0.4714, 1.0/3), d(0.8165, -0.4714, 1.0/3);
pt2ind map;
_us_recurse(a, b, c, B, map, n);
_us_recurse(d, c, b, B, map, n);
_us_recurse(a, d, b, B, map, n);
_us_recurse(a, c, d, B, map, n);
// Make that tetrahedron a unit sphere (the noramlization) and then scale and translate it appropiately
for (size_t i = 0; i < map.size(); ++i)
{
B.vertex(i)->point() = pt + r*normalized(B.vertex(i)->point() - CGAL::ORIGIN);
}
B.end_surface();
}
static void _us_recurse(const Point3& a, const Point3& b, const Point3& c,
Builder& B, pt2ind& map, int n)
{
if (n == 0)
{
// Base case: add a triangle
size_t va = vert_ind(a, B, map);
size_t vb = vert_ind(b, B, map);
size_t vc = vert_ind(c, B, map);
B.begin_facet();
B.add_vertex_to_facet(va);
B.add_vertex_to_facet(vb);
B.add_vertex_to_facet(vc);
B.end_facet();
}
else
{
// Bisect each side of the triangle
Point3 ab((a.x() + b.x())/2, (a.y() + b.y())/2, (a.z() + b.z())/2);
Point3 ac((a.x() + c.x())/2, (a.y() + c.y())/2, (a.z() + c.z())/2);
Point3 bc((b.x() + c.x())/2, (b.y() + c.y())/2, (b.z() + c.z())/2);
// Recurse into the four sub-triangles
_us_recurse(a, ab, ac, B, map, n-1);
_us_recurse(ab, b, bc, B, map, n-1);
_us_recurse(bc, c, ac, B, map, n-1);
_us_recurse(ab, bc, ac, B, map, n-1);
}
}
static size_t vert_ind(const Point3& v, Builder& B, pt2ind& map)
{
pt2ind::iterator itr = map.find(v);
if (itr != map.end()) { return itr->second; }
size_t idx = map.size();
B.add_vertex(v);
map.insert(itr, std::make_pair(v, idx));
return idx;
}
};
Polyhedron3* point2sphere(const Point3& pt, double r, size_t n)
{
Build_sphere<Polyhedron3::HalfedgeDS> bs(pt, r, n);
Polyhedron3* P = new Polyhedron3();
P->delegate(bs);
return P;
}
std::vector<Polyhedron3*> points2spheres(const std::vector<Point3>& pts, double r, size_t n)
{
std::vector<Polyhedron3*> spheres;
spheres.reserve(pts.size());
for (std::vector<Point3>::const_iterator itr = pts.begin(), end = pts.end(); itr != end; ++itr)
{
spheres.push_back(point2sphere(*itr, r, n));
}
return spheres;
}