package rescuecore2.misc.geometry.spatialindex; import org.junit.Test; import org.junit.Before; import org.junit.After; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.hasItems; import java.util.Collection; import java.util.List; import java.util.ArrayList; import rescuecore2.misc.geometry.Point2D; import rescuecore2.misc.geometry.Line2D; import rescuecore2.misc.geometry.GeometryTools2D; import rescuecore2.log.Logger; public class BBTreeTest { private static final int NUM_POINTS = 1000; private static final int NUM_LINES = 1000; private static final int RANDOM_REGION_TEST_COUNT = 10; private BBTree tree; private List<Point2D> points; private List<Line2D> lines; private List<Indexable> all; @Before public void setup() { tree = new BBTree(); points = new ArrayList<Point2D>(NUM_POINTS); lines = new ArrayList<Line2D>(NUM_LINES); all = new ArrayList<Indexable>(NUM_POINTS + NUM_LINES); } /* @After public void cleanup() { Logger.debug("*******************************************************"); } */ @Test public void testRetrieveAllPoints() { // Logger.debug("testRetrieveAllPoints()"); createPoints(); // tree.logTree(); // Check that all points are retrieved if we search the whole space Collection<Indexable> found = tree.getItemsInRegion(0, 0, 1, 1); assertEquals(NUM_POINTS, found.size()); assertThat(found, hasItems(points.toArray(new Indexable[0]))); } @Test public void testRetrieveAllLines() { // Logger.debug("testRetrieveAllLines()"); createLines(); // tree.logTree(); // Check that all lines are retrieved if we search the whole space Collection<Indexable> found = tree.getItemsInRegion(0, 0, 1, 1); assertEquals(NUM_LINES, found.size()); assertThat(found, hasItems(lines.toArray(new Indexable[0]))); } @Test public void testRetrieveAllPointsAndLines() { // Logger.debug("testRetrieveAllPointsAndLines()"); createPoints(); createLines(); // tree.logTree(); // Check that all points and lines are retrieved if we search the whole space Collection<Indexable> found = tree.getItemsInRegion(0, 0, 1, 1); assertEquals(NUM_POINTS + NUM_LINES, found.size()); assertThat(found, hasItems(all.toArray(new Indexable[0]))); } @Test public void testRetrieveSomePoints() { // Logger.debug("testRetrieveSomePoints()"); createPoints(); // tree.logTree(); // Search a bunch of subspaces // Left half checkRegion(0, 0, 0.5, 1); // Right half checkRegion(0.5, 0, 1, 1); // Bottom half checkRegion(0, 0, 1, 0.5); // Top half checkRegion(0, 0.5, 1, 1); // Centre checkRegion(0.25, 0.25, 0.75, 0.75); // A few others for (int i = 0; i < RANDOM_REGION_TEST_COUNT; ++i) { double xMin = Math.random(); double yMin = Math.random(); double xMax = Math.random(); double yMax = Math.random(); checkRegion(Math.min(xMin, xMax), Math.min(yMin, yMax), Math.max(xMin, xMax), Math.max(yMin, yMax)); } } @Test public void testRetrieveSomeLines() { // Logger.debug("testRetrieveSomeLines()"); createLines(); // tree.logTree(); // Search a bunch of subspaces // Left half checkRegion(0, 0, 0.5, 1); // Right half checkRegion(0.5, 0, 1, 1); // Bottom half checkRegion(0, 0, 1, 0.5); // Top half checkRegion(0, 0.5, 1, 1); // Centre checkRegion(0.25, 0.25, 0.75, 0.75); // A few others for (int i = 0; i < RANDOM_REGION_TEST_COUNT; ++i) { double xMin = Math.random(); double yMin = Math.random(); double xMax = Math.random(); double yMax = Math.random(); checkRegion(Math.min(xMin, xMax), Math.min(yMin, yMax), Math.max(xMin, xMax), Math.max(yMin, yMax)); } } @Test public void testRetrieveSomePointsAndLines() { // Logger.debug("testRetrieveSomePointsAndLines()"); createPoints(); createLines(); // tree.logTree(); // Search a bunch of subspaces // Left half checkRegion(0, 0, 0.5, 1); // Right half checkRegion(0.5, 0, 1, 1); // Bottom half checkRegion(0, 0, 1, 0.5); // Top half checkRegion(0, 0.5, 1, 1); // Centre checkRegion(0.25, 0.25, 0.75, 0.75); // A few others for (int i = 0; i < RANDOM_REGION_TEST_COUNT; ++i) { double xMin = Math.random(); double yMin = Math.random(); double xMax = Math.random(); double yMax = Math.random(); checkRegion(Math.min(xMin, xMax), Math.min(yMin, yMax), Math.max(xMin, xMax), Math.max(yMin, yMax)); } } private void createPoints() { for (int i = 0; i < NUM_POINTS; ++i) { Point2D p = new Point2D(Math.random(), Math.random()); points.add(p); tree.insert(p); } all.addAll(points); } private void createLines() { for (int i = 0; i < NUM_LINES; ++i) { Line2D l = new Line2D(new Point2D(Math.random(), Math.random()), new Point2D(Math.random(), Math.random())); lines.add(l); tree.insert(l); } all.addAll(lines); } private void checkRegion(double xMin, double yMin, double xMax, double yMax) { Collection<Indexable> found = tree.getItemsInRegion(xMin, yMin, xMax, yMax); Collection<Indexable> shouldBeFound = new ArrayList<Indexable>(); shouldBeFound.addAll(findPoints(xMin, yMin, xMax, yMax)); shouldBeFound.addAll(findLines(xMin, yMin, xMax, yMax)); // Logger.debug("Checking region " + xMin + ", " + yMin + " -> " + xMax + ", " + yMax); // Logger.debug("Should find " + shouldBeFound); // Logger.debug("Actually found " + found); assertEquals(shouldBeFound.size(), found.size()); assertThat(found, hasItems(shouldBeFound.toArray(new Indexable[0]))); } private Collection<Indexable> findPoints(double xMin, double yMin, double xMax, double yMax) { Collection<Indexable> result = new ArrayList<Indexable>(points.size()); for (Point2D next : points) { if (next.getX() >= xMin && next.getX() <= xMax && next.getY() >= yMin && next.getY() <= yMax) { result.add(next); } } return result; } private Collection<Indexable> findLines(double xMin, double yMin, double xMax, double yMax) { Collection<Indexable> result = new ArrayList<Indexable>(lines.size()); for (Line2D next : lines) { if (GeometryTools2D.clipToRectangle(next, xMin, yMin, xMax, yMax) != null) { result.add(next); } } return result; } }