QuadTree refactoring
This commit is contained in:
@@ -209,7 +209,7 @@ public class WorldGenerationQueue implements Closeable
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("queueing exception: "+e.getMessage(), e);
|
||||
generationQueueStarted = false;
|
||||
this.generationQueueStarted = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class RenderBufferHandler
|
||||
if (renderSection != null)
|
||||
{
|
||||
ColumnRenderSource sectionRenderSource = renderSection.getRenderSource();
|
||||
// if the render source is present, attempt to load it
|
||||
// if the render source is present, attempt to build it
|
||||
if (sectionRenderSource != null)
|
||||
{
|
||||
ColumnRenderSource[] adjacentRenderSources = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length];
|
||||
|
||||
@@ -57,10 +57,10 @@ public class QuadNode<T>
|
||||
|
||||
|
||||
/**
|
||||
* Use {@link QuadNode#getChildValueCount()} if you want the number of non-null child values.
|
||||
* Use {@link QuadNode#getNonNullChildCount()} if you want the number of non-null child values.
|
||||
* @return the number of non-null child nodes
|
||||
*/
|
||||
public int getChildCount()
|
||||
public int getTotalChildCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -74,13 +74,13 @@ public class QuadNode<T>
|
||||
}
|
||||
|
||||
/** @return the number of children that have non-null values */
|
||||
public int getChildValueCount()
|
||||
public int getNonNullChildCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
QuadNode<T> child = this.getChildByIndex(i);
|
||||
if (child != null && (child.value != null || child.getChildValueCount() != 0))
|
||||
if (child != null && (child.value != null || child.getNonNullChildCount() != 0))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
@@ -296,29 +296,30 @@ public class QuadNode<T>
|
||||
}
|
||||
|
||||
|
||||
if (nwChild != null)
|
||||
{
|
||||
removedItemConsumer.accept(nwChild.value);
|
||||
}
|
||||
nwChild = null;
|
||||
|
||||
if (neChild != null)
|
||||
if (this.nwChild != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(neChild.value);
|
||||
removedItemConsumer.accept(this.nwChild.value);
|
||||
}
|
||||
neChild = null;
|
||||
this.nwChild = null;
|
||||
|
||||
if (seChild != null)
|
||||
if (this.neChild != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(seChild.value);
|
||||
removedItemConsumer.accept(this.neChild.value);
|
||||
}
|
||||
seChild = null;
|
||||
this.neChild = null;
|
||||
|
||||
if (swChild != null)
|
||||
if (this.seChild != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(swChild.value);
|
||||
removedItemConsumer.accept(this.seChild.value);
|
||||
}
|
||||
swChild = null;
|
||||
this.seChild = null;
|
||||
|
||||
if (this.swChild != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(this.swChild.value);
|
||||
}
|
||||
this.swChild = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -328,6 +329,6 @@ public class QuadNode<T>
|
||||
//==============//
|
||||
|
||||
@Override
|
||||
public String toString() { return "pos: "+this.sectionPos+", children #: "+this.getChildCount()+", value: "+this.value; }
|
||||
public String toString() { return "pos: "+this.sectionPos+", children #: "+this.getTotalChildCount()+", value: "+this.value; }
|
||||
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class QuadTree<T>
|
||||
//=====================//
|
||||
|
||||
/** @return the node at the given section position */
|
||||
public final QuadNode<T> getNode(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null); }
|
||||
public final QuadNode<T> getNode(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, false); }
|
||||
/** @return the value at the given section position */
|
||||
public final T getValue(DhSectionPos pos) throws IndexOutOfBoundsException
|
||||
{
|
||||
@@ -88,13 +88,14 @@ public class QuadTree<T>
|
||||
public final T setValue(DhSectionPos pos, T value) throws IndexOutOfBoundsException
|
||||
{
|
||||
T previousValue = this.getValue(pos);
|
||||
this.getOrSetNode(pos, true, value);
|
||||
this.getOrSetNode(pos, true, value, true);
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
protected final QuadNode<T> getOrSetNode(DhSectionPos pos, boolean setNewValue, T newValue) throws IndexOutOfBoundsException
|
||||
/** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */
|
||||
protected final QuadNode<T> getOrSetNode(DhSectionPos pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException
|
||||
{
|
||||
if (this.isSectionPosInBounds(pos))
|
||||
if (!runBoundaryChecks || this.isSectionPosInBounds(pos))
|
||||
{
|
||||
DhSectionPos rootPos = pos.convertToDetailLevel(this.treeMaxDetailLevel);
|
||||
int ringListPosX = rootPos.sectionX;
|
||||
@@ -224,16 +225,22 @@ public class QuadTree<T>
|
||||
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMaxDetailLevel),
|
||||
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.z, this.treeMaxDetailLevel));
|
||||
|
||||
if (!this.topRingList.getCenter().equals(expectedCenterPos))
|
||||
if (this.topRingList.getCenter().equals(expectedCenterPos))
|
||||
{
|
||||
this.topRingList.moveTo(expectedCenterPos.x, expectedCenterPos.y, (quadNode) ->
|
||||
{
|
||||
if (quadNode != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(quadNode.value);
|
||||
}
|
||||
});
|
||||
// tree doesn't need to be moved
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// remove out of bounds root nodes
|
||||
this.topRingList.moveTo(expectedCenterPos.x, expectedCenterPos.y, (quadNode) ->
|
||||
{
|
||||
if (quadNode != null && removedItemConsumer != null)
|
||||
{
|
||||
removedItemConsumer.accept(quadNode.value);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public final DhBlockPos2D getCenterBlockPos() { return this.centerBlockPos; }
|
||||
@@ -246,27 +253,55 @@ public class QuadTree<T>
|
||||
// base methods //
|
||||
//==============//
|
||||
|
||||
public boolean isEmpty() { return this.leafNodeCount() == 0; } // TODO this should be rewritten to short-circuit
|
||||
public boolean isEmpty() { return this.count() == 0; } // TODO this should be rewritten to short-circuit
|
||||
|
||||
public int leafNodeCount()
|
||||
/** @return the number of non-null nodes in the tree */
|
||||
public int count()
|
||||
{
|
||||
int count = 0;
|
||||
for (QuadNode<T> node : this.topRingList)
|
||||
{
|
||||
if (node != null)
|
||||
if (node == null)
|
||||
{
|
||||
Iterator<QuadNode<T>> leafNodeIterator = node.getLeafNodeIterator();
|
||||
while (leafNodeIterator.hasNext())
|
||||
continue;
|
||||
}
|
||||
|
||||
Iterator<QuadNode<T>> nodeIterator = node.getNodeIterator();
|
||||
while (nodeIterator.hasNext())
|
||||
{
|
||||
if(nodeIterator.next().value != null)
|
||||
{
|
||||
leafNodeIterator.next();
|
||||
count++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/** @return the number of leaf nodes in the tree */
|
||||
public int leafNodeCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (QuadNode<T> node : this.topRingList)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Iterator<QuadNode<T>> leafNodeIterator = node.getLeafNodeIterator();
|
||||
while (leafNodeIterator.hasNext())
|
||||
{
|
||||
leafNodeIterator.next();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// TODO comment, currently a tree will always have 9 root nodes, because the tree will grow all the way up to the top, if this is ever changed then these values must also change
|
||||
public int ringListWidth() { return 3; }
|
||||
public int ringListHalfWidth() { return 1; }
|
||||
@@ -309,7 +344,7 @@ public class QuadTree<T>
|
||||
DhSectionPos rootPos = new DhSectionPos(QuadTree.this.treeMaxDetailLevel, pos2D.x, pos2D.y);
|
||||
if (QuadTree.this.isSectionPosInBounds(rootPos))
|
||||
{
|
||||
iteratorPosQueue.add(rootPos);
|
||||
this.iteratorPosQueue.add(rootPos);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -347,9 +382,12 @@ public class QuadTree<T>
|
||||
private final QuadTreeRootPosIterator rootNodeIterator;
|
||||
private Iterator<QuadNode<T>> currentNodeIterator;
|
||||
|
||||
private QuadNode<T> lastNode = null;
|
||||
|
||||
private final boolean onlyReturnLeaves;
|
||||
|
||||
|
||||
|
||||
public QuadTreeNodeIterator(boolean onlyReturnLeaves)
|
||||
{
|
||||
this.rootNodeIterator = new QuadTreeRootPosIterator(false);
|
||||
@@ -383,7 +421,8 @@ public class QuadTree<T>
|
||||
}
|
||||
|
||||
|
||||
return this.currentNodeIterator.next();
|
||||
this.lastNode = this.currentNodeIterator.next();
|
||||
return this.lastNode;
|
||||
}
|
||||
|
||||
/** @return null if no new iterator could be found */
|
||||
@@ -403,9 +442,21 @@ public class QuadTree<T>
|
||||
}
|
||||
|
||||
|
||||
/** Unimplemented */
|
||||
@Override
|
||||
public void remove() { throw new UnsupportedOperationException("remove"); }
|
||||
public void remove()
|
||||
{
|
||||
if (this.lastNode == null)
|
||||
{
|
||||
throw new NoSuchElementException("No last node found.");
|
||||
}
|
||||
|
||||
|
||||
QuadNode<T> node = QuadTree.this.getOrSetNode(this.lastNode.sectionPos, true, null, false);
|
||||
if (node != null)
|
||||
{
|
||||
node.deleteAllChildren();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super QuadNode<T>> action) { Iterator.super.forEachRemaining(action); }
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class QuadTreeNodeIterator<T> implements Iterator<QuadNode<T>>
|
||||
QuadNode<T> childNode = parentNode.getChildByIndex(i);
|
||||
if (childNode != null)
|
||||
{
|
||||
if (childNode.getChildCount() == 0)
|
||||
if (childNode.getTotalChildCount() == 0)
|
||||
{
|
||||
this.iteratorNodeQueue.add(childNode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user