Ticket #17614: 17614-v2a.patch
File 17614-v2a.patch, 10.5 KB (added by , 6 years ago) |
---|
-
src/org/openstreetmap/josm/data/osm/WaySegment.java
12 12 /** 13 13 * The way. 14 14 */ 15 public Way way;15 public final Way way; 16 16 17 17 /** 18 18 * The index of one of the 2 nodes in the way. The other node has the 19 19 * index <code>lowerIndex + 1</code>. 20 20 */ 21 public int lowerIndex;21 public final int lowerIndex; 22 22 23 23 /** 24 24 * Constructs a new {@code WaySegment}. -
src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java
471 471 // the two polygons may only share one or more segments but they may also intersect 472 472 Area a1 = new Area(pd1.get()); 473 473 Area a2 = new Area(pd2.get()); 474 PolygonIntersection areaRes = Geometry.polygonIntersection(a1, a2 , 1e-6);474 PolygonIntersection areaRes = Geometry.polygonIntersection(a1, a2); 475 475 if (areaRes == PolygonIntersection.OUTSIDE) 476 476 return ExtPolygonIntersection.OUTSIDE; 477 477 return ExtPolygonIntersection.CROSSING; -
src/org/openstreetmap/josm/tools/Geometry.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.tools; 3 3 4 import java.awt.Rectangle;5 4 import java.awt.geom.Area; 6 5 import java.awt.geom.Line2D; 7 6 import java.awt.geom.Path2D; 7 import java.awt.geom.PathIterator; 8 import java.awt.geom.Rectangle2D; 8 9 import java.math.BigDecimal; 9 10 import java.math.MathContext; 10 11 import java.util.ArrayList; … … 71 72 CROSSING 72 73 } 73 74 75 /** threshold value for size of intersection area given in east/north space */ 76 public static final double INTERSECTION_EPS_EAST_NORTH = 0.01; 77 74 78 /** 75 79 * Will find all intersection and add nodes there for list of given ways. 76 80 * Handles self-intersections too. … … 577 581 public static PolygonIntersection polygonIntersection(List<? extends INode> first, List<? extends INode> second) { 578 582 Area a1 = getArea(first); 579 583 Area a2 = getArea(second); 580 return polygonIntersection(a1, a2 );584 return polygonIntersection(a1, a2, INTERSECTION_EPS_EAST_NORTH); 581 585 } 582 586 583 587 /** 584 * Tests if two polygons intersect. 588 * Tests if two polygons intersect. It is assumed that the area is given in East North points. 585 589 * @param a1 Area of first polygon 586 590 * @param a2 Area of second polygon 587 591 * @return intersection kind … … 588 592 * @since 6841 589 593 */ 590 594 public static PolygonIntersection polygonIntersection(Area a1, Area a2) { 591 return polygonIntersection(a1, a2, 1.0);595 return polygonIntersection(a1, a2, INTERSECTION_EPS_EAST_NORTH); 592 596 } 593 597 594 598 /** … … 603 607 Area inter = new Area(a1); 604 608 inter.intersect(a2); 605 609 606 Rectangle bounds = inter.getBounds(); 607 608 if (inter.isEmpty() || bounds.getHeight()*bounds.getWidth() <= eps) { 610 if (inter.isEmpty() || !checkIntersection(inter, eps)) { 609 611 return PolygonIntersection.OUTSIDE; 610 612 } else if (a2.getBounds2D().contains(a1.getBounds2D()) && inter.equals(a1)) { 611 613 return PolygonIntersection.FIRST_INSIDE_SECOND; … … 617 619 } 618 620 619 621 /** 622 * Check an intersection area which might describe multiple small polygons. 623 * Return true if any of the polygons is bigger than the given threshold. 624 * @param inter the intersection area 625 * @param eps an area threshold, everything below is considered an empty intersection 626 * @return true if any of the polygons is bigger than the given threshold. 627 */ 628 private static boolean checkIntersection(Area inter, double eps) { 629 PathIterator pit = inter.getPathIterator(null); 630 double[] res = new double[6]; 631 Rectangle2D r = new Rectangle2D.Double(); 632 while (!pit.isDone()) { 633 int type = pit.currentSegment(res); 634 switch (type) { 635 case PathIterator.SEG_MOVETO: 636 r = new Rectangle2D.Double(res[0], res[1], 0, 0); 637 break; 638 case PathIterator.SEG_LINETO: 639 r.add(res[0], res[1]); 640 break; 641 case PathIterator.SEG_CLOSE: 642 if (r.getWidth() > eps || r.getHeight() > eps) 643 return true; 644 break; 645 default: 646 break; 647 } 648 pit.next(); 649 } 650 return false; 651 } 652 653 /** 620 654 * Tests if point is inside a polygon. The polygon can be self-intersecting. In such case the contains function works in xor-like manner. 621 655 * @param polygonNodes list of nodes from polygon path. 622 656 * @param point the point to test … … 777 811 * Returns angle of a corner defined with 3 point coordinates. 778 812 * 779 813 * @param p1 first point 780 * @param p2 Common endpoint814 * @param common Common end point 781 815 * @param p3 third point 782 816 * @return Angle in radians (-pi, pi] 783 817 */ 784 public static double getCornerAngle(EastNorth p1, EastNorth p2, EastNorth p3) {818 public static double getCornerAngle(EastNorth p1, EastNorth common, EastNorth p3) { 785 819 786 820 CheckParameterUtil.ensure(p1, "p1", EastNorth::isValid); 787 CheckParameterUtil.ensure( p2, "p2", EastNorth::isValid);821 CheckParameterUtil.ensure(common, "p2", EastNorth::isValid); 788 822 CheckParameterUtil.ensure(p3, "p3", EastNorth::isValid); 789 823 790 Double result = getSegmentAngle(p2, p1) - getSegmentAngle(p2, p3);824 double result = getSegmentAngle(common, p1) - getSegmentAngle(common, p3); 791 825 if (result <= -Math.PI) { 792 826 result += 2 * Math.PI; 793 827 } -
test/unit/org/openstreetmap/josm/tools/GeometryTest.java
2 2 package org.openstreetmap.josm.tools; 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertNotEquals; 5 6 6 7 import java.io.FileInputStream; 7 8 import java.util.Arrays; … … 158 159 assertEquals(new EastNorth(125, 300), Geometry.getCentroidEN(Arrays.asList(en1, en2))); 159 160 assertEquals(new EastNorth(150, 266d + 2d/3d), Geometry.getCentroidEN(Arrays.asList(en1, en2, en3))); 160 161 } 162 163 164 /** 165 * Test of {@link Geometry#polygonIntersection} method with two triangles. 166 */ 167 @Test 168 public void testPolygonIntersectionTriangles() { 169 Node node1 = new Node(new LatLon(0.0, 1.0)); 170 Node node2 = new Node(new LatLon(0.0, 2.0)); 171 Node node3 = new Node(new LatLon(5.0, 1.5)); 172 List<Node> poly1 = Arrays.asList(node1, node2, node3, node1); 173 Node node4 = new Node(new LatLon(10.0, 1.0)); 174 Node node5 = new Node(new LatLon(10.0, 2.0)); 175 Node node6 = new Node(new LatLon(5.000001, 1.5)); 176 List<Node> poly2 = Arrays.asList(node4, node5, node6, node4); 177 // no intersection, not even touching 178 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 179 node5.setCoor(new LatLon(5.0, 1.5)); 180 // touching in a single point with two different nodes 181 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 182 node5.setCoor(new LatLon(4.99999999, 1.5)); 183 // now node5 lies inside way1, intersection is a very small area, in OSM precision nodes are equal 184 assertEquals(node5.getCoor().getRoundedToOsmPrecision(), node3.getCoor().getRoundedToOsmPrecision()); 185 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 186 node5.setCoor(new LatLon(4.9999999, 1.5)); 187 // intersection area is too big to ignore 188 assertNotEquals(node5.getCoor().getRoundedToOsmPrecision(), node3.getCoor().getRoundedToOsmPrecision()); 189 assertEquals(Geometry.PolygonIntersection.CROSSING, Geometry.polygonIntersection(poly1, poly2)); 190 } 191 192 /** 193 * Test of {@link Geometry#polygonIntersection} method with two V-shapes 194 */ 195 @Test 196 public void testPolygonIntersectionVShapes() { 197 Node node1 = new Node(new LatLon(1.0, 1.0)); 198 Node node2 = new Node(new LatLon(2.0, 2.0)); 199 Node node3 = new Node(new LatLon(0.9, 1.0)); 200 Node node4 = new Node(new LatLon(2.0, 0.0)); 201 List<Node> poly1 = Arrays.asList(node1, node2, node3, node4, node1); 202 Node node5 = new Node(new LatLon(3.0, 1.0)); 203 Node node6 = new Node(new LatLon(2.0, 2.0)); // like node2 204 Node node7 = new Node(new LatLon(3.1, 1.0)); 205 Node node8 = new Node(new LatLon(2.0, 0.0)); // like node4 206 List<Node> poly2 = Arrays.asList(node5, node6, node7, node8, node5); 207 208 // touching in two points but not overlapping 209 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 210 211 // touching in one point, small overlap at the other 212 node6.setCoor(new LatLon(1.9999999, 2.0)); 213 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 214 215 // touching in one point, small overlap at the other 216 node6.setCoor(new LatLon(1.999999, 2.0)); 217 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 218 219 // touching in one point, too large overlap at the other 220 node6.setCoor(new LatLon(1.99999, 2.0)); 221 assertEquals(Geometry.PolygonIntersection.CROSSING, Geometry.polygonIntersection(poly1, poly2)); 222 223 // two small overlaps, but clearly visible because lines are crossing 224 node6.setCoor(new LatLon(1.999999, 2.0)); 225 node8.setCoor(new LatLon(1.999999, 0.0)); 226 assertEquals(Geometry.PolygonIntersection.OUTSIDE, Geometry.polygonIntersection(poly1, poly2)); 227 } 161 228 }