26 struct rtree_node :
public rtree_elt_base {
27 std::unique_ptr<rtree_elt_base> left, right;
28 rtree_node(
const base_node& bmin,
const base_node& bmax,
29 std::unique_ptr<rtree_elt_base> &&left_,
30 std::unique_ptr<rtree_elt_base> &&right_)
31 : rtree_elt_base(false, bmin, bmax), left(
std::move(left_)),
32 right(
std::move(right_)) { }
35 struct rtree_leaf :
public rtree_elt_base {
37 rtree_leaf(
const base_node& bmin,
const base_node& bmax,
38 rtree::pbox_cont& lst_)
39 : rtree_elt_base(true, bmin, bmax) { lst.swap(lst_); }
43 static void update_box(base_node& bmin, base_node& bmax,
44 const base_node& a,
const base_node& b) {
45 base_node::iterator itmin=bmin.begin(), itmax=bmax.begin();
47 itmin[i] = std::min(itmin[i], a.at(i));
48 itmax[i] = std::max(itmax[i], b.at(i));
52 inline static bool r1_ge_r2(
const base_node& min1,
const base_node& max1,
53 const base_node& min2,
const base_node& max2) {
55 if (!(min1[i] <= min2[i] && max1[i] >= max2[i]))
return false;
59 inline static bool r1_inter_r2(
const base_node& min1,
const base_node& max1,
60 const base_node& min2,
const base_node& max2) {
62 if (max1[i] < min2[i] || min1[i] > max2[i])
return false;
67 struct intersection_p {
68 const base_node min,max;
69 intersection_p(
const base_node& min_,
const base_node& max_)
70 : min(min_), max(max_) {}
71 bool operator()(
const base_node& min2,
const base_node& max2)
72 {
return r1_inter_r2(min,max,min2,max2); }
73 bool accept(
const base_node& min2,
const base_node& max2)
74 {
return operator()(min2,max2); }
79 const base_node min,max;
80 contains_p(
const base_node& min_,
const base_node& max_)
81 : min(min_), max(max_) {}
82 bool operator()(
const base_node& min2,
const base_node& max2)
83 {
return r1_ge_r2(min2,max2,min,max); }
84 bool accept(
const base_node& min2,
const base_node& max2)
85 {
return r1_inter_r2(min,max,min2,max2); }
90 const base_node min,max;
91 contained_p(
const base_node& min_,
const base_node& max_)
92 : min(min_), max(max_) {}
93 bool accept(
const base_node& min2,
const base_node& max2)
94 {
return r1_inter_r2(min,max,min2,max2); }
95 bool operator()(
const base_node& min2,
const base_node& max2)
96 {
return r1_ge_r2(min,max,min2,max2); }
102 has_point_p(
const base_node& P_) : P(P_) {}
103 bool operator()(
const base_node& min2,
const base_node& max2) {
105 if (P[i] < min2[i] || P[i] > max2[i])
return false;
108 bool accept(
const base_node& min2,
const base_node& max2)
109 {
return operator()(min2,max2); }
114 struct intersect_line {
116 const base_small_vector dirv;
117 intersect_line(
const base_node& org_,
const base_small_vector &dirv_)
118 : org(org_), dirv(dirv_) {}
119 bool operator()(
const base_node& min2,
const base_node& max2) {
121 GMM_ASSERT1(N == min2.size(),
"Dimensions mismatch");
123 if (dirv[i] != scalar_type(0)) {
124 scalar_type a1=(min2[i]-org[i])/dirv[i], a2=(max2[i]-org[i])/dirv[i];
125 bool interf1 =
true, interf2 =
true;
128 scalar_type y1 = org[j] + a1*dirv[j], y2 = org[j] + a2*dirv[j];
129 if (y1 < min2[j] || y1 > max2[j]) interf1 =
false;
130 if (y2 < min2[j] || y2 > max2[j]) interf2 =
false;
132 if (interf1 || interf2)
return true;
136 bool accept(
const base_node& min2,
const base_node& max2)
137 {
return operator()(min2,max2); }
142 struct intersect_line_and_box {
144 const base_small_vector dirv;
145 const base_node min,max;
146 intersect_line_and_box(
const base_node& org_,
147 const base_small_vector &dirv_,
148 const base_node& min_,
const base_node& max_)
149 : org(org_), dirv(dirv_), min(min_), max(max_) {}
150 bool operator()(
const base_node& min2,
const base_node& max2) {
152 GMM_ASSERT1(N == min2.size(),
"Dimensions mismatch");
153 if (!(r1_inter_r2(min,max,min2,max2)))
return false;
155 if (dirv[i] != scalar_type(0)) {
156 scalar_type a1=(min2[i]-org[i])/dirv[i], a2=(max2[i]-org[i])/dirv[i];
157 bool interf1 =
true, interf2 =
true;
160 scalar_type y1 = org[j] + a1*dirv[j], y2 = org[j] + a2*dirv[j];
161 if (y1 < min2[j] || y1 > max2[j]) interf1 =
false;
162 if (y2 < min2[j] || y2 > max2[j]) interf2 =
false;
164 if (interf1 || interf2)
return true;
168 bool accept(
const base_node& min2,
const base_node& max2)
169 {
return operator()(min2,max2); }
173 template <
typename Predicate>
174 static void find_matching_boxes_(rtree_elt_base *n, rtree::pbox_set& boxlst,
177 const rtree_leaf *rl =
static_cast<rtree_leaf*
>(n);
178 for (rtree::pbox_cont::const_iterator it = rl->lst.begin();
179 it != rl->lst.end(); ++it) {
180 if (p((*it)->min, (*it)->max)) { boxlst.insert(*it); }
183 const rtree_node *rn =
static_cast<rtree_node*
>(n);
184 if (p.accept(rn->left->rmin,rn->left->rmax))
185 bgeot::find_matching_boxes_(rn->left.get(), boxlst, p);
186 if (p.accept(rn->right->rmin,rn->right->rmax))
187 bgeot::find_matching_boxes_(rn->right.get(), boxlst, p);
191 void rtree::find_intersecting_boxes(
const base_node& bmin,
192 const base_node& bmax,
194 boxlst.clear();
if (!root) build_tree();
195 if (root) find_matching_boxes_(root.get(),boxlst,intersection_p(bmin,bmax));
198 void rtree::find_containing_boxes(
const base_node& bmin,
199 const base_node& bmax, pbox_set& boxlst) {
200 boxlst.clear();
if (!root) build_tree();
201 if (root) find_matching_boxes_(root.get(), boxlst, contains_p(bmin,bmax));
204 void rtree::find_contained_boxes(
const base_node& bmin,
205 const base_node& bmax, pbox_set& boxlst) {
206 boxlst.clear();
if (!root) build_tree();
207 if (root) find_matching_boxes_(root.get(), boxlst, contained_p(bmin,bmax));
210 void rtree::find_boxes_at_point(
const base_node& P, pbox_set& boxlst) {
211 boxlst.clear();
if (!root) build_tree();
212 if (root) find_matching_boxes_(root.get(), boxlst, has_point_p(P));
215 void rtree::find_line_intersecting_boxes(
const base_node& org,
216 const base_small_vector& dirv,
218 boxlst.clear();
if (!root) build_tree();
219 if (root) find_matching_boxes_(root.get(),boxlst,intersect_line(org, dirv));
222 void rtree::find_line_intersecting_boxes(
const base_node& org,
223 const base_small_vector& dirv,
224 const base_node& bmin,
225 const base_node& bmax,
227 boxlst.clear();
if (!root) build_tree();
229 find_matching_boxes_(root.get(), boxlst,
230 intersect_line_and_box(org, dirv, bmin, bmax));
237 static bool split_test(
const rtree::pbox_cont& b,
238 const base_node& bmin,
const base_node& bmax,
239 unsigned dir, scalar_type& split_v) {
240 scalar_type v = bmin[dir] + (bmax[dir] - bmin[dir])/2; split_v = v;
242 for (rtree::pbox_cont::const_iterator it = b.begin(); it!=b.end(); ++it) {
243 if ((*it)->max[dir] < v) {
244 if (cnt == 0) split_v = (*it)->max[dir];
245 else split_v = std::max((*it)->max[dir],split_v);
249 return (cnt > 0 && cnt < b.size());
258 static std::unique_ptr<rtree_elt_base> build_tree_(rtree::pbox_cont b,
259 const base_node& bmin,
260 const base_node& bmax,
263 scalar_type split_v(0);
264 unsigned split_dir = unsigned((last_dir+1)%N);
265 bool split_ok =
false;
266 if (b.size() > rtree_elt_base::RECTS_PER_LEAF) {
267 for (
size_type itry=0; itry < N; ++itry) {
268 if (split_test(b, bmin, bmax, split_dir, split_v))
269 { split_ok =
true;
break; }
270 split_dir = unsigned((split_dir+1)%N);
275 for (rtree::pbox_cont::const_iterator it = b.begin();
276 it != b.end(); ++it) {
277 if ((*it)->min[split_dir] < split_v) cnt1++;
278 if ((*it)->max[split_dir] > split_v) cnt2++;
280 assert(cnt1); assert(cnt2);
281 GMM_ASSERT1(cnt1+cnt2 >= b.size(),
"internal error");
282 rtree::pbox_cont v1(cnt1), v2(cnt2);
283 base_node bmin1(bmax), bmax1(bmin);
284 base_node bmin2(bmax), bmax2(bmin);
286 for (rtree::pbox_cont::const_iterator it = b.begin();
287 it != b.end(); ++it) {
288 if ((*it)->min[split_dir] < split_v) {
290 update_box(bmin1,bmax1,(*it)->min,(*it)->max);
292 if ((*it)->max[split_dir] > split_v) {
294 update_box(bmin2,bmax2,(*it)->min,(*it)->max);
298 bmin1[k] = std::max(bmin1[k],bmin[k]);
299 bmax1[k] = std::min(bmax1[k],bmax[k]);
300 bmin2[k] = std::max(bmin2[k],bmin[k]);
301 bmax2[k] = std::min(bmax2[k],bmax[k]);
303 bmax1[split_dir] = std::min(bmax1[split_dir], split_v);
304 bmin2[split_dir] = std::max(bmin2[split_dir], split_v);
305 assert(cnt1 == v1.size()); assert(cnt2 == v2.size());
306 return std::make_unique<rtree_node>
308 build_tree_(v1, bmin1, bmax1, split_dir),
309 build_tree_(v2, bmin2, bmax2, split_dir));
311 return std::make_unique<rtree_leaf>(bmin, bmax, b);
315 void rtree::build_tree() {
316 if (boxes.size() == 0)
return;
317 getfem::local_guard lock = locks_.get_lock();
319 pbox_cont b(boxes.size());
320 pbox_cont::iterator b_it = b.begin();
321 base_node bmin(boxes.front().min), bmax(boxes.front().max);
322 for (box_cont::const_iterator it=boxes.begin(); it != boxes.end(); ++it) {
323 update_box(bmin,bmax,(*it).min,(*it).max);
326 root = build_tree_(b, bmin, bmax, 0);
329 static void dump_tree_(rtree_elt_base *p,
int level,
size_type& count) {
331 for (
int i=0; i < level; ++i) cout <<
" ";
332 cout <<
"span=" << p->rmin <<
".." << p->rmax <<
" ";
334 rtree_leaf *rl =
static_cast<rtree_leaf*
>(p);
335 cout <<
"Leaf [" << rl->lst.size() <<
" elts] = ";
336 for (
size_type i=0; i < rl->lst.size(); ++i)
337 cout <<
" " << rl->lst[i]->id;
339 count += rl->lst.size();
342 const rtree_node *rn =
static_cast<rtree_node*
>(p);
343 if (rn->left) { dump_tree_(rn->left.get(), level+1, count); }
344 if (rn->right) { dump_tree_(rn->right.get(), level+1, count); }
349 cout <<
"tree dump follows\n";
350 if (!root) build_tree();
352 dump_tree_(root.get(), 0, count);
353 cout <<
" --- end of tree dump, nb of rectangles: " << boxes.size()
354 <<
", rectangle ref in tree: " << count <<
"\n";
size_t size_type
used as the common size type in the library
region-tree for window/point search on a set of rectangles.