diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNode.java b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNode.java index 4226c0f4e..82402c197 100644 --- a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNode.java +++ b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNode.java @@ -248,11 +248,11 @@ public class QuadNode // iterators // //===========// - public Iterator> getNodeIterator() { return new QuadNodeIterator<>(this, false, this.minimumDetailLevel); } - public Iterator> getLeafNodeIterator() { return new QuadNodeIterator<>(this, true, this.minimumDetailLevel); } + public Iterator> getNodeIterator() { return new QuadNodeIterator<>(this, false); } + public Iterator> getLeafNodeIterator() { return new QuadNodeIterator<>(this, true); } - public Iterator> getDirectChildNodeIterator() { return new QuadNodeIterator<>(this, false, this.sectionPos.sectionDetailLevel); } - public Iterator getDirectChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this, true); } + public Iterator> getDirectChildNodeIterator() { return new QuadNodeDirectChildNodeIterator<>(this); } + public Iterator getDirectChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); } diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeChildIndexIterator.java b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeChildIndexIterator.java new file mode 100644 index 000000000..d1f7adbee --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeChildIndexIterator.java @@ -0,0 +1,57 @@ +package com.seibel.lod.core.util.objects.quadTree; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.function.Consumer; + +public class QuadNodeChildIndexIterator implements Iterator +{ + private final Queue iteratorQueue = new LinkedList<>(); + + + + public QuadNodeChildIndexIterator(QuadNode parentNode, boolean returnNullChildPos) + { + // only get the children if this section isn't at the bottom of the tree + if (parentNode.sectionPos.sectionDetailLevel > parentNode.minimumDetailLevel) + { + // go over each child pos + for (int i = 0; i < 4; i++) + { + // add index to queue if either not null or we want to return null values as well + if (returnNullChildPos || parentNode.getChildByIndex(i) != null) + { + this.iteratorQueue.add(i); + } + } + } + } + + + + @Override + public boolean hasNext() { return this.iteratorQueue.size() != 0; } + + @Override + public Integer next() + { + if (!this.hasNext()) + { + throw new NoSuchElementException(); + } + + + return this.iteratorQueue.poll(); + } + + + /** Unimplemented */ + @Override + public void remove() { throw new UnsupportedOperationException("remove"); } + + @Override + public void forEachRemaining(Consumer action) { Iterator.super.forEachRemaining(action); } + +} diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildNodeIterator.java b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildNodeIterator.java new file mode 100644 index 000000000..bb54de35b --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildNodeIterator.java @@ -0,0 +1,45 @@ +package com.seibel.lod.core.util.objects.quadTree; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.function.Consumer; + +public class QuadNodeDirectChildNodeIterator implements Iterator> +{ + private final QuadNodeChildIndexIterator childIndexIterator; + private final QuadNode parentNode; + + + public QuadNodeDirectChildNodeIterator(QuadNode parentNode) + { + this.parentNode = parentNode; + this.childIndexIterator = new QuadNodeChildIndexIterator<>(this.parentNode, false); + } + + + + @Override + public boolean hasNext() { return this.childIndexIterator.hasNext(); } + + @Override + public QuadNode next() + { + if (!this.hasNext()) + { + throw new NoSuchElementException(); + } + + + int childIndex = this.childIndexIterator.next(); + return this.parentNode.getChildByIndex(childIndex); + } + + + /** Unimplemented */ + @Override + public void remove() { throw new UnsupportedOperationException("remove"); } + + @Override + public void forEachRemaining(Consumer> action) { Iterator.super.forEachRemaining(action); } + +} \ No newline at end of file diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildPosIterator.java b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildPosIterator.java index e0d376c4e..7565501cb 100644 --- a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildPosIterator.java +++ b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeDirectChildPosIterator.java @@ -3,34 +3,25 @@ package com.seibel.lod.core.util.objects.quadTree; import com.seibel.lod.core.pos.DhSectionPos; import java.util.Iterator; -import java.util.LinkedList; import java.util.NoSuchElementException; -import java.util.Queue; import java.util.function.Consumer; public class QuadNodeDirectChildPosIterator implements Iterator { - private final Queue iteratorPosQueue = new LinkedList<>(); + private final QuadNodeChildIndexIterator childIndexIterator; + private final QuadNode parentNode; - - public QuadNodeDirectChildPosIterator(QuadNode parentNode, boolean returnNullChildPos) + public QuadNodeDirectChildPosIterator(QuadNode parentNode) { - // go over each child pos - for (int i = 0; i < 4; i++) - { - // add pos to queue if either not null or we want to return null values as well - if (returnNullChildPos || parentNode.getChildByIndex(i) != null) - { - this.iteratorPosQueue.add(parentNode.sectionPos.getChildByIndex(i)); - } - } + this.parentNode = parentNode; + this.childIndexIterator = new QuadNodeChildIndexIterator<>(this.parentNode, true); } @Override - public boolean hasNext() { return this.iteratorPosQueue.size() != 0; } + public boolean hasNext() { return this.childIndexIterator.hasNext(); } @Override public DhSectionPos next() @@ -41,8 +32,8 @@ public class QuadNodeDirectChildPosIterator implements Iterator } - DhSectionPos iteratorPos = this.iteratorPosQueue.poll(); - return iteratorPos; + int childIndex = this.childIndexIterator.next(); + return this.parentNode.sectionPos.getChildByIndex(childIndex); } diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeIterator.java b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeIterator.java index 6c0223488..2e3624e15 100644 --- a/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeIterator.java +++ b/core/src/main/java/com/seibel/lod/core/util/objects/quadTree/QuadNodeIterator.java @@ -20,11 +20,11 @@ class QuadNodeIterator implements Iterator> - public QuadNodeIterator(QuadNode rootNode, boolean onlyReturnLeafValues, byte highestDetailLevel) + public QuadNodeIterator(QuadNode rootNode, boolean onlyReturnLeafValues) { this.onlyReturnLeafValues = onlyReturnLeafValues; // TODO the naming conversion for these are flipped in a lot of places - this.highestDetailLevel = highestDetailLevel; + this.highestDetailLevel = rootNode.minimumDetailLevel; this.iteratorDetailLevel = rootNode.sectionPos.sectionDetailLevel; @@ -72,10 +72,7 @@ class QuadNodeIterator implements Iterator> @Override - public boolean hasNext() - { - return this.iteratorNodeQueue.size() != 0; - } + public boolean hasNext() { return this.iteratorNodeQueue.size() != 0; } @Override public QuadNode next() diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java index 50e0919a0..c03719014 100644 --- a/core/src/test/java/tests/QuadTreeTest.java +++ b/core/src/test/java/tests/QuadTreeTest.java @@ -540,56 +540,60 @@ public class QuadTreeTest } -// @Test -// public void QuadNodeDetailLimitTest() -// { -// AbstractTestTreeParams treeParams = new MediumTestTree(); -// QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte)6); -// Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMaxDetailLevel); -// -// // create the root node -// testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); -// -// // recurse down the tree -// AtomicInteger minimumDetailLevelReachedRef = new AtomicInteger(tree.treeMaxDetailLevel); -// tree.forEachRootNode((rootNode) -> -// { -// rootNode.forEachDirectChildNode((quadNode, sectionPos) -> -// { -// // all sections will be null -// rootNode.setValue(sectionPos, 0); -// }); -// -// rootNode.forEachDirectChildNode((quadNode, sectionPos) -> -// { -// recursivelyCreateNodeChildren(quadNode, tree.treeMinDetailLevel, minimumDetailLevelReachedRef); -// }); -// }); -// -// // confirm that the tree can and did iterate all the way down to the minimum detail level -// Assert.assertEquals("Minimum detail level never reached", minimumDetailLevelReachedRef.get(), tree.treeMinDetailLevel); -// } + @Test + public void QuadNodeDetailLimitTest() + { + AbstractTestTreeParams treeParams = new MediumTestTree(); + QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte)6); + Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMaxDetailLevel); + + // create the root node + testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); + + // recurse down the tree + AtomicInteger minimumDetailLevelReachedRef = new AtomicInteger(tree.treeMaxDetailLevel); + Iterator> rootNodeIterator = tree.rootNodeIterator(); + while (rootNodeIterator.hasNext()) + { + QuadNode rootNode = rootNodeIterator.next(); + Iterator rootNodeDirectChildPosIterator = rootNode.getDirectChildPosIterator(); + while (rootNodeDirectChildPosIterator.hasNext()) + { + DhSectionPos sectionPos = rootNodeDirectChildPosIterator.next(); + + // all sections will be null + rootNode.setValue(sectionPos, 0); + } + + Iterator> rootNodeDirectChildIterator = rootNode.getDirectChildNodeIterator(); + while (rootNodeDirectChildIterator.hasNext()) + { + QuadNode quadNode = rootNodeDirectChildIterator.next(); + recursivelyCreateNodeChildren(quadNode, tree.treeMinDetailLevel, minimumDetailLevelReachedRef); + } + } + + // confirm that the tree can and did iterate all the way down to the minimum detail level + Assert.assertEquals("Incorrect minimum detail level reached.", tree.treeMinDetailLevel, minimumDetailLevelReachedRef.get()); + } private void recursivelyCreateNodeChildren(QuadNode node, byte minDetailLevel, AtomicInteger minimumDetailLevelReachedRef) { boolean childNodesCreated = false; boolean childNodesIterated = false; - Iterator> directChildIterator; // fill in the null children - directChildIterator = node.getDirectChildNodeIterator(); - while (directChildIterator.hasNext()) + Iterator directChildPosIterator = node.getDirectChildPosIterator(); + while (directChildPosIterator.hasNext()) { - QuadNode childNode = directChildIterator.next(); - - node.setValue(childNode.sectionPos, 0); + node.setValue(directChildPosIterator.next(), 0); childNodesCreated = true; } // attempt to recurse down these new children - directChildIterator = node.getDirectChildNodeIterator(); + Iterator> directChildIterator = node.getDirectChildNodeIterator(); while (directChildIterator.hasNext()) { QuadNode childNode = directChildIterator.next(); @@ -627,7 +631,10 @@ public class QuadTreeTest Iterator directChildIterator = rootNode.getDirectChildPosIterator(); while (directChildIterator.hasNext()) { - rootNode.setValue(directChildIterator.next(), 1); + DhSectionPos sectionPos = directChildIterator.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);