1 #include "SpatIndex.hpp"
2
3 // for concave hull merging decisions
4 #include <libslic3r/SLA/BoostAdapter.hpp>
5
6 #ifdef _MSC_VER
7 #pragma warning(push)
8 #pragma warning(disable: 4244)
9 #pragma warning(disable: 4267)
10 #endif
11
12 #include "boost/geometry/index/rtree.hpp"
13
14 #ifdef _MSC_VER
15 #pragma warning(pop)
16 #endif
17
18 namespace Slic3r { namespace sla {
19
20 /* **************************************************************************
21 * PointIndex implementation
22 * ************************************************************************** */
23
24 class PointIndex::Impl {
25 public:
26 using BoostIndex = boost::geometry::index::rtree< PointIndexEl,
27 boost::geometry::index::rstar<16, 4> /* ? */ >;
28
29 BoostIndex m_store;
30 };
31
PointIndex()32 PointIndex::PointIndex(): m_impl(new Impl()) {}
~PointIndex()33 PointIndex::~PointIndex() {}
34
PointIndex(const PointIndex & cpy)35 PointIndex::PointIndex(const PointIndex &cpy): m_impl(new Impl(*cpy.m_impl)) {}
PointIndex(PointIndex && cpy)36 PointIndex::PointIndex(PointIndex&& cpy): m_impl(std::move(cpy.m_impl)) {}
37
operator =(const PointIndex & cpy)38 PointIndex& PointIndex::operator=(const PointIndex &cpy)
39 {
40 m_impl.reset(new Impl(*cpy.m_impl));
41 return *this;
42 }
43
operator =(PointIndex && cpy)44 PointIndex& PointIndex::operator=(PointIndex &&cpy)
45 {
46 m_impl.swap(cpy.m_impl);
47 return *this;
48 }
49
insert(const PointIndexEl & el)50 void PointIndex::insert(const PointIndexEl &el)
51 {
52 m_impl->m_store.insert(el);
53 }
54
remove(const PointIndexEl & el)55 bool PointIndex::remove(const PointIndexEl& el)
56 {
57 return m_impl->m_store.remove(el) == 1;
58 }
59
60 std::vector<PointIndexEl>
query(std::function<bool (const PointIndexEl &)> fn) const61 PointIndex::query(std::function<bool(const PointIndexEl &)> fn) const
62 {
63 namespace bgi = boost::geometry::index;
64
65 std::vector<PointIndexEl> ret;
66 m_impl->m_store.query(bgi::satisfies(fn), std::back_inserter(ret));
67 return ret;
68 }
69
nearest(const Vec3d & el,unsigned k=1) const70 std::vector<PointIndexEl> PointIndex::nearest(const Vec3d &el, unsigned k = 1) const
71 {
72 namespace bgi = boost::geometry::index;
73 std::vector<PointIndexEl> ret; ret.reserve(k);
74 m_impl->m_store.query(bgi::nearest(el, k), std::back_inserter(ret));
75 return ret;
76 }
77
size() const78 size_t PointIndex::size() const
79 {
80 return m_impl->m_store.size();
81 }
82
foreach(std::function<void (const PointIndexEl &)> fn)83 void PointIndex::foreach(std::function<void (const PointIndexEl &)> fn)
84 {
85 for(auto& el : m_impl->m_store) fn(el);
86 }
87
foreach(std::function<void (const PointIndexEl &)> fn) const88 void PointIndex::foreach(std::function<void (const PointIndexEl &)> fn) const
89 {
90 for(const auto &el : m_impl->m_store) fn(el);
91 }
92
93 /* **************************************************************************
94 * BoxIndex implementation
95 * ************************************************************************** */
96
97 class BoxIndex::Impl {
98 public:
99 using BoostIndex = boost::geometry::index::
100 rtree<BoxIndexEl, boost::geometry::index::rstar<16, 4> /* ? */>;
101
102 BoostIndex m_store;
103 };
104
BoxIndex()105 BoxIndex::BoxIndex(): m_impl(new Impl()) {}
~BoxIndex()106 BoxIndex::~BoxIndex() {}
107
BoxIndex(const BoxIndex & cpy)108 BoxIndex::BoxIndex(const BoxIndex &cpy): m_impl(new Impl(*cpy.m_impl)) {}
BoxIndex(BoxIndex && cpy)109 BoxIndex::BoxIndex(BoxIndex&& cpy): m_impl(std::move(cpy.m_impl)) {}
110
operator =(const BoxIndex & cpy)111 BoxIndex& BoxIndex::operator=(const BoxIndex &cpy)
112 {
113 m_impl.reset(new Impl(*cpy.m_impl));
114 return *this;
115 }
116
operator =(BoxIndex && cpy)117 BoxIndex& BoxIndex::operator=(BoxIndex &&cpy)
118 {
119 m_impl.swap(cpy.m_impl);
120 return *this;
121 }
122
insert(const BoxIndexEl & el)123 void BoxIndex::insert(const BoxIndexEl &el)
124 {
125 m_impl->m_store.insert(el);
126 }
127
remove(const BoxIndexEl & el)128 bool BoxIndex::remove(const BoxIndexEl& el)
129 {
130 return m_impl->m_store.remove(el) == 1;
131 }
132
query(const BoundingBox & qrbb,BoxIndex::QueryType qt)133 std::vector<BoxIndexEl> BoxIndex::query(const BoundingBox &qrbb,
134 BoxIndex::QueryType qt)
135 {
136 namespace bgi = boost::geometry::index;
137
138 std::vector<BoxIndexEl> ret; ret.reserve(m_impl->m_store.size());
139
140 switch (qt) {
141 case qtIntersects:
142 m_impl->m_store.query(bgi::intersects(qrbb), std::back_inserter(ret));
143 break;
144 case qtWithin:
145 m_impl->m_store.query(bgi::within(qrbb), std::back_inserter(ret));
146 }
147
148 return ret;
149 }
150
size() const151 size_t BoxIndex::size() const
152 {
153 return m_impl->m_store.size();
154 }
155
foreach(std::function<void (const BoxIndexEl &)> fn)156 void BoxIndex::foreach(std::function<void (const BoxIndexEl &)> fn)
157 {
158 for(auto& el : m_impl->m_store) fn(el);
159 }
160
161 }} // namespace Slic3r::sla
162