From c911ae372b2fba98b172bdc7aa796c99af34395d Mon Sep 17 00:00:00 2001 From: Marta Todea-Pako Date: Sun, 12 Dec 2021 21:39:26 +0200 Subject: [PATCH 1/2] Implement Highway Intersection Check --- docs/available_checks.md | 1 + docs/checks/highwayIntersectionCheck.md | 19 ++ .../HighwayIntersectionCheck.java | 166 +++++++++++ .../HighwayIntersectionCheckTest.java | 125 ++++++++ .../HighwayIntersectionTestCaseRule.java | 269 ++++++++++++++++++ 5 files changed, 580 insertions(+) create mode 100644 docs/checks/highwayIntersectionCheck.md create mode 100644 src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java create mode 100644 src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheckTest.java create mode 100644 src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionTestCaseRule.java diff --git a/docs/available_checks.md b/docs/available_checks.md index b52d25f6c..45218183b 100644 --- a/docs/available_checks.md +++ b/docs/available_checks.md @@ -125,3 +125,4 @@ This document is a list of tables with a description and link to documentation f | [MalformedPolyLineCheck](checks/malformedPolyLineCheck.md) | This check identifies lines that have only one point, or none, and the ones that are too long. | | [SelfIntersectingPolylineCheck](checks/selfIntersectingPolylineCheck.md) | The purpose of this check is to identify all edges/lines/areas in Atlas that have self-intersecting polylines, or geometries that intersects itself in some form. | | [WaterWayCheck](checks/waterWayCheck.md) | This check finds closed waterways (circular water motion), waterways without a place for water to go (a "sink"), crossing waterways, and waterways that go uphill (requires elevation data). | +| [HighwayIntersectionCheck](checks/highwayIntersectionCheck.md) | The purpose of this check is to identify highways intersecting power or waterway objects invalidly. | \ No newline at end of file diff --git a/docs/checks/highwayIntersectionCheck.md b/docs/checks/highwayIntersectionCheck.md new file mode 100644 index 000000000..9a263591b --- /dev/null +++ b/docs/checks/highwayIntersectionCheck.md @@ -0,0 +1,19 @@ +# Highway Intersection Check + +#### Description + +The purpose of this check is to flag highways intersecting power or waterway objects. + +*dam* and *weir* waterway objects are not flagged, these type of waterways can intersect with highways. + +For waterway objects the intersection with a highway having *leisure=slipway* or *ford=yes* tag is allowed, and they are not flagged. + +#### Configuration + +There are no configurables for this check. + +#### Code Review + +#### More Information + +Please see the source code for HighwayIntersectionCheck here: [HighwayIntersectionCheck](../../src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java) \ No newline at end of file diff --git a/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java b/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java new file mode 100644 index 000000000..7ebedd425 --- /dev/null +++ b/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java @@ -0,0 +1,166 @@ +package org.openstreetmap.atlas.checks.validation.intersections; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.openstreetmap.atlas.checks.atlas.predicates.TagPredicates; +import org.openstreetmap.atlas.checks.atlas.predicates.TypePredicates; +import org.openstreetmap.atlas.checks.base.BaseCheck; +import org.openstreetmap.atlas.checks.flag.CheckFlag; +import org.openstreetmap.atlas.geography.Location; +import org.openstreetmap.atlas.geography.PolyLine; +import org.openstreetmap.atlas.geography.Rectangle; +import org.openstreetmap.atlas.geography.atlas.Atlas; +import org.openstreetmap.atlas.geography.atlas.items.AtlasObject; +import org.openstreetmap.atlas.geography.atlas.items.Edge; +import org.openstreetmap.atlas.tags.FordTag; +import org.openstreetmap.atlas.tags.HighwayTag; +import org.openstreetmap.atlas.tags.LeisureTag; +import org.openstreetmap.atlas.tags.WaterwayTag; +import org.openstreetmap.atlas.tags.annotations.validation.Validators; +import org.openstreetmap.atlas.utilities.collections.Iterables; +import org.openstreetmap.atlas.utilities.configuration.Configuration; + +/** + * Flags waterway and power line edge items that are crossed by navigable edges (having way specific + * highway tag). If the way is a waterway and the crossing way has {@code ford=yes} or + * {@code leisure=slipway} tags, then the crossing is accepted. {@code dam} and {@code weir} + * waterways are not checked, those type of ways can cross other highways. + * + * @author pako.todea + */ +public class HighwayIntersectionCheck extends BaseCheck +{ + + private static final long serialVersionUID = 1L; + private static final String INSTRUCTION_FORMAT = "The water/powerline with id {0,number,#} has invalid crossings " + + "with {1}. A navigable way can not cross a power line or a water."; + private static final String INVALID_EDGE_FORMAT = "Edge {0,number,#} is crossing invalidly with {1}."; + private static final List FALLBACK_INSTRUCTIONS = Arrays.asList(INSTRUCTION_FORMAT, + INVALID_EDGE_FORMAT); + + /** + * Checks whether the given {@link Edge}s cross each other. + * + * @param edge + * {@link Edge} being crossed + * @param crossingEdge + * Crossing {@link Edge} + * @param intersection + * Intersection {@link Location} + * @return {@code true} if given {@link Edge}s cross each other + */ + private static boolean isCross(final Edge edge, final Edge crossingEdge, + final Location intersection) + { + final PolyLine edgeAsPolyLine = edge.asPolyLine(); + final PolyLine crossingEdgeAsPolyLine = crossingEdge.asPolyLine(); + return edgeAsPolyLine.contains(intersection) + && crossingEdgeAsPolyLine.contains(intersection); + } + + public HighwayIntersectionCheck(final Configuration configuration) + { + super(configuration); + } + + @Override + public boolean validCheckForObject(final AtlasObject object) + { + return TypePredicates.IS_EDGE.test(object) + && (TagPredicates.IS_POWER_LINE.test(object) || this.isWaterwayToCheck(object)); + } + + @Override + protected Optional flag(final AtlasObject object) + { + final Edge edge = (Edge) object; + final Atlas atlas = edge.getAtlas(); + final Rectangle edgeBounds = edge.bounds(); + + final Set invalidIntersectingEdges = Iterables + .asList(atlas.edgesIntersecting(edgeBounds, HighwayTag::isWayOnlyTag)).stream() + .filter(crossingEdge -> TagPredicates.IS_POWER_LINE.test(edge) + || !FordTag.isYes(crossingEdge)) + .filter(crossingEdge -> TagPredicates.IS_POWER_LINE.test(edge) + || !Validators.isOfType(crossingEdge, LeisureTag.class, LeisureTag.SLIPWAY)) + .filter(crossingEdge -> crossingEdge.getIdentifier() != edge.getIdentifier()) + .filter(crossingEdge -> !crossingEdge.isReversedEdge(edge)) + .filter(crossingEdge -> this.getIntersection(edge, crossingEdge).stream() + .anyMatch(intersection -> isCross(edge, crossingEdge, intersection))) + .collect(Collectors.toSet()); + + if (invalidIntersectingEdges.size() > 0) + { + return this.createHighwayIntersectionCheckFlag(edge, invalidIntersectingEdges); + } + + return Optional.empty(); + } + + @Override + protected List getFallbackInstructions() + { + return FALLBACK_INSTRUCTIONS; + } + + /** + * Function that creates highway intersection check flag. + * + * @param edge + * Atlas object. + * @param crossingEdges + * collected edges for a given atlas object. + * @return newly created highway intersection check flag including crossing edges locations. + */ + private Optional createHighwayIntersectionCheckFlag(final Edge edge, + final Set crossingEdges) + { + final CheckFlag newFlag = new CheckFlag(this.getTaskIdentifier(edge)); + this.markAsFlagged(edge.getIdentifier()); + final Set points = crossingEdges.stream() + .filter(crossEdge -> crossEdge.getIdentifier() != edge.getIdentifier()) + .flatMap(crossEdge -> this.getIntersection(edge, crossEdge).stream()) + .collect(Collectors.toSet()); + newFlag.addInstruction( + this.getLocalizedInstruction(0, edge.getOsmIdentifier(), crossingEdges.stream() + .map(AtlasObject::getOsmIdentifier).collect(Collectors.toSet()))); + newFlag.addPoints(points); + newFlag.addObject(edge); + return Optional.of(newFlag); + } + + /** + * This function returns the set of intersection locations for the given edges. + * + * @param firstEdge + * the first Edge + * @param secondEdge + * the second edge + * @return set of intersection locations. + */ + private Set getIntersection(final Edge firstEdge, final Edge secondEdge) + { + final PolyLine firstEdgeAsPolyLine = firstEdge.asPolyLine(); + final PolyLine secondEdgeAsPolyLine = secondEdge.asPolyLine(); + return firstEdgeAsPolyLine.intersections(secondEdgeAsPolyLine); + } + + /** + * Checks whether the given {@link AtlasObject} is a waterway to check. + * + * @param edge + * the {@link AtlasObject} to check + * @return true if the given {@link AtlasObject} should be ckecked + */ + private boolean isWaterwayToCheck(final AtlasObject edge) + { + return Validators.hasValuesFor(edge, WaterwayTag.class) + && !(HighwayTag.highwayTag(edge).isPresent() + && (WaterwayTag.get(edge).get().name().equalsIgnoreCase("dam") + || WaterwayTag.get(edge).get().name().equalsIgnoreCase("weir"))); + } +} diff --git a/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheckTest.java b/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheckTest.java new file mode 100644 index 000000000..3240935c9 --- /dev/null +++ b/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheckTest.java @@ -0,0 +1,125 @@ +package org.openstreetmap.atlas.checks.validation.intersections; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.openstreetmap.atlas.checks.configuration.ConfigurationResolver; +import org.openstreetmap.atlas.checks.validation.verifier.ConsumerBasedExpectedCheckVerifier; +import org.openstreetmap.atlas.utilities.configuration.Configuration; + +/** + * @author pako.todea + */ +public class HighwayIntersectionCheckTest +{ + + @Rule + public HighwayIntersectionTestCaseRule setup = new HighwayIntersectionTestCaseRule(); + + @Rule + public ConsumerBasedExpectedCheckVerifier verifier = new ConsumerBasedExpectedCheckVerifier(); + + private final Configuration configuration = ConfigurationResolver.emptyConfiguration(); + + @Test + public void testInvalidCrossingHighwayLeisureEdges() + { + this.verifier.actual(this.setup.invalidCrossingWaterwayLeisureEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(2, flag.getFlaggedObjects().size())); + } + + @Test + public void testInvalidCrossingHighwayPowerLineEdges() + { + this.verifier.actual(this.setup.invalidCrossingHighwayPowerLineEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(2, flag.getFlaggedObjects().size())); + } + + @Test + public void testInvalidCrossingHighwayWaterEdges() + { + this.verifier.actual(this.setup.invalidCrossingHighwayWaterEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(2, flag.getFlaggedObjects().size())); + } + + @Test + public void testInvalidCrossingPowerLineFordYesEdges() + { + this.verifier.actual(this.setup.invalidCrossingPowerLineFordYesEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(2, flag.getFlaggedObjects().size())); + } + + @Test + public void testInvalidCrossingPowerLineLeisureSlipwayEdges() + { + this.verifier.actual(this.setup.invalidCrossingPowerLineLeisureSlipwayEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(2, flag.getFlaggedObjects().size())); + } + + @Test + public void testInvalidMultipleCrossingHighwayWaterEdges() + { + this.verifier.actual(this.setup.invalidMultipleCrossingHighwayWaterEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + this.verifier.verify(flag -> Assert.assertEquals(3, flag.getFlaggedObjects().size())); + } + + @Test + public void testNoCrossingHighwayPowerLineEdges() + { + this.verifier.actual(this.setup.noCrossingHighwayPowerLineEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testNoCrossingHighwayWaterEdges() + { + this.verifier.actual(this.setup.noCrossingHighwayWaterEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidCrossingHighwayFordYesEdges() + { + this.verifier.actual(this.setup.validCrossingWaterwayFordYesEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidCrossingHighwayLeisureSlipwayEdges() + { + this.verifier.actual(this.setup.validCrossingWaterwayLeisureSlipwayEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidCrossingHighwayWaterwayDamEdges() + { + this.verifier.actual(this.setup.validCrossingHighwayWaterwayDamEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidCrossingHighwayWaterwayWeirEdges() + { + this.verifier.actual(this.setup.validCrossingHighwayWaterwayWeirEdges(), + new HighwayIntersectionCheck(this.configuration)); + this.verifier.verifyEmpty(); + } +} diff --git a/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionTestCaseRule.java b/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionTestCaseRule.java new file mode 100644 index 000000000..59c42af3e --- /dev/null +++ b/src/test/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionTestCaseRule.java @@ -0,0 +1,269 @@ +package org.openstreetmap.atlas.checks.validation.intersections; + +import org.openstreetmap.atlas.geography.atlas.Atlas; +import org.openstreetmap.atlas.utilities.testing.CoreTestRule; +import org.openstreetmap.atlas.utilities.testing.TestAtlas; + +/** + * {@link HighwayIntersectionCheckTest} data generator + * + * @author pako.todea + */ +public class HighwayIntersectionTestCaseRule extends CoreTestRule +{ + + private static final String LOCATION_1 = "47.576973, -122.304985"; + private static final String LOCATION_2 = "47.575661, -122.304222"; + private static final String LOCATION_3 = "47.574612, -122.305855"; + private static final String LOCATION_4 = "47.575371, -122.308121"; + private static final String LOCATION_5 = "47.576485, -122.307098"; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_3), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas noCrossingHighwayWaterEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas invalidCrossingHighwayWaterEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_4), + @TestAtlas.Loc(value = LOCATION_5) }, tags = { "highway=primary" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas invalidMultipleCrossingHighwayWaterEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_3), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "power=line" }) }) + private Atlas noCrossingHighwayPowerLineEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "power=line" }) }) + private Atlas invalidCrossingHighwayPowerLineEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=dam", + "highway=service" }) }) + private Atlas validCrossingHighwayWaterwayDamEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=weir", + "highway=service" }) }) + private Atlas validCrossingHighwayWaterwayWeirEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway", + "ford=yes" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas validCrossingWaterwayFordYesEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway", + "ford=yes" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "power=line" }) }) + private Atlas invalidCrossingPowerLineFordYesEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway", + "leisure=slipway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas validCrossingWaterwayLeisureSlipwayEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway", + "leisure=slipway" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "power=line" }) }) + private Atlas invalidCrossingPowerLineLeisureSlipwayEdges; + + @TestAtlas( + // nodes + nodes = { @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_1)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_2)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_3)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_4)), + @TestAtlas.Node(coordinates = @TestAtlas.Loc(value = LOCATION_5)) }, + // edges + edges = { + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_1), + @TestAtlas.Loc(value = LOCATION_2) }, tags = { "highway=motorway", + "leisure=dance" }), + @TestAtlas.Edge(coordinates = { @TestAtlas.Loc(value = LOCATION_2), + @TestAtlas.Loc(value = LOCATION_4) }, tags = { "waterway=stream" }) }) + private Atlas invalidCrossingWaterwayLeisureEdges; + + public Atlas invalidCrossingHighwayPowerLineEdges() + { + return this.invalidCrossingHighwayPowerLineEdges; + } + + public Atlas invalidCrossingHighwayWaterEdges() + { + return this.invalidCrossingHighwayWaterEdges; + } + + public Atlas invalidCrossingPowerLineFordYesEdges() + { + return this.invalidCrossingPowerLineFordYesEdges; + } + + public Atlas invalidCrossingPowerLineLeisureSlipwayEdges() + { + return this.invalidCrossingPowerLineLeisureSlipwayEdges; + } + + public Atlas invalidCrossingWaterwayLeisureEdges() + { + return this.invalidCrossingWaterwayLeisureEdges; + } + + public Atlas invalidMultipleCrossingHighwayWaterEdges() + { + return this.invalidMultipleCrossingHighwayWaterEdges; + } + + public Atlas noCrossingHighwayPowerLineEdges() + { + return this.noCrossingHighwayPowerLineEdges; + } + + public Atlas noCrossingHighwayWaterEdges() + { + return this.noCrossingHighwayWaterEdges; + } + + public Atlas validCrossingHighwayWaterwayDamEdges() + { + return this.validCrossingHighwayWaterwayDamEdges; + } + + public Atlas validCrossingHighwayWaterwayWeirEdges() + { + return this.validCrossingHighwayWaterwayWeirEdges; + } + + public Atlas validCrossingWaterwayFordYesEdges() + { + return this.validCrossingWaterwayFordYesEdges; + } + + public Atlas validCrossingWaterwayLeisureSlipwayEdges() + { + return this.validCrossingWaterwayLeisureSlipwayEdges; + } +} From d08d3ac9ebbce433ea94efb257668520022da083 Mon Sep 17 00:00:00 2001 From: Marta Todea-Pako Date: Sun, 12 Dec 2021 22:59:20 +0200 Subject: [PATCH 2/2] Fix Sonar issues --- .../HighwayIntersectionCheck.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java b/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java index 7ebedd425..cd9710dd1 100644 --- a/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java +++ b/src/main/java/org/openstreetmap/atlas/checks/validation/intersections/HighwayIntersectionCheck.java @@ -93,7 +93,7 @@ protected Optional flag(final AtlasObject object) .anyMatch(intersection -> isCross(edge, crossingEdge, intersection))) .collect(Collectors.toSet()); - if (invalidIntersectingEdges.size() > 0) + if (!invalidIntersectingEdges.isEmpty()) { return this.createHighwayIntersectionCheckFlag(edge, invalidIntersectingEdges); } @@ -158,9 +158,17 @@ private Set getIntersection(final Edge firstEdge, final Edge secondEdg */ private boolean isWaterwayToCheck(final AtlasObject edge) { - return Validators.hasValuesFor(edge, WaterwayTag.class) - && !(HighwayTag.highwayTag(edge).isPresent() - && (WaterwayTag.get(edge).get().name().equalsIgnoreCase("dam") - || WaterwayTag.get(edge).get().name().equalsIgnoreCase("weir"))); + boolean validForCheck = false; + if (Validators.hasValuesFor(edge, WaterwayTag.class)) + { + final Optional waterwayTagValue = WaterwayTag.get(edge); + if (waterwayTagValue.isPresent()) + { + validForCheck = !(HighwayTag.highwayTag(edge).isPresent() + && (waterwayTagValue.get().name().equalsIgnoreCase("dam") + || waterwayTagValue.get().name().equalsIgnoreCase("weir"))); + } + } + return validForCheck; } }