aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/BHTree.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/media/j3d/BHTree.java')
-rw-r--r--src/javax/media/j3d/BHTree.java1154
1 files changed, 0 insertions, 1154 deletions
diff --git a/src/javax/media/j3d/BHTree.java b/src/javax/media/j3d/BHTree.java
deleted file mode 100644
index 260448c..0000000
--- a/src/javax/media/j3d/BHTree.java
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
- * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- */
-
-package javax.media.j3d;
-
-import java.util.ArrayList;
-import java.util.Vector;
-
-import javax.vecmath.Point4d;
-
-class BHTree {
-
- Locale locale;
-
- private BHNode root;
- private BHInsertStructure insertStructure = null;
-
- // Temporary point, so we dont generate garbage
- Point4d tPoint4d = new Point4d();
-
- // A flag to signal that number of renderAtoms sent to RenderBin is stable.
- private boolean stable = false;
-
- // An estimate of the maxmium depth of this tree (upper bound).
- int estMaxDepth;
-
- static final double LOG_OF_2 = Math.log(2);
-
- // Assume that the size avg. leaf node is 256 bytes. For a 64bit system, we'll
- // down with max depth of 56 for an ideal balance tree.
- static final int DEPTH_UPPER_BOUND = 56;
- static final int INCR_DEPTH_BOUND = 5;
- int depthUpperBound = DEPTH_UPPER_BOUND;
-
- BHTree() {
- locale = null;
- root = null;
- }
-
- BHTree(Locale loc) {
- locale = loc;
- root = null;
- }
-
- BHTree(BHNode bhArr[]) {
- locale = null;
- root = null;
- create(bhArr);
- }
-
- void setLocale(Locale loc) {
- locale = loc;
- }
-
- Locale getLocale() {
- return locale;
- }
-
- void cluster(BHInternalNode root, BHNode[] bhArr) {
-
- if(J3dDebug.devPhase) {
- if(J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "BHTree.java :In cluster length is " + bhArr.length
- + "\n")) {
-
- for(int i=0; i<bhArr.length; i++) {
- System.err.println(bhArr[i]);
- }
- }
- }
-
- if((bhArr == null) || (bhArr.length < 2) || (root == null)){
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_1,
- "BHTree.java : cluster : trouble! \n");
- return;
- }
-
- int centerValuesIndex[] = new int[bhArr.length];
- float centerValues[][] = computeCenterValues(bhArr, centerValuesIndex);
-
- constructTree(root, bhArr, centerValues, centerValuesIndex);
-
- }
-
- // bhArr can only contains BHLeafNode.
-
- void boundsChanged(BHNode bhArr[], int size) {
- // Mark phase.
- markParentChain(bhArr, size);
-
- // Compute phase.
- root.updateMarkedBoundingHull();
- }
-
-
- // Return true if bhTree's root in encompass by frustumBBox and nothing changed.
- boolean getVisibleBHTrees(RenderBin rBin, ArrayList bhTrees,
- BoundingBox frustumBBox, long referenceTime,
- boolean stateChanged, int visibilityPolicy,
- boolean singleLocale) {
-
- int i, j, size;
-
- if ((frustumBBox != null) && (root != null)) {
-
- boolean inSide = aEncompassB(frustumBBox, root.bHull);
- /*
- System.err.println("stateChanged is " + stateChanged);
- System.err.println("frustumBBox is " + frustumBBox);
- System.err.println("root.bHull is " + root.bHull);
- System.err.println("inSide is " + inSide);
- */
-
- if(singleLocale && !stateChanged && inSide && stable) {
- // just return the whole tree, no change in render mol..
- // System.err.println("Optimize case 1 ..." + this);
- bhTrees.add(root);
- return true;
- }
- else if(!stateChanged && inSide) {
- // the whole tree is in, but we've to be sure that RenderBin is
- // stable ...
- // System.err.println("Optimize case 2 ..." + this);
- select(rBin, bhTrees, frustumBBox, root, referenceTime,
- visibilityPolicy, true);
-
- bhTrees.add(root);
- stable = true;
- } else {
- // System.err.println("Not in Optimize case ..." + this);
- select(rBin, bhTrees, frustumBBox, root, referenceTime,
- visibilityPolicy, false);
-
- stable = false;
- }
-
- }
-
- return false;
- }
-
- private void select(RenderBin rBin, ArrayList bhTrees, BoundingBox frustumBBox,
- BHNode bh, long referenceTime, int visibilityPolicy,
- boolean inSide) {
-
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return;
- }
-
- switch(bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- if((((BHLeafNode) bh).leafIF instanceof GeometryAtom) &&
- (((BHLeafNode) bh).isEnable(visibilityPolicy)) &&
- ((inSide) || (frustumBBox.intersect(bh.bHull)))) {
-
- // do render atom setup.
- rBin.processGeometryAtom((GeometryAtom)
- (((BHLeafNode)bh).leafIF),
- referenceTime);
- if(!inSide) {
- bhTrees.add(bh);
- }
- }
- break;
- case BHNode.BH_TYPE_INTERNAL:
- if(inSide) {
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getRightChild(),
- referenceTime, visibilityPolicy, true);
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getLeftChild(),
- referenceTime, visibilityPolicy, true);
- }
- else if(aEncompassB(frustumBBox, bh.bHull)) {
- bhTrees.add(bh);
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getRightChild(),
- referenceTime, visibilityPolicy, true);
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getLeftChild(),
- referenceTime, visibilityPolicy, true);
- }
- else if(frustumBBox.intersect(bh.bHull)) {
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getRightChild(),
- referenceTime, visibilityPolicy, false);
- select(rBin, bhTrees, frustumBBox,
- ((BHInternalNode)bh).getLeftChild(),
- referenceTime, visibilityPolicy, false);
- }
- break;
- }
- }
-
- // returns true iff the bBox is completely inside aBox
- // i.e. bBoxl values are strictly less than or equal to all aBox values.
- static boolean aEncompassB(BoundingBox aBox, BoundingBox bBox) {
- return ((aBox.upper.x >= bBox.upper.x) &&
- (aBox.upper.y >= bBox.upper.y) &&
- (aBox.upper.z >= bBox.upper.z) &&
- (aBox.lower.x <= bBox.lower.x) &&
- (aBox.lower.y <= bBox.lower.y) &&
- (aBox.lower.z <= bBox.lower.z));
- }
-
-
- BHLeafInterface selectAny(GeometryAtom atom, int accurancyMode) {
- if (atom.source.geometryList == null)
- return null;
- BHNode bhNode = doSelectAny(atom, root, accurancyMode);
- if (bhNode == null) {
- return null;
- }
-
- return ((BHLeafNode) bhNode).leafIF;
- }
-
-
- BHLeafInterface selectAny(GeometryAtom atoms[], int size, int accurancyMode) {
- BHNode bhNode = doSelectAny(atoms, size, root, accurancyMode);
- if (bhNode == null) {
- return null;
- }
-
- return ((BHLeafNode) bhNode).leafIF;
- }
-
-
- private BHNode doSelectAny(GeometryAtom atoms[],int atomSize,
- BHNode bh, int accurancyMode) {
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return null;
- }
- switch (bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- BHLeafInterface leaf = ((BHLeafNode) bh).leafIF;
- GeometryAtom atom;
- int i;
-
- if (leaf instanceof GeometryAtom) {
- GeometryAtom leafAtom = (GeometryAtom) leaf;
-
- if (((BHLeafNode) bh).isEnable() &&
- leafAtom.source.isCollidable) {
-
- // atom self intersection between atoms[]
- for (i=atomSize-1; i >=0; i--) {
- if (atoms[i] == leafAtom) {
- return null;
- }
- }
- for (i=atomSize-1; i >=0; i--) {
- atom = atoms[i];
- if ((atom.source.sourceNode != leafAtom.source.sourceNode) &&
- (atom.source.collisionVwcBound.intersect(leafAtom.source.collisionVwcBound)) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- ((leafAtom.source.geometryList != null) &&
- (atom.source.intersectGeometryList(leafAtom.source))))) {
- return bh;
- }
- }
- }
- } else if (leaf instanceof GroupRetained) {
- if (((BHLeafNode) bh).isEnable() &&
- ((GroupRetained) leaf).sourceNode.collidable) {
- for (i=atomSize-1; i >=0; i--) {
- atom = atoms[i];
- if (atom.source.collisionVwcBound.intersect(bh.bHull) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- (atom.source.intersectGeometryList(
- atom.source.getCurrentLocalToVworld(0), bh.bHull)))) {
- return bh;
- }
- }
- }
- }
- return null;
- case BHNode.BH_TYPE_INTERNAL:
- for (i=atomSize-1; i >=0; i--) {
- atom = atoms[i];
- if (atom.source.collisionVwcBound.intersect(bh.bHull))
- {
- BHNode hitNode = doSelectAny(atoms,
- atomSize,
- ((BHInternalNode) bh).getRightChild(),
- accurancyMode);
- if (hitNode != null)
- return hitNode;
-
- return doSelectAny(atoms, atomSize,
- ((BHInternalNode) bh).getLeftChild(),
- accurancyMode);
- }
- }
- return null;
- }
- return null;
- }
-
-
- private BHNode doSelectAny(GeometryAtom atom, BHNode bh, int accurancyMode) {
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return null;
- }
- switch (bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- BHLeafInterface leaf = ((BHLeafNode) bh).leafIF;
- if (leaf instanceof GeometryAtom) {
- GeometryAtom leafAtom = (GeometryAtom) leaf;
- if ((atom.source.sourceNode != leafAtom.source.sourceNode) &&
- (((BHLeafNode) bh).isEnable()) &&
- (leafAtom.source.isCollidable) &&
- (atom.source.collisionVwcBound.intersect(leafAtom.source.collisionVwcBound)) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- ((leafAtom.source.geometryList != null) &&
- (atom.source.intersectGeometryList(leafAtom.source))))) {
- return bh;
- }
- } else if (leaf instanceof GroupRetained) {
- if (((BHLeafNode) bh).isEnable() &&
- ((GroupRetained) leaf).sourceNode.collidable &&
- atom.source.collisionVwcBound.intersect(bh.bHull) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- (atom.source.intersectGeometryList(
- atom.source.getCurrentLocalToVworld(0), bh.bHull)))) {
- return bh;
- }
- }
- return null;
- case BHNode.BH_TYPE_INTERNAL:
- if (atom.source.collisionVwcBound.intersect(bh.bHull)) {
- BHNode hitNode = doSelectAny(atom,
- ((BHInternalNode) bh).getRightChild(),
- accurancyMode);
- if (hitNode != null)
- return hitNode;
-
- return doSelectAny(atom,
- ((BHInternalNode) bh).getLeftChild(),
- accurancyMode);
- }
- return null;
- }
- return null;
- }
-
- BHLeafInterface selectAny(Bounds bound, int accurancyMode,
- NodeRetained armingNode) {
- if (bound == null) {
- return null;
- }
- BHNode bhNode = doSelectAny(bound, root, accurancyMode, armingNode);
- if (bhNode == null) {
- return null;
- }
- return ((BHLeafNode) bhNode).leafIF;
- }
-
- private BHNode doSelectAny(Bounds bound, BHNode bh, int accurancyMode,
- NodeRetained armingNode) {
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return null;
- }
-
- switch (bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- BHLeafInterface leaf = ((BHLeafNode) bh).leafIF;
- if (leaf instanceof GeometryAtom) {
- GeometryAtom leafAtom = (GeometryAtom) leaf;
- if ((((BHLeafNode) bh).isEnable()) &&
- (leafAtom.source.isCollidable) &&
- (bound.intersect(leafAtom.source.collisionVwcBound)) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- ((leafAtom.source.geometryList != null) &&
- (leafAtom.source.intersectGeometryList(
- leafAtom.source.getCurrentLocalToVworld(0), bound))))) {
- return bh;
- }
- } else if (leaf instanceof GroupRetained) {
- if ((leaf != armingNode) &&
- ((BHLeafNode) bh).isEnable() &&
- ((GroupRetained) leaf).sourceNode.collidable &&
- bound.intersect(bh.bHull)) {
- return bh;
- }
- }
- return null;
- case BHNode.BH_TYPE_INTERNAL:
- if (bound.intersect(bh.bHull)) {
- BHNode hitNode = doSelectAny(bound,
- ((BHInternalNode) bh).getRightChild(),
- accurancyMode,
- armingNode);
- if (hitNode != null)
- return hitNode;
-
- return doSelectAny(bound,
- ((BHInternalNode) bh).getLeftChild(),
- accurancyMode,
- armingNode);
- }
- return null;
- }
- return null;
- }
-
-
- BHLeafInterface selectAny(Bounds bound, int accurancyMode,
- GroupRetained armingGroup) {
- if (bound == null) {
- return null;
- }
- BHNode bhNode = doSelectAny(bound, root, accurancyMode, armingGroup);
- if (bhNode == null) {
- return null;
- }
- return ((BHLeafNode) bhNode).leafIF;
- }
-
- private BHNode doSelectAny(Bounds bound, BHNode bh, int accurancyMode,
- GroupRetained armingGroup) {
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return null;
- }
- switch (bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- BHLeafInterface leaf = ((BHLeafNode) bh).leafIF;
-
- if (leaf instanceof GeometryAtom) {
- GeometryAtom leafAtom = (GeometryAtom) leaf;
- if ((((BHLeafNode) bh).isEnable()) &&
- (leafAtom.source.isCollidable) &&
- (bound.intersect(leafAtom.source.collisionVwcBound)) &&
- (!isDescendent(leafAtom.source.sourceNode,
- armingGroup, leafAtom.source.key)) &&
- ((accurancyMode == WakeupOnCollisionEntry.USE_BOUNDS) ||
- ((leafAtom.source.geometryList != null) &&
- (leafAtom.source.intersectGeometryList(
- leafAtom.source.getCurrentLocalToVworld(0), bound))))) {
- return bh;
- }
- } else if (leaf instanceof GroupRetained) {
- GroupRetained group = (GroupRetained) leaf;
- if (((BHLeafNode) bh).isEnable() &&
- group.sourceNode.collidable &&
- bound.intersect(bh.bHull) &&
- !isDescendent(group.sourceNode, armingGroup, group.key)) {
- return bh;
- }
- }
- return null;
- case BHNode.BH_TYPE_INTERNAL:
- if (bound.intersect(bh.bHull)) {
- BHNode hitNode = doSelectAny(bound,
- ((BHInternalNode) bh).getRightChild(),
- accurancyMode,
- armingGroup);
- if (hitNode != null)
- return hitNode;
-
- return doSelectAny(bound,
- ((BHInternalNode) bh).getLeftChild(),
- accurancyMode,
- armingGroup);
- }
- return null;
- }
- return null;
- }
-
- // Return true if node is a descendent of group
- private boolean isDescendent(NodeRetained node,
- GroupRetained group,
- HashKey key) {
-
- synchronized (group.universe.sceneGraphLock) {
- if (node.inSharedGroup) {
- // getlastNodeId() will destroy this key
- if (key != null) {
- key = new HashKey(key);
- }
- }
-
- do {
- if (node == group) {
- return true;
- }
- if (node instanceof SharedGroupRetained) {
- // retrieve the last node ID
- String nodeId = key.getLastNodeId();
- NodeRetained prevNode = node;
- Vector<NodeRetained> parents = ((SharedGroupRetained)node).parents;
- for(int i=parents.size()-1; i >=0; i--) {
- NodeRetained link = parents.get(i);
- if (link.nodeId.equals(nodeId)) {
- node = link;
- break;
- }
- }
- if (prevNode == node) {
- // branch is already detach
- return true;
- }
- }
- node = node.parent;
- } while (node != null); // reach Locale
- }
- return false;
- }
-
-
- void select(PickShape pickShape, UnorderList hitArrList) {
-
- if((pickShape == null)||(root == null))
- return;
-
- doSelect(pickShape, hitArrList, root, tPoint4d);
-
- }
-
-
- private void doSelect(PickShape pickShape, UnorderList hitArrList,
- BHNode bh, Point4d pickPos) {
-
- if ((bh == null) || (bh.bHull.isEmpty())) {
- return;
- }
-
- switch(bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- if (((BHLeafNode)(bh)).isEnable() &&
- (((BHLeafNode) bh).leafIF instanceof GeometryAtom) &&
- ((GeometryAtom) (((BHLeafNode)
- bh).leafIF)).source.isPickable &&
- pickShape.intersect(bh.bHull, pickPos)) {
- hitArrList.add(bh);
- }
- break;
- case BHNode.BH_TYPE_INTERNAL:
- if (pickShape.intersect(bh.bHull, pickPos)) {
- doSelect(pickShape,
- hitArrList,
- ((BHInternalNode)bh).getRightChild(),
- pickPos);
- doSelect(pickShape,
- hitArrList,
- ((BHInternalNode)bh).getLeftChild(),
- pickPos);
- }
- break;
- }
- }
-
- BHNode selectAny(PickShape pickShape) {
-
- if((pickShape == null)||(root == null))
- return null;
-
- return doSelectAny(pickShape, root, tPoint4d);
-
- }
-
-
- private BHNode doSelectAny(PickShape pickShape, BHNode bh, Point4d pickPos) {
-
- BHNode hitNode = null;
-
- if((bh == null) || (bh.bHull.isEmpty()))
- return null;
-
- switch(bh.nodeType) {
- case BHNode.BH_TYPE_LEAF:
- if (((BHLeafNode)(bh)).isEnable() &&
- (((BHLeafNode) bh).leafIF instanceof GeometryAtom) &&
- ((GeometryAtom) (((BHLeafNode)
- bh).leafIF)).source.isPickable &&
- pickShape.intersect(bh.bHull, pickPos)) {
- return bh;
- }
- break;
- case BHNode.BH_TYPE_INTERNAL:
- if (pickShape.intersect(bh.bHull, pickPos)) {
- hitNode = doSelectAny(pickShape,
- ((BHInternalNode)bh).getRightChild(),
- pickPos);
-
- if (hitNode != null) {
- return hitNode;
- }
-
- return doSelectAny(pickShape,
- ((BHInternalNode)bh).getLeftChild(),
- pickPos);
- }
- break;
- }
- return null;
- }
-
-
- private void create(BHNode bhArr[]) {
- int i;
-
- if(bhArr == null) {
- root = null;
- return;
- }
-
- if(bhArr.length == 1) {
- bhArr[0].computeBoundingHull();
- root = (BHNode)bhArr[0];
- return;
- }
-
- int centerValuesIndex[] = new int[bhArr.length];
- float centerValues[][] = computeCenterValues(bhArr, centerValuesIndex);
-
- /*
- System.err.println("Length of array is " + bhArr.length);
- for(int kk=0; kk<bhArr.length;kk++) {
- System.err.println("( " + centerValues[kk][0] + ", " +
- centerValues[kk][1] + ", " + centerValues[kk][2] + " )");
- }
- */
-
- root = new BHInternalNode();
- constructTree((BHInternalNode) root, bhArr, centerValues,
- centerValuesIndex);
-
-
- if(J3dDebug.devPhase && J3dDebug.debug)
- gatherTreeStatistics();
-
- }
-
- void insert(BHNode bhArr[], int size) {
- // first pass: add all elements to the tree creating k array internal
- // nodes using the auxiliaryInsertStucture
- // second pass: go through all elements of the auxiliaryInsertStructure
- // and then update these nodes reclustering the trees with the new
- // k element siblings ...
-
- if(J3dDebug.devPhase && J3dDebug.debug)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "BHTree.java : Insert - bhArr.length is " +
- bhArr.length + "\n");
-
- if((bhArr == null) || (size < 1) || (bhArr.length < 1))
- return;
-
- if(root == null) {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "BHTree.java : Tree has not be created yet.\n");
-
- // This extra "new" is needed, because create() require its input
- // array's length be equal to the number of inserted nodes.
- BHNode[] newbhArr = new BHNode[size];
- System.arraycopy(bhArr, 0, newbhArr, 0, size);
- create(newbhArr);
- return;
- }
-
- if(root.nodeType == BHNode.BH_TYPE_LEAF) {
- BHNode[] oldBhArr = bhArr;
- bhArr = new BHNode[size + 1];
- System.arraycopy(oldBhArr, 0, bhArr, 0, size);
- bhArr[size] = root;
- create(bhArr);
- return;
- }
-
- if(insertStructure == null) {
- insertStructure = new BHInsertStructure(size);
- }
- else {
- insertStructure.clear();
- }
-
- for (int i=0; i<size; i++) {
- // test if its inside the 'root' element
- if ( root.isInside(bhArr[i].bHull) ) {
- ((BHInternalNode)root).insert(bhArr[i], insertStructure);
- }
- else {
- // extend the bounds of root by joining with current element
- root.bHull.combine(bhArr[i].bHull);
- insertStructure.lookupAndInsert(root, bhArr[i]);
- }
- }
-
- insertStructure.updateBoundingTree(this);
- // System.err.println("BHTree - Inserting ...");
-
- // Issue 353: clear temporary insertStructure so we don't leak.
- insertStructure.clear();
-
- // Guard against size<1 is done at the start of this method.
- estMaxDepth += (int) (Math.log(size)/LOG_OF_2) + 1;
-
- if(estMaxDepth > depthUpperBound) {
- int maxDepth = root.computeMaxDepth(0);
- int leafCount = root.countNumberOfLeaves();
- double compDepth = Math.log(leafCount)/LOG_OF_2;
- /*
- System.err.println("BHTree - evaluate for reConstructTree ...");
- System.err.println("compDepth " + compDepth);
- System.err.println("maxDepth " + maxDepth);
- System.err.println("leafCount " + leafCount);
- */
-
- // Upper bound guard.
- if(maxDepth > depthUpperBound) {
- reConstructTree(leafCount);
- maxDepth = root.computeMaxDepth(0);
- /*
- System.err.println("BHTree - Did reConstructTree ...");
- System.err.println("compDepth " + compDepth);
- System.err.println("maxDepth " + maxDepth);
- */
- }
-
- // Adjust depthUpperBound according to app. need.
- // If we encounter lots of overlapping bounds, the re-balanced
- // tree may not be an ideal balance tree. So there might be a
- // likehood of maxDepth exceeding the preset depthUpperBound.
- if(maxDepth > depthUpperBound) {
- depthUpperBound = depthUpperBound + INCR_DEPTH_BOUND;
- }else if((depthUpperBound != DEPTH_UPPER_BOUND) &&
- (maxDepth * 1.5 < depthUpperBound)) {
- depthUpperBound = depthUpperBound - INCR_DEPTH_BOUND;
-
- if(depthUpperBound < DEPTH_UPPER_BOUND) {
- // Be sure that DEPTH_UPPER_BOUND is the min.
- depthUpperBound = DEPTH_UPPER_BOUND;
- }
- }
-
- // This is the only place for resetting estMaxDepth to the tree real
- // maxDepth. Hence in cases where tree may get deteriorate fast, such
- // as multiple inserts and deletes frequently. estMaxDepth is accuminated,
- // and will lead to tree re-evaluation and possibly re-balancing.
- estMaxDepth = maxDepth;
- }
-
- }
-
-
- // mark all elements of the node and its parent as needing updating
- private void markParentChain(BHNode[] nArr, int size) {
- BHNode node;
-
- for(int i=0; i<size; i++) {
- node = nArr[i];
- node.mark = true;
- while((node.parent != null) && (node.parent.mark == false)) {
- node = node.parent;
- node.mark = true;
- }
- }
- }
-
- // mark all elements of the node and its parent as needing updating
- private void markParentChain(BHNode node) {
- node.mark = true;
- while((node.parent != null) && (node.parent.mark == false)) {
- node = node.parent;
- node.mark = true;
- }
- }
-
- // Delete a series of n node elements from the input binary tree.
- // These elements are removed from the tree in a 2 phase process.
- // First, all elements to be removed are marked and all parent
- // chains are marked ... then a second phase of the algorithm goes
- // through and deletes them and updates all of the bounds ...
-
- // delete the n elements in the array from the tree
- void delete(BHNode bhArr[], int size) {
- BHNode node;
-
- /*
- if((bhArr == null) || (bhArr.length < 1))
- return;
- System.err.println("BHTree.java : delete - bhArr.length is " +
- bhArr.length);
- for(int i=0; i<bhArr.length; i++)
- System.err.println("bhArr[" + i +"] " + bhArr[i]);
-
- */
-
- for(int i=0; i<size; i++) {
- if((bhArr[i] != null) && (bhArr[i].nodeType == BHNode.BH_TYPE_LEAF)) {
- markParentChain(bhArr[i]);
- } else {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_1,
- "Warning, element " + i + " is null/not leaf node.\n"
- + "Error in deletion routine, element " +
- bhArr[i] + "\n" +
- "In tree = " + this +
- " can not delete it ...\n");
- }
-
- }
-
- root = root.deleteAndUpdateMarkedNodes();
-
- if(J3dDebug.devPhase)
- if (root == null) {
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "Tree has been completely deleted ...\n");
- }
- }
-
- // compute the center values along each of the three dimensions given
- // the array of leaf objects to be split and joined
- float[][] computeCenterValues(BHNode[] bhArr, int[] cIndex) {
- float centers[][] = new float[bhArr.length][3];
-
- // compute the center values of the input array of nodes
- for ( int i=0; i < bhArr.length; i++ ) {
- cIndex[i] = i;
-
- bhArr[i].computeBoundingHull();
-
- centers[i][0] =
- (float)((bhArr[i].bHull.upper.x + bhArr[i].bHull.lower.x))/ 2.0f;
- centers[i][1] =
- (float)((bhArr[i].bHull.upper.y + bhArr[i].bHull.lower.y)) / 2.0f;
- centers[i][2] =
- (float)((bhArr[i].bHull.upper.z + bhArr[i].bHull.lower.z)) / 2.0f;
-
- }
- return centers;
- }
-
-
- void computeMeansAndSumSquares(float[][] centerValues, int[] centerValuesIndex,
- float[] means, float[] ss) {
-
- int i, arrLen;
- float sumCenters[] = new float[3];
- float temp = 0.0f;
-
- arrLen = centerValuesIndex.length;
- // Initialization.
- for(i=2; i>=0; i--) {
- sumCenters[i] = 0.0f;
- ss[i] = 0.0f;
- }
-
- for(i=arrLen-1; i>=0 ; i--) {
- sumCenters[0] += centerValues[centerValuesIndex[i]][0];
- sumCenters[1] += centerValues[centerValuesIndex[i]][1];
- sumCenters[2] += centerValues[centerValuesIndex[i]][2];
- }
-
- means[0] = sumCenters[0]/(float)arrLen;
- means[1] = sumCenters[1]/(float)arrLen;
- means[2] = sumCenters[2]/(float)arrLen;
-
- for(i=arrLen-1; i>=0 ; i--) {
- temp = (centerValues[centerValuesIndex[i]][0] - means[0]);
- ss[0] += (temp*temp);
- temp = (centerValues[centerValuesIndex[i]][1] - means[1]);
- ss[1] += (temp*temp);
- temp = (centerValues[centerValuesIndex[i]][2] - means[2]);
- ss[2] += (temp*temp);
-
- }
-
- }
-
- // find the split axis (the highest ss and return its index) for
- // a given set of ss values
- int findSplitAxis ( float ss[] ) {
- int splitAxis = -1;
- float maxSS = 0.0f;
-
- // the largest ss index value
- for (int i=0; i < 3; i++) {
- if ( ss[i] > maxSS ) {
- maxSS = ss[i];
- splitAxis = i;
- }
- }
- return splitAxis;
- }
-
- // Recursive method for constructing a binary tree.
- void constructTree( BHInternalNode parent, BHNode bhArr[],
- float[][] centerValues,
- int[] centerValuesIndex ){
-
- int i, splitAxis;
- int rightSetCount = 0;
- int leftSetCount = 0;
- float means[] = new float[3];
- float ss[] = new float[3];
-
- if(J3dDebug.devPhase)
- if ( bhArr.length <= 1 ) {
- // this is only here for debugging can be removed after testing
- // to ensure that it never gets called
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_1,
- "constructTree - bhArr.length <= 1. Bad !!!\n");
- }
-
- computeMeansAndSumSquares(centerValues, centerValuesIndex, means, ss);
-
- splitAxis = findSplitAxis(ss);
-
- // an array of decision variables for storing the values of inside
- // the right or left set for a particular element of bhArr.
- // true if its in the left set, false if its in the right set
- boolean leftOrRightSet[] = new boolean[bhArr.length];
-
- if ( splitAxis == -1 ) {
- // This is bad. Since we can't find a split axis, the best thing
- // to do is to split the set in two sets; each with about the
- // same number of elements. By doing this we can avoid constructing
- // a skew tree.
-
- // split elements into half.
- for ( i=0; i < bhArr.length; i++) {
- if(leftSetCount > rightSetCount) {
- rightSetCount++;
- leftOrRightSet[i] = false;
- } else {
- leftSetCount++;
- leftOrRightSet[i] = true;
- }
- }
- }
- else {
- for ( i=0; i < bhArr.length; i++) {
- // the split criterion, special multiple equals cases added
- if ( centerValues[centerValuesIndex[i]][splitAxis] <
- means[splitAxis]) {
-
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "Found a left element\n");
- leftSetCount++;
- leftOrRightSet[i] = true;
- } else if ( centerValues[centerValuesIndex[i]][splitAxis] >
- means[splitAxis]) {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "Found a right element\n");
- rightSetCount++;
- leftOrRightSet[i] = false;
- } else {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4,
- "Found an equal element\n");
- if(leftSetCount > rightSetCount) {
- rightSetCount++;
- leftOrRightSet[i] = false;
- } else {
- leftSetCount++;
- leftOrRightSet[i] = true;
- }
- }
- }
- }
-
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_2,
- "LeftSetCount " + leftSetCount + " RightSetCount "+
- rightSetCount + "\n");
-
-
- // Don't think that this guard is needed, but still like to have it.
- // Just in case, bad means and the sum of squares might lead us into the guard.
- if (leftSetCount == bhArr.length) {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_1,
- "Split Axis of = " + splitAxis + " didn't yield "+
- "any split among the objects ?\n");
- // split elements into half
- rightSetCount = 0;
- leftSetCount = 0;
- for ( i=0; i < bhArr.length; i++) {
- if(leftSetCount > rightSetCount) {
- rightSetCount++;
- leftOrRightSet[i] = false;
- } else {
- leftSetCount++;
- leftOrRightSet[i] = true;
- }
- }
- } else if (rightSetCount == bhArr.length) {
- if(J3dDebug.devPhase)
- J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_1,
- "Split Axis of = " + splitAxis + " didn't yield "+
- "any split among the objects ?\n");
- // split elements into half
- rightSetCount = 0;
- leftSetCount = 0;
- for ( i=0; i < bhArr.length; i++) {
- if(leftSetCount > rightSetCount) {
- rightSetCount++;
- leftOrRightSet[i] = false;
- } else {
- leftSetCount++;
- leftOrRightSet[i] = true;
- }
- }
- }
-
- if(J3dDebug.devPhase)
- if(J3dDebug.doDebug(J3dDebug.bHTree, J3dDebug.LEVEL_4))
- // check to make sure that rightSet and leftSet sum to the
- // number of elements in the original array.
- if ( bhArr.length != (rightSetCount + leftSetCount) ) {
- System.err.println("An error has occurred in spliting");
- }
-
- BHNode rightSet[] = new BHNode[rightSetCount];
- BHNode leftSet[] = new BHNode[leftSetCount];
- int centerValuesIndexR[] = new int[rightSetCount];
- int centerValuesIndexL[] = new int[leftSetCount];
-
- rightSetCount = 0;
- leftSetCount = 0;
-
- for (i=0; i < bhArr.length; i++) {
- if ( leftOrRightSet[i] ) { // element in left set
- leftSet[leftSetCount] = bhArr[i];
- centerValuesIndexL[leftSetCount] = centerValuesIndex[i];
- leftSetCount++;
- } else {
- rightSet[rightSetCount] = bhArr[i];
- centerValuesIndexR[rightSetCount] = centerValuesIndex[i];
- rightSetCount++;
- }
- }
-
- if (rightSet.length != 1) {
- parent.rChild = new BHInternalNode();
- parent.rChild.setParent(parent);
- constructTree((BHInternalNode)(parent.rChild), rightSet, centerValues,
- centerValuesIndexR);
- } else {
- parent.rChild = rightSet[0];
- parent.rChild.setParent(parent);
- }
-
- if (leftSet.length != 1) {
- parent.lChild = new BHInternalNode();
- parent.lChild.setParent(parent);
- constructTree((BHInternalNode)(parent.lChild), leftSet, centerValues,
- centerValuesIndexL);
- } else {
- parent.lChild = leftSet[0];
- parent.lChild.setParent(parent);
- }
-
- parent.combineBHull(parent.rChild, parent.lChild);
- }
-
-
- void reConstructTree(int numOfLeaf) {
- if(root == null)
- return;
-
- BHNode bhArr[] = new BHNode[numOfLeaf];
- int index[] = new int[1];
- index[0] = 0;
- root.destroyTree(bhArr, index);
-
- /*
- if(bhArr.length != index[0])
- System.err.println("BHTree - This isn't right!!! - bhArr.length " +
- bhArr.length + " index " + index[0]);
- */
-
- create(bhArr);
-
- }
-
- void gatherTreeStatistics() {
-
- int leafCount = root.countNumberOfLeaves();
- int internalCount = root.countNumberOfInternals();
- int maxDepth = root.computeMaxDepth(0);
- float averageDepth = root.computeAverageLeafDepth ( leafCount, 0);
-
-
- System.err.println("Statistics for tree = " + this);
- System.err.println("Total Number of nodes in tree = " +
- (leafCount + internalCount) );
- System.err.println("Number of Leaf Nodes = " + leafCount );
- System.err.println("Number of Internal Nodes = " + internalCount );
- System.err.println("Maximum Leaf depth = " + maxDepth );
- System.err.println("Average Leaf depth = " + averageDepth );
- System.err.println("root.bHull = " + root.bHull);
- // printTree(root);
-
- }
-
-
- void printTree(BHNode bh) {
- if(bh!= null) {
- if(bh.nodeType == BHNode.BH_TYPE_INTERNAL) {
- System.err.println("BH_TYPE_INTERNAL - bHull : " + bh);
- System.err.println(bh.bHull);
- System.err.println("rChild : " + ((BHInternalNode)bh).rChild +
- " lChild : " + ((BHInternalNode)bh).lChild);
- printTree(((BHInternalNode)bh).rChild);
- printTree(((BHInternalNode)bh).lChild);
- }
- else if(bh.nodeType == BHNode.BH_TYPE_LEAF) {
- System.err.println("BH_TYPE_LEAF - bHull : " + bh);
- System.err.println(bh.bHull);
- }
-
- }
-
-
- }
-}
-
-
-
-
-
-