| 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; |