- use coordinates in Node to avoid calculation in query()
- inline node overlap check in query
This commit is contained in:
Hannes Janetzek 2014-02-08 16:52:27 +01:00
parent 1d0fcedeb0
commit 7f64fff46d
2 changed files with 53 additions and 42 deletions

View File

@ -12,34 +12,32 @@ import org.slf4j.LoggerFactory;
*
* ... in case this generic isnt obvious at first sight.
* */
public abstract class BoxTree<Box extends BoxItem<E>, E>
extends QuadTree<BoxNode<Box>, Box> {
public abstract class BoxTree<Box extends BoxItem<E>, E> extends QuadTree<BoxNode<Box>, Box> {
final static Logger log = LoggerFactory.getLogger(BoxTree.class);
static boolean dbg = false;
int extents;
int maxDepth;
protected final int extents;
protected final int maxDepth;
public static class BoxNode<T extends BoxItem<?>> extends Node<BoxNode<T>, T> {
// for non-recursive traversal
BoxNode<T> next;
public int x;
public int y;
public int size;
// TODO make final? or update to the actual used extent?
public int x1;
public int y1;
public int x2;
public int y2;
//BoxItem<T> list;
public boolean overlaps(T it) {
return (x < it.x2) &&
(y < it.y2) &&
(it.x1 < x + size) &&
(it.y1 < y + size);
return (x1 < it.x2) && (y1 < it.y2) && (it.x1 < x2) && (it.y1 < y2);
}
@Override
public String toString() {
return x + ":" + y + ":" + size;
return x1 + ":" + y1 + ":" + (x2 - x1);
}
}
@ -68,10 +66,7 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
public int y2;
public boolean overlaps(BoxItem<T> it) {
return (x1 < it.x2)
&& (it.x1 < x2)
&& (y1 < it.y2)
&& (it.y1 < y2);
return (x1 < it.x2) && (it.x1 < x2) && (y1 < it.y2) && (it.y1 < y2);
}
}
@ -92,9 +87,10 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
public BoxTree(int extents, int maxDepth) {
super();
// size is -extents to +extents
this.root.size = extents * 2;
this.root.x = -extents;
this.root.y = -extents;
this.root.x1 = -extents;
this.root.y1 = -extents;
this.root.x2 = extents;
this.root.y2 = extents;
this.extents = extents;
this.maxDepth = maxDepth;
@ -132,7 +128,6 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
boolean drop = false;
//O:
while (stack != null) {
/** pop cur from stack */
@ -173,30 +168,36 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
}
/** put children on stack which overlap with box */
if ((c = cur.child00) != null && c.overlaps(box)) {
if ((c = cur.child00) != null &&
(x1 < c.x2) && (y1 < c.y2) &&
(c.x1 < x2) && (c.y1 < y2)) {
c.next = stack;
stack = c;
}
if ((c = cur.child01) != null && c.overlaps(box)) {
if ((c = cur.child01) != null &&
(x1 < c.x2) && (y1 < c.y2) &&
(c.x1 < x2) && (c.y1 < y2)) {
c.next = stack;
stack = c;
}
if ((c = cur.child10) != null && c.overlaps(box)) {
if ((c = cur.child10) != null &&
(x1 < c.x2) && (y1 < c.y2) &&
(c.x1 < x2) && (c.y1 < y2)) {
c.next = stack;
stack = c;
}
if ((c = cur.child11) != null && c.overlaps(box)) {
if ((c = cur.child11) != null &&
(x1 < c.x2) && (y1 < c.y2) &&
(c.x1 < x2) && (c.y1 < y2)) {
c.next = stack;
stack = c;
}
}
/** dont keep dangling references */
while (stack != null)
stack = stack.next;
/* gwt optimizer found this cannot be reached :) */
//while (stack != null)
// stack = stack.next;
return drop ? 1 : 0;
}
@ -248,10 +249,9 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
public BoxNode<Box> create(BoxNode<Box> parent, int i) {
BoxNode<Box> node = new BoxNode<Box>();
int size = parent.size >> 1;
node.x = parent.x;
node.y = parent.y;
node.size = size;
int size = (parent.x2 - parent.x1) >> 1;
node.x1 = parent.x1;
node.y1 = parent.y1;
if (i == 0) {
// top-left
@ -259,18 +259,21 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
} else if (i == 1) {
// bottom-left
parent.child10 = node;
node.y += size;
node.y1 += size;
} else if (i == 2) {
// top-right
parent.child01 = node;
node.x += size;
node.x1 += size;
} else {
// bottom-right
parent.child11 = node;
node.x += size;
node.y += size;
node.x1 += size;
node.y1 += size;
}
node.x2 = node.x1 + size;
node.y2 = node.y1 + size;
node.parent = parent;
return node;
@ -294,13 +297,13 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
for (int level = 0; level <= maxDepth; level++) {
// half size of tile at current z
//int hsize = (extents >> level);
int hsize = cur.size >> 1;
int hsize = (cur.x2 - cur.x1) >> 1;
// center of tile (shift by -extents)
//int cx = px + hsize - extents;
//int cy = py + hsize - extents;
int cx = cur.x + hsize;
int cy = cur.y + hsize;
int cx = cur.x1 + hsize;
int cy = cur.y1 + hsize;
child = null;
//int childPos = -1;
@ -330,9 +333,11 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
idY++;
}
}
//log.debug("child {}", child);
if (cur == minNode && child != null)
minNode = cur;
if (child == null || level == maxDepth) {
// push item onto list of this node
box.next = cur.item;
@ -342,7 +347,6 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
log.debug("insert at: " + level + " / " + idX + ":"
+ idY + " -- " + x1 + ":" + y1
+ " /" + (x2) + "x" + (y2));
break;
}
cur = child;
@ -350,6 +354,11 @@ public abstract class BoxTree<Box extends BoxItem<E>, E>
}
public void setMinNode(int x1, int y1, int x2, int y2) {
/* TODO find lowest node that fully contains the region
* and set it as start for following queries */
}
public abstract boolean process(BoxNode<Box> nodes);
public void clear() {

View File

@ -23,6 +23,8 @@ public abstract class QuadTree<T extends Node<T, E>, E> {
protected final T root;
protected T minNode;
protected T pool;
public QuadTree() {