/** * @return A simple QuadTree with 6 entries for tests. */ private QuadTree<String> getTestTree() { QuadTree<String> qt = new QuadTree<>(-50.0, -50.0, +150.0, +150.0); qt.put(10.0, 10.0, "10.0, 10.0"); qt.put(15.0, 15.0, "15.0, 15.0"); qt.put(-15.0, 0.0, "-15.0, 0.0"); qt.put(20.0, 10.0, "20.0, 10.0"); qt.put(100.0, 0.0, "100.0, 0.0"); qt.put(15.0, 15.0, "15.0, 15.0 B"); return qt; }
private void generateRow(final double y, final Supplier<T> initialValueSupplier, final Geometry bounds) { for (double x = getMinX(y); x <= quadTree.getMaxEasting(); x += getCentroidDistanceX()) { Coordinate coord = new Coordinate(x, y); if (bounds.contains(geometryFactory.createPoint(coord))) quadTree.put(x, y, new Cell<>(coord, initialValueSupplier.get())); } }
public void put( final Coord coord , final T element ) { elements.add( new Tuple< Coord , T >( coord , element ) ); if ( quadTree != null && inBounds( coord ) ) { quadTree.put( coord.getX() , coord.getY() , element ); } else { minX = Math.min( coord.getX() , minX ); minY = Math.min( coord.getY() , minY ); maxX = Math.max( coord.getX() , maxX ); maxY = Math.max( coord.getY() , maxY ); quadTree = null; } }
@Test public void testGetRect() { QuadTree<String> qt = new QuadTree<>(0, 0, 1000, 1000); qt.put(100, 200, "node1"); qt.put(400, 900, "node2"); qt.put(700, 300, "node3"); qt.put(900, 400, "node4"); Collection<String> values = new ArrayList<>(); qt.getRectangle(new Rect(400, 300, 700, 900), values); Assert.assertEquals(2, values.size()); Assert.assertTrue(values.contains("node2")); Assert.assertTrue(values.contains("node3")); }
private void buildQuadTree() { assert minX <= maxX : minX +" > "+maxX; assert minY <= maxY : minY +" > "+maxY; this.quadTree = new QuadTree<T>( minX - EPSILON , minY - EPSILON , maxX + EPSILON , maxY + EPSILON ); for ( Tuple< Coord , T > element : elements ) { try { quadTree.put( element.getFirst().getX(), element.getFirst().getY(), element.getSecond() ); } catch ( Exception e ) { // if insertion fail, give more informative error message. throw new RuntimeException( "problem at inserting element " +elements.indexOf( element )+" of " +elements.size()+": " +element+" with bounds" +" minX="+minX +" minY="+minY +" maxX="+maxX +" maxY="+maxY , e ); } } }
@Test public void testGetXY_EntryOnDividingBorder() { QuadTree<String> qt = new QuadTree<>(0, 0, 40, 60); qt.put(10.0, 10.0, "10.0, 10.0"); qt.put(20.0, 20.0, "20.0, 20.0"); // on vertical border qt.put(20.0, 30.0, "20.0, 30.0"); // exactly on center qt.put(30.0, 30.0, "30.0, 30.0"); // on horizontal border assertEquals("20.0, 20.0", qt.getClosest(20.0, 20.0)); assertEquals("20.0, 30.0", qt.getClosest(20.0, 30.0)); assertEquals("30.0, 30.0", qt.getClosest(30.0, 30.0)); }
/** * tests that also for a large number of entries, values() returns the correct result. */ @Test public void testGetValues() { double minX = -1000; double minY = -5000; double maxX = 20000; double maxY = 12000; Random r = new Random(20181017L); List<String> expected = new ArrayList<>(1000); QuadTree<String> qt = new QuadTree<>(minX, minY, maxX, maxY); for (int i = 0; i < 1000; i++) { double x = minX + r.nextDouble() * (maxX - minX); double y = minY + r.nextDouble() * (maxY - minY); String value = "ITEM_" + i; qt.put(x, y, value); expected.add(value); } List<String> items = new ArrayList<>(qt.values()); Assert.assertEquals(1000, items.size()); items.sort(String::compareTo); expected.sort(String::compareTo); for (int i = 0; i < 1000; i++) { Assert.assertEquals(expected.get(i), items.get(i)); } }
@Test public void testGetRect_flatNetwork() { QuadTree<String> qt = new QuadTree<>(0, 0, 1000, 0); qt.put(0, 0, "node1"); qt.put(100, 0, "node2"); qt.put(500, 0, "node3"); qt.put(900, 0, "node4"); Collection<String> values = new ArrayList<>(); qt.getRectangle(new Rect(90, -10, 600, +10), values); Assert.assertEquals(2, values.size()); Assert.assertTrue(values.contains("node2")); Assert.assertTrue(values.contains("node3")); Collection<String> values2 = new ArrayList<>(); qt.getRectangle(new Rect(90, 0, 600, 0), values2); Assert.assertEquals(2, values2.size()); Assert.assertTrue(values2.contains("node2")); Assert.assertTrue(values2.contains("node3")); }
@Test public void testValuesIterator_ConcurrentModification() { QuadTree<String> qt = getTestTree(); Iterator<String> iter = qt.values().iterator(); assertTrue(iter.hasNext()); assertNotNull(iter.next()); qt.put(39.0, 52.1, "39.0 52.1"); assertTrue(iter.hasNext()); // hasNext() should not yet provoke exception try { iter.next(); fail("missing exception."); } catch (ConcurrentModificationException e) { log.info("catched expected exception: ", e); } }
@Test public void testGetXY_EntryOnOutsideBorder() { QuadTree<String> qt = new QuadTree<>(0.0, 0.0, 40.0, 60.0); // the 4 corners qt.put(0.0, 0.0, "SW"); qt.put(40.0, 0.0, "SE"); qt.put(0.0, 60.0, "NW"); qt.put(40.0, 60.0, "NE"); // the 4 sides qt.put(10.0, 60.0, "N"); qt.put(40.0, 10.0, "E"); qt.put(10.0, 0.0, "S"); qt.put(0.0, 10.0, "W"); assertEquals("SW", qt.getClosest(0.0, 0.0)); assertEquals("SE", qt.getClosest(40.0, 0.0)); assertEquals("NW", qt.getClosest(0.0, 60.0)); assertEquals("NE", qt.getClosest(40.0, 60.0)); assertEquals("N", qt.getClosest(10.0, 60.0)); assertEquals("E", qt.getClosest(40.0, 10.0)); assertEquals("S", qt.getClosest(10.0, 0.0)); assertEquals("W", qt.getClosest(0.0, 10.0)); }
@Test public void testGetDistance_EntryOnOutsideBorder() { QuadTree<String> qt = new QuadTree<>(0.0, 0.0, 40.0, 60.0); // the 4 corners qt.put(0.0, 0.0, "SW"); qt.put(40.0, 0.0, "SE"); qt.put(0.0, 60.0, "NW"); qt.put(40.0, 60.0, "NE"); // the 4 sides qt.put(10.0, 60.0, "N"); qt.put(40.0, 10.0, "E"); qt.put(10.0, 0.0, "S"); qt.put(0.0, 10.0, "W"); assertContains(new String[] {"SW"}, qt.getDisk(3.0, 0.0, 3.0)); assertContains(new String[] {"SE"}, qt.getDisk(40.0, 3.0, 3.0)); assertContains(new String[] {"NW"}, qt.getDisk(3.0, 60.0, 3.0)); assertContains(new String[] {"NE"}, qt.getDisk(40.0, 57.0, 3.0)); assertContains(new String[] {"N"}, qt.getDisk(7.0, 60.0, 3.0)); assertContains(new String[] {"E"}, qt.getDisk(40.0, 13.0, 3.0)); assertContains(new String[] {"S"}, qt.getDisk(13.0, 0.0, 3.0)); assertContains(new String[] {"W"}, qt.getDisk(3.0, 10.0, 3.0)); }
/** * Test putting values into a QuadTree using {@link QuadTree#put(double, double, Object)}. */ @Test public void testPut() { QuadTree<String> qt = new QuadTree<>(-50.0, -50.0, +150.0, +150.0); assertEquals(0, qt.size()); qt.put(10.0, 10.0, "10.0, 10.0"); assertEquals(1, qt.size()); qt.put(15.0, 15.0, "15.0, 15.0"); assertEquals(2, qt.size()); qt.put(-15.0, 0.0, "-15.0, 0.0"); assertEquals(3, qt.size()); qt.put(20.0, 10.0, "20.0, 10.0"); assertEquals(4, qt.size()); qt.put(100.0, 0.0, "100.0, 0.0"); assertEquals(5, qt.size()); qt.put(15.0, 15.0, "15.0, 15.0"); // insert an object a second time, shouldn't be added assertEquals(5, qt.size()); qt.put(15.0, 15.0, "15.0, 15.0 B"); // insert a second object at an existing place assertEquals(6, qt.size()); }
private void setActivityCoord2NearestReceiverPointId () { double gap = noiseParams.getReceiverPointGap(); Counter counter = new Counter("fill quadtree #") ; QuadTree<ReceiverPoint> qTree = new QuadTree<>(xCoordMin - 4*gap, yCoordMin - 4* gap, xCoordMax + 4*gap, yCoordMax + 4*gap); for(ReceiverPoint p: receiverPoints.values()) { qTree.put(p.getCoord().getX(), p.getCoord().getY(), p); counter.incCounter(); } counter.printCounter(); counter = new Counter("compute nearest receiver-points #"); for (Coord coord : consideredActivityCoordsForSpatialFunctionality) { // TODO maybe add a check here so we consider only the rp in the 9 surrounding cells? ReceiverPoint rp = qTree.getClosest(coord.getX(), coord.getY()); if(rp != null) { if(activityCoord2receiverPointId.put(coord, rp.getId()) != null){ log.warn("this must not happen"); } } counter.incCounter(); } counter.printCounter(); }
@Test public void testGetDistance_EntryOnDividingBorder() { QuadTree<String> qt = new QuadTree<>(0, 0, 40, 60); qt.put(10.0, 10.0, "10.0, 10.0"); qt.put(20.0, 20.0, "20.0, 20.0"); // on vertical border qt.put(20.0, 30.0, "20.0, 30.0"); // exactly on center qt.put(30.0, 30.0, "30.0, 30.0"); // on horizontal border qt.put(12.0, 15.0, "12.0, 15.0"); qt.put(10.0, 25.0, "10.0, 25.0"); assertContains(new String[] {"10.0, 10.0"}, qt.getDisk(10.0, 7.0, 3.0)); assertContains(new String[] {"10.0, 10.0"}, qt.getDisk(10.0, 12.0, 2.0)); assertContains(new String[] {"10.0, 10.0"}, qt.getDisk(7.0, 10.0, 3.0)); assertContains(new String[] {"10.0, 10.0"}, qt.getDisk(13.0, 10.0, 3.0)); assertContains(new String[] {"20.0, 20.0"}, qt.getDisk(20.0, 23.0, 3.0)); assertContains(new String[] {"20.0, 30.0"}, qt.getDisk(20.0, 27.0, 3.0)); assertContains(new String[] {"30.0, 30.0"}, qt.getDisk(27.0, 30.0, 3.0)); assertContains(new String[] {"12.0, 15.0"}, qt.getDisk(15.0, 15.0, 3.0)); assertContains(new String[] {"10.0, 25.0"}, qt.getDisk(10.0, 28.0, 3.0)); }
private QuadTree<ActivityFacility> buildFacQuadTree(String type, TreeMap<Id<ActivityFacility>,ActivityFacility> facilities_of_type) { Gbl.startMeasurement(); log.info(" building " + type + " facility quad tree"); double minx = Double.POSITIVE_INFINITY; double miny = Double.POSITIVE_INFINITY; double maxx = Double.NEGATIVE_INFINITY; double maxy = Double.NEGATIVE_INFINITY; for (final ActivityFacility f : facilities_of_type.values()) { if (f.getCoord().getX() < minx) { minx = f.getCoord().getX(); } if (f.getCoord().getY() < miny) { miny = f.getCoord().getY(); } if (f.getCoord().getX() > maxx) { maxx = f.getCoord().getX(); } if (f.getCoord().getY() > maxy) { maxy = f.getCoord().getY(); } } minx -= 1.0; miny -= 1.0; maxx += 1.0; maxy += 1.0; System.out.println(" xrange(" + minx + "," + maxx + "); yrange(" + miny + "," + maxy + ")"); QuadTree<ActivityFacility> quadtree = new QuadTree<ActivityFacility>(minx, miny, maxx, maxy); for (final ActivityFacility f : facilities_of_type.values()) { quadtree.put(f.getCoord().getX(),f.getCoord().getY(),f); } log.info(" done"); Gbl.printRoundTime(); Gbl.printMemoryUsage(); return quadtree; }
private Tuple<QuadTree<ActivityFacilityWithIndex>, ActivityFacilityImpl[]> getTuple(String activityType) { TreesBuilder treesBuilder = new TreesBuilder(CollectionUtils.stringToSet(activityType), this.scenario.getNetwork(), this.dccg); treesBuilder.setActTypeConverter(this.getConverter()); treesBuilder.createTrees(scenario.getActivityFacilities()); ActivityFacilityImpl[] facilities = treesBuilder.getFacilitiesOfType().get(activityType); /* * Create a copy of the treesBuilder.getQuadTreesOfType() outcome where the * ActivityFacility objects are replaced by ActivityFacilityWithIndex objects. * TODO: let the TreeBuilder use ActivityFacilityWithIndex objects directly? */ QuadTree<ActivityFacilityWithIndex> quadTree = null; QuadTree<ActivityFacility> qt = treesBuilder.getQuadTreesOfType().get(activityType); if (qt != null) { double minX = qt.getMinEasting(); double maxX = qt.getMaxEasting(); double minY = qt.getMinNorthing(); double maxY = qt.getMaxNorthing(); quadTree = new QuadTree<ActivityFacilityWithIndex>(minX, minY, maxX, maxY); for (ActivityFacility activityFacility : qt.values()) { quadTree.put(activityFacility.getCoord().getX(), activityFacility.getCoord().getY(), this.faciliesWithIndexMap.get(activityFacility.getId())); } } return new Tuple<QuadTree<ActivityFacilityWithIndex>, ActivityFacilityImpl[]>(quadTree, facilities); }
public void finishInit() { double minX = Double.POSITIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; double maxX = Double.NEGATIVE_INFINITY; double maxY = Double.NEGATIVE_INFINITY; for (TransitRouterNetworkNode node : getNodes().values()) if(node.line == null) { Coord c = node.stop.getStopFacility().getCoord(); if (c.getX() < minX) minX = c.getX(); if (c.getY() < minY) minY = c.getY(); if (c.getX() > maxX) maxX = c.getX(); if (c.getY() > maxY) maxY = c.getY(); } QuadTree<TransitRouterNetworkNode> quadTree = new QuadTree<TransitRouterNetworkNode>(minX, minY, maxX, maxY); for (TransitRouterNetworkNode node : getNodes().values()) { if(node.line == null) { Coord c = node.stop.getStopFacility().getCoord(); quadTree.put(c.getX(), c.getY(), node); } } this.qtNodes = quadTree; } public static TransitRouterNetworkWW createFromSchedule(final Network network, final TransitSchedule schedule, final double maxBeelineWalkConnectionDistance) {
private QuadTree<TransitStopFacility> createTransitStopFacilityQuadTree(Set<TransitStopFacility> stops) { double minX = Double.POSITIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; double maxX = Double.NEGATIVE_INFINITY; double maxY = Double.NEGATIVE_INFINITY; for (TransitStopFacility stop : stops) { Coord c = stop.getCoord(); if (c.getX() < minX) { minX = c.getX(); } if (c.getY() < minY) { minY = c.getY(); } if (c.getX() > maxX) { maxX = c.getX(); } if (c.getY() > maxY) { maxY = c.getY(); } } QuadTree<TransitStopFacility> quadTree = new QuadTree<TransitStopFacility>(minX, minY, maxX, maxY); for (TransitStopFacility stop : stops) { Coord c = stop.getCoord(); quadTree.put(c.getX(), c.getY(), stop); } return quadTree; }
for (WrappedTransitRouteStop stop : routeStops) { Coord c = stop.transitRouteStop.getStopFacility().getCoord(); quadTree.put(c.getX(), c.getY(), stop);
/** * Tests that a once obtained values-collection is indeed a live view * on the QuadTree, so when the QuadTree changes, the view is updated * as well. */ @Test public void testValues_isView() { QuadTree<String> qt = getTestTree(); int size = qt.size(); Collection<String> values = qt.values(); valuesTester(qt.size(), values); qt.put(80.0, 80.0, "80.0, 80.0"); assertEquals(size + 1, qt.size()); valuesTester(size + 1, values); qt.put(75.0, 75.0, "75.0, 75.0"); assertEquals(size + 2, qt.size()); valuesTester(size + 2, values); assertTrue(qt.remove(80.0, 80.0, "80.0, 80.0")); assertEquals(size + 1, qt.size()); valuesTester(size + 1, values); }