/** * Try several searches and see if they all produce good results. Just fine the nearest-neighbor */ @Test public void findClosest_basic_1() { KdTreeSearchN 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); }
/** Randomly generate several searches and check the result */ @Test public void randomTests() { KdTreeSearchN 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)); } } }
/** 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}, null); KdTreeSearchN alg = createAlg(); alg.setTree(tree); alg.setMaxDistance(2); found.reset(); alg.findNeighbor(new double[] {11, 8}, 1, found); assertEquals(0, found.size); found.reset(); alg.findNeighbor(new double[] {1, 1.5}, 1, found); assertEquals(1, found.size); assertTrue(found.data[0].node == tree.root); }
/** The tree is empty and it should always fail */ @Test public void findClosest_empty() { KdTreeSearchN alg = createAlg(); alg.setTree(new KdTree(2)); found.reset(); alg.findNeighbor(new double[] {11, 8}, 2, found); assertEquals(0, found.size()); }
/** See if it can handle a null leaf */ @Test public void findClosest_nullLeaf() { KdTreeSearchN 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); }
/** Make sure the distance it returns is correct */ @Test public void checkDistance() { KdTreeSearchN 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 = found.get(0).node.point[0] - pt[0]; double d1 = found.get(0).node.point[1] - pt[1]; assertEquals(d0 * d0 + d1 * d1, found.get(0).distance, 1e-8); }
/** See of it can handle duplicate values correctly */ @Test public void checkDuplicates() { KdTreeSearchN alg = createAlg(); KdTree tree = createTreeDuplicates(); alg.setTree(tree); alg.setMaxDistance(Double.MAX_VALUE); double[] pt = new double[] {1, 2}; found.reset(); alg.findNeighbor(pt, 3, found); assertEquals(3, found.size); // make sure each instance is unique for (int i = 0; i < 3; i++) { double[] a = found.get(i).node.point; for (int j = i + 1; j < 3; j++) { assertTrue(found.get(j).node.point != a); } } }