Fix and update QuadTree/Node iterators
This commit is contained in:
@@ -3,6 +3,9 @@ package com.seibel.lod.core.util.objects.quadTree;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.objects.quadTree.iterators.QuadNodeDirectChildIterator;
|
||||
import com.seibel.lod.core.util.objects.quadTree.iterators.QuadNodeDirectChildPosIterator;
|
||||
import com.seibel.lod.core.util.objects.quadTree.iterators.QuadTreeNodeIterator;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -119,19 +122,35 @@ public class QuadNode<T>
|
||||
* @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node
|
||||
* @return the node at the given position
|
||||
*/
|
||||
public T getValue(DhSectionPos sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); }
|
||||
public QuadNode<T> getNode(DhSectionPos sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); }
|
||||
|
||||
/**
|
||||
* @param sectionPos must be 1 detail level lower than this node's detail level
|
||||
* @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node
|
||||
* @return the node at the given position before the new node was set
|
||||
* @return the value at the given position before the new value was set
|
||||
*/
|
||||
public T setValue(DhSectionPos sectionPos, T newValue) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, true, newValue); }
|
||||
public T setValue(DhSectionPos sectionPos, T newValue) throws IllegalArgumentException
|
||||
{
|
||||
QuadNode<T> previousNode = this.getNode(sectionPos);
|
||||
if (previousNode != null)
|
||||
{
|
||||
T previousValue = previousNode.value;
|
||||
previousNode.value = newValue;
|
||||
return previousValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.getOrSetValue(sectionPos, true, newValue);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputSectionPos must be 1 detail level lower than this node's detail level
|
||||
* @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this
|
||||
* @return the node at the given position before the new node was set (if the new node should be set)
|
||||
*/
|
||||
private T getOrSetValue(DhSectionPos inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException
|
||||
private QuadNode<T> getOrSetValue(DhSectionPos inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException
|
||||
{
|
||||
// debug validation
|
||||
|
||||
@@ -162,12 +181,11 @@ public class QuadNode<T>
|
||||
if (inputSectionPos.sectionDetailLevel == this.sectionPos.sectionDetailLevel)
|
||||
{
|
||||
// this node is the requested position
|
||||
T returnValue = this.value;
|
||||
if (replaceValue)
|
||||
{
|
||||
this.value = newValue;
|
||||
}
|
||||
return returnValue;
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -248,11 +266,12 @@ public class QuadNode<T>
|
||||
// iterators //
|
||||
//===========//
|
||||
|
||||
public Iterator<QuadNode<T>> getNodeIterator() { return new QuadNodeIterator<>(this, false); }
|
||||
public Iterator<QuadNode<T>> getLeafNodeIterator() { return new QuadNodeIterator<>(this, true); }
|
||||
public Iterator<QuadNode<T>> getNodeIterator() { return new QuadTreeNodeIterator<>(this, false); }
|
||||
public Iterator<QuadNode<T>> getLeafNodeIterator() { return new QuadTreeNodeIterator<>(this, true); }
|
||||
|
||||
public Iterator<QuadNode<T>> getDirectChildNodeIterator() { return new QuadNodeDirectChildNodeIterator<>(this); }
|
||||
public Iterator<DhSectionPos> getDirectChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); }
|
||||
/** positions can point to null children */
|
||||
public Iterator<DhSectionPos> getChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); }
|
||||
public Iterator<QuadNode<T>> getChildNodeIterator() { return new QuadNodeDirectChildIterator<>(this); }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -71,12 +71,28 @@ public class QuadTree<T>
|
||||
// getters and setters //
|
||||
//=====================//
|
||||
|
||||
/** @return the value at the given section position */
|
||||
public final T get(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSet(pos, false, null); }
|
||||
/** @return the value that was previously in the given position, null if nothing */
|
||||
public final T set(DhSectionPos pos, T value) throws IndexOutOfBoundsException { return this.getOrSet(pos, true, value); }
|
||||
/** @return the node at the given section position */
|
||||
public final QuadNode<T> getNode(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null); }
|
||||
/** @return the value at the given section position */
|
||||
public final T getValue(DhSectionPos pos) throws IndexOutOfBoundsException
|
||||
{
|
||||
QuadNode<T> node = this.getNode(pos);
|
||||
if (node != null)
|
||||
{
|
||||
return node.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final T getOrSet(DhSectionPos pos, boolean setNewValue, T newValue) throws IndexOutOfBoundsException
|
||||
/** @return the value that was previously in the given position, null if nothing */
|
||||
public final T setValue(DhSectionPos pos, T value) throws IndexOutOfBoundsException
|
||||
{
|
||||
T previousValue = this.getValue(pos);
|
||||
this.getOrSetNode(pos, true, value);
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
protected final QuadNode<T> getOrSetNode(DhSectionPos pos, boolean setNewValue, T newValue) throws IndexOutOfBoundsException
|
||||
{
|
||||
if (this.isSectionPosInBounds(pos))
|
||||
{
|
||||
@@ -103,12 +119,12 @@ public class QuadTree<T>
|
||||
}
|
||||
|
||||
|
||||
T returnValue = topQuadNode.getValue(pos);
|
||||
QuadNode<T> returnNode = topQuadNode.getNode(pos);
|
||||
if (setNewValue)
|
||||
{
|
||||
topQuadNode.setValue(pos, newValue);
|
||||
}
|
||||
return returnValue;
|
||||
return returnNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,7 +182,7 @@ public class QuadTree<T>
|
||||
DhSectionPos childPos = pos.getChildByIndex(i);
|
||||
if (this.isSectionPosInBounds(childPos))
|
||||
{
|
||||
T value = this.get(childPos);
|
||||
T value = this.getValue(childPos);
|
||||
if (includeNullValues || value != null)
|
||||
{
|
||||
childCount++;
|
||||
@@ -183,7 +199,7 @@ public class QuadTree<T>
|
||||
// iterators //
|
||||
//===========//
|
||||
|
||||
public Iterator<QuadNode<T>> rootNodeIterator() { return new QuadTreeRootNodeIterator(); }
|
||||
/** can include null nodes */
|
||||
public Iterator<DhSectionPos> rootNodePosIterator() { return new QuadTreeRootPosIterator(true); }
|
||||
|
||||
public Iterator<QuadNode<T>> nodeIterator() { return new QuadTreeNodeIterator(false); }
|
||||
@@ -309,7 +325,8 @@ public class QuadTree<T>
|
||||
}
|
||||
|
||||
|
||||
return this.iteratorPosQueue.poll();
|
||||
DhSectionPos sectionPos = this.iteratorPosQueue.poll();
|
||||
return sectionPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -321,40 +338,9 @@ public class QuadTree<T>
|
||||
public void forEachRemaining(Consumer<? super DhSectionPos> action) { Iterator.super.forEachRemaining(action); }
|
||||
}
|
||||
|
||||
private class QuadTreeRootNodeIterator implements Iterator<QuadNode<T>>
|
||||
{
|
||||
private final QuadTreeRootPosIterator rootPosIterator;
|
||||
|
||||
public QuadTreeRootNodeIterator()
|
||||
{
|
||||
this.rootPosIterator = new QuadTreeRootPosIterator(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasNext() { return this.rootPosIterator.hasNext(); }
|
||||
|
||||
@Override
|
||||
public QuadNode<T> next()
|
||||
{
|
||||
DhSectionPos pos = this.rootPosIterator.next();
|
||||
return QuadTree.this.topRingList.get(pos.sectionX, pos.sectionZ);
|
||||
}
|
||||
|
||||
|
||||
/** Unimplemented */
|
||||
@Override
|
||||
public void remove() { throw new UnsupportedOperationException("remove"); }
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super QuadNode<T>> action) { Iterator.super.forEachRemaining(action); }
|
||||
|
||||
}
|
||||
|
||||
private class QuadTreeNodeIterator implements Iterator<QuadNode<T>>
|
||||
{
|
||||
private final QuadTreeRootNodeIterator rootNodeIterator;
|
||||
private final QuadTreeRootPosIterator rootNodeIterator;
|
||||
private Iterator<QuadNode<T>> currentNodeIterator;
|
||||
|
||||
private final boolean onlyReturnLeaves;
|
||||
@@ -362,28 +348,56 @@ public class QuadTree<T>
|
||||
|
||||
public QuadTreeNodeIterator(boolean onlyReturnLeaves)
|
||||
{
|
||||
this.rootNodeIterator = new QuadTreeRootNodeIterator();
|
||||
this.rootNodeIterator = new QuadTreeRootPosIterator(false);
|
||||
this.onlyReturnLeaves = onlyReturnLeaves;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasNext() { return this.rootNodeIterator.hasNext() || this.currentNodeIterator.hasNext(); }
|
||||
public boolean hasNext()
|
||||
{
|
||||
if (!this.rootNodeIterator.hasNext() && this.currentNodeIterator != null && !this.currentNodeIterator.hasNext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (this.currentNodeIterator == null || !this.currentNodeIterator.hasNext())
|
||||
{
|
||||
this.currentNodeIterator = this.getNextChildNodeIterator();
|
||||
}
|
||||
return this.currentNodeIterator != null && this.currentNodeIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadNode<T> next()
|
||||
{
|
||||
if (this.currentNodeIterator == null)
|
||||
if (this.currentNodeIterator == null || !this.currentNodeIterator.hasNext())
|
||||
{
|
||||
QuadNode<T> rootNode = this.rootNodeIterator.next();
|
||||
this.currentNodeIterator = this.onlyReturnLeaves ? rootNode.getLeafNodeIterator() : rootNode.getNodeIterator();
|
||||
this.currentNodeIterator = this.getNextChildNodeIterator();
|
||||
}
|
||||
|
||||
|
||||
return this.currentNodeIterator.next();
|
||||
}
|
||||
|
||||
/** @return null if no new iterator could be found */
|
||||
private Iterator<QuadNode<T>> getNextChildNodeIterator()
|
||||
{
|
||||
Iterator<QuadNode<T>> nodeIterator = null;
|
||||
while((nodeIterator == null || !nodeIterator.hasNext()) && this.rootNodeIterator.hasNext())
|
||||
{
|
||||
DhSectionPos sectionPos = this.rootNodeIterator.next();
|
||||
QuadNode<T> rootNode = QuadTree.this.getNode(sectionPos);
|
||||
if (rootNode != null)
|
||||
{
|
||||
nodeIterator = this.onlyReturnLeaves ? rootNode.getLeafNodeIterator() : rootNode.getNodeIterator();
|
||||
}
|
||||
}
|
||||
return nodeIterator;
|
||||
}
|
||||
|
||||
|
||||
/** Unimplemented */
|
||||
@Override
|
||||
|
||||
+6
-3
@@ -1,4 +1,6 @@
|
||||
package com.seibel.lod.core.util.objects.quadTree;
|
||||
package com.seibel.lod.core.util.objects.quadTree.iterators;
|
||||
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -23,6 +25,7 @@ public class QuadNodeChildIndexIterator<T> implements Iterator<Integer>
|
||||
// add index to queue if either not null or we want to return null values as well
|
||||
if (returnNullChildPos || parentNode.getChildByIndex(i) != null)
|
||||
{
|
||||
// TODO is it possible that a child could be outside the parent QuadTree's radius?
|
||||
this.iteratorQueue.add(i);
|
||||
}
|
||||
}
|
||||
@@ -42,8 +45,8 @@ public class QuadNodeChildIndexIterator<T> implements Iterator<Integer>
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
|
||||
return this.iteratorQueue.poll();
|
||||
Integer index = this.iteratorQueue.poll();
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -1,16 +1,19 @@
|
||||
package com.seibel.lod.core.util.objects.quadTree;
|
||||
package com.seibel.lod.core.util.objects.quadTree.iterators;
|
||||
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class QuadNodeDirectChildNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
public class QuadNodeDirectChildIterator<T> implements Iterator<QuadNode<T>>
|
||||
{
|
||||
private final QuadNodeChildIndexIterator<T> childIndexIterator;
|
||||
private final QuadNode<T> parentNode;
|
||||
|
||||
|
||||
public QuadNodeDirectChildNodeIterator(QuadNode<T> parentNode)
|
||||
public QuadNodeDirectChildIterator(QuadNode<T> parentNode)
|
||||
{
|
||||
this.parentNode = parentNode;
|
||||
this.childIndexIterator = new QuadNodeChildIndexIterator<>(this.parentNode, false);
|
||||
@@ -31,7 +34,8 @@ public class QuadNodeDirectChildNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
|
||||
|
||||
int childIndex = this.childIndexIterator.next();
|
||||
return this.parentNode.getChildByIndex(childIndex);
|
||||
QuadNode<T> node = this.parentNode.getChildByIndex(childIndex);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -1,6 +1,7 @@
|
||||
package com.seibel.lod.core.util.objects.quadTree;
|
||||
package com.seibel.lod.core.util.objects.quadTree.iterators;
|
||||
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
@@ -33,7 +34,8 @@ public class QuadNodeDirectChildPosIterator<T> implements Iterator<DhSectionPos>
|
||||
|
||||
|
||||
int childIndex = this.childIndexIterator.next();
|
||||
return this.parentNode.sectionPos.getChildByIndex(childIndex);
|
||||
DhSectionPos sectionPos = this.parentNode.sectionPos.getChildByIndex(childIndex);
|
||||
return sectionPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,4 +46,4 @@ public class QuadNodeDirectChildPosIterator<T> implements Iterator<DhSectionPos>
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super DhSectionPos> action) { Iterator.super.forEachRemaining(action); }
|
||||
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -1,4 +1,6 @@
|
||||
package com.seibel.lod.core.util.objects.quadTree;
|
||||
package com.seibel.lod.core.util.objects.quadTree.iterators;
|
||||
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -6,7 +8,7 @@ import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class QuadNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
public class QuadTreeNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
{
|
||||
/** lowest numerical value, inclusive */
|
||||
private final byte highestDetailLevel;
|
||||
@@ -20,7 +22,7 @@ class QuadNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
|
||||
|
||||
|
||||
public QuadNodeIterator(QuadNode<T> rootNode, boolean onlyReturnLeafValues)
|
||||
public QuadTreeNodeIterator(QuadNode<T> rootNode, boolean onlyReturnLeafValues)
|
||||
{
|
||||
this.onlyReturnLeafValues = onlyReturnLeafValues;
|
||||
// TODO the naming conversion for these are flipped in a lot of places
|
||||
@@ -104,6 +106,7 @@ class QuadNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
Queue<QuadNode<T>> parentNodes = new LinkedList<>(this.validNodesForDetailLevel);
|
||||
this.validNodesForDetailLevel.clear();
|
||||
|
||||
// populate the list of nodes for this level
|
||||
for (QuadNode<T> parentNode : parentNodes)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -277,11 +277,14 @@ public class QuadTreeTest
|
||||
// root nodes
|
||||
int rootNodeCount = 0;
|
||||
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
Iterator<DhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> rootNode = rootNodeIterator.next();
|
||||
rootNodeCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
|
||||
if (rootNode != null)
|
||||
{
|
||||
rootNodeCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect root count", 1, rootNodeCount);
|
||||
|
||||
@@ -391,25 +394,31 @@ public class QuadTreeTest
|
||||
|
||||
// confirm the root node were added
|
||||
int rootNodeCount = 0;
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
Iterator<DhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
rootNodeIterator.next();
|
||||
rootNodeCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
|
||||
if (rootNode != null)
|
||||
{
|
||||
rootNodeCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect root count", 1, rootNodeCount);
|
||||
|
||||
// attempt to get and remove, each node in the tree
|
||||
int rootNodePosCount = 0;
|
||||
Iterator<DhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
|
||||
rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos rootNodePos = rootNodePosIterator.next();
|
||||
|
||||
testGet(tree, rootNodePos, 0);
|
||||
testSet(tree, rootNodePos, null);
|
||||
|
||||
rootNodePosCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodePos);
|
||||
if (rootNode != null)
|
||||
{
|
||||
testGet(tree, rootNodePos, 0);
|
||||
testSet(tree, rootNodePos, null);
|
||||
|
||||
rootNodePosCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect root count", 1, rootNodePosCount);
|
||||
|
||||
@@ -441,17 +450,20 @@ public class QuadTreeTest
|
||||
Iterator<DhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos sectionPos = rootNodePosIterator.next();
|
||||
testSet(tree, sectionPos, 0);
|
||||
testSet(tree, rootNodePosIterator.next(), 0);
|
||||
}
|
||||
|
||||
|
||||
// 4 root nodes should be added
|
||||
int rootNodeCount = 0;
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> rootNode = rootNodeIterator.next();
|
||||
rootNodeCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
|
||||
if (rootNode != null)
|
||||
{
|
||||
rootNodeCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect root count", expectedRootNodeCount, rootNodeCount);
|
||||
}
|
||||
@@ -472,11 +484,14 @@ public class QuadTreeTest
|
||||
testSet(tree, new DhSectionPos(tree.treeMaxDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class);
|
||||
|
||||
int rootNodeCount = 0;
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
Iterator<DhSectionPos> rootNodeIterator = tree.rootNodePosIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> rootNode = rootNodeIterator.next();
|
||||
rootNodeCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodeIterator.next());
|
||||
if (rootNode != null)
|
||||
{
|
||||
rootNodeCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect leaf value sum", 1, rootNodeCount);
|
||||
|
||||
@@ -508,11 +523,14 @@ public class QuadTreeTest
|
||||
|
||||
|
||||
int rootNodeCount = 0;
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
Iterator<DhSectionPos> rootNodeIterator = tree.rootNodePosIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> rootNode = rootNodeIterator.next();
|
||||
rootNodeCount++;
|
||||
QuadNode<Integer> rootNode = tree.getNode(rootNodeIterator.next());
|
||||
if (rootNode != null)
|
||||
{
|
||||
rootNodeCount++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("incorrect leaf value sum", 4, rootNodeCount);
|
||||
|
||||
@@ -550,26 +568,37 @@ public class QuadTreeTest
|
||||
// create the root node
|
||||
testSet(tree, new DhSectionPos((byte)10, 0, 0), 1);
|
||||
|
||||
// recurse down the tree
|
||||
|
||||
|
||||
AtomicInteger minimumDetailLevelReachedRef = new AtomicInteger(tree.treeMaxDetailLevel);
|
||||
Iterator<QuadNode<Integer>> rootNodeIterator = tree.rootNodeIterator();
|
||||
while (rootNodeIterator.hasNext())
|
||||
|
||||
// recurse down the tree
|
||||
Iterator<DhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
|
||||
while (rootNodePosIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> rootNode = rootNodeIterator.next();
|
||||
Iterator<DhSectionPos> rootNodeDirectChildPosIterator = rootNode.getDirectChildPosIterator();
|
||||
while (rootNodeDirectChildPosIterator.hasNext())
|
||||
DhSectionPos sectionPos = rootNodePosIterator.next();
|
||||
QuadNode<Integer> rootNode = tree.getNode(sectionPos);
|
||||
if (rootNode != null)
|
||||
{
|
||||
DhSectionPos sectionPos = rootNodeDirectChildPosIterator.next();
|
||||
// fill in the root node's direct children
|
||||
Iterator<DhSectionPos> childPosIterator = rootNode.getChildPosIterator();
|
||||
while (childPosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos rootChildPos = childPosIterator.next();
|
||||
rootNode.setValue(rootChildPos, 0);
|
||||
}
|
||||
|
||||
// all sections will be null
|
||||
rootNode.setValue(sectionPos, 0);
|
||||
}
|
||||
|
||||
Iterator<QuadNode<Integer>> rootNodeDirectChildIterator = rootNode.getDirectChildNodeIterator();
|
||||
while (rootNodeDirectChildIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> quadNode = rootNodeDirectChildIterator.next();
|
||||
recursivelyCreateNodeChildren(quadNode, tree.treeMinDetailLevel, minimumDetailLevelReachedRef);
|
||||
|
||||
|
||||
// recursively create child nodes down to the minimum detail level
|
||||
Iterator<QuadNode<Integer>> ChildIterator = rootNode.getChildNodeIterator();
|
||||
while (ChildIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> childNode = ChildIterator.next();
|
||||
Assert.assertNotNull(childNode); // TODO is this correct?
|
||||
|
||||
recursivelyCreateNodeChildren(childNode, tree.treeMinDetailLevel, minimumDetailLevelReachedRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,19 +613,20 @@ public class QuadTreeTest
|
||||
|
||||
|
||||
// fill in the null children
|
||||
Iterator<DhSectionPos> directChildPosIterator = node.getDirectChildPosIterator();
|
||||
while (directChildPosIterator.hasNext())
|
||||
Iterator<DhSectionPos> directChildIterator = node.getChildPosIterator();
|
||||
while (directChildIterator.hasNext())
|
||||
{
|
||||
node.setValue(directChildPosIterator.next(), 0);
|
||||
node.setValue(directChildIterator.next(), 0);
|
||||
childNodesCreated = true;
|
||||
}
|
||||
|
||||
|
||||
// attempt to recurse down these new children
|
||||
Iterator<QuadNode<Integer>> directChildIterator = node.getDirectChildNodeIterator();
|
||||
directChildIterator = node.getChildPosIterator();
|
||||
while (directChildIterator.hasNext())
|
||||
{
|
||||
QuadNode<Integer> childNode = directChildIterator.next();
|
||||
DhSectionPos sectionPos = directChildIterator.next();
|
||||
QuadNode<Integer> childNode = node.getNode(sectionPos);
|
||||
|
||||
Assert.assertTrue("Child node recurred too low. Min detail level: "+minDetailLevel+", node detail level: "+childNode.sectionPos.sectionDetailLevel, childNode.sectionPos.sectionDetailLevel >= minDetailLevel);
|
||||
recursivelyCreateNodeChildren(childNode, minDetailLevel, minimumDetailLevelReachedRef);
|
||||
@@ -628,15 +658,15 @@ public class QuadTreeTest
|
||||
public void quadNodeChildPositionIndexTest()
|
||||
{
|
||||
QuadNode<Integer> rootNode = new QuadNode<>(new DhSectionPos((byte)10, 0, 0), (byte)0);
|
||||
Iterator<DhSectionPos> directChildIterator = rootNode.getDirectChildPosIterator();
|
||||
while (directChildIterator.hasNext())
|
||||
Iterator<DhSectionPos> directChildPosIterator = rootNode.getChildPosIterator();
|
||||
while (directChildPosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos sectionPos = directChildIterator.next();
|
||||
DhSectionPos sectionPos = directChildPosIterator.next();
|
||||
Assert.assertNotEquals("Root node pos shouldn't be included in direct child pos iteration", sectionPos, rootNode.sectionPos);
|
||||
|
||||
rootNode.setValue(sectionPos, 1);
|
||||
}
|
||||
Assert.assertEquals("node not filled", rootNode.getChildValueCount(), 4);
|
||||
Assert.assertEquals("node not filled", 4, rootNode.getChildValueCount());
|
||||
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -648,6 +678,53 @@ public class QuadTreeTest
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quadNodeChildPositionOutOfBoundsTest()
|
||||
{
|
||||
int treeWidthInBlocks = 64;
|
||||
QuadTree<Integer> tree = new QuadTree<>(treeWidthInBlocks, new DhBlockPos2D(-2, 0), (byte)0);
|
||||
|
||||
|
||||
|
||||
// center root node
|
||||
DhSectionPos centerNodePos = new DhSectionPos((byte)1, 0, 0);
|
||||
|
||||
// create node
|
||||
tree.setValue(centerNodePos, 0);
|
||||
QuadNode<Integer> centerRootNode = tree.getNode(centerNodePos);
|
||||
Assert.assertNotNull(centerRootNode);
|
||||
|
||||
// child pos in bounds of the tree
|
||||
Iterator<DhSectionPos> childPosIterator = centerRootNode.getChildPosIterator();
|
||||
while (childPosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos childPos = childPosIterator.next();
|
||||
centerRootNode.setValue(childPos, 1);
|
||||
}
|
||||
Assert.assertEquals("center node not filled", 4, centerRootNode.getChildValueCount());
|
||||
|
||||
|
||||
|
||||
// edge root node
|
||||
DhSectionPos offsetNodePos = new DhSectionPos((byte)1, -17, -16);
|
||||
|
||||
// create node
|
||||
tree.setValue(offsetNodePos, 0);
|
||||
QuadNode<Integer> offsetRootNode = tree.getNode(offsetNodePos);
|
||||
Assert.assertNotNull(offsetRootNode);
|
||||
|
||||
// child pos in bounds of the tree
|
||||
childPosIterator = offsetRootNode.getChildPosIterator();
|
||||
while (childPosIterator.hasNext())
|
||||
{
|
||||
DhSectionPos childPos = childPosIterator.next();
|
||||
offsetRootNode.setValue(childPos, 1);
|
||||
}
|
||||
// TODO James thought this shouldn't work for all 4 nodes, but he must've thought wrong.
|
||||
Assert.assertEquals("offset should only contain some children.", 4, offsetRootNode.getChildValueCount());
|
||||
|
||||
}
|
||||
|
||||
// this is here for quickly testing the toString method, it should never fail
|
||||
@Test
|
||||
public void toStringTest()
|
||||
@@ -675,7 +752,7 @@ public class QuadTreeTest
|
||||
// set
|
||||
try
|
||||
{
|
||||
Integer previousValue = tree.set(pos, setValue);
|
||||
Integer previousValue = tree.setValue(pos, setValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -696,7 +773,7 @@ public class QuadTreeTest
|
||||
{
|
||||
try
|
||||
{
|
||||
Integer getResult = tree.get(pos);
|
||||
Integer getResult = tree.getValue(pos);
|
||||
Assert.assertEquals("get failed "+pos, getValue, getResult);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -734,11 +811,11 @@ public class QuadTreeTest
|
||||
private static class MediumTestTree extends AbstractTestTreeParams
|
||||
{
|
||||
public int getWidthInBlocks() { return 1024; }
|
||||
|
||||
}
|
||||
|
||||
private static class TinyTestTree extends AbstractTestTreeParams
|
||||
{
|
||||
// top detail level = 6
|
||||
public int getWidthInBlocks() { return 32; }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user