From d97f603fba0ff686028da02a9727631d7f3297d4 Mon Sep 17 00:00:00 2001 From: SeH <1s1e1h1@gmail.com> Date: Sun, 14 Jun 2015 01:02:50 -0400 Subject: [PATCH] octree testing --- .../spangraph/spacetime/AbstractOctree.java | 104 ++++++++++++------ src/main/java/toxi/geom/AABB.java | 11 +- .../syncleus/spangraph/geom/OctreeTest.java | 59 ++++++++-- 3 files changed, 120 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java b/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java index 7650bc3..b1f725a 100644 --- a/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java +++ b/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java @@ -14,7 +14,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * alternative tree recursion limit, number of world units when cells are * not subdivided any further */ - protected float minNodeSize = 4; + protected float minNodeSize = 0.1f; /** * @@ -69,8 +69,9 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * @param size * size of the tree volume along a single axis */ - public AbstractOctree(Vec3D o, float size) { + public AbstractOctree(Vec3D o, float size, float minResolution) { this(null, o, size / 2); + this.minNodeSize = minResolution; } /** @@ -81,10 +82,10 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * point collection * @return true, if all points have been added successfully. */ - public boolean addAll(Collection<XYZ> points) { + public boolean put(Collection<XYZ> points) { boolean addedAll = true; for (XYZ p : points) { - addedAll &= addPoint(p); + addedAll &= put(p); } return addedAll; } @@ -97,10 +98,10 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * @param p * @return true, if point has been added successfully */ - public boolean addPoint(final XYZ p) { + public boolean put(final XYZ p) { final float halfSize = this.halfSize; - AbstractOctree[] children = this.children; + // check if point is inside cube if (containsPoint(p)) { @@ -125,7 +126,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D { halfSize * 0.5f); numChildren++; } - return children[octant].addPoint(p); + return children[octant].put(p); } } return false; @@ -140,12 +141,12 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * Applies the given {@link OctreeVisitor} implementation to this node and * all of its children. */ - public void forEach(Consumer<AbstractOctree> visitor) { + public void forEachRecursive(Consumer<AbstractOctree> visitor) { visitor.accept(this); if (numChildren > 0) { for (AbstractOctree c : children) { if (c != null) { - c.forEach(visitor); + c.forEachRecursive(visitor); } } } @@ -262,22 +263,35 @@ public class AbstractOctree<L> extends AABB implements Shape3D { return parent; } - public List<XYZ> getPoints() { - return getPoints(new ArrayList()); + public Collection<XYZ> getPoints() { + return points; + } + + public int countPointsRecursively() { + final int[] x = {0}; + forEachRecursive(n -> x[0] += n.countPoints()); + return x[0]; + } + + public int countPoints() { + if (points == null) return 0; + return points.size(); + } + + public List<XYZ> getPointsRecursively() { + return getPointsRecursively(new ArrayList()); } /** * @return the points */ - public List<XYZ> getPoints(List<XYZ> results) { + public List<XYZ> getPointsRecursively(List<XYZ> results) { if (points != null) { + results.addAll(points); } else if (numChildren > 0) { for (int i = 0; i < 8; i++) { if (children[i] != null) { - List<XYZ> childPoints = children[i].getPoints(); - if (childPoints != null) { - results.addAll(childPoints); - } + children[i].getPointsRecursively(results); } } } @@ -291,7 +305,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D { * AABB * @return all points with the box volume */ - public List<XYZ> getPointsWithinBox(AABB b) { + @Deprecated public List<XYZ> getPointsWithinBox(AABB b) { ArrayList<XYZ> results = null; if (this.intersectsBox(b)) { if (points != null) { @@ -320,6 +334,42 @@ public class AbstractOctree<L> extends AABB implements Shape3D { return results; } + public void forEachInBox(AABB b, Consumer<XYZ> c) { + if (this.intersectsBox(b)) { + if (points != null) { + for (XYZ q : points) { + if (q.isInAABB(b)) { + c.accept(q); + } + } + } else if (numChildren > 0) { + for (int i = 0; i < 8; i++) { + if (children[i] != null) { + children[i].forEachInBox(b, c); + } + } + } + } + } + public void forEachInSphere(Sphere s, Consumer<XYZ> c) { + + if (this.intersectsSphere(s)) { + if (points != null) { + for (XYZ q : points) { + if (s.containsPoint(q)) { + c.accept(q); + } + } + } else if (numChildren > 0) { + for (int i = 0; i < 8; i++) { + AbstractOctree cc = children[i]; + if (cc != null) { + cc.forEachInSphere(s, c); + } + } + } + } + } /** * Selects all stored points within the given sphere volume * @@ -356,25 +406,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D { return results; } - public void forEachInSphere(Sphere s, Consumer<XYZ> c) { - if (this.intersectsSphere(s)) { - if (points != null) { - for (XYZ q : points) { - if (s.containsPoint(q)) { - c.accept(q); - } - } - } else if (numChildren > 0) { - for (int i = 0; i < 8; i++) { - AbstractOctree cc = children[i]; - if (cc != null) { - cc.forEachInSphere(s, c); - } - } - } - } - } /** * Selects all stored points within the given sphere volume @@ -390,7 +422,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D { /** * @return the size */ - public float getSize() { + public float getScale() { return size; } diff --git a/src/main/java/toxi/geom/AABB.java b/src/main/java/toxi/geom/AABB.java index d0a0017..d8b33c3 100644 --- a/src/main/java/toxi/geom/AABB.java +++ b/src/main/java/toxi/geom/AABB.java @@ -133,7 +133,7 @@ public class AABB extends Vec3D implements Shape3D { * box dimensions (the box will be double the size in each * direction) */ - public AABB(roVec3D pos, roVec3D extent) { + public AABB(XYZ pos, roVec3D extent) { super(pos); setExtent(extent); } @@ -208,11 +208,10 @@ public class AABB extends Vec3D implements Shape3D { * box to check * @return true, if boxes overlap */ - public boolean intersectsBox(AABB box) { - Vec3D t = box.sub(this); - return MathUtils.abs(t.x) <= (extent.x + box.extent.x) - && MathUtils.abs(t.y) <= (extent.y + box.extent.y) - && MathUtils.abs(t.z) <= (extent.z + box.extent.z); + public boolean intersectsBox(final AABB box) { + return MathUtils.abs(box.x - x) <= (extent.x + box.extent.x) + && MathUtils.abs(box.y - y) <= (extent.y + box.extent.y) + && MathUtils.abs(box.z - z) <= (extent.z + box.extent.z); } /** diff --git a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java index b86305c..5c18d3c 100644 --- a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java +++ b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java @@ -1,6 +1,13 @@ package com.syncleus.spangraph.geom; +import com.syncleus.spangraph.spacetime.AbstractOctree; import org.junit.Test; +import toxi.geom.AABB; +import toxi.geom.Vec3D; + +import java.util.List; + +import static org.junit.Assert.assertEquals; /** * Created by me on 6/13/15. @@ -8,18 +15,46 @@ import org.junit.Test; public class OctreeTest { @Test public void test1() { - Octree o = new Octree(2, new Point(0,0,0)); - o.add(1, 1, 0); - o.add(0, 1, 0); - o.add(0, 0, 1); - o.add(0, 0, 1.25); - o.add(0, 0, 1.5); - o.add(0, 0, -1); - o.add(0, 0, -1.25); - o.add(0, 0, -1.50); - o.add(0, 0, -1.55); - o.add(0, 0, -1.575); - o.print_tree(); + AbstractOctree o = new AbstractOctree( + new Vec3D(-2f, -2f, -2f), 4f, 0.05f); + + o.put(new Vec3D(1, 1, 0)); + o.put(new Vec3D(0, 1, 0)); + o.put(new Vec3D(0, 0, 1)); + o.put(new Vec3D(0, 0, 1.25f)); + o.put(new Vec3D(0, 0, 1.5f)); + o.put(new Vec3D(0, 0, -1)); + o.put(new Vec3D(0, 0, -1.25f)); + o.put(new Vec3D(0, 0, -1.50f)); + o.put(new Vec3D(0, 0, -1.55f)); + o.put(new Vec3D(0, 0, -1.575f)); + + o.forEachRecursive(x -> { + + List p = (((AbstractOctree) x).getPointsRecursively()); + //if (!p.isEmpty()) + //System.out.println(x + " " + p); + }); + + //System.out.println("size: " + o.getNumChildren()); + + assertEquals(o.countPointsRecursively(), 10); + + int[] sphereCount = new int[1]; + o.forEachInSphere(new Vec3D(0, 0, -0.75f), 0.5f, x -> { + sphereCount[0]++; + }); + assertEquals(2, sphereCount[0]); + + int[] boxCount = new int[1]; + + AABB aabb = new AABB(new Vec3D(0f, -0.5f, -2.0f), new Vec3D(0.5f, 0.5f, 0.5f)); + o.forEachInBox(aabb, x -> { + boxCount[0]++; + }); + assertEquals(3, boxCount[0]); + + //o.print_tree(); } } -- GitLab