From 6650096dae54b7ac44165002eb70f62aaa253bee Mon Sep 17 00:00:00 2001 From: "taylor.smock" Date: Tue, 6 Aug 2024 21:29:28 +0000 Subject: [PATCH] Fix #23290: When an object is not in the appropriate region based off of the center of its bbox, check all the nodes. This does not appear to have a significant performance impact; this may change as more region specific presets are created. git-svn-id: https://josm.openstreetmap.de/svn/trunk@19170 0c6e7542-c601-0410-84e7-c038aed88b3b --- .../data/validation/tests/TagChecker.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java index c9ab9ecc42d..6608bc6dd77 100644 --- a/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java +++ b/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java @@ -38,9 +38,14 @@ import org.openstreetmap.josm.command.ChangePropertyKeyCommand; import org.openstreetmap.josm.command.Command; import org.openstreetmap.josm.command.SequenceCommand; +import org.openstreetmap.josm.data.coor.ILatLon; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.AbstractPrimitive; import org.openstreetmap.josm.data.osm.DataSet; +import org.openstreetmap.josm.data.osm.INode; +import org.openstreetmap.josm.data.osm.IPrimitive; +import org.openstreetmap.josm.data.osm.IRelation; +import org.openstreetmap.josm.data.osm.IWay; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.OsmUtils; @@ -805,7 +810,9 @@ private void tagCheckReal(TaggingPreset preset, OsmPrimitive p, LatLon center, L */ private void tagCheckReal(TaggingPreset preset, OsmPrimitive p, LatLon center, RegionSpecific data) { // First, check if we aren't in the region for the tag - if (latLonInRegions(center, data.regions()) == data.exclude_regions()) { + if (latLonInRegions(center, data.regions()) == data.exclude_regions() + // Check to ensure that no nodes are in the region if the center is not in the region + && !primitiveInRegions(p, data.regions(), data.exclude_regions())) { final String key; final String value; if (data instanceof PresetListEntry) { @@ -838,16 +845,34 @@ private void tagCheckReal(TaggingPreset preset, OsmPrimitive p, LatLon center, R } } + /** + * Check if a primitive is in the specified regions + * @param primitive The primitive to recursively check + * @param regions The regions to look for + * @param excludeRegions Whether or not we are looking to exclude the regions (see {@link RegionSpecific#exclude_regions()}) + * @return {@code true} if the primitive is in a region that it should not be + */ + private static boolean primitiveInRegions(IPrimitive primitive, Collection regions, boolean excludeRegions) { + if (primitive instanceof INode) { + return latLonInRegions((INode) primitive, regions) == excludeRegions; + } else if (primitive instanceof IWay) { + return ((IWay) primitive).getNodes().stream().anyMatch(n -> primitiveInRegions(n, regions, excludeRegions)); + } else if (primitive instanceof IRelation) { + return ((IRelation) primitive).getMemberPrimitivesList().stream().anyMatch(p -> primitiveInRegions(p, regions, excludeRegions)); + } + throw new IllegalArgumentException("Unknown primitive type: " + primitive); + } + /** * Check if the specified latlon is inside any of the specified regions * @param latLon The {@link LatLon} to check * @param regions The regions to see if the {@link LatLon} is in * @return {@code true} if the coordinate is inside any of the regions */ - private static boolean latLonInRegions(LatLon latLon, Collection regions) { + private static boolean latLonInRegions(ILatLon latLon, Collection regions) { if (regions != null) { for (String region : regions) { - if (Territories.isIso3166Code(region, latLon)) { + if (Territories.isIso3166Code(region, latLon instanceof LatLon ? (LatLon) latLon : new LatLon(latLon))) { return true; } }