From 3b518fd8c848cd312e0fbb5633130db89fb25bc2 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Sat, 3 Mar 2018 21:40:22 +0100
Subject: [PATCH] Add support for crossing of residential areas with something.

---
 data/validator/geometry.mapcss                     |  3 +-
 .../openstreetmap/josm/data/validation/Test.java   |  9 +++
 .../josm/data/validation/tests/CrossingWays.java   | 81 ++++++++++++++++++----
 3 files changed, 80 insertions(+), 13 deletions(-)

diff --git a/data/validator/geometry.mapcss b/data/validator/geometry.mapcss
index 971ba7cf7..9dc1831b7 100644
--- a/data/validator/geometry.mapcss
+++ b/data/validator/geometry.mapcss
@@ -184,7 +184,8 @@ area:closed:areaStyle[tag("natural") = parent_tag("natural")] ⧉ area:closed:ar
   throwWarning: tr("Overlapping Identical Natural Areas");
 }
 
-area:closed:areaStyle[tag("landuse") = parent_tag("landuse")] ⧉ area:closed:areaStyle[landuse] {
+area:closed:areaStyle[landuse!=residential][tag("landuse") = parent_tag("landuse")] ⧉
+ area:closed:areaStyle[landuse!=residential][landuse] {
   throwWarning: tr("Overlapping Identical Landuses");
 }
 
diff --git a/src/org/openstreetmap/josm/data/validation/Test.java b/src/org/openstreetmap/josm/data/validation/Test.java
index 8aaf54553..d17163ea1 100644
--- a/src/org/openstreetmap/josm/data/validation/Test.java
+++ b/src/org/openstreetmap/josm/data/validation/Test.java
@@ -346,6 +346,15 @@ public class Test implements OsmPrimitiveVisitor, Comparable<Test> {
         return p.hasTagDifferent("building", "no", "entrance");
     }
 
+    /**
+     * Determines if the specified primitive denotes a residential area.
+     * @param p The primitive to be tested
+     * @return True if landuse key is equal to residential
+     */
+    protected static final boolean isResidentialArea(OsmPrimitive p) {
+        return p.get("landuse") == "residential";
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(name, description);
diff --git a/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java b/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java
index dd91a119f..d7941d809 100644
--- a/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java
+++ b/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java
@@ -5,6 +5,7 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.geom.Point2D;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +35,7 @@ public abstract class CrossingWays extends Test {
     static final String HIGHWAY = "highway";
     static final String RAILWAY = "railway";
     static final String WATERWAY = "waterway";
+    static final String LANDUSE = "landuse";
 
     /** All way segments, grouped by cells */
     private final Map<Point2D, List<WaySegment>> cellSegments = new HashMap<>(1000);
@@ -64,7 +66,8 @@ public abstract class CrossingWays extends Test {
                     || w.hasKey(WATERWAY)
                     || isRailway(w)
                     || isCoastline(w)
-                    || isBuilding(w));
+                    || isBuilding(w)
+                    || isResidentialArea(w));
         }
 
         @Override
@@ -77,6 +80,9 @@ public abstract class CrossingWays extends Test {
             if (w1.hasKey(HIGHWAY) && w2.hasKey(HIGHWAY) && !Objects.equals(w1.get("level"), w2.get("level"))) {
                 return true;
             }
+            if ((w1.hasKey(HIGHWAY) && isResidentialArea(w2))
+             || (w2.hasKey(HIGHWAY) && isResidentialArea(w1)))
+                return true;
             if (isSubwayOrTramOrRazed(w2)) {
                 return true;
             }
@@ -90,18 +96,69 @@ public abstract class CrossingWays extends Test {
             return isProposedOrAbandoned(w2);
         }
 
+        private String getWayType(Way w) {
+            if (isBuilding(w))
+                return "building";
+            else if (w.hasKey(HIGHWAY))
+                return "highway";
+            else if (isResidentialArea(w))
+                return "residential area";
+            else if (w.hasKey(WATERWAY))
+                return "waterway";
+            else
+                return "way";
+        }
+
         @Override
         String createMessage(Way w1, Way w2) {
-            if (isBuilding(w1)) {
-                return tr("Crossing buildings");
-            } else if (w1.hasKey(WATERWAY) && w2.hasKey(WATERWAY)) {
-                return tr("Crossing waterways");
-            } else if ((w1.hasKey(HIGHWAY) && w2.hasKey(WATERWAY))
-                    || (w2.hasKey(HIGHWAY) && w1.hasKey(WATERWAY))) {
-                return tr("Crossing waterway/highway");
-            } else {
-                return tr("Crossing ways");
-            }
+            String[] types = { getWayType(w1), getWayType(w2) };
+            Arrays.sort(types);
+
+            if (types[0] == types[1])
+                switch(types[0]) {
+                    case "building":
+                        return tr("Crossing buildings");
+                    case "highway":
+                        return tr("Crossing highways");
+                    case "residential area":
+                        return tr("Crossing residential areas");
+                    case "waterway":
+                        return tr("Crossing waterways");
+                    default:
+                        return tr("Crossing ways");
+                }
+            else
+                switch (types[0]) {
+                    case "building":
+                        switch (types[1]) {
+                            case "highway":
+                                return tr("Crossing building/highway");
+                            case "residential area":
+                                return tr("Crossing building/residential area");
+                            case "waterway":
+                                return tr("Crossing building/waterway");
+                            default:
+                                return tr("Crossing building/way");
+                        }
+                    case "highway":
+                        switch (types[1]) {
+                            case "residential area":
+                                return tr("Crossing highway/residential area");
+                            case "waterway":
+                                return tr("Crossing highway/waterway");
+                            default:
+                                return tr("Crossing highway/way");
+                        }
+                    case "residential area":
+                        switch (types[1]) {
+                            case "waterway":
+                                return tr("Crossing residential area/waterway");
+                            default:
+                                return tr("Crossing residential area/way");
+                        }
+                    default:
+                        return tr("Crossing residential area/waterway");
+                }
         }
     }
 
@@ -235,7 +292,7 @@ public abstract class CrossingWays extends Test {
     }
 
     static boolean isCoastline(OsmPrimitive w) {
-        return w.hasTag("natural", "water", "coastline") || w.hasTag("landuse", "reservoir");
+        return w.hasTag("natural", "water", "coastline") || w.hasTag(LANDUSE, "reservoir");
     }
 
     static boolean isHighway(OsmPrimitive w) {
-- 
2.16.3

