Changeset 15959 in josm for trunk/src/org/openstreetmap/josm/gui
- Timestamp:
- 2020-02-29T08:07:39+01:00 (5 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui/mappaint
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java
r15938 r15959 3 3 4 4 import java.awt.geom.Area; 5 import java.util.HashMap;6 5 import java.util.LinkedHashSet; 6 import java.util.List; 7 7 import java.util.Map; 8 8 import java.util.Set; … … 10 10 import org.openstreetmap.josm.data.osm.IPrimitive; 11 11 import org.openstreetmap.josm.data.osm.Relation; 12 import org.openstreetmap.josm.data.osm.Way; 13 import org.openstreetmap.josm.data.osm.WaySegment; 12 14 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; 13 15 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector; … … 72 74 73 75 /** 76 * Crossing ways result from CrossingFinder, filled for incomplete ways/relations 77 */ 78 public Map<IPrimitive, Map<List<Way>, List<WaySegment>>> crossingWaysMap; 79 80 /** 74 81 * Intersection areas (only filled with CrossingFinder if children is not null) 75 82 */ 76 83 public Map<IPrimitive, Area> intersections; 84 85 /** 86 * Cache for multipolygon areas, can be null, used with CrossingFinder 87 */ 88 public Map<IPrimitive, Area> mpAreaCache; 77 89 78 90 /** … … 126 138 this.context = other.getContext(); 127 139 this.children = other.children == null ? null : new LinkedHashSet<>(other.children); 128 this.intersections = other.intersections == null ? null : new HashMap<>(other.intersections); 140 this.intersections = other.intersections; 141 this.crossingWaysMap = other.crossingWaysMap; 142 this.mpAreaCache = other.mpAreaCache; 129 143 } 130 144 … … 294 308 children = null; 295 309 intersections = null; 310 crossingWaysMap = null; 296 311 } 297 312 -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
r15938 r15959 5 5 6 6 import java.awt.geom.Area; 7 import java.awt.geom.Point2D; 7 8 import java.text.MessageFormat; 8 9 import java.util.ArrayList; … … 12 13 import java.util.LinkedHashSet; 13 14 import java.util.List; 15 import java.util.Map; 14 16 import java.util.Objects; 15 17 import java.util.function.IntFunction; … … 26 28 import org.openstreetmap.josm.data.osm.OsmUtils; 27 29 import org.openstreetmap.josm.data.osm.Relation; 30 import org.openstreetmap.josm.data.osm.Way; 31 import org.openstreetmap.josm.data.osm.WaySegment; 28 32 import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor; 29 33 import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache; 34 import org.openstreetmap.josm.data.validation.tests.CrossingWays; 30 35 import org.openstreetmap.josm.gui.mappaint.Environment; 31 36 import org.openstreetmap.josm.gui.mappaint.Range; … … 303 308 private final String layer; 304 309 private Area area; 310 /** Will contain all way segments, grouped by cells */ 311 Map<Point2D, List<WaySegment>> cellSegments; 305 312 306 313 private CrossingFinder(Environment e) { 307 314 super(e); 308 CheckParameterUtil.ensureThat( e.osm instanceof IWay, "Only ways are supported");315 CheckParameterUtil.ensureThat(isArea(e.osm), "Only areas are supported"); 309 316 layer = OsmUtils.getLayer(e.osm); 310 317 } 311 318 312 @Override 313 public void visit(IWay<?> w) { 314 if (Objects.equals(layer, OsmUtils.getLayer(w)) 315 && left.matches(new Environment(w).withParent(e.osm)) 316 && e.osm instanceof IWay) { 317 if (area == null) { 318 area = Geometry.getAreaEastNorth(e.osm); 319 } 320 Pair<PolygonIntersection, Area> is = Geometry.polygonIntersectionResult( 321 Geometry.getAreaEastNorth(w), area, Geometry.INTERSECTION_EPS_EAST_NORTH); 322 if (Geometry.PolygonIntersection.CROSSING == is.a) { 323 addToChildren(e, w); 324 // store intersection area to improve highlight and zoom to problem 325 if (e.intersections == null) { 326 e.intersections = new HashMap<>(); 319 private Area getAreaEastNorth(IPrimitive p, Environment e) { 320 if (e.mpAreaCache != null && p.isMultipolygon()) { 321 Area a = e.mpAreaCache.get(p); 322 if (a == null) { 323 a = Geometry.getAreaEastNorth(p); 324 e.mpAreaCache.put(p, a); 325 } 326 return a; 327 } 328 return Geometry.getAreaEastNorth(p); 329 } 330 331 private Map<List<Way>, List<WaySegment>> findCrossings(IPrimitive area, 332 Map<Point2D, List<WaySegment>> cellSegments) { 333 /** The detected crossing ways */ 334 Map<List<Way>, List<WaySegment>> crossingWays = new HashMap<>(50); 335 if (area instanceof Way) { 336 CrossingWays.findIntersectingWay((Way) area, cellSegments, crossingWays, false); 337 } else if (area instanceof Relation && area.isMultipolygon()) { 338 Relation r = (Relation) area; 339 for (Way w : r.getMemberPrimitives(Way.class)) { 340 if (!w.hasIncompleteNodes()) { 341 CrossingWays.findIntersectingWay(w, cellSegments, crossingWays, false); 327 342 } 328 e.intersections.put(w, is.b); 343 } 344 } 345 return crossingWays; 346 } 347 348 @Override 349 public void visit(Collection<? extends IPrimitive> primitives) { 350 List<? extends IPrimitive> toIgnore; 351 if (e.osm instanceof Relation) { 352 toIgnore = ((IRelation<?>) e.osm).getMemberPrimitivesList(); 353 } else { 354 toIgnore = null; 355 } 356 357 for (IPrimitive p : primitives) { 358 if (isPrimitiveUsable(p) && Objects.equals(layer, OsmUtils.getLayer(p)) 359 && left.matches(new Environment(p).withParent(e.osm)) && isArea(p) 360 && (toIgnore == null || !toIgnore.contains(p))) { 361 if (area == null) { 362 area = getAreaEastNorth(e.osm, e); 363 } 364 Area otherArea = getAreaEastNorth(p, e); 365 if (area.isEmpty() || otherArea.isEmpty()) { 366 if (cellSegments == null) { 367 // lazy initialisation 368 cellSegments = new HashMap<>(); 369 findCrossings(e.osm, cellSegments); // ignore self intersections etc. here 370 } 371 // need a copy 372 final Map<Point2D, List<WaySegment>> tmpCellSegments = new HashMap<>(cellSegments); 373 // calculate all crossings between e.osm and p 374 Map<List<Way>, List<WaySegment>> crossingWays = findCrossings(p, tmpCellSegments); 375 if (!crossingWays.isEmpty()) { 376 addToChildren(e, p); 377 if (e.crossingWaysMap == null) { 378 e.crossingWaysMap = new HashMap<>(); 379 } 380 e.crossingWaysMap.put(p, crossingWays); 381 } 382 } else { 383 // we have complete data. This allows to find intersections with shared nodes 384 // See #16707 385 Pair<PolygonIntersection, Area> is = Geometry.polygonIntersectionResult( 386 otherArea, area, Geometry.INTERSECTION_EPS_EAST_NORTH); 387 if (Geometry.PolygonIntersection.CROSSING == is.a) { 388 addToChildren(e, p); 389 // store intersection area to improve highlight and zoom to problem 390 if (e.intersections == null) { 391 e.intersections = new HashMap<>(); 392 } 393 e.intersections.put(p, is.b); 394 } 395 } 329 396 } 330 397 } … … 453 520 return ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type ? e.children != null : e.children == null; 454 521 455 } else if (ChildOrParentSelectorType.CROSSING == type && e.osm instanceof IWay) {522 } else if (ChildOrParentSelectorType.CROSSING == type) { 456 523 e.parent = e.osm; 457 if (right instanceof OptimizedGeneralSelector 458 && e.osm.getDataSet() != null 459 && ((OptimizedGeneralSelector) right).matchesBase(OsmPrimitiveType.WAY)) { 524 if (e.osm.getDataSet() != null && isArea(e.osm)) { 460 525 final CrossingFinder crossingFinder = new CrossingFinder(e); 461 crossingFinder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox())); 526 visitBBox(e, crossingFinder); 527 return e.children != null; 462 528 } 463 529 return e.children != null;
Note:
See TracChangeset
for help on using the changeset viewer.