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

View File

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