Ticket #19136: 19136.6.patch

File 19136.6.patch, 9.9 KB (added by GerdP, 4 years ago)

improved version, see comment:43

  • src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java

     
    120120
    121121    /**
    122122     * Various style-related checks:<ul>
     123     * <li>{@link #NO_STYLE}: No area style for multipolygon</li>
    123124     * <li>{@link #INNER_STYLE_MISMATCH}: With the currently used mappaint style the style for inner way equals the multipolygon style</li>
    124      * <li>{@link #OUTER_STYLE_MISMATCH}: Style for outer way mismatches</li>
     125     * <li>{@link #OUTER_STYLE_MISMATCH}: With the currently used mappaint style the style for outer way mismatches the area style</li>
    125126     * <li>{@link #OUTER_STYLE}: Area style on outer way</li>
    126127     * </ul>
    127128     * @param r relation
     
    128129     * @param polygon multipolygon
    129130     */
    130131    private void checkStyleConsistency(Relation r, Multipolygon polygon) {
    131         ElemStyles styles = MapPaintStyles.getStyles();
    132         if (styles != null && !r.isBoundary()) {
     132        if (MapPaintStyles.getStyles() != null && !r.isBoundary()) {
    133133            AreaElement area = ElemStyles.getAreaElemStyle(r, false);
    134             boolean areaStyle = area != null;
    135             // If area style was not found for relation then use style of ways
    136134            if (area == null) {
    137                 for (Way w : polygon.getOuterWays()) {
    138                     area = ElemStyles.getAreaElemStyle(w, true);
    139                     if (area != null) {
    140                         break;
    141                     }
    142                 }
    143                 if (area == null) {
    144                     errors.add(TestError.builder(this, Severity.OTHER, NO_STYLE)
    145                             .message(tr("No area style for multipolygon"))
    146                             .primitives(r)
    147                             .build());
    148                 }
    149             }
    150 
    151             if (area != null) {
     135                errors.add(TestError.builder(this, Severity.OTHER, NO_STYLE)
     136                        .message(tr("No area style for multipolygon"))
     137                        .primitives(r)
     138                        .build());
     139            } else {
    152140                for (Way wInner : polygon.getInnerWays()) {
    153                     if (area.equals(ElemStyles.getAreaElemStyle(wInner, false))) {
     141                    if (wInner.isClosed() && area.equals(ElemStyles.getAreaElemStyle(wInner, false))) {
    154142                        errors.add(TestError.builder(this, Severity.OTHER, INNER_STYLE_MISMATCH)
    155143                                .message(tr("With the currently used mappaint style the style for inner way equals the multipolygon style"))
    156144                                .primitives(Arrays.asList(r, wInner))
     
    159147                    }
    160148                }
    161149                for (Way wOuter : polygon.getOuterWays()) {
     150                    if (!wOuter.isArea())
     151                        continue;
    162152                    AreaElement areaOuter = ElemStyles.getAreaElemStyle(wOuter, false);
    163153                    if (areaOuter != null) {
    164154                        if (!area.equals(areaOuter)) {
    165                             String message = !areaStyle ? tr("Style for outer way mismatches")
    166                                     : tr("With the currently used mappaint style the style for outer way mismatches the area style");
    167155                            errors.add(TestError.builder(this, Severity.OTHER, OUTER_STYLE_MISMATCH)
    168                                     .message(message)
     156                                    .message(tr("With the currently used mappaint style the style for outer way mismatches the area style"))
    169157                                    .primitives(Arrays.asList(r, wOuter))
    170158                                    .highlight(wOuter)
    171159                                    .build());
    172                         } else if (areaStyle) { /* style on outer way of multipolygon, but equal to polygon */
     160                        } else { /* style on outer way of multipolygon, but equal to polygon */
    173161                            errors.add(TestError.builder(this, Severity.WARNING, OUTER_STYLE)
    174162                                    .message(tr("Area style on outer way"))
    175163                                    .primitives(Arrays.asList(r, wOuter))
  • src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

     
    3838import org.openstreetmap.josm.command.SequenceCommand;
    3939import org.openstreetmap.josm.data.osm.AbstractPrimitive;
    4040import org.openstreetmap.josm.data.osm.OsmPrimitive;
     41import org.openstreetmap.josm.data.osm.Relation;
    4142import org.openstreetmap.josm.data.osm.Tag;
    4243import org.openstreetmap.josm.data.osm.TagMap;
    4344import org.openstreetmap.josm.data.osm.Tagged;
     
    188189    protected static final int MISSPELLED_VALUE_NO_FIX  = 1215;
    189190    protected static final int UNUSUAL_UNICODE_CHAR_VALUE = 1216;
    190191    protected static final int INVALID_PRESETS_TYPE     = 1217;
     192    protected static final int MULTIPOLYGON_NO_AREA     = 1218;
     193    protected static final int MULTIPOLYGON_INCOMPLETE  = 1219;
     194    protected static final int MULTIPOLYGON_NO_TAG      = 1220;
    191195    // CHECKSTYLE.ON: SingleSpaceSeparator
    192196
    193197    protected EditableList sourcesList;
     
    622626            }
    623627        }
    624628
     629        if (p instanceof Relation && p.hasTag("type", "multipolygon")) {
     630            checkMultipolygonTags(p);
     631        }
     632
    625633        if (checkPresetsTypes) {
    626634            TagMap tags = p.getKeys();
    627635            TaggingPresetType presetType = TaggingPresetType.forPrimitive(p);
     
    659667        }
    660668    }
    661669
     670    private void checkMultipolygonTags(OsmPrimitive p) {
     671        if (p.isAnnotated() || hasAcceptedPrimaryTagForMultipolygon(p))
     672            return;
     673        Map<String, String> filteredTags = p.getInterestingTags();
     674        TestError.Builder builder = null;
     675        if (filteredTags.size() == 1) {
     676            builder = TestError.builder(this, Severity.ERROR, MULTIPOLYGON_NO_TAG)
     677                    .message(tr("multipolygon relation: no further tags"));
     678        }
     679        if (filteredTags.size() == 2) {
     680            if (filteredTags.containsKey("name")) {
     681                builder = TestError.builder(this, Severity.ERROR, MULTIPOLYGON_INCOMPLETE)
     682                        .message(tr("multipolygon relation: only {0} tag", "name"));
     683            }
     684            if (filteredTags.containsKey("area")) {
     685                builder = TestError.builder(this, Severity.WARNING, MULTIPOLYGON_INCOMPLETE)
     686                        .message(tr("multipolygon relation: only {0} tag", "area"));
     687
     688            }
     689        }
     690        if (builder == null && filteredTags.containsKey("surface")) {
     691            builder = TestError.builder(this, Severity.OTHER, MULTIPOLYGON_INCOMPLETE)
     692                    .message(tr("multipolygon relation: only {0} tag", "surface"));
     693        }
     694        if (builder == null) {
     695            builder = TestError.builder(this, Severity.WARNING, MULTIPOLYGON_NO_AREA)
     696                    .message(tr("multipolygon relation: found no area type tag"));
     697        }
     698        errors.add(builder.primitives(p).build());
     699    }
     700
     701    /**
     702     * Check if a multipolygon has a main tag that describes the type of area. Accepts also some deprecated tags and typos.
     703     * @param p the multipolygon
     704     * @return true if the multipolygon has a main tag that (likely) describes the type of area.
     705     */
     706    private static boolean hasAcceptedPrimaryTagForMultipolygon(OsmPrimitive p) {
     707        if (p.hasKey("landuse", "amenity", "building", "building:part", "area:highway", "shop", "place", "landform",
     708                "piste:type", "sport", "golf", "landcover", "aeroway", "office", "healthcare", "disused:amenity",
     709                "disused:landuse", "disused:building", "disused:leisure"))
     710            return true;
     711        if (p.hasTagDifferent("natural", "tree", "peek", "saddle", "tree_row")
     712                || p.hasTagDifferent("man_made", "survey_point", "mast", "flagpole", "manhole", "watertap")
     713                || p.hasTagDifferent("highway", "crossing", "bus_stop", "turning_circle", "street_lamp",
     714                        "traffic_signals", "stop", "milestone", "mini_roundabout", "motorway_junction", "passing_place",
     715                        "speed_camera", "traffic_mirror", "trailhead", "turning_circle", "turning_loop", "toll_gantry")
     716                || p.hasTagDifferent("tourism", "attraction", "artwork")
     717                || p.hasTagDifferent("leisure", "picnic_table", "slipway", "firepit")
     718                || p.hasTagDifferent("historic", "wayside_cross", "milestone"))
     719            return true;
     720        return p.hasTag("barrier", "hedge", "retaining_wall")
     721                || p.hasTag("boundary", "national_park", "protected_area")
     722                || p.hasTag("public_transport", "platform", "station")
     723                || p.hasTag("railway", "platform")
     724                || p.hasTag("waterway", "riverbank")
     725                || p.hasTag("indoor", "corridor", "room", "area")
     726                || p.hasTag("power", "substation", "generator", "plant", "switchgear", "converter", "sub_station")
     727                || p.hasTag("seamark:type", "harbour", "fairway", "anchorage", "landmark", "berth", "harbour_basin",
     728                        "separation_zone")
     729                || (p.get("seamark:type") != null && p.get("seamark:type").matches(".*\\_(area|zone)$"))
     730                || p.hasTag("junction", "yes");
     731
     732    }
     733
    662734    private void checkSingleTagValueSimple(MultiMap<OsmPrimitive, String> withErrors, OsmPrimitive p, String s, String key, String value) {
    663735        if (!checkValues || value == null)
    664736            return;