diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 9a75670e909..e1c1492fbed 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -236,9 +236,9 @@ void testRunDrtStopbasedExample() { var expectedStats = Stats.newBuilder() .rejectionRate(0.05) .rejections(17) - .waitAverage(260.41) - .inVehicleTravelTimeMean(374.87) - .totalTravelTimeMean(635.28) + .waitAverage(260.24) + .inVehicleTravelTimeMean(375.14) + .totalTravelTimeMean(635.38) .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); @@ -271,9 +271,9 @@ public void install() { var expectedStats = Stats.newBuilder() .rejectionRate(0.05) .rejections(17) - .waitAverage(261.88) - .inVehicleTravelTimeMean(376.04) - .totalTravelTimeMean(637.93) + .waitAverage(261.71) + .inVehicleTravelTimeMean(376.32) + .totalTravelTimeMean(638.03) .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); @@ -294,8 +294,8 @@ void testRunServiceAreabasedExampleWithSpeedUp() { var expectedStats = Stats.newBuilder() .rejectionRate(0.02) .rejections(9) - .waitAverage(224.56) - .inVehicleTravelTimeMean(392.65) + .waitAverage(224.46) + .inVehicleTravelTimeMean(392.74) .totalTravelTimeMean(617.21) .build(); diff --git a/matsim/src/main/java/org/matsim/core/utils/collections/QuadTree.java b/matsim/src/main/java/org/matsim/core/utils/collections/QuadTree.java index 1c82fe31965..8131abb837a 100644 --- a/matsim/src/main/java/org/matsim/core/utils/collections/QuadTree.java +++ b/matsim/src/main/java/org/matsim/core/utils/collections/QuadTree.java @@ -69,7 +69,7 @@ public class QuadTree implements Serializable { * @param maxY The largest y coordinate (northing, latitude) expected */ public QuadTree(final double minX, final double minY, final double maxX, final double maxY) { - this.top = new Node(minX, minY, maxX, maxY); + this.top = new Node<>(minX, minY, maxX, maxY); } /** @@ -140,7 +140,7 @@ public T getClosest(final double x, final double y) { * @return the objects found within distance to x/y */ public Collection getDisk(final double x, final double y, final double distance) { - return this.top.get(x, y, distance, new ArrayList<>()); + return this.top.get(x, y, distance * distance, new ArrayList<>()); } /** @@ -152,12 +152,12 @@ public Collection getDisk(final double x, final double y, final double distan * * @param x left-right location, longitude * @param y up-down location, latitude - * @param r_min inner ring radius - * @param r_max outer rind radius + * @param rMin inner ring radius + * @param rMax outer rind radius * @return objects within the ring */ - public Collection getRing(final double x, final double y, final double r_min, final double r_max) { - return this.top.get(x, y, r_min, r_max, new ArrayList<>()); + public Collection getRing(final double x, final double y, final double rMin, final double rMax) { + return this.top.get(x, y, rMin * rMin, rMax * rMax, new ArrayList<>()); } /** @@ -284,10 +284,10 @@ public double getMaxNorthing() { */ public Collection values() { if (this.values == null) { - this.values = new AbstractCollection() { + this.values = new AbstractCollection<>() { @Override public Iterator iterator() { - Iterator iterator = new Iterator() { + return new Iterator<>() { private final int expectedModCount = QuadTree.this.modCount; private Leaf currentLeaf = firstLeaf(); private int nextIndex = 0; @@ -346,7 +346,6 @@ public void remove() { } }; - return iterator; } @Override @@ -440,17 +439,44 @@ public double calcDistance(final double x, final double y) { } /** - * Calculates the distance from the given point to the furthest corner of the rectangle - * + * Calculates the square of the (minimum) distance of a given point to the border of the + * rectangle. If the point lies within the rectangle, the distance + * is zero. + * + * @param x left-right location + * @param y up-down location + * @return square of distance to border, 0 if inside rectangle or on border + */ + public double calcDistanceSqr(final double x, final double y) { + double distanceX; + double distanceY; + + if (this.minX <= x && x <= this.maxX) { + distanceX = 0; + } else { + distanceX = Math.min(Math.abs(this.minX - x), Math.abs(this.maxX - x)); + } + if (this.minY <= y && y <= this.maxY) { + distanceY = 0; + } else { + distanceY = Math.min(Math.abs(this.minY - y), Math.abs(this.maxY - y)); + } + + return distanceX * distanceX + distanceY * distanceY; + } + + /** + * Calculates the square of the distance from the given point to the furthest corner of the rectangle + * * @param x left-right location * @param y up-down location - * @return distance to furthest corner of the rectangle + * @return square of distance to the furthest corner of the rectangle */ - public double calcMaxDistance(final double x, final double y) { + public double calcMaxDistanceSqr(final double x, final double y) { double distanceX = Math.max(Math.abs(this.minX - x), Math.abs(this.maxX - x)); double distanceY = Math.max(Math.abs(this.minY - y), Math.abs(this.maxY - y)); - return Math.sqrt(distanceX * distanceX + distanceY * distanceY); + return distanceX * distanceX + distanceY * distanceY; } @@ -550,25 +576,25 @@ public Rect union(final Rect r) { /** * Increases the size of the rectangle by scaleX and scaleY. - * + * * (and "increase by" means: * 1.0: increase it by 100% (scale it by 2.0) * -0.5: decrease it by 50% (scale it by 0.5) * 0.0: do nothing) michaz - * + * */ - + public Rect scale(double scaleX, double scaleY) { scaleY *= this.centerY - this.minY; scaleX *= this.centerX - this.minX; return new Rect(this.minX - scaleX, this.minY-scaleY, this.maxX + scaleX, this.maxY + scaleY); } - + @Override public String toString() { return "topLeft: ("+minX+","+minY+") bottomRight: ("+maxX+","+maxY+")"; } - + } protected static class Leaf implements Serializable { @@ -652,7 +678,7 @@ public boolean put(final Leaf leaf) { } public boolean put(final double x, final double y, final T value) { - return put(new Leaf(x, y, value)); + return put(new Leaf<>(x, y, value)); } public boolean remove(final double x, final double y, final T value) { @@ -667,7 +693,7 @@ public boolean remove(final double x, final double y, final T value) { } if (leaf.values != null) { if (leaf.values.remove(value)) { - if (leaf.values.size() == 0) { + if (leaf.values.isEmpty()) { this.leaves.remove(leaf); } return true; @@ -699,27 +725,27 @@ public void clear() { } } - /* default */ T get(final double x, final double y, final MutableDouble bestDistance) { + /* default */ T get(final double x, final double y, final MutableDouble bestDistanceSqr) { if (this.hasChilds) { T closest = null; Node bestChild = this.getChild(x, y); if (bestChild != null) { - closest = bestChild.get(x, y, bestDistance); + closest = bestChild.get(x, y, bestDistanceSqr); } - if (bestChild != this.northwest && this.northwest.bounds.calcDistance(x, y) < bestDistance.value) { - T value = this.northwest.get(x, y, bestDistance); + if (bestChild != this.northwest && this.northwest.bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) { + T value = this.northwest.get(x, y, bestDistanceSqr); if (value != null) { closest = value; } } - if (bestChild != this.northeast && this.northeast.bounds.calcDistance(x, y) < bestDistance.value) { - T value = this.northeast.get(x, y, bestDistance); + if (bestChild != this.northeast && this.northeast.bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) { + T value = this.northeast.get(x, y, bestDistanceSqr); if (value != null) { closest = value; } } - if (bestChild != this.southeast && this.southeast.bounds.calcDistance(x, y) < bestDistance.value) { - T value = this.southeast.get(x, y, bestDistance); + if (bestChild != this.southeast && this.southeast.bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) { + T value = this.southeast.get(x, y, bestDistanceSqr); if (value != null) { closest = value; } } - if (bestChild != this.southwest && this.southwest.bounds.calcDistance(x, y) < bestDistance.value) { - T value = this.southwest.get(x, y, bestDistance); + if (bestChild != this.southwest && this.southwest.bounds.calcDistanceSqr(x, y) < bestDistanceSqr.value) { + T value = this.southwest.get(x, y, bestDistanceSqr); if (value != null) { closest = value; } } return closest; @@ -728,12 +754,12 @@ public void clear() { T closest = null; if (this.leaves != null) { for (Leaf leaf : this.leaves) { - double distance = Math.sqrt( - (leaf.x - x) * (leaf.x - x) - + (leaf.y - y) * (leaf.y - y)); - if (distance < bestDistance.value) { - bestDistance.value = distance; - closest = leaf.value != null ? leaf.value : leaf.values.get(0); + double deltaX = leaf.x - x; + double deltaY = leaf.y - y; + double distanceSqr = deltaX * deltaX + deltaY * deltaY; + if (distanceSqr < bestDistanceSqr.value) { + bestDistanceSqr.value = distanceSqr; + closest = leaf.value != null ? leaf.value : leaf.values.getFirst(); } } } @@ -751,7 +777,7 @@ public void clear() { if (this.hasChilds) { // note: this could probably be improved. The idea here // is NOT to dive in quadrants which we know do not contain points - // in the ellipse. + // in the ellipse. // This is done, but we will also dive in some quadrants not intersecting // the ellipse, which is just a loss of time (the sum of the minimum distances // to an area is always lower than the munimum of the sum of the distances, @@ -807,29 +833,27 @@ public void clear() { return values; } - /* default */ Collection get(final double x, final double y, final double maxDistance, final Collection values) { + /* default */ Collection get(final double x, final double y, final double maxDistanceSqr, final Collection values) { if (this.hasChilds) { - if (this.northwest.bounds.calcDistance(x, y) <= maxDistance) { - this.northwest.get(x, y, maxDistance, values); + if (this.northwest.bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) { + this.northwest.get(x, y, maxDistanceSqr, values); } - if (this.northeast.bounds.calcDistance(x, y) <= maxDistance) { - this.northeast.get(x, y, maxDistance, values); + if (this.northeast.bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) { + this.northeast.get(x, y, maxDistanceSqr, values); } - if (this.southeast.bounds.calcDistance(x, y) <= maxDistance) { - this.southeast.get(x, y, maxDistance, values); + if (this.southeast.bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) { + this.southeast.get(x, y, maxDistanceSqr, values); } - if (this.southwest.bounds.calcDistance(x, y) <= maxDistance) { - this.southwest.get(x, y, maxDistance, values); + if (this.southwest.bounds.calcDistanceSqr(x, y) <= maxDistanceSqr) { + this.southwest.get(x, y, maxDistanceSqr, values); } return values; } // no more childs, so we must contain the closest object if (this.leaves != null) { for (Leaf leaf : this.leaves) { - double distance = Math.sqrt( - (leaf.x - x) * (leaf.x - x) - + (leaf.y - y) * (leaf.y - y)); - if (distance <= maxDistance) { + double distanceSqr = (leaf.x - x) * (leaf.x - x) + (leaf.y - y) * (leaf.y - y); + if (distanceSqr <= maxDistanceSqr) { if (leaf.value != null) { values.add(leaf.value); } else { @@ -841,22 +865,20 @@ public void clear() { return values; } - /* default */ Collection get(final double x, final double y, final double r_min, final double r_max, - Collection values) { + /* default */ Collection get(final double x, final double y, final double rMinSqr, final double rMaxSqr, + Collection values) { if (this.hasChilds) { - stepInto(this.northwest, x, y, r_min, r_max, values); - stepInto(this.northeast, x, y, r_min, r_max, values); - stepInto(this.southeast, x, y, r_min, r_max, values); - stepInto(this.southwest, x, y, r_min, r_max, values); + stepIntoSqr(this.northwest, x, y, rMinSqr, rMaxSqr, values); + stepIntoSqr(this.northeast, x, y, rMinSqr, rMaxSqr, values); + stepIntoSqr(this.southeast, x, y, rMinSqr, rMaxSqr, values); + stepIntoSqr(this.southwest, x, y, rMinSqr, rMaxSqr, values); return values; } // no more childs, so we must contain the closest object if (this.leaves != null) { for (Leaf leaf : this.leaves) { - double distance = Math.sqrt( - (leaf.x - x) * (leaf.x - x) - + (leaf.y - y) * (leaf.y - y)); - if (distance <= r_max && distance >= r_min) { + double distanceSqr = (leaf.x - x) * (leaf.x - x) + (leaf.y - y) * (leaf.y - y); + if (distanceSqr <= rMaxSqr && distanceSqr >= rMinSqr) { if (leaf.value != null) { values.add(leaf.value); } else { @@ -868,12 +890,12 @@ public void clear() { return values; } - private void stepInto(Node node, double x, double y, double r_min, double r_max, Collection values) { - double minDistance = node.bounds.calcDistance(x, y); - double maxDistance = node.bounds.calcMaxDistance(x, y); + private void stepIntoSqr(Node node, double x, double y, double rMinSqr, double rMaxSqr, Collection values) { + double minDistanceSqr = node.bounds.calcDistanceSqr(x, y); + double maxDistanceSqr = node.bounds.calcMaxDistanceSqr(x, y); - if(minDistance <= r_max && maxDistance >= r_min) { - node.get(x, y, r_min, r_max, values); + if (minDistanceSqr <= rMaxSqr && maxDistanceSqr >= rMinSqr) { + node.get(x, y, rMinSqr, rMaxSqr, values); } } @@ -978,14 +1000,13 @@ private Node getChild(final double x, final double y) { if (leaf == null) { leaf = this.northeast.firstLeaf(); } return leaf; } - return (this.leaves == null || this.leaves.isEmpty()) ? null : this.leaves.get(0); + return (this.leaves == null || this.leaves.isEmpty()) ? null : this.leaves.getFirst(); } /* default */ boolean nextLeaf(final Leaf currentLeaf, final MutableLeaf nextLeaf) { if (this.hasChilds) { - boolean found = false; if (currentLeaf.x <= this.bounds.centerX && currentLeaf.y <= this.bounds.centerY) { - found = this.southwest.nextLeaf(currentLeaf, nextLeaf); + boolean found = this.southwest.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.northwest.firstLeaf(); } if (nextLeaf.value == null) { nextLeaf.value = this.southeast.firstLeaf(); } @@ -994,7 +1015,7 @@ private Node getChild(final double x, final double y) { } } if (currentLeaf.x <= this.bounds.centerX && currentLeaf.y >= this.bounds.centerY) { - found = this.northwest.nextLeaf(currentLeaf, nextLeaf); + boolean found = this.northwest.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.southeast.firstLeaf(); } if (nextLeaf.value == null) { nextLeaf.value = this.northeast.firstLeaf(); } @@ -1002,7 +1023,7 @@ private Node getChild(final double x, final double y) { } } if (currentLeaf.x >= this.bounds.centerX && currentLeaf.y <= this.bounds.centerY) { - found = this.southeast.nextLeaf(currentLeaf, nextLeaf); + boolean found = this.southeast.nextLeaf(currentLeaf, nextLeaf); if (found) { if (nextLeaf.value == null) { nextLeaf.value = this.northeast.firstLeaf(); } return true; diff --git a/matsim/src/test/java/org/matsim/core/utils/collections/QuadTreeTest.java b/matsim/src/test/java/org/matsim/core/utils/collections/QuadTreeTest.java index 61f66e6a0ce..e029ced4705 100644 --- a/matsim/src/test/java/org/matsim/core/utils/collections/QuadTreeTest.java +++ b/matsim/src/test/java/org/matsim/core/utils/collections/QuadTreeTest.java @@ -49,7 +49,7 @@ */ public class QuadTreeTest { - private final static Logger log = LogManager.getLogger(QuadTreeTest.class); + private final static Logger LOG = LogManager.getLogger(QuadTreeTest.class); /** * @return A simple QuadTree with 6 entries for tests. @@ -110,7 +110,7 @@ void testPutOutsideBounds() { Assertions.fail( "no exception when adding an element on the left" ); } catch (IllegalArgumentException e) { - log.info( "catched expected exception" , e ); + LOG.info( "caught expected exception" , e ); } try { @@ -118,7 +118,7 @@ void testPutOutsideBounds() { Assertions.fail( "no exception when adding an element on the right" ); } catch (IllegalArgumentException e) { - log.info( "catched expected exception" , e ); + LOG.info( "caught expected exception" , e ); } try { @@ -126,7 +126,7 @@ void testPutOutsideBounds() { Assertions.fail( "no exception when adding an element above" ); } catch (IllegalArgumentException e) { - log.info( "catched expected exception" , e ); + LOG.info( "caught expected exception" , e ); } try { @@ -134,7 +134,7 @@ void testPutOutsideBounds() { Assertions.fail( "no exception when adding an element below" ); } catch (IllegalArgumentException e) { - log.info( "catched expected exception" , e ); + LOG.info( "caught expected exception" , e ); } } @@ -381,7 +381,7 @@ void testGetRect() { qt.put(400, 900, "node2"); qt.put(700, 300, "node3"); qt.put(900, 400, "node4"); - + Collection values = new ArrayList<>(); qt.getRectangle(new Rect(400, 300, 700, 900), values); Assertions.assertEquals(2, values.size()); @@ -531,7 +531,7 @@ void testValuesIterator_ConcurrentModification() { fail("missing exception."); } catch (ConcurrentModificationException e) { - log.info("catched expected exception: ", e); + LOG.info("caught expected exception: ", e); } } @@ -565,8 +565,6 @@ void testExecute() { /** * Tests that by serializing and de-serializing a QuadTree, all important attributes * of the QuadTree are maintained. At the moment, this is essentially the size-attribute. - * @throws IOException - * @throws ClassNotFoundException */ @Test void testSerialization() throws IOException, ClassNotFoundException { @@ -579,7 +577,7 @@ void testSerialization() throws IOException, ClassNotFoundException { ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray()); ObjectInputStream in = new ObjectInputStream(inStream); - QuadTree qt2 = (QuadTree)in.readObject(); + @SuppressWarnings("unchecked") QuadTree qt2 = (QuadTree)in.readObject(); in.close(); assertEquals(qt.size(), qt2.size()); valuesTester(qt2.size(), qt2.values()); @@ -587,13 +585,10 @@ void testSerialization() throws IOException, ClassNotFoundException { /** * An internal helper method to do the real testing. - * - * @param treeSize - * @param values */ private void valuesTester(final int treeSize, final Collection values) { int counter = 0; - for (String value : values) { + for (String ignored : values) { counter++; } assertEquals(treeSize, counter); @@ -601,11 +596,7 @@ private void valuesTester(final int treeSize, final Collection values) { } /** - * Checks that the given collection contains exactly all of the exptectedEntries, but none more. - * - * @param - * @param expectedEntries - * @param collection + * Checks that the given collection contains exactly all expectedEntries, but none more. */ private void assertContains(final T[] expectedEntries, final Collection collection) { assertEquals(expectedEntries.length, collection.size()); @@ -615,7 +606,7 @@ private void assertContains(final T[] expectedEntries, final Collection c } /** - * An internal class to test the execute()-methods + * An internal class to test the execute-methods * */ static class TestExecutor implements QuadTree.Executor { @@ -634,7 +625,7 @@ public void execute(final double x, final double y, final String object) { */ @Test void testGetRing() { - QuadTree qt = new QuadTree(0, 0, 3, 3); + QuadTree qt = new QuadTree<>(0, 0, 3, 3); for(int x = 0; x < 4; x++) { for(int y = 0; y < 4; y++) { @@ -643,39 +634,39 @@ void testGetRing() { } Collection result = qt.getRing(1, 1, 0, 1); - assertEquals(result.contains("1,1"), true); - assertEquals(result.contains("0,1"), true); - assertEquals(result.contains("1,0"), true); - assertEquals(result.contains("2,1"), true); - assertEquals(result.contains("1,2"), true); + assertTrue(result.contains("1,1")); + assertTrue(result.contains("0,1")); + assertTrue(result.contains("1,0")); + assertTrue(result.contains("2,1")); + assertTrue(result.contains("1,2")); result = qt.getRing(1, 1, 0.5, 1); - assertEquals(result.contains("1,1"), false); - assertEquals(result.contains("0,1"), true); - assertEquals(result.contains("1,0"), true); - assertEquals(result.contains("2,1"), true); - assertEquals(result.contains("1,2"), true); + assertFalse(result.contains("1,1")); + assertTrue(result.contains("0,1")); + assertTrue(result.contains("1,0")); + assertTrue(result.contains("2,1")); + assertTrue(result.contains("1,2")); result = qt.getRing(1, 1, 1.1, 1); - assertEquals(result.size(), 0); + assertEquals(0, result.size()); result = qt.getRing(1, 1, 0, 0); - assertEquals(result.size(), 1); - assertEquals(result.contains("1,1"), true); + assertEquals(1, result.size()); + assertTrue(result.contains("1,1")); result = qt.getRing(-1, 1, 1, 1.4); - assertEquals(result.size(), 1); - assertEquals(result.contains("0,1"), true); + assertEquals(1, result.size()); + assertTrue(result.contains("0,1")); result = qt.getRing(-1, 1, 1, 1.5); - assertEquals(result.size(), 3); - assertEquals(result.contains("0,1"), true); - assertEquals(result.contains("0,0"), true); - assertEquals(result.contains("0,2"), true); - - result = qt.getRing(0, 0, Math.sqrt(18), Math.sqrt(18)); - assertEquals(result.size(), 1); - assertEquals(result.contains("3,3"), true); + assertEquals(3, result.size()); + assertTrue(result.contains("0,1")); + assertTrue(result.contains("0,0")); + assertTrue(result.contains("0,2")); + + result = qt.getRing(0, 0, Math.sqrt(18.0), Math.sqrt(18.000001)); + assertEquals(1, result.size()); + assertTrue(result.contains("3,3")); } /** @@ -753,15 +744,15 @@ private static void measurePerformance() { } long endTimeQuery = System.currentTimeMillis(); - log.info("init time: " + (endTimeInit - startTimeInit) / 1000.0 + " sec."); - log.info("query time: " + (endTimeQuery - startTimeQuery) / 1000.0 + " sec."); - log.info("memory usage: " + (usedMemAfter - usedMemBefore) / 1024 / 1024.0 + " MB"); - log.info("check, ignore: " + countFirstQuadrant); + LOG.info("init time: {} sec.", (endTimeInit - startTimeInit) / 1000.0); + LOG.info("query time: {} sec.", (endTimeQuery - startTimeQuery) / 1000.0); + LOG.info("memory usage: {} MB", (usedMemAfter - usedMemBefore) / 1024 / 1024.0); + LOG.info("check, ignore: {}", countFirstQuadrant); } public static void main(String[] args) { for (int i = 0; i < 5; i++) { - log.info("Round " + i); + LOG.info("Round {}", i); measurePerformance(); } }