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