| 172 | | final Set<OsmPrimitive> referrers = new HashSet<>(); |
| 173 | | |
| 174 | | if (way.isClosed()) { |
| 175 | | // for closed way we need to check all adjacent ways |
| 176 | | for (Node n: way.getNodes()) { |
| 177 | | referrers.addAll(n.getReferrers()); |
| | 171 | for (int i = 0; i < way.getNodesCount(); i++) { |
| | 172 | Node n = way.getNode(i); |
| | 173 | if (!IN_DOWNLOADED_AREA.test(n)) |
| | 174 | return true; |
| | 175 | Set<Way> otherWays = new HashSet<>(); |
| | 176 | otherWays.addAll(Utils.filteredCollection(n.getReferrers(), Way.class)); |
| | 177 | if (otherWays.size() == 1) |
| | 178 | continue; |
| | 179 | otherWays.remove(way); |
| | 180 | otherWays.removeIf(w -> !highway.startsWith(w.get(HIGHWAY)) || w.getNodesCount() < 2); |
| | 181 | if (otherWays.isEmpty()) |
| | 182 | continue; |
| | 183 | //TODO: ignore ways which are not allowed because of turn restrictions, oneway attributes or access rules? |
| | 184 | HashSet<Way> sameTag = new HashSet<>(); |
| | 185 | for (Way ow : otherWays) { |
| | 186 | if (highway.equals(ow.get(HIGHWAY))) |
| | 187 | sameTag.add(ow); |
| | 188 | else |
| | 189 | return true; |
| 184 | | // Find ways of same class (exact class of class_link) |
| 185 | | List<Way> sameClass = Utils.filteredCollection(referrers, Way.class).stream().filter( |
| 186 | | otherWay -> !way.equals(otherWay) && otherWay.hasTag(HIGHWAY, highway, highway.replaceAll("_link$", ""))) |
| 187 | | .collect(Collectors.toList()); |
| 188 | | if (sameClass.size() > 1) { |
| 189 | | // It is possible to have a class_link between 2 segments of same class |
| 190 | | // in roundabout designs that physically separate a specific turn from the main roundabout |
| 191 | | // But if we have more than a single adjacent class, and one of them is a roundabout, that's an error |
| 192 | | for (Way w : sameClass) { |
| 193 | | if (w.hasTag("junction", "roundabout")) { |
| 194 | | return false; |
| 195 | | } |
| | 199 | } |
| | 200 | |
| | 201 | /** |
| | 202 | * Check if the two given connected ways form a sharp angle. |
| | 203 | * @param way 1st way |
| | 204 | * @param nodePos node position of connecting node in 1st way |
| | 205 | * @param otherWay the 2nd way |
| | 206 | * @return true if angle is sharp |
| | 207 | */ |
| | 208 | private static boolean isSharpAngle(Way way, int nodePos, Way otherWay) { |
| | 209 | Node n = way.getNode(nodePos); |
| | 210 | Node n0 = way.getNode(nodePos == 0 ? 1 : nodePos -1); |
| | 211 | |
| | 212 | Node n2 = null; |
| | 213 | for (int i = 0; i < otherWay.getNodesCount(); i++) { |
| | 214 | if (n == otherWay.getNode(i)) { |
| | 215 | n2 = otherWay.getNode(i > 0 ? i-1 : 1); |
| | 216 | break; |