Changeset 6607 in josm for trunk/src/org/openstreetmap/josm/tools
- Timestamp:
- 2014-01-03T11:12:16+01:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/tools/Geometry.java
r6566 r6607 9 9 import java.math.MathContext; 10 10 import java.util.ArrayList; 11 import java.util.Collections; 11 12 import java.util.Comparator; 13 import java.util.EnumSet; 14 import java.util.HashSet; 12 15 import java.util.LinkedHashSet; 13 16 import java.util.List; … … 23 26 import org.openstreetmap.josm.data.osm.Node; 24 27 import org.openstreetmap.josm.data.osm.NodePositionComparator; 28 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 29 import org.openstreetmap.josm.data.osm.Relation; 30 import org.openstreetmap.josm.data.osm.RelationMember; 25 31 import org.openstreetmap.josm.data.osm.Way; 26 32 … … 736 742 } 737 743 } 744 745 public static class MultiPolygonMembers { 746 public final Set<Way> outers = new HashSet<Way>(); 747 public final Set<Way> inners = new HashSet<Way>(); 748 749 public MultiPolygonMembers(Relation multiPolygon) { 750 for (RelationMember m : multiPolygon.getMembers()) { 751 if (m.getType().equals(OsmPrimitiveType.WAY)) { 752 if (m.getRole().equals("outer")) { 753 outers.add(m.getWay()); 754 } else if (m.getRole().equals("inner")) { 755 inners.add(m.getWay()); 756 } 757 } 758 } 759 } 760 } 761 762 /** 763 * Tests if the {@code node} is inside the multipolygon {@code multiPolygon}. The nullable argument 764 * {@code isOuterWayAMatch} allows to decide if the immediate {@code outer} way of the multipolygon is a match. 765 */ 766 public static boolean isNodeInsideMultiPolygon(Node node, Relation multiPolygon, Predicate<Way> isOuterWayAMatch) { 767 return isPolygonInsideMultiPolygon(Collections.singletonList(node), multiPolygon, isOuterWayAMatch); 768 } 769 770 /** 771 * Tests if the polygon formed by {@code nodes} is inside the multipolygon {@code multiPolygon}. The nullable argument 772 * {@code isOuterWayAMatch} allows to decide if the immediate {@code outer} way of the multipolygon is a match. 773 * <p/> 774 * If {@code nodes} contains exactly one element, then it is checked whether that one node is inside the multipolygon. 775 */ 776 public static boolean isPolygonInsideMultiPolygon(List<Node> nodes, Relation multiPolygon, Predicate<Way> isOuterWayAMatch) { 777 // Extract outer/inner members from multipolygon 778 MultiPolygonMembers mpm = new MultiPolygonMembers(multiPolygon); 779 // Test if object is inside an outer member 780 for (Way out : mpm.outers) { 781 if (nodes.size() == 1 782 ? nodeInsidePolygon(nodes.get(0), out.getNodes()) 783 : EnumSet.of(PolygonIntersection.FIRST_INSIDE_SECOND, PolygonIntersection.CROSSING).contains(polygonIntersection(nodes, out.getNodes()))) { 784 boolean insideInner = false; 785 // If inside an outer, check it is not inside an inner 786 for (Way in : mpm.inners) { 787 if (polygonIntersection(in.getNodes(), out.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND 788 && (nodes.size() == 1 789 ? nodeInsidePolygon(nodes.get(0), in.getNodes()) 790 : polygonIntersection(nodes, in.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND)) { 791 insideInner = true; 792 break; 793 } 794 } 795 // Inside outer but not inside inner -> the polygon appears to be inside a the multipolygon 796 if (!insideInner) { 797 // Final check using predicate 798 if (isOuterWayAMatch == null || isOuterWayAMatch.evaluate(out)) { 799 return true; 800 } 801 } 802 } 803 } 804 return false; 805 } 738 806 }
Note:
See TracChangeset
for help on using the changeset viewer.