/** * Adds a node to the priority queue. * * @param closestDistanceSq The closest distance that a point in the region could possibly be target */ protected void addToQueue(double closestDistanceSq , KdTree.Node node , P target ) { if( !node.isLeaf() ) { Helper h; if( unused.isEmpty() ) { h = new Helper(); } else { h = unused.remove( unused.size()-1 ); } h.closestPossibleSq = closestDistanceSq; h.node = node; queue.add(h); } else { checkBestDistance(node, target); } }
/** * Adds a node to the priority queue. * * @param closestDistanceSq The closest distance that a point in the region could possibly be target */ protected void addToQueue(double closestDistanceSq , KdTree.Node node , P target ) { if( !node.isLeaf() ) { Helper h; if( unused.isEmpty() ) { h = new Helper(); } else { h = unused.remove( unused.size()-1 ); } h.closestPossibleSq = closestDistanceSq; h.node = node; queue.add(h); } else { checkBestDistance(node, target); } }
private static void flattenTree(KdTree.Node n , List<double[]> data ) { data.add((double[])n.point); if( !n.isLeaf() ) { flattenTree(n.left,data); flattenTree(n.right,data); } }
return; if( node.isLeaf() ) {
return; if( node.isLeaf() ) {
if( node.isLeaf() ) { return;
if( node.isLeaf() ) { return;
/** * Traverse a node down to a leaf. Unexplored branches are added to the priority queue. */ protected void searchNode(P target, KdTree.Node n) { while( n != null) { checkBestDistance(n, target); if( n.isLeaf() ) break; // select the most promising branch to investigate first KdTree.Node nearer,further; double splitValue = distance.valueAt( (P)n.point , n.split ); if( distance.valueAt( target , n.split ) <= splitValue ) { nearer = n.left; further = n.right; } else { nearer = n.right; further = n.left; } // See if it is possible for 'further' to contain a better node double dx = splitValue - distance.valueAt(target, n.split ); if( further != null && canImprove(dx*dx) ) { addToQueue(dx*dx, further, target ); } n = nearer; } }
/** * Traverse a node down to a leaf. Unexplored branches are added to the priority queue. */ protected void searchNode(P target, KdTree.Node n) { while( n != null) { checkBestDistance(n, target); if( n.isLeaf() ) break; // select the most promising branch to investigate first KdTree.Node nearer,further; double splitValue = distance.valueAt( (P)n.point , n.split ); if( distance.valueAt( target , n.split ) <= splitValue ) { nearer = n.left; further = n.right; } else { nearer = n.right; further = n.left; } // See if it is possible for 'further' to contain a better node double dx = splitValue - distance.valueAt(target, n.split ); if( further != null && canImprove(dx*dx) ) { addToQueue(dx*dx, further, target ); } n = nearer; } }
/** * Basic tests to see if it can handle different sized input lists. */ @Test public void construct() { KdTreeConstructor<double[]> alg = new KdTreeConstructor<>(new KdTreeMemory(),createSplitter(1,1,false)); // test an empty list List<double[]> points = new ArrayList<>(); KdTree tree = alg.construct(points,false); assertEquals(2, tree.N); assertNull(tree.root); // add a point points.add( new double[]{1,2}); tree = alg.construct(points,false); assertEquals(2, tree.N); assertSame(tree.root.point, points.get(0)); assertTrue(tree.root.isLeaf()); // add another point. These input points are ignored by the dummy splitter points.add( new double[]{1,2,4,5}); tree = alg.construct(points,false); assertEquals(2, tree.N); assertTrue(tree.root.left.isLeaf()); assertTrue(tree.root.right.isLeaf()); }
/** * Same test as above but with associated data */ @Test public void computeBranch_trackIndexes() { DummySplitter splitter = createSplitter(1,1,true); splitter.splitAxis = 1; splitter.splitPoint = new double[]{2,3}; splitter.splitIndex = 2; KdTreeConstructor<double[]> alg = new KdTreeConstructor<>(new KdTreeMemory(),splitter); KdTree.Node n = alg.computeBranch(new ArrayList<>(),new GrowQueue_I32()); assertSame(n.point, splitter.splitPoint); assertEquals(n.split, splitter.splitAxis); assertEquals(n.index, splitter.splitIndex); assertTrue(n.left.isLeaf()); assertTrue(n.right.isLeaf()); assertSame(n.left.point, splitter.left.get(0)); assertEquals(n.left.index, splitter.leftIndex.get(0)); assertSame(n.right.point, splitter.right.get(0)); assertEquals(n.right.index, splitter.rightIndex.get(0)); }
@Test public void computeChild() { KdTreeConstructor<double[]> alg = new KdTreeConstructor<>(distance); List<double[]> points = new ArrayList<>(); GrowQueue_I32 data = new GrowQueue_I32(); // empty lists should be null KdTree.Node n = new KdTree.Node(); n.point = new double[2]; n.index = 1; KdTree.Node found = alg.computeChild(points,data); assertNull(found); // add a point points.add( new double[2] ); data.add(2); found = alg.computeChild(points,data); assertTrue(found.isLeaf()); assertSame(found.point, points.get(0)); assertEquals(found.index, data.get(0)); // for all the other cases it will create a branch. testing that will require a bit more work... }
/** * Makes sure a branch is created correctly given the results from the splitter */ @Test public void computeBranch_dontTrack() { DummySplitter splitter = createSplitter(1,1,false); splitter.splitAxis = 1; splitter.splitPoint = new double[]{2,3}; KdTreeConstructor<double[]> alg = new KdTreeConstructor<>(new KdTreeMemory(),splitter); KdTree.Node n = alg.computeBranch(new ArrayList<>(),null); assertSame(n.point, splitter.splitPoint); assertEquals(n.split, splitter.splitAxis); assertEquals(-2, n.index); // default value in splitter assertTrue(n.left.isLeaf()); assertTrue(n.right.isLeaf()); assertSame(n.left.point, splitter.left.get(0)); assertEquals(-1, n.left.index); assertSame(n.right.point, splitter.right.get(0)); assertEquals(-1, n.right.index); }