| | 263 | /** |
| | 264 | * Check two areas for intersection, if found, find elements to highlight |
| | 265 | * @param a1 1st area |
| | 266 | * @param a2 2nd area |
| | 267 | * @param p2 primitive that is or contains area a2 |
| | 268 | * @param nodes1 List of nodes used to calculate 1st area |
| | 269 | * @param nodes2 List of nodes used to calculate 2nd area |
| | 270 | */ |
| | 271 | void checkIntersection (Area a1, Area a2, OsmPrimitive p2, List<Node> nodes1, List<Node> nodes2 ) { |
| | 272 | if (!a1.getBounds2D().intersects(a2.getBounds2D())) |
| | 273 | return; |
| | 274 | Area inter = new Area (a1); |
| | 275 | inter.intersect(a2); |
| | 276 | Rectangle bounds = inter.getBounds(); |
| | 277 | PolygonIntersection is; |
| | 278 | if (inter.isEmpty() || bounds.getHeight()*bounds.getWidth() <= 1.0) { |
| | 279 | is = PolygonIntersection.OUTSIDE; |
| | 280 | } else if (a2.getBounds2D().contains(a1.getBounds2D()) && inter.equals(a1)) { |
| | 281 | is = PolygonIntersection.FIRST_INSIDE_SECOND; |
| | 282 | } else if (a1.getBounds2D().contains(a2.getBounds2D()) && inter.equals(a2)) { |
| | 283 | is = PolygonIntersection.SECOND_INSIDE_FIRST; |
| | 284 | } else { |
| | 285 | is = PolygonIntersection.CROSSING; |
| | 286 | } |
| | 287 | |
| | 288 | if (is == PolygonIntersection.CROSSING) { |
| | 289 | e.child = p2; |
| | 290 | // either one area is contained in the other or they are crossing |
| | 291 | if (e.parent.isMultipolygon() || p2.isMultipolygon() || (nodes1.size() > 10 && nodes2.size() > 10)) { |
| | 292 | // calculate bounding box of intersection plus 0.1 m to catch nodes for better highlighting |
| | 293 | EastNorth en1 = new EastNorth(bounds.getMinX(), bounds.getMinY()); |
| | 294 | EastNorth en2 = new EastNorth(bounds.getMaxX(), bounds.getMaxY()); |
| | 295 | LatLon ll1 = Main.getProjection().getBaseProjection().eastNorth2latlon(en1); |
| | 296 | LatLon ll2 = Main.getProjection().getBaseProjection().eastNorth2latlon(en2); |
| | 297 | double inc = 0.1 * (360.0d / (Ellipsoid.WGS84.a * 2 * Math.PI)); |
| | 298 | BBox searchBox = new BBox (ll1.getX() - inc, ll1.getY() - inc ,ll2.getX() + inc, ll2.getY() + inc); |
| | 299 | List<Node> nearNodes = e.osm.getDataSet().searchNodes(searchBox); |
| | 300 | HashSet<Node> nodes = new HashSet<>(); |
| | 301 | nodes.addAll(nodes1); |
| | 302 | nodes.addAll(nodes2); |
| | 303 | nearNodes.retainAll(nodes); |
| | 304 | e.hilite = new ArrayList<>(nearNodes); |
| | 305 | if (p2.isMultipolygon() || e.parent.isMultipolygon()) { |
| | 306 | // try to find ways which are involved |
| | 307 | List<Way> nearWays = e.osm.getDataSet().searchWays(new BBox(ll1.getX(), ll1.getY(), ll2.getX(), ll2.getY())); |
| | 308 | for (Way w1 : nearWays) { |
| | 309 | if (w1.getNodesCount() > 100) |
| | 310 | continue; |
| | 311 | for (OsmPrimitive ref : w1.getReferrers()) { |
| | 312 | if (ref == p2 || ref == e.parent) |
| | 313 | e.hilite.add(w1); |
| | 314 | } |
| | 315 | } |
| | 316 | } |
| | 317 | } |
| | 318 | } |
| | 319 | |
| | 320 | } |
| 252 | | if (e.osm instanceof Way && Geometry.PolygonIntersection.CROSSING.equals( |
| 253 | | Geometry.polygonIntersection(w.getNodes(), ((Way) e.osm).getNodes()))) { |
| 254 | | e.child = w; |
| | 324 | // check way-way intersection |
| | 325 | Area a = Geometry.getArea(w.getNodes()); |
| | 326 | Area b = Geometry.getArea(((Way) e.osm).getNodes()); |
| | 327 | checkIntersection(a, b, w, w.getNodes(), ((Way) e.osm).getNodes()); |
| | 328 | return; |
| | 329 | } |
| | 330 | if (e.parent.isMultipolygon()) { |
| | 331 | // check mp-way intersection |
| | 332 | if (e.child == null && left.matches(new Environment(w).withParent(e.parent))) { |
| | 333 | if (checkedPrimitives.contains(w)) |
| | 334 | return; |
| | 335 | checkedPrimitives.add(w); |
| | 336 | for (OsmPrimitive p : w.getReferrers()) { |
| | 337 | if (p == e.parent) |
| | 338 | return; |
| | 339 | } |
| | 340 | Multipolygon polygon = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) e.parent); |
| | 341 | if (polygon == null) |
| | 342 | return; |
| | 343 | Area a1 = Geometry.getArea(w.getNodes()); |
| | 344 | for (PolyData pd : polygon.getCombinedPolygons()) { |
| | 345 | Area a2 = new Area(pd.get()); |
| | 346 | checkIntersection(a1, a2, w, w.getNodes(), pd.getNodes()); |
| | 347 | if (e.child != null) |
| | 348 | return; |
| | 349 | } |
| | 351 | if (e.child == null) { |
| | 352 | // is way member of a matching mp relation ? |
| | 353 | for (OsmPrimitive otherParent : w.getReferrers()) { |
| | 354 | if (otherParent.isMultipolygon() && !otherParent.isIncomplete() && e.parent != otherParent) { |
| | 355 | if (left.matches(new Environment(otherParent).withParent(otherParent))) { |
| | 356 | if (checkedPrimitives.contains(otherParent)) |
| | 357 | return; |
| | 358 | checkedPrimitives.add(otherParent); |
| | 359 | if (((Relation) otherParent).hasIncompleteMembers() ) |
| | 360 | return; |
| | 361 | // okay, we have two different complete multipolygons, check if they are overlapping |
| | 362 | Multipolygon p1 = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) e.parent); |
| | 363 | if (p1 == null) |
| | 364 | return; |
| | 365 | Multipolygon p2 = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) otherParent); |
| | 366 | if (p2 == null) |
| | 367 | return; |
| | 368 | for (PolyData pd1 : p1.getCombinedPolygons()) { |
| | 369 | Area a1 = new Area(pd1.get()); |
| | 370 | for (PolyData pd2 : p2.getCombinedPolygons()) { |
| | 371 | Area a2 = new Area(pd2.get()); |
| | 372 | checkIntersection(a1, a2, otherParent, pd1.getNodes(), pd2.getNodes()); |
| | 373 | if (e.child != null) |
| | 374 | return; |
| | 375 | } |
| | 376 | } |
| | 377 | } |
| | 378 | } |
| | 379 | } |
| | 380 | } |
| | 381 | // } else { |
| | 382 | // for (OsmPrimitive otherParent : w.getReferrers()) { |
| | 383 | // if (otherParent.isMultipolygon() && ((Relation) otherParent).hasIncompleteMembers() == false) { |
| | 384 | // if (left.matches(new Environment(otherParent).withParent(otherParent))) { |
| | 385 | // checkedPrimitives.add(otherParent); |
| | 386 | // if (e.parent == otherParent || ((Relation) otherParent).hasIncompleteMembers() ) |
| | 387 | // return; |
| | 388 | // // we have a matching way that might cross a multipolygon, check if they are overlapping |
| | 389 | // Area a1 = Geometry.getArea(((Way) e.osm).getNodes()); |
| | 390 | // |
| | 391 | // Multipolygon p2 = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) otherParent); |
| | 392 | // if (p2 == null) |
| | 393 | // return; |
| | 394 | // for (PolyData pd2 : p2.getCombinedPolygons()) { |
| | 395 | // Area a2 = new Area(pd2.get()); |
| | 396 | // checkIntersection(a1, a2, otherParent, ((Way) e.osm).getNodes(), pd2.getNodes()); |
| | 397 | // if (e.child != null) |
| | 398 | // return; |
| | 399 | // } |
| | 400 | // } |
| | 401 | // } |
| | 402 | // } |
| | 498 | } else if (ChildOrParentSelectorType.CROSSING.equals(type) && e.osm.isMultipolygon()) { |
| | 499 | Relation r = (Relation) e.osm; |
| | 500 | if (r.hasIncompleteMembers()) |
| | 501 | return false; |
| | 502 | List<RelationMember> members = r.getMembers(); |
| | 503 | for (int i = 0; i < members.size(); i++) { |
| | 504 | OsmPrimitive member = members.get(i).getMember(); |
| | 505 | if (member instanceof Way) { |
| | 506 | Environment ew = new Environment(member); |
| | 507 | ew.parent = e.osm; |
| | 508 | final CrossingFinder crossingFinder = new CrossingFinder(ew); |
| | 509 | if (right instanceof OptimizedGeneralSelector |
| | 510 | && ((OptimizedGeneralSelector) right).matchesBase(OsmPrimitiveType.WAY)) { |
| | 511 | List<Way> nearWays = ew.osm.getDataSet().searchWays(ew.osm.getBBox()); |
| | 512 | crossingFinder.visit(nearWays); |
| | 513 | if (ew.child != null) { |
| | 514 | e.child = ew.child; |
| | 515 | e.hilite = ew.hilite; |
| | 516 | return true; |
| | 517 | } |
| | 518 | } |
| | 519 | } |
| | 520 | } |
| | 521 | return e.child != null; |