package org.squidy.nodes.optitrack.gestures; import java.util.ArrayList; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; public class OctreeNode { public static float NO_MIN_SIZE = -1; public static float DEFAULT_MIN_SIZE = 5; protected ArrayList<OctreeLeaf> items; protected OctreeNode[] branch; protected int maxItems; protected float minSize; public OctreeBox bounds; /// <summary> Added to avoid problems when a node is completely filled with a /// single point value. /// </summary> protected boolean allTheSamePoint; protected float firstX; protected float firstY; protected float firstZ; /// <summary> Constructor to use if you are going to store the Objects in /// x/y space, and there is really no smallest node size.</summary> /// <param name="Top">northern border of node coverage.</param> /// <param name="Left">western border of node coverage.</param> /// <param name="Bottom">southern border of node coverage.</param> /// <param name="Right">eastern border of node coverage.</param> /// <param name="maximumItems">number of items to hold in a node before /// splitting itself into four branch and redispensing the /// items into them.</param> public OctreeNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maximumItems) { this(xMax, xMin, yMax, yMin, zMax, zMin, maximumItems, NO_MIN_SIZE); } /// <summary> Constructor to use if you are going to store the Objects in x/y /// space, and there is a smallest node size because you don't want /// the nodes to be smaller than a group of pixels.</summary> /// <param name="Top">northern border of node coverage.</param> /// <param name="Left">western border of node coverage.</param> /// <param name="Bottom">southern border of node coverage.</param> /// <param name="Right">eastern border of node coverage.</param> /// <param name="maximumItems">number of items to hold in a node before /// splitting itself into four branch and redispensing the items into them.</param> /// <param name="minimumSize">the minimum difference between the boundaries of the node.</param> public OctreeNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maximumItems, float minimumSize) { bounds = new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin); maxItems = maximumItems; minSize = minimumSize; items = new ArrayList(10); } /// <summary>Return true if the node has branch. </summary> public boolean hasChildren() { if (branch != null) return true; else return false; } /// <summary> This method splits the node into four branch, and disperses /// the items into the branch. The split only happens if the /// boundary size of the node is larger than the minimum size (if /// we care). The items in this node are cleared after they are put /// into the branch. /// </summary> protected void split() { // Make sure we're bigger than the minimum, if we care, if (minSize != NO_MIN_SIZE) if (Math.abs(bounds.Top - bounds.Bottom) < minSize && Math.abs(bounds.Right - bounds.Left) < minSize && Math.abs(bounds.Front - bounds.Back) < minSize) return; float nsHalf = (float)(bounds.Top - (bounds.Top - bounds.Bottom) * 0.5); float ewHalf = (float)(bounds.Right - (bounds.Right - bounds.Left) * 0.5); float fbHalf = (float)(bounds.Front - (bounds.Front - bounds.Back) * 0.5); branch = new OctreeNode[8]; branch[0] = new OctreeNode(ewHalf, bounds.Left, bounds.Front, fbHalf, bounds.Top, nsHalf, maxItems); //left-front-top branch[1] = new OctreeNode(bounds.Right, ewHalf, bounds.Front, fbHalf, bounds.Top, nsHalf, maxItems); branch[2] = new OctreeNode(ewHalf, bounds.Left, bounds.Front, fbHalf, nsHalf, bounds.Bottom, maxItems); branch[3] = new OctreeNode(bounds.Right, ewHalf, bounds.Front, fbHalf, nsHalf, bounds.Bottom, maxItems); branch[4] = new OctreeNode(ewHalf, bounds.Left, fbHalf, bounds.Back, bounds.Top, nsHalf, maxItems); //left-back-top branch[5] = new OctreeNode(bounds.Right, ewHalf, fbHalf, bounds.Back, bounds.Top, nsHalf, maxItems); branch[6] = new OctreeNode(ewHalf, bounds.Left, fbHalf, bounds.Back, nsHalf, bounds.Bottom, maxItems); branch[7] = new OctreeNode(bounds.Right, ewHalf, fbHalf, bounds.Back, nsHalf, bounds.Bottom, maxItems); ArrayList<OctreeLeaf> temp = (ArrayList)items.clone(); items.clear(); /*IEnumerator things = temp.GetEnumerator(); while (things.MoveNext()) { AddNode((OctreeLeaf)things.Current); }*/ for (OctreeLeaf leaf : temp) { AddNode(leaf); } } /// <summary> Get the node that covers a certain x/y pair.</summary> /// <param name="x">up-down location in Octree Grid (x, y)</param> /// <param name="y">left-right location in Octree Grid (y, x)</param> /// <returns> node if child covers the point, null if the point is /// out of range.</returns> protected OctreeNode getChild(float x, float y, float z) { if (bounds.pointWithinBounds(x, y, z)) { if (branch != null) { for (int i = 0; i < branch.length; i++) if (branch[i].bounds.pointWithinBounds(x, y, z)) return branch[i].getChild(x, y, z); } else return this; } return null; } /// <summary> Add a Object into the tree at a location.</summary> /// <param name="x">up-down location in Octree Grid (x, y)</param> /// <param name="y">left-right location in Octree Grid (y, x)</param> /// <param name="obj">Object to add to the tree.</param> /// <returns> true if the pution worked.</returns> public boolean AddNode(float x, float y, float z, Object obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(float x, float y, float z, int obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } /*public boolean AddNode(float x, float y, float z, uint obj) { return AddNode(new OctreeLeaf(x, y, z, obj)); }*/ public boolean AddNode(float x, float y, float z, short obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(float x, float y, float z, long obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(float x, float y, float z, float obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(float x, float y, float z, double obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(float x, float y, float z, boolean obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(Vector3f vector, Object obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3f vector, int obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } /*public boolean AddNode(Vector3f vector, uint obj) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); }*/ public boolean AddNode(Vector3f vector, short obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3f vector, long obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3f vector, float obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3f vector, double obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3f vector, boolean obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(double x, double y, double z, Object obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(double x, double y, double z, StaticGesture staticGesture, int index, String gestureName, String handSide) { return AddNode(new OctreeLeaf((float)x, (float)y, (float)z, staticGesture, index, gestureName, handSide)); } /*public boolean AddNode(double x, double y, double z, uint obj) { return AddNode(new OctreeLeaf(x, y, z, obj)); }*/ public boolean AddNode(double x, double y, double z, short obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(double x, double y, double z, long obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(double x, double y, double z, float obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(double x, double y, double z, double obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(double x, double y, double z, boolean obj, String name) { return AddNode(new OctreeLeaf(x, y, z, obj, name)); } public boolean AddNode(Vector3d vector, Object obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3d vector, int obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } /*public boolean AddNode(Vector3d vector, uint obj) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); }*/ public boolean AddNode(Vector3d vector, short obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3d vector, long obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3d vector, float obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3d vector, double obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } public boolean AddNode(Vector3d vector, boolean obj, String name) { return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj, name)); } /// <summary> Add a OctreeLeaf into the tree at a location.</summary> /// <param name="leaf">Object-location composite</param> /// <returns> true if the pution worked.</returns> public boolean AddNode(OctreeLeaf leaf) { if (branch == null) { this.items.add(leaf); if (this.items.size() == 1) { this.allTheSamePoint = true; this.firstX = leaf.X; this.firstY = leaf.Y; this.firstZ = leaf.Z; } else { if (this.firstX != leaf.X || this.firstY != leaf.Y || this.firstZ != leaf.Z) { this.allTheSamePoint = false; } } if (this.items.size() > maxItems && !this.allTheSamePoint) split(); return true; } else { OctreeNode node = getChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return node.AddNode(leaf); } } return false; } /// <summary> Remove a Object out of the tree at a location. /// /// </summary> /// <param name="x">up-down location in Octree Grid (x, y) /// <param name="y">left-right location in Octree Grid (y, x) /// <returns> the Object removed, null if the Object not found. /// </returns> public Object RemoveNode(float x, float y, float z, Object obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(float x, float y, float z, int obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } /*public Object RemoveNode(float x, float y, float z, uint obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj)); }*/ public Object RemoveNode(float x, float y, float z, short obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(float x, float y, float z, long obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(float x, float y, float z, float obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(float x, float y, float z, double obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(float x, float y, float z, boolean obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(Vector3f vector, Object obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3f vector, int obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } /*public Object RemoveNode(Vector3f vector, uint obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); }*/ public Object RemoveNode(Vector3f vector, short obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3f vector, long obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3f vector, float obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3f vector, double obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3f vector, boolean obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(double x, double y, double z, Object obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(double x, double y, double z, int obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } /*public Object RemoveNode(double x, double y, double z, uint obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj)); }*/ public Object RemoveNode(double x, double y, double z, short obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(double x, double y, double z, long obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(double x, double y, double z, float obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(double x, double y, double z, double obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(double x, double y, double z, boolean obj) { return RemoveNode(new OctreeLeaf(x, y, z, obj,"")); } public Object RemoveNode(Vector3d vector, Object obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3d vector, int obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } /*public Object RemoveNode(Vector3d vector, uint obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); }*/ public Object RemoveNode(Vector3d vector, short obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3d vector, long obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3d vector, float obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3d vector, double obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } public Object RemoveNode(Vector3d vector, boolean obj) { return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj,"")); } /// <summary> Remove a OctreeLeaf out of the tree at a location. /// /// </summary> /// <param name="leaf">Object-location composite /// <returns> the Object removed, null if the Object not found. /// </returns> public Object RemoveNode(OctreeLeaf leaf) { if (branch == null) { // This must be the node that has it... for (int i = 0; i < items.size(); i++) { OctreeLeaf qtl = items.get(i); if (leaf.LeafObject == qtl.LeafObject) { items.remove(i); return qtl.LeafObject; } } } else { OctreeNode node = getChild(leaf.X, leaf.Y, leaf.Z); if (node != null) { return node.RemoveNode(leaf); } } return null; } /// <summary> Get an Object closest to a x/y.</summary> /// <param name="x">up-down location in Octree Grid (x, y)</param> /// <param name="y">left-right location in Octree Grid (y, x)</param> /// <returns> the Object that matches the best distance, null if no Objects were found. </returns> public Object GetNode(float x, float y, float z) { return GetNode(x, y, z, Double.MAX_VALUE); } public Object GetNode(Vector3f vector) { return GetNode(vector.x, vector.y, vector.z, Double.MAX_VALUE); } public Object GetNode(double x, double y, double z) { return GetNode(x, y, z, Double.MAX_VALUE); } public Object GetNode(Vector3d vector) { return GetNode(vector.x, vector.y, vector.z, Double.MAX_VALUE); } /// <summary> Get an Object closest to a x/y/z. If there are branches at /// this node, then the branches are searched. The branches are /// checked first, to see if they are closer than the best distance /// already found. If a closer Object is found, bestDistance will /// be updated with a new Double Object that has the new distance.</summary> /// <param name="x">left-right location in Octree Grid</param> /// <param name="y">up-down location in Octree Grid</param> /// <param name="z">front-nack location in Octree Grid</param> /// <param name="bestDistance">the closest distance of the Object found so far.</param> /// <returns> the Object that matches the best distance, null if no closer Objects were found.</returns> public Object GetNode(float x, float y, float z, double ShortestDistance) { double distance; Object closest = null; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); StaticGesture sg = (StaticGesture)leaf.LeafObject; sg.setDistance(leaf.LeafIndex, distance); // System.out.println(sg); if (distance < ShortestDistance) { ShortestDistance = distance; closest = leaf.LeafObject; } } return closest; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance < ShortestDistance) { Object test = branch[i].GetNode(x, y, z, ShortestDistance); if (test != null) closest = test; } } } return closest; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="ShortestDistance"></param> /// <returns></returns> public Object GetNode(Vector3f vector, double ShortestDistance) { return GetNode(vector.x, vector.y, vector.z, ShortestDistance); } /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="ShortestDistance"></param> /// <returns></returns> public Object GetNode(double x, double y, double z, double ShortestDistance) { Object closest = null; double distance; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); StaticGesture sg = (StaticGesture)leaf.LeafObject; sg.setDistance(leaf.LeafIndex, distance); if (distance < ShortestDistance) { ShortestDistance = distance; leaf.LeafDistance = distance; closest = leaf; } } return closest; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance < ShortestDistance) { Object test = branch[i].GetNode(x, y, z, ShortestDistance); if (test != null) closest = test; } } } return closest; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="ShortestDistance"></param> /// <returns></returns> public Object GetNode(Vector3d vector, double ShortestDistance) { return GetNode(vector.x, vector.y, vector.z, ShortestDistance); } /// <summary> Get all the Objects within a bounding box.</summary> /// <param name="Top">top location in Octree Grid (x, y)</param> /// <param name="Left">left location in Octree Grid (y, x)</param> /// <param name="Bottom">lower location in Octree Grid (x, y)</param> /// <param name="Right">right location in Octree Grid (y, x)</param> /// <returns> Vector of Objects. </returns> /*public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), ArrayList.Synchronized(new ArrayList(10))); }*/ public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), new ArrayList(10)); } /// <summary> /// /// </summary> /// <param name="xMax"></param> /// <param name="xMin"></param> /// <param name="yMax"></param> /// <param name="yMin"></param> /// <param name="zMax"></param> /// <param name="zMin"></param> /// <returns></returns> /*public ArrayList GetNode(double xMax, double xMin, double yMax, double yMin, double zMax, double zMin) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), ArrayList.Synchronized(new ArrayList(10))); }*/ public ArrayList GetNode(double xMax, double xMin, double yMax, double yMin, double zMax, double zMin) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), new ArrayList(10)); } /// <summary> Get all the Objects within a bounding box.</summary> /// <param name="Top">top location in Octree Grid (x, y)</param> /// <param name="Left">left location in Octree Grid (y, x)</param> /// <param name="Bottom">lower location in Octree Grid (x, y)</param> /// <param name="Right">right location in Octree Grid (y, x)</param> /// <param name="vector">current vector of Objects.</param> /// <returns> Vector of Objects. </returns> public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, ArrayList nodes) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), nodes); } /// <summary> /// /// </summary> /// <param name="xMax"></param> /// <param name="xMin"></param> /// <param name="yMax"></param> /// <param name="yMin"></param> /// <param name="zMax"></param> /// <param name="zMin"></param> /// <param name="nodes"></param> /// <returns></returns> public ArrayList GetNode(double xMax, double xMin, double yMax, double yMin, double zMax, double zMin, ArrayList nodes) { return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), nodes); } /// <summary> Get all the Objects within a bounding box.</summary> /// <param name="rect">boundary of area to fill.</param> /// <param name="vector">current vector of Objects.</param> /// <returns> updated Vector of Objects.</returns> public ArrayList GetNode(OctreeBox rect, ArrayList nodes) { if (branch == null) { /*IEnumerator things = this.items.GetEnumerator(); while (things.MoveNext()) { OctreeLeaf qtl = (OctreeLeaf)things.Current; if (rect.pointWithinBounds(qtl.X, qtl.Y, qtl.Z)) nodes.Add(qtl.LeafObject); }*/ for (OctreeLeaf qtl : this.items) { if (rect.pointWithinBounds(qtl.X, qtl.Y, qtl.Z)) nodes.add(qtl.LeafObject); } } else { for (int i = 0; i < branch.length; i++) { if (branch[i].bounds.within(rect)) branch[i].GetNode(rect, nodes); } } return nodes; } /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="radius"></param> /// <returns></returns> public ArrayList GetNodes(float x, float y, float z, double radius) { ArrayList Nodes = new ArrayList(); double distance; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); if (distance < radius) Nodes.add(leaf.LeafObject); } return Nodes; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance < radius) { Object test = branch[i].GetNode(x, y, z, radius); if (test != null) Nodes.add(test); } } } return Nodes; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="radius"></param> /// <returns></returns> public ArrayList GetNodes(Vector3f vector, double radius) { return GetNodes(vector.x, vector.y, vector.z, radius); } /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="radius"></param> /// <returns></returns> public ArrayList GetNodes(double x, double y, double z, double radius) { ArrayList Nodes = new ArrayList(); double distance; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); if (distance < radius) Nodes.add(leaf.LeafObject); } return Nodes; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance < radius) { Object test = branch[i].GetNode(x, y, z, radius); if (test != null) Nodes.add(test); } } } return Nodes; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="radius"></param> /// <returns></returns> public ArrayList GetNodes(Vector3d vector, double radius) { return GetNodes(vector.x, vector.y, vector.z, radius); } /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="MinRadius"></param> /// <param name="MaxRadius"></param> /// <returns></returns> public ArrayList GetNodes(float x, float y, float z, double MinRadius, double MaxRadius) { ArrayList Nodes = new ArrayList(); double distance, minDistance = 1e32; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); if (distance >= MinRadius && distance < MaxRadius) { //if (distance <= minDistance) //closest Object first //{ // Nodes.Insert(0, leaf.LeafObject); // minDistance = Math.Min(minDistance, distance); // } // else Nodes.add(leaf.LeafObject); } } return Nodes; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance > MinRadius && childDistance <= MaxRadius) { Object test = branch[i].GetNode(x, y, z, MinRadius); if (test != null) Nodes.add(test); } } } return Nodes; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="MinRadius"></param> /// <param name="MaxRadius"></param> /// <returns></returns> public ArrayList GetNodes(Vector3f vector, double MinRadius, double MaxRadius) { return GetNodes(vector.x, vector.y, vector.z, MinRadius, MaxRadius); } /// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="MinRadius"></param> /// <param name="MaxRadius"></param> /// <returns></returns> public ArrayList GetNodes(double x, double y, double z, double MinRadius, double MaxRadius) { ArrayList Nodes = new ArrayList(); double distance, minDistance = 1e32; if (branch == null) { for (OctreeLeaf leaf : this.items) { distance = Math.sqrt( Math.pow(x - leaf.X, 2.0) + Math.pow(y - leaf.Y, 2.0) + Math.pow(z - leaf.Z, 2.0)); if (distance >= MinRadius && distance < MaxRadius) { // if (distance <= minDistance) //closest Object first // { // Nodes.Insert(0, leaf.LeafObject); // minDistance = Math.Min(minDistance, distance); // } // else Nodes.add(leaf.LeafObject); } } return Nodes; } else { // Check the distance of the bounds of the branch, // versus the bestDistance. If there is a boundary that // is closer, then it is possible that another node has an // Object that is closer. for (int i = 0; i < branch.length; i++) { double childDistance = branch[i].bounds.borderDistance(x, y, z); if (childDistance >= MinRadius && childDistance < MaxRadius) { Object test = branch[i].GetNode(x, y, z, MaxRadius); if (test != null) { Nodes.add(test); } } } } return Nodes; } /// <summary> /// /// </summary> /// <param name="vector"></param> /// <param name="MinRadius"></param> /// <param name="MaxRadius"></param> /// <returns></returns> public ArrayList GetNodes(Vector3d vector, double MinRadius, double MaxRadius) { return GetNodes(vector.x, vector.y, vector.z, MinRadius, MaxRadius); } /// <summary>Clear the tree below this node. </summary> public void Clear() { this.items.clear(); if (branch != null) { for (int i = 0; i < branch.length; i++) { branch[i].Clear(); } branch = null; } } }