Skip to content
Snippets Groups Projects
Commit 62c8817a authored by Daniel Schramm's avatar Daniel Schramm
Browse files

ClosestNodeMultipleVisitor repeated tree traversal reduced

parent 9d9fcd93
No related branches found
No related tags found
No related merge requests found
......@@ -59,54 +59,18 @@ public class ClosestNodeMultipleVisitor extends ClosestNodeAbstractVisitor {
return;
}
KdNode foundNode = closestNode(kdTree.getRoot());
final double closestDistance = MeshPoint.distance(getPoint3d(), foundNode.getLocation());
synchronized (this) {
if (updateMinimalDistance(closestDistance)) {
closest.clear();
}
}
// There is no closer point than the 'closestFound' in our tree.
// Search for other closest points with the same distance.
while (foundNode != null) {
final double distanceFound = MeshPoint.distance(getPoint3d(), foundNode.getLocation());
synchronized (this) {
if (distanceFound == getDistance()) {
closest.add(foundNode);
} else { // There is a closer point found in some other tree visited by this visitor
return;
}
}
foundNode = closestNodeOmitting(root);
}
}
/*
* Find an undiscovered node with its distance equal to 'distance'.
*
* - Discovered nodes are those stored in the 'closest' set.
* - We are not looking for distance closer than 'distance' because
* from the method {@link cz.fidentis.analyst.visitors.kdtree.ClosestNodeMultipleVisitor#visitKdTree}
* we already know distance to the closest node of the visited tree.
*/
private KdNode closestNodeOmitting(KdNode root) {
if (root == null) {
return null;
}
KdNode searchedNode = root;
/*
* First, find the closest node
* Reduce the search space by exploring the area where the closest node
* may theoretically be located.
*/
KdNode nearNode = null;
KdNode searchedNode = root;
while (searchedNode != null) {
final Vector3d nodePos = searchedNode.getLocation();
final double dist = MeshPoint.distance(getPoint3d(), nodePos);
synchronized (this) {
if (dist == getDistance() && !closest.contains(searchedNode)) {
nearNode = searchedNode;
if (updateMinimalDistance(dist) && !closest.isEmpty()) {
closest.clear();
}
}
......@@ -118,20 +82,23 @@ public class ClosestNodeMultipleVisitor extends ClosestNodeAbstractVisitor {
}
/*
* Second, search for a vertex that could be potentially closer than
* the nearest vertex already found
* Search for vertices that could be potentially closer than
* the closest distance already found or at the same distance.
*/
final Queue<KdNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
searchedNode = queue.poll();
Vector3d nodePos = searchedNode.getLocation();
final Vector3d nodePos = searchedNode.getLocation();
final double dist = MeshPoint.distance(getPoint3d(), nodePos);
synchronized (this) {
if (dist == getDistance() && !closest.contains(searchedNode)) {
nearNode = searchedNode;
if (updateMinimalDistance(dist)) {
closest.clear();
closest.add(searchedNode);
} else if (dist == getDistance()) {
closest.add(searchedNode);
}
}
......@@ -156,8 +123,6 @@ public class ClosestNodeMultipleVisitor extends ClosestNodeAbstractVisitor {
}
}
}
return nearNode;
}
}
......@@ -110,4 +110,55 @@ public class ClosestNodeMultipleVisitorTest {
assertEquals(8, closestFound.size());
testContainsExactlyPositions(closest, closestFound);
}
@Test
public void threeTreesSingleClosestTest() {
final Set<MeshPoint> closest = getTreeNodesSymmetric(1);
final KdTree kdTreeClosest = new KdTree(closest);
final KdTree kdTree1 = new KdTree(getTreeNodesSymmetric(2));
final KdTree kdTree2 = new KdTree(getTreeNodesSymmetric(3));
final ClosestNodeMultipleVisitor visitor = new ClosestNodeMultipleVisitor(centerNode, false);
kdTree1.accept(visitor);
kdTreeClosest.accept(visitor);
kdTree2.accept(visitor);
final Set<KdNode> closestFound = visitor.getClosestNodes();
assertEquals(8, closestFound.size());
testContainsExactlyPositions(closest, closestFound);
}
@Test
public void threeTreesTwoClosestTest() {
final Set<MeshPoint> closest = getTreeNodesSymmetric(1);
final Set<MeshPoint> closest1 = new HashSet<>();
final Set<MeshPoint> closest2 = new HashSet<>();
boolean odd = true;
for (final MeshPoint point: closest) {
if (odd) {
closest1.add(point);
} else {
closest2.add(point);
}
odd = !odd;
}
assertEquals(8, closest.size());
assertEquals(4, closest1.size());
assertEquals(4, closest2.size());
final KdTree kdTreeClosest1 = new KdTree(closest1);
final KdTree kdTreeClosest2 = new KdTree(closest2);
final KdTree kdTree = new KdTree(getTreeNodesSymmetric(2));
final ClosestNodeMultipleVisitor visitor = new ClosestNodeMultipleVisitor(centerNode, false);
kdTreeClosest1.accept(visitor);
kdTree.accept(visitor);
kdTreeClosest2.accept(visitor);
final Set<KdNode> closestFound = visitor.getClosestNodes();
assertEquals(8, closestFound.size());
testContainsExactlyPositions(closest, closestFound);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment