Ticket #17914: 17914.patch
File 17914.patch, 6.8 KB (added by , 5 years ago) |
---|
-
src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
13 13 import java.util.HashMap; 14 14 import java.util.HashSet; 15 15 import java.util.Iterator; 16 import java.util.LinkedHashSet; 16 17 import java.util.List; 17 18 import java.util.Map; 18 19 import java.util.Map.Entry; 19 20 import java.util.Objects; 20 21 import java.util.Set; 22 import java.util.stream.Collectors; 21 23 22 24 import org.openstreetmap.josm.data.coor.EastNorth; 23 25 import org.openstreetmap.josm.data.coor.LatLon; … … 53 55 private final int code; 54 56 private final boolean isHighwayTest; 55 57 58 static final double DETOUR_FACTOR = 4; 59 56 60 protected abstract boolean isCandidate(OsmPrimitive p); 57 61 58 62 protected boolean isWantedWay(Way w) { … … 374 378 } 375 379 fillSearchNodes(endnodes); 376 380 if (!searchNodes.isEmpty()) { 377 maxLen = 4* mindist;381 maxLen = DETOUR_FACTOR * mindist; 378 382 if (isHighwayTest) { 379 383 addErrors(Severity.WARNING, getHighwayEndNodesNearOtherHighway(), tr("Way end node near other highway")); 380 384 } else { … … 385 389 /* the following two should use a shorter distance */ 386 390 boolean includeOther = isBeforeUpload ? ValidatorPrefHelper.PREF_OTHER_UPLOAD.get() : ValidatorPrefHelper.PREF_OTHER.get(); 387 391 if (minmiddledist > 0.0 && includeOther) { 388 maxLen = 4* minmiddledist;392 maxLen = DETOUR_FACTOR * minmiddledist; 389 393 fillSearchNodes(middlenodes); 390 394 addErrors(Severity.OTHER, getWayNodesNearOtherWay(), tr("Way node near other way")); 391 395 fillSearchNodes(othernodes); … … 431 435 * @return true if a reasonable connection was found 432 436 */ 433 437 boolean isConnectedTo(Node startNode) { 434 return isConnectedTo(startNode, new HashSet<>(), 0);438 return isConnectedTo(startNode, new LinkedHashSet<>(), 0, w); 435 439 } 436 440 437 441 /** … … 439 443 * @param node the given node 440 444 * @param visited set of visited nodes 441 445 * @param len length of the travelled route 446 * @param parent the previous parent way 442 447 * @return true if a reasonable connection was found 443 448 */ 444 private boolean isConnectedTo(Node node, Set<Node> visited, double len) { 449 private boolean isConnectedTo(Node node, Set<Node> visited, double len, Way parent) { 450 if (len > maxLen) { 451 return false; 452 } 445 453 if (n1 == node || n2 == node) { 446 454 return true; 447 455 } 448 if (len > maxLen) {449 return false;450 }451 456 if (visited != null) { 452 457 visited.add(node); 453 for (final Way way : node.getParentWays()) { 454 if (isWantedWay(way)) { 455 List<Node> nextNodes = new ArrayList<>(); 456 int pos = way.getNodes().indexOf(node); 457 if (pos > 0) { 458 nextNodes.add(way.getNode(pos - 1)); 459 } 460 if (pos + 1 < way.getNodesCount()) { 461 nextNodes.add(way.getNode(pos + 1)); 462 } 463 for (Node next : nextNodes) { 464 final boolean containsN = visited.contains(next); 465 visited.add(next); 466 if (!containsN && isConnectedTo(next, visited, 467 len + node.getCoor().greatCircleDistance(next.getCoor()))) { 468 return true; 458 List<Way> wantedParents = node.getParentWays().stream().filter(p -> isWantedWay(p)) 459 .collect(Collectors.toList()); 460 if (wantedParents.size() > 1 && wantedParents.indexOf(parent) != wantedParents.size() - 1) { 461 // we want to find a different way. so move known way to the end of the list 462 wantedParents.remove(parent); 463 wantedParents.add(parent); 464 } 465 466 for (final Way way : wantedParents) { 467 List<Node> nextNodes = new ArrayList<>(); 468 int pos = way.getNodes().indexOf(node); 469 if (pos > 0) { 470 nextNodes.add(way.getNode(pos - 1)); 471 } 472 if (pos + 1 < way.getNodesCount()) { 473 nextNodes.add(way.getNode(pos + 1)); 474 } 475 for (Node next : nextNodes) { 476 final boolean containsN = visited.contains(next); 477 visited.add(next); 478 if (!containsN) { 479 double lastLen = node.getCoor().greatCircleDistance(next.getCoor()); 480 if (isConnectedTo(next, visited, len + lastLen, way)) { 481 Node uncon = visited.iterator().next(); 482 EastNorth cl = calcClosest(uncon); 483 double detourLen = len + lastLen + next.getCoor() 484 .greatCircleDistance(ProjectionRegistry.getProjection().eastNorth2latlon(cl)); 485 if (detourLen > maxLen) 486 return false; 487 double directDist = getDist(uncon); 488 return directDist > 0.1 && (visited.size() > 2 || DETOUR_FACTOR * directDist > detourLen); 469 489 } 470 490 } 471 491 } … … 474 494 return false; 475 495 } 476 496 477 double getDist(Node n) {497 private EastNorth calcClosest(Node n) { 478 498 EastNorth coord = n.getEastNorth(); 479 499 if (coord == null) 480 return Double.NaN; 481 EastNorth closest = Geometry.closestPointToSegment(n1.getEastNorth(), n2.getEastNorth(), coord); 482 return n.getCoor().greatCircleDistance(ProjectionRegistry.getProjection().eastNorth2latlon(closest)); 500 return null; 501 return Geometry.closestPointToSegment(n1.getEastNorth(), n2.getEastNorth(), coord); 483 502 } 484 503 504 double getDist(Node n) { 505 EastNorth closest = calcClosest(n); 506 return closest != null 507 ? n.getCoor().greatCircleDistance(ProjectionRegistry.getProjection().eastNorth2latlon(closest)) 508 : Double.NaN; 509 } 510 485 511 private boolean nearby(Node n, double dist) { 486 512 if (w.containsNode(n)) 487 513 return false;