/** * Make sure the distance it returns is correct */ @Test public void checkDistance() { KdTreeSearch1<double[]> alg = createAlg(); KdTree tree = createTreeA(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); double[] pt = new double[]{11.5,8.2}; KdTree.Node found = alg.findNeighbor(pt); double d0 = ((double[])found.point)[0]-pt[0]; double d1 = ((double[])found.point)[1]-pt[1]; assertEquals(d0*d0 + d1*d1,alg.getDistance(),1e-8); } }
/** * See if it can handle a null leaf */ @Test public void findClosest_nullLeaf() { KdTreeSearch1<double[]> alg = createAlg(); KdTree tree = createTreeWithNull(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); // the first decision will be incorrect and it will need to back track KdTree.Node found = alg.findNeighbor(new double[]{2, 3}); assertSame(found, tree.root); }
/** * Randomly generate several searches and check the result */ @Test public void randomTests() { KdTreeSearchN<double[]> alg = createAlg(); KdTree tree = StandardKdTreeSearch1Tests.createTreeA(); alg.setTree(tree); List<double[]> data = new ArrayList<double[]>(); flattenTree(tree.root,data); for( int i = 0; i < 100; i++ ) { int searchN = rand.nextInt(data.size()+5)+1; double[] target = data.get( rand.nextInt(data.size())); double maxDistance = rand.nextDouble()*10; List<double[]> expected = findNeighbors(data,target,maxDistance,searchN); found.reset(); alg.setMaxDistance(maxDistance); alg.findNeighbor(target, searchN, found); assertEquals(expected.size(),found.size); for( int j = 0; j < expected.size(); j++ ) { checkContains(expected.get(j)); } } }
/** * The tree is empty and it should always fail */ @Test public void findClosest_empty() { KdTreeSearch1<double[]> alg = createAlg(); alg.setTree( new KdTree(2) ); KdTree.Node found = alg.findNeighbor(new double[]{11, 8}); assertNull(found); }
/** * See if it can handle a null leaf */ @Test public void findClosest_nullLeaf() { KdTreeSearchN<double[]> alg = createAlg(); KdTree tree = StandardKdTreeSearch1Tests.createTreeWithNull(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); // the first decision will be incorrect and it will need to back track found.reset(); alg.findNeighbor(new double[]{2, 3}, 1, found); assertTrue(found.get(0).node == tree.root); }
/** * Provide an insufficient number of steps to produce an optimal solution and see if it produces the expected * result */ @Test public void checkMaxNodes() { KdTree tree = StandardKdTreeSearch1Tests.createTreeA(); BBF alg = new BBF(0,2); alg.setTree(tree); KdTree.Node found = alg.findClosest(new double[]{12,2}); // The first search from the root node is not counted. In that search it will traverse down to a leaf assertTrue(found==tree.root.left.right); }
/** * The tree is a leaf and should always return the same result */ @Test public void findClosest_leaf() { KdTree tree = new KdTree(2); tree.root = new KdTree.Node(new double[]{1,2}); KdTreeSearch1<double[]> alg =createAlg(); alg.setTree( tree ); KdTree.Node found = alg.findNeighbor(new double[]{11, 8}); assertSame(found, tree.root); found = alg.findNeighbor(new double[]{2, 5}); assertSame(found, tree.root); }
/** * Try several searches and see if they all produce good results */ @Test public void findClosest_basic() { KdTreeSearch1<double[]> alg = createAlg(); KdTree tree = createTreeA(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); // the first decision will be incorrect and it will need to back track KdTree.Node found = alg.findNeighbor(new double[]{11, 8}); assertSame(found, tree.root.right.right); // the root will be the best match found = alg.findNeighbor(new double[]{1.001, 1.99999}); assertSame(found, tree.root); // a point on the left branch will be a perfect fit found = alg.findNeighbor(new double[]{2, 0.8}); assertSame(found, tree.root.left.right); // a point way outside the tree's bounds found = alg.findNeighbor(new double[]{-10000, 0.5}); assertSame(found, tree.root.left.left); }
/** * Provide an insufficient number of steps to produce an optimal solution and see if it produces the expected * result */ @Test public void checkMaxNodes() { KdTree tree = StandardKdTreeSearch1Tests.createTreeA(); KdTreeSearch1Bbf<double[]> alg = new KdTreeSearch1Bbf<>(new KdTreeEuclideanSq_F64(2),0); alg.setTree(tree); KdTree.Node found = alg.findNeighbor(new double[]{12, 2}); // The first search from the root node is not counted. In that search it will traverse down to a leaf assertTrue(found==tree.root.left.right); }
/** * See if max distance is being respected */ @Test public void findClosest_maxDistance() { KdTree tree = new KdTree(2); tree.root = new KdTree.Node(new double[]{1,2}); KdTreeSearch1<double[]> alg = createAlg(); alg.setTree( tree ); alg.setMaxDistance(2); KdTree.Node found = alg.findNeighbor(new double[]{11, 8}); assertNull(found); found = alg.findNeighbor(new double[]{1, 1.5}); assertSame(found, tree.root); }
/** * Provide multiple trees for input and see if it finds the best one */ @Test public void multiTreeSearch() { KdTree forest[] = new KdTree[2]; forest[0] = StandardKdTreeSearch1Tests.createTreeA(); forest[1] = new KdTree(2); forest[1].root = new KdTree.Node(new double[]{12,2}); BBF alg = new BBF(200,3); alg.setTrees(forest); KdTree.Node found = alg.findClosest(new double[]{12,3}); // make sure it searched some nodes besides the root ones assertTrue(alg.numNodesSearched>0); // the best node should be the root node in the second forest assertTrue(found==forest[1].root); }
/** * Provide multiple trees for input and see if it finds the best one */ @Test public void multiTreeSearch() { KdTree forest[] = new KdTree[2]; forest[0] = StandardKdTreeSearch1Tests.createTreeA(); forest[1] = new KdTree(2); forest[1].root = new KdTree.Node(new double[]{12,2}); KdTreeSearch1Bbf<double[]> alg = new KdTreeSearch1Bbf<>(new KdTreeEuclideanSq_F64(2),200); alg.setTrees(forest); KdTree.Node found = alg.findNeighbor(new double[]{12, 3}); // make sure it searched some nodes besides the root ones assertTrue(alg.numNodesSearched>0); // the best node should be the root node in the second forest assertSame(found, forest[1].root); }
/** * Make sure the distance it returns is correct */ @Test public void checkDistance() { KdTreeSearchN<double[]> alg = createAlg(); KdTree tree = StandardKdTreeSearch1Tests.createTreeA(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); double[] pt = new double[]{11.5,8.2}; found.reset(); alg.findNeighbor(pt, 1, found); assertEquals(1,found.size); double d0 = ((double[])found.get(0).node.point)[0]-pt[0]; double d1 = ((double[])found.get(0).node.point)[1]-pt[1]; assertEquals(d0*d0 + d1*d1,found.get(0).distance,1e-8); }
/** * Try several searches and see if they all produce good results. Just fine the nearest-neighbor */ @Test public void findClosest_basic_1() { KdTreeSearchN<double[]> alg = createAlg(); KdTree tree = StandardKdTreeSearch1Tests.createTreeA(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); // the first decision will be incorrect and it will need to back track found.reset(); alg.findNeighbor(new double[]{11, 8}, 1, found); assertEquals(1,found.size); assertTrue(found.data[0].node == tree.root.right.right); // the root will be the best found.reset(); alg.findNeighbor(new double[]{1.001, 1.99999}, 1, found); assertTrue(found.data[0].node == tree.root); // a point on the left branch will be a perfect fit found.reset(); alg.findNeighbor(new double[]{2, 0.8}, 1, found); assertTrue(found.data[0].node == tree.root.left.right); // a point way outside the tree's bounds found.reset(); alg.findNeighbor(new double[]{-10000, 0.5}, 1, found); assertTrue(found.data[0].node == tree.root.left.left); }