- Timestamp:
- 2014-01-03T11:12:16+01:00 (11 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/validation/tests/BuildingInBuilding.java
r6494 r6607 73 73 } 74 74 75 protected class MultiPolygonMembers {76 private final Set<Way> outers = new HashSet<Way>();77 private final Set<Way> inners = new HashSet<Way>();78 public MultiPolygonMembers(Relation multiPolygon) {79 for (RelationMember m : multiPolygon.getMembers()) {80 if (m.getType().equals(OsmPrimitiveType.WAY)) {81 if (m.getRole().equals("outer")) {82 outers.add(m.getWay());83 } else if (m.getRole().equals("inner")) {84 inners.add(m.getWay());85 }86 }87 }88 }89 }90 91 75 protected boolean sameLayers(Way w1, Way w2) { 92 76 String l1 = w1.get("layer") != null ? w1.get("layer") : "0"; 93 77 String l2 = w2.get("layer") != null ? w2.get("layer") : "0"; 94 78 return l1.equals(l2); 95 }96 97 protected boolean isWayInsideMultiPolygon(Way object, Relation multiPolygon) {98 // Extract outer/inner members from multipolygon99 MultiPolygonMembers mpm = new MultiPolygonMembers(multiPolygon);100 // Test if object is inside an outer member101 for (Way out : mpm.outers) {102 PolygonIntersection inter = Geometry.polygonIntersection(object.getNodes(), out.getNodes());103 if (inter == PolygonIntersection.FIRST_INSIDE_SECOND || inter == PolygonIntersection.CROSSING) {104 boolean insideInner = false;105 // If inside an outer, check it is not inside an inner106 for (Way in : mpm.inners) {107 if (Geometry.polygonIntersection(in.getNodes(), out.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND &&108 Geometry.polygonIntersection(object.getNodes(), in.getNodes()) == PolygonIntersection.FIRST_INSIDE_SECOND) {109 insideInner = true;110 break;111 }112 }113 // Inside outer but not inside inner -> the building appears to be inside a buiding114 if (!insideInner) {115 // Final check on "layer" tag. Buildings of different layers may be superposed116 if (sameLayers(object, out)) {117 return true;118 }119 }120 }121 }122 return false;123 79 } 124 80 … … 132 88 } 133 89 134 protected boolean evaluateWay( Way w, Way object) {90 protected boolean evaluateWay(final Way w, Way object) { 135 91 if (w.equals(object)) return false; 136 92 … … 151 107 // Else, test if w is inside one of the multipolygons 152 108 for (OsmPrimitive bmp : buildingMultiPolygons) { 153 if (bmp instanceof Relation && isWayInsideMultiPolygon(w, (Relation) bmp)) { 109 if (bmp instanceof Relation && Geometry.isPolygonInsideMultiPolygon(w.getNodes(), (Relation) bmp, new Predicate<Way>() { 110 @Override 111 public boolean evaluate(Way outer) { 112 return sameLayers(w, outer); 113 } 114 })) { 154 115 return true; 155 116 } … … 160 121 161 122 protected boolean evaluateRelation(Relation r, Way object) { 162 MultiPolygonMembers mpm = newMultiPolygonMembers((Relation) p);123 Geometry.MultiPolygonMembers mpm = new Geometry.MultiPolygonMembers((Relation) p); 163 124 for (Way out : mpm.outers) { 164 125 if (evaluateWay(out, object)) { -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
r6561 r6607 80 80 | < CARET: "^" > 81 81 | < FULLSTOP: "." > 82 | < CONTAINS: "∋" > 82 83 | < COMMENT_START: "/*" > : COMMENT 83 84 | < UNEXPECTED_CHAR : ~[] > // avoid TokenMgrErrors because they are hard to recover from … … 262 263 Selector child_selector() : 263 264 { 264 boolean parentSelector = false;265 Selector.ChildOrParentSelectorType type = null; 265 266 Condition c; 266 267 List<Condition> conditions = new ArrayList<Condition>(); … … 272 273 selLeft=selector() w() 273 274 ( 274 ( <GREATER> { parentSelector = false; } | <LESS> { parentSelector = true; } ) 275 ( ( c=condition(Context.LINK) | c=class_or_pseudoclass(Context.LINK) ) { conditions.add(c); } )* 275 ( 276 ( <GREATER> { type = Selector.ChildOrParentSelectorType.CHILD; } | <LESS> { type = Selector.ChildOrParentSelectorType.PARENT; } ) 277 ( ( c=condition(Context.LINK) | c=class_or_pseudoclass(Context.LINK) ) { conditions.add(c); } )* 278 | 279 <CONTAINS> { type = Selector.ChildOrParentSelectorType.CONTAINS; } 280 ) 276 281 { selLink = new LinkSelector(conditions); } 277 282 w() 278 283 selRight=selector() w() 279 284 )? 280 { return selRight != null ? new ChildOrParentSelector(selLeft, selLink, selRight, parentSelector) : selLeft; }285 { return selRight != null ? new ChildOrParentSelector(selLeft, selLink, selRight, type) : selLeft; } 281 286 } 282 287 -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
r6561 r6607 15 15 import org.openstreetmap.josm.gui.mappaint.Environment; 16 16 import org.openstreetmap.josm.gui.mappaint.Range; 17 import org.openstreetmap.josm.tools.Geometry; 17 18 import org.openstreetmap.josm.tools.Pair; 18 19 import org.openstreetmap.josm.tools.Utils; … … 33 34 34 35 public Range getRange(); 36 37 public static enum ChildOrParentSelectorType { 38 CHILD, PARENT, CONTAINS 39 } 35 40 36 41 /** … … 54 59 /** true, if this represents a parent selector (otherwise it is a child selector) 55 60 */ 56 private final boolean parentSelector;61 private final ChildOrParentSelectorType type; 57 62 58 63 /** … … 60 65 * @param a the first selector 61 66 * @param b the second selector 62 * @param parentSelector if true, this is a parent selector; otherwise a child selector67 * @param type the selector type 63 68 */ 64 public ChildOrParentSelector(Selector a, LinkSelector link, Selector b, boolean parentSelector) {69 public ChildOrParentSelector(Selector a, LinkSelector link, Selector b, ChildOrParentSelectorType type) { 65 70 this.left = a; 66 71 this.link = link; 67 72 this.right = b; 68 this. parentSelector = parentSelector;73 this.type = type; 69 74 } 70 75 … … 142 147 } 143 148 149 private class ContainsFinder extends AbstractVisitor { 150 private final Environment e; 151 private final List<Node> nodes; 152 153 private ContainsFinder(Environment e) { 154 this.e = e; 155 if (e.osm instanceof Node) { 156 nodes = Collections.singletonList((Node) e.osm); 157 } else if (e.osm instanceof Way) { 158 nodes = ((Way) e.osm).getNodes(); 159 } else { 160 throw new IllegalArgumentException("Relations not supported"); 161 } 162 } 163 164 @Override 165 public void visit(Node n) { 166 } 167 168 @Override 169 public void visit(Way w) { 170 if (e.parent == null && left.matches(e.withPrimitive(w))) { 171 if (nodes.size() == 1 172 ? Geometry.nodeInsidePolygon(nodes.get(0), w.getNodes()) 173 : Geometry.PolygonIntersection.FIRST_INSIDE_SECOND.equals(Geometry.polygonIntersection(nodes, w.getNodes()))) { 174 e.parent = w; 175 e.index = 0; 176 } 177 } 178 } 179 180 @Override 181 public void visit(Relation r) { 182 if (e.parent == null && left.matches(e.withPrimitive(r))) { 183 if (r.isMultipolygon() && Geometry.isPolygonInsideMultiPolygon(nodes, r, null)) { 184 e.parent = r; 185 e.index = 0; 186 } 187 } 188 } 189 } 190 144 191 @Override 145 192 public boolean matches(Environment e) { … … 147 194 return false; 148 195 149 if (!parentSelector) { 196 if (ChildOrParentSelectorType.CONTAINS.equals(type)) { 197 final OsmPrimitive rightPrimitive = e.osm; 198 final ContainsFinder containsFinder = new ContainsFinder(e); 199 for (final OsmPrimitive p : rightPrimitive.getDataSet().allPrimitives()) { 200 if (rightPrimitive.equals(p)) { 201 continue; 202 } 203 p.accept(containsFinder); 204 if (e.parent != null) { 205 e.osm = rightPrimitive; 206 return true; 207 } 208 } 209 } else if (ChildOrParentSelectorType.CHILD.equals(type)) { 150 210 MatchingReferrerFinder collector = new MatchingReferrerFinder(e); 151 211 e.osm.visitReferrers(collector); … … 195 255 @Override 196 256 public String toString() { 197 return left + " "+ (parentSelector? "<" : ">")+link+" " +right;257 return left + " " + (ChildOrParentSelectorType.PARENT.equals(type) ? "<" : ">") + link + " " + right; 198 258 } 199 259 } -
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.