From c48c620963b0e8f1701f3bd462310130e61dbc0f Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Thu, 11 Sep 2014 20:19:09 +0200 Subject: [PATCH] BoxTree: - return false from search() when search callback returned false - fix removal: unlink next item - add clearToPool() --- vtm/src/org/oscim/utils/quadtree/BoxTree.java | 193 ++++++++++++++---- 1 file changed, 150 insertions(+), 43 deletions(-) diff --git a/vtm/src/org/oscim/utils/quadtree/BoxTree.java b/vtm/src/org/oscim/utils/quadtree/BoxTree.java index df78ed5a..dc199273 100644 --- a/vtm/src/org/oscim/utils/quadtree/BoxTree.java +++ b/vtm/src/org/oscim/utils/quadtree/BoxTree.java @@ -59,12 +59,9 @@ public class BoxTree, E> extends TileIndex, T> { public static class BoxNode> extends TreeNode, T> { // TODO this is redundant - use tile ids - public int x1; - public int y1; - public int x2; - public int y2; + public int x1, x2, y1, y2; - // inherits BoxItem item; + /* inherits BoxItem item; */ @Override public String toString() { @@ -73,6 +70,13 @@ public class BoxTree, E> extends TileIndex, T> { } public static class BoxItem extends Inlist> { + public int x1, x2, y1, y2; + + public T item; + + public BoxItem() { + } + public BoxItem(int x1, int y1, int x2, int y2) { this.x1 = x1; this.y1 = y1; @@ -80,6 +84,13 @@ public class BoxTree, E> extends TileIndex, T> { this.y2 = y2; } + public BoxItem(float x1, float y1, float x2, float y2) { + this.x1 = (int) x1; + this.y1 = (int) y1; + this.x2 = (int) x2; + this.y2 = (int) y2; + } + public BoxItem(org.oscim.core.Box box, T item) { this.x1 = (int) box.minX; this.y1 = (int) box.minY; @@ -88,24 +99,41 @@ public class BoxTree, E> extends TileIndex, T> { this.item = item; } + public boolean overlaps(BoxItem it) { + return !((x1 > it.x2) || (it.x1 > x2) || (y1 > it.y2) || (it.y1 > y2)); + } + + public void setExtents(float[] obb, float add) { + setExtents(obb, add, obb.length); + } + + public void setExtents(float[] obb, float add, int length) { + float x1, y1, x2, y2; + x1 = x2 = obb[0]; + y1 = y2 = obb[1]; + + for (int i = 2, n = length; i < n; i += 2) { + float x = obb[i]; + if (x < x1) + x1 = x; + else if (x > x2) + x2 = x; + + float y = obb[i + 1]; + if (y < y1) + y1 = y; + else if (y > y2) + y2 = y; + } + this.x1 = (int) (x1 - add); + this.y1 = (int) (y1 - add); + this.x2 = (int) (x2 + add); + this.y2 = (int) (y2 + add); + } + @Override public String toString() { - return x1 + "," + y1 + "/" + x2 + "," + y2; - } - - public T item; - - public BoxItem() { - - } - - public int x1; - public int x2; - public int y1; - public int y2; - - public boolean overlaps(BoxItem it) { - return !((x1 > it.x2) || (it.x1 > x2) || (y1 > it.y2) || (it.y1 > y2)); + return "[" + x1 + ',' + y1 + '/' + x2 + ',' + y2 + ']'; } } @@ -117,12 +145,18 @@ public class BoxTree, E> extends TileIndex, T> { return ((x > 0) && (x & (x - 1)) == 0); } + /** + * BoxTreee for the range [-extents, extents] + * + * @param extents must be power of two + * @param maxDepth must be <= 30 + */ public BoxTree(int extents, int maxDepth) { super(); if (!isPowerOfTwo(extents)) throw new IllegalArgumentException("Extents must be power of two!"); - //size is -extents to +extents + /* size is -extents to +extents */ this.root.x1 = -extents; this.root.y1 = -extents; this.root.x2 = extents; @@ -157,21 +191,26 @@ public class BoxTree, E> extends TileIndex, T> { }; }; - public boolean search(T box, SearchCb cb, Object ctxt) { + /** + * @return false when search was aborted + */ + public boolean search(BoxItem box, SearchCb cb, Object ctxt) { BoxNode n; Stack> stack = stackPool.get(); stack.push(root); - O: while (!stack.empty()) { + while (!stack.empty()) { n = stack.pop(); /* process overlapping items from cur node */ for (BoxItem it = n.item; it != null; it = it.next) { if (it.overlaps(box)) { - if (!cb.call(it.item, ctxt)) - break O; + if (!cb.call(it.item, ctxt)) { + stackPool.release(stack); + return false; + } } } @@ -207,22 +246,25 @@ public class BoxTree, E> extends TileIndex, T> { else if (overlaps(n.child11, box)) stack.push(n.child11); } + stackPool.release(stack); - return false; + return true; } public interface SearchBoxCb> { boolean call(T item); } - public boolean search(T box, SearchBoxCb cb) { + public boolean search(BoxItem box, SearchBoxCb cb) { BoxNode n; - BoxNode start = getNode(box, false); - if (start == null) - return false; + + if (root.refs == 0) { + //log.debug("emtpy"); + return true; + } Stack> stack = stackPool.get(); - stack.push(start); + stack.push(root); while (!stack.empty()) { n = stack.pop(); @@ -265,10 +307,13 @@ public class BoxTree, E> extends TileIndex, T> { /* push next level child onto stack */ if (overlaps(n.child00, box)) stack.push(n.child00); + else if (overlaps(n.child01, box)) stack.push(n.child01); + else if (overlaps(n.child10, box)) stack.push(n.child10); + else if (overlaps(n.child11, box)) stack.push(n.child11); } @@ -285,7 +330,7 @@ public class BoxTree, E> extends TileIndex, T> { boolean call(E item); } - public boolean collect(SearchNodeCb> cb) { + public void collect(SearchNodeCb> cb) { BoxNode n; Stack> stack = stackPool.get(); @@ -332,7 +377,6 @@ public class BoxTree, E> extends TileIndex, T> { stack.push(n.child11); } stackPool.release(stack); - return false; } public BoxNode create(BoxNode parent, int i) { @@ -340,6 +384,7 @@ public class BoxTree, E> extends TileIndex, T> { if (pool != null) { node = pool; pool = pool.parent; + node.refs = 0; } else node = new BoxNode(); @@ -457,24 +502,20 @@ public class BoxTree, E> extends TileIndex, T> { if (level < maxDepth) { if (x2 < cx) { if (y2 < cy) { - if ((child = cur.child00) == null) - return false; + child = cur.child00; } else if (y1 >= cy) { - if ((child = cur.child01) == null) - return false; + child = cur.child01; } } else if (x1 >= cx) { if (y2 < cy) { - if ((child = cur.child10) == null) - return false; + child = cur.child10; } else if (y1 >= cy) { - if ((child = cur.child11) == null) - return false; + child = cur.child11; } } } if (child == null) { - /* push item onto list of this node */ + BoxItem prev = cur.item; for (BoxItem it = cur.item; it != null; it = it.next) { @@ -492,7 +533,9 @@ public class BoxTree, E> extends TileIndex, T> { } else prev.next = it.next; + it.next = null; remove(cur); + return true; } prev = it; @@ -565,6 +608,70 @@ public class BoxTree, E> extends TileIndex, T> { root.refs = 0; } + public void clearToPool() { + BoxNode node = root; + + while (true) { + /* traverse down */ + if (node.child00 != null) { + node = node.child00; + continue; + } + if (node.child01 != null) { + node = node.child01; + continue; + } + if (node.child10 != null) { + node = node.child10; + continue; + } + if (node.child11 != null) { + node = node.child11; + continue; + } + + if (node == root) + break; + + /* traverse up */ + BoxNode parent = node.parent; + + /* unlink from parent */ + switch (node.id) { + case 0: + parent.child00 = null; + break; + case 1: + parent.child01 = null; + break; + case 2: + parent.child10 = null; + break; + case 3: + parent.child11 = null; + break; + } + + /* release items */ + node.item = null; + node.refs = 0; + + /* add n back to pool */ + node.parent = pool; + pool = node; + + /* continue with parent node */ + node = parent; + } + + root.child00 = null; + root.child01 = null; + root.child10 = null; + root.child11 = null; + root.item = null; + root.refs = 0; + } + public int size() { return root.refs; }