5 * Created by Bryan Donlan on Tue 10 Jan 2006.
6 * Copyright (c) 2006 Bryan Donlan. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
32 #include <boost/lambda/lambda.hpp>
33 #include "slaballoc.h"
36 // REGION_MAX should be odd, or adjust REGION_MIN manually
38 #define REGION_MIN (int)(REGION_MAX / 2)
40 typedef unsigned long long u64_t
;
41 using namespace boost::lambda
;
47 Region() { xmin
= xmax
= ymin
= ymax
= 0; }
49 template<class Archive
>
50 void serialize(Archive
& ar
, const unsigned int version
)
56 bool contains(int x
, int y
) const {
57 return (x
>= xmin
&& x
<= xmax
&&
58 y
>= ymin
&& y
<= ymax
62 bool overlaps(const Region
&r2
) const {
63 return (xmin
<= r2
.xmax
&& xmax
>= r2
.xmin
)
64 && (ymin
<= r2
.ymax
&& ymax
>= r2
.ymin
);
67 Region
expand(const Region
&r2
) {
69 if (r1
.xmin
> r2
.xmin
)
71 if (r1
.xmax
< r2
.xmax
)
73 if (r1
.ymin
> r2
.ymin
)
75 if (r1
.ymax
< r2
.ymax
)
81 return (u64_t
)(xmax
- xmin
) * (u64_t
)(ymax
- ymin
);
84 std::string
to_s() const {
85 std::ostringstream oss
;
86 oss
<< "(" << xmin
<< " - " << xmax
<< ", " << ymin
<< " - " << ymax
<< ")";
90 bool operator==(const Region
&r2
) const {
91 return (xmin
== r2
.xmin
)
98 bool operator!=(const Region
&r2
) const {
99 return !(*this == r2
);
102 Region(const Region
&r2
)
103 : xmin(r2
.xmin
), xmax(r2
.xmax
),
104 ymin(r2
.ymin
), ymax(r2
.ymax
)
106 assert(xmin
<= xmax
);
107 assert(ymin
<= ymax
);
110 Region(int xmin_
, int xmax_
, int ymin_
, int ymax_
)
111 : xmin(xmin_
), xmax(xmax_
), ymin(ymin_
), ymax(ymax_
)
113 assert(xmin
<= xmax
);
114 assert(ymin
<= ymax
);
118 template <class T
> struct RBranch
;
119 template <class T
> struct RData
;
120 template <class T
> class RTree
;
126 unsigned int parent_idx
;
129 virtual void scan(const Region
&target
, std::vector
<RData
<T
> *> &list
) = 0;
130 virtual RData
<T
> *scan(const Region
&target
) = 0;
132 virtual RBranch
<T
> *chooseleaf(const Region
&)
135 RNode(const Region
&r_
, RTree
<T
> *t
) : r(r_
), parent(NULL
), parent_idx(UINT_MAX
), tree(t
)
141 virtual std::string
dump() = 0;
143 virtual size_t size() const = 0; // Leaves
144 virtual size_t inner_size() const = 0; // All nodes
145 virtual void expensive_checks() {}
149 struct RBranch
: public RNode
<T
> {
150 unsigned int child_count
; // : CLD_BITS;
151 bool is_leaf
: 1; // if true, all of children are RLeafs
152 RNode
<T
> *children
[REGION_MAX
];
156 virtual size_t size() const { return sz
; }
158 virtual size_t inner_size() const { return isz
; }
160 void expensive_checks() {
163 for (unsigned int i
= 0; i
< child_count
; i
++) {
164 assert(children
[i
]->parent
== this);
165 assert(children
[i
]->parent_idx
== i
);
166 children
[i
]->expensive_checks();
170 std::cerr
<< "expensive_checks() fail, was = " << r_
.to_s() << std::endl
;
179 this->sz
= children
[0]->size();
180 this->isz
= children
[0]->inner_size() + 1;
181 this->r
= children
[0]->r
;
182 for (unsigned int i
= 1; i
< child_count
; i
++) {
183 this->r
= this->r
.expand(children
[i
]->r
);
184 this->sz
+= children
[i
]->size();
185 this->isz
+= children
[i
]->inner_size();
190 RBranch
<T
> *p
= this;
197 void add_kid(RNode
<T
> *n
) {
198 assert(child_count
< REGION_MAX
);
199 children
[child_count
] = n
;
201 n
->parent_idx
= child_count
;
207 void drop_kid(unsigned int idx
, std::deque
<RNode
<T
> *> &reloc
, RBranch
<T
> *&root
) { // not yet used
208 assert(child_count
&& idx
< child_count
);
211 for (unsigned int i
= idx
; i
< child_count
; i
++) {
212 children
[i
] = children
[i
+ 1];
213 children
[i
]->parent_idx
= i
;
216 if (child_count
< REGION_MIN
) {
217 reloc
.push_back(this);
219 this->parent
->drop_kid(this->parent_idx
, reloc
, root
);
221 assert(root
== this);
230 void add_multi(RNode
<T
> **n
, int count
) {
231 assert(child_count
+ count
<= REGION_MAX
);
232 for (int i
= 0; i
< count
; i
++) {
233 children
[child_count
+ i
] = n
[i
];
234 children
[child_count
+ i
]->parent
= this;
235 children
[child_count
+ i
]->parent_idx
= child_count
+ i
;
238 child_count
+= count
;
243 RBranch(const Region
&r
, RTree
<T
> *t
) : RNode
<T
>(r
, t
) {
244 // Convenience for the main RTree initializer
251 virtual void scan(const Region
&target
, std::vector
<RData
<T
> *> &list
) {
252 if (!this->r
.overlaps(target
))
254 for (unsigned int i
= 0; i
< child_count
; i
++)
255 if (children
[i
]->r
.overlaps(target
))
256 children
[i
]->scan(target
, list
);
259 virtual RData
<T
> *scan(const Region
&target
) {
260 if (!this->r
.overlaps(target
))
262 for (unsigned int i
= 0; i
< child_count
; i
++) {
263 if (children
[i
]->r
.overlaps(target
)) {
264 RData
<T
> *ret
= children
[i
]->scan(target
);
271 virtual RBranch
<T
> *chooseleaf(const Region
&target
) {
275 RBranch
<T
> *best
= dynamic_cast<RBranch
<T
> *>(children
[0]);
276 unsigned long expansion
= ULONG_MAX
;
278 for (unsigned int i
= 0; i
< child_count
; i
++) {
279 u64_t orig_area
= children
[i
]->r
.area();
280 u64_t new_area
= children
[i
]->r
.expand(target
).area();
281 u64_t exp
= new_area
- orig_area
;
282 if (exp
< expansion
) {
283 best
= dynamic_cast<RBranch
<T
> *>(children
[i
]);
288 return best
->chooseleaf(target
);
291 void insert(RNode
<T
> *node
, RBranch
<T
> *&root
) {
293 assert(!dynamic_cast<RBranch
<T
> *>(node
));
295 assert(dynamic_cast<RBranch
<T
> *>(node
));
297 if (child_count
== REGION_MAX
)
303 void divide(std::list
<RNode
<T
> *> &inlist
, std::list
<RNode
<T
> *> &node1
, std::list
<RNode
<T
> *> &node2
) {
304 // quadratic time split
305 // Described in Guttman, A. 1988. R-trees: a dynamic index structure for spatial searching.
309 size_t orig_size
= inlist
.size();
311 assert(!node1
.size() && !node2
.size());
313 typename
std::list
<RNode
<T
> *>::iterator best1
, best2
;
315 typename
std::list
<RNode
<T
> *>::iterator i1
, i2
;
317 for (i1
= inlist
.begin(); i1
!= inlist
.end(); i1
++) {
318 for (i2
= inlist
.begin(); i2
!= inlist
.end(); i2
++) {
321 Region j
= (*i1
)->r
.expand((*i2
)->r
);
322 u64_t d
= j
.area() - (*i1
)->r
.area() - (*i2
)->r
.area();
331 Region
r1((*best1
)->r
);
332 Region
r2((*best2
)->r
);
334 node1
.push_back(*best1
);
335 node2
.push_back(*best2
);
340 while (inlist
.size()) {
341 if (inlist
.size() + node1
.size() == REGION_MIN
) {
342 std::copy(inlist
.begin(), inlist
.end(), std::inserter(node1
, node1
.end()));
346 if (inlist
.size() + node2
.size() == REGION_MIN
) {
347 std::copy(inlist
.begin(), inlist
.end(), std::inserter(node2
, node2
.end()));
352 typename
std::list
<RNode
<T
> *>::iterator best
;
355 for (typename
std::list
<RNode
<T
> *>::iterator i
= inlist
.begin(); i
!= inlist
.end(); i
++) {
357 u64_t d1
= r1
.expand(r
).area() - r1
.area();
358 u64_t d2
= r2
.expand(r
).area() - r2
.area();
359 u64_t diff
= (d1
< d2
) ? d2
- d1
: d1
- d2
;
360 if (diff
>= best_diff
) {
366 Region
&r
= (*best
)->r
;
367 u64_t d1
= r1
.expand(r
).area() - r1
.area();
368 u64_t d2
= r2
.expand(r
).area() - r2
.area();
369 int choice
= 0; // node1, node2
375 else if (r1
.area() > r2
.area())
377 else if (r2
.area() > r1
.area())
379 else if (node1
.size() > node2
.size())
381 else if (node2
.size() > node1
.size())
383 else choice
= 1; // arbitrary tiebreaker
388 node1
.push_back(*best
);
391 node2
.push_back(*best
);
397 assert(orig_size
== node1
.size() + node2
.size());
400 void split(RBranch
<T
> *&root
) {
401 assert(child_count
== REGION_MAX
);
403 unsigned int split
= child_count
/ 2;
404 RBranch
<T
> *newbranch
= new(this->tree
->branches
) RBranch
<T
>(children
[split
]->r
, this->tree
);
406 newbranch
->is_leaf
= this->is_leaf
;
408 std::list
<RNode
<T
> *> l
, n1
, n2
;
409 std::copy(children
, children
+ child_count
, std::inserter(l
, l
.end()));
410 assert(l
.size() == child_count
);
412 assert(l
.size() == 0);
413 assert(n1
.size() + n2
.size() == REGION_MAX
);
415 std::copy(n1
.begin(), n1
.end(), children
);
416 std::copy(n2
.begin(), n2
.end(), newbranch
->children
);
418 child_count
= n1
.size();
419 newbranch
->child_count
= n2
.size();
421 for (unsigned int i
= 0; i
< child_count
; i
++) {
422 children
[i
]->parent
= this;
423 children
[i
]->parent_idx
= i
;
426 for (unsigned int i
= 0; i
< newbranch
->child_count
; i
++) {
427 newbranch
->children
[i
]->parent
= newbranch
;
428 newbranch
->children
[i
]->parent_idx
= i
;
432 newbranch
->minimize();
434 if (!this->parent
) { // Need to make a new root!
435 root
= new(this->tree
->branches
) RBranch
<T
>(this->r
, this->tree
);
436 root
->is_leaf
= false;
437 root
->insert(this, root
);
440 this->parent
->insert(newbranch
, root
);
442 // std::cerr << "Split! After split, myct " << this->child_count <<
443 // " newbranch " << newbranch->child_count << " root " << root->child_count << std::endl;
446 root
->expensive_checks();
449 virtual std::string
dump() {
451 Region
test(children
[0]->r
);
452 std::ostringstream oss
;
453 oss
<< "RBranch " << this->r
.to_s() << " {" << std::endl
;
454 for (unsigned int i
= 0; i
< child_count
; i
++) {
455 oss
<< "#" << i
<< " " << children
[i
]->dump() << std::endl
;
456 test
= test
.expand(children
[i
]->r
);
462 oss
<< "NOK " << test
.to_s();
463 test2
.expand(this->r
);
464 if (test2
!= test
) oss
<< " NOTMIN ";
466 oss
<< "}" << std::endl
;
470 SLAB_CLASS(RBranch
<T
>)
474 struct RData
: public RNode
<T
> {
477 virtual size_t size() const { return 1; }
479 virtual size_t inner_size() const { return 1; }
481 virtual void scan(const Region
&target
, std::vector
<RData
<T
> *> &list
) {
482 if (!this->r
.overlaps(target
))
484 list
.push_back(this);
486 virtual RData
<T
> *scan(const Region
&target
) {
487 if (this->r
.overlaps(target
))
492 RData(const Region
&r_
, RTree
<T
> *t
, const T
&obj_
) : RNode
<T
>(r_
, t
), obj(obj_
) { }
495 std::ostringstream oss
;
496 oss
<< "RData " << this->r
.to_s() << " -> " << /* obj.to_s() */ (void *)&obj
<< std::endl
;
507 SlabAllocator branches
;
508 DestructingSlab leaves
;
511 void free_node(RNode
<T
> *n
) { delete n
; }
514 friend class RBranch
<T
>;
517 // Wrapper to enforce encapsulation
522 const Region
®ion() const { assert(node
); return node
->r
; }
523 T
&data() { assert(node
); return node
->obj
; }
525 friend std::vector
<ptr
> RTree::find(const Region
&r
);
526 ptr(RData
<T
> *n
, RTree
<T
> *t
) : node(n
), tree(t
) { }
527 ptr(RData
<T
> &n
, RTree
<T
> *t
) : node(&n
), tree(t
) {}
529 ptr(const ptr
&p
) : node(p
.node
), tree(p
.tree
) {}
531 std::deque
<RNode
<T
> *> reloc
;
532 assert(node
&& node
->parent
);
533 node
->parent
->drop_kid(node
->parent_idx
, reloc
, tree
->root
);
534 tree
->free_node(node
);
536 while (!reloc
.empty()) {
537 RNode
<T
> *node
= reloc
.front();
539 RBranch
<T
> *br
= dynamic_cast<RBranch
<T
> *>(node
);
541 // This is probably slightly inefficient but should work
542 for (unsigned int i
= 0; i
< br
->child_count
; i
++) {
543 reloc
.push_back(br
->children
[i
]);
548 tree
->root
= new(this->tree
->branches
) RBranch
<T
>(node
->r
, tree
);
549 tree
->root
->chooseleaf(node
->r
)->insert(node
, tree
->root
);
556 RTree() : root(NULL
) {}
558 void insert(const Region
&r
, const T
&val
) {
559 RData
<T
> *node
= new(leaves
) RData
<T
>(r
, this, val
);
561 root
= new(branches
) RBranch
<T
>(r
, this);
562 root
->chooseleaf(r
)->insert(node
, root
);
565 std::vector
<ptr
> find(const Region
&r
) {
566 if (!root
) return std::vector
<ptr
>();
567 std::vector
<RData
<T
> *> list
;
570 typename
std::vector
<RData
<T
> *>::iterator i
= list
.begin();
571 std::vector
<ptr
> out
;
572 while (i
!= list
.end()) {
573 out
.push_back(ptr(*i
, this));
580 std::vector
<ptr
> find(int x
, int y
) {
581 Region
r(x
, y
, x
, y
);
585 T
*find_one(const Region
&r
) {
586 if (!root
) return NULL
;
588 RData
<T
> *ret
= root
->scan(r
);
589 if (!ret
) return NULL
;
600 template<class Archive
>
601 void save(Archive
& ar
, const unsigned int version
) const {
602 std::vector
<RData
<T
> *> l
;
603 Region
za_warudo(INT_MIN
, INT_MIN
, INT_MAX
, INT_MAX
);
605 root
->scan(za_warudo
, l
);
606 size_t len
= l
.size();
607 assert(len
== size());
609 std::for_each(l
.start(), l
.end(),
610 ar
& (*_1
)->* &RData
<T
>::r
& (*_1
)->* &RData
<T
>::obj
);
613 template<class Archive
>
614 void load(Archive
& ar
, const unsigned int version
) {
622 for (size_t i
= 0; i
< len
; i
++) {
631 void check() { if (root
) root
->expensive_checks(); }
632 size_t size() const { return root
? root
->size() : 0; }
633 size_t inner_size() const { return root
? root
->inner_size() : 0; }
637 // vim: set ts=4 tw=4 noet :