diff --git a/config/configuration.json b/config/configuration.json index 18877cd9b..b86f78491 100644 --- a/config/configuration.json +++ b/config/configuration.json @@ -1008,6 +1008,18 @@ "tags":"highway" } }, + "SeparateSidewalkTagCheck": { + "edge.length": 20.0, + "sidewalk.search.distance": 15.0, + "maximum.highway.type": "primary", + "challenge": { + "description": "Tasks contain separately mapped sidewalks that are inconsistent with highway's sidewalk tags.", + "blurb": "Modify sidewalks and highway sidewalks tags consistency", + "instruction": "Open your favorite editor and edit sidewalk tag", + "difficulty": "EASY", + "defaultPriority": "LOW" + } + }, "ShadowDetectionCheck": { "challenge": { "description": "Verify the height and level tags to make sure the building does not float in 3D", diff --git a/docs/available_checks.md b/docs/available_checks.md index b4b020a35..e5e5c1af1 100644 --- a/docs/available_checks.md +++ b/docs/available_checks.md @@ -99,6 +99,7 @@ This document is a list of tables with a description and link to documentation f | [MixedCaseNameCheck](checks/mixedCaseNameCheck.md) | The purpose of this check is to identify names that contain invalid mixed cases so that they can be edited to be the standard format. | | [RoadNameGapCheck](checks/RoadNameGapCheck.md) | The purpose of this check is to identify edge connected between two edges whose name tag is same. Flag the edge if the edge has a name tag different to name tag of edges connected to it or if there is no name tag itself. | [RoadNameSpellingConsistencyCheck](checks/RoadNameSpellingConsistencyCheck.md) | The purpose of this check is to identify road segments that have a name Tag with a different spelling from that of other segments of the same road. This check is primarily meant to catch small errors in spelling, such as a missing letter, letter accent mixups, or capitalization errors. | +| [SeparateSidewalkTagCheck](checks/separateSidewalkTagCheck.md) | The purpose of this check is to validate tagging consistency between sidewalk=* tags are used on a highway with separately mapped sidewalk(s). | | [SimilarTagValueCheck](checks/SimilarTagValueCheck.md) | The purpose of this check is to identify tags whose values are either duplicates or similar enough to warrant someone to look at them. | | ShortNameCheck | The short name check will validate that any and all names contain at least 2 letters in the name. | | [StreetNameCheck](checks/streetNameCheck.md) |This check looks for "ss" or "ß" in street_name or name tags in AUT, CHE, DEU and LIE. | diff --git a/docs/checks/separateSidewalkTagCheck.md b/docs/checks/separateSidewalkTagCheck.md new file mode 100644 index 000000000..be98941bc --- /dev/null +++ b/docs/checks/separateSidewalkTagCheck.md @@ -0,0 +1,43 @@ +# Separate Sidewalk Tag Check + +#### Description +A check to validate that when sidewalk=* tags are used on a highway that any separately mapped sidewalk(s) are consistent with the highway’s sidewalk tags. + +#### Live Example +Please note that examples below might be fixed olready. +1) [id:42023472](https://www.openstreetmap.org/way/42023472) +2) [id:415202408](https://www.openstreetmap.org/way/415202408) +3) [id:370064399](https://www.openstreetmap.org/way/370064399) +4) [id:684661218](https://www.openstreetmap.org/way/684661218) + + +#### Code Review +In [Atlas](https://github.com/osmlab/atlas), OSM elements are represented as Edges, Points, Lines, +Nodes & Relations; in our case, we’re working with [Edges](https://github.com/osmlab/atlas/blob/dev/src/main/java/org/openstreetmap/atlas/geography/atlas/items/Edge.java) that have Sidewalk tags. +In OpenStreetMap, [Sidewalks](https://wiki.openstreetmap.org/wiki/Key:sidewalk) ma + +Our first goal is to validate the incoming Atlas Object. +* Must be a valid main Edge +* Must have not already been flagged +* Must be car navigable +* Must have [Sidewalks](https://wiki.openstreetmap.org/wiki/Key:sidewalk) tags +* Must not be a closed way [OSM-wiki:Closed Way](https://wiki.openstreetmap.org/wiki/Item:Q4669) +* Must not be a [dual carriageway](https://wiki.openstreetmap.org/wiki/Tag:dual_carriageway%3Dyes). +* Must have a certain length (default 20 meters) + +Our second goal is to search for [separately mapped Sidewalks](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dfootway) around the Edge midpoint within certain search distance (default 15 meters). We use a [boxAround](https://github.com/osmlab/atlas/blob/dev/src/main/java/org/openstreetmap/atlas/geography/Location.java#L211) +to gather all sidewalks. + +After we found separately mapped sidewalks, we ensure that +* Sidewalk is on the same layer with the highway +* Sidewalk is not crossing the highway +* Sidewalk is not sharing a location with the highway +* Sidewalk is more or less parallel with the highway + +Our third goal is to identify the side (left|right) for every separately mapped sidewalk. + +After we identified the side, we ensure that tagging of highway sidewalk is consistent with separately mapped sidewalk. + + +To learn more about the code, please look at the comments in the source code for the check. +[SeparateSidewalkTagCheck.java](../../src/main/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheck.java) \ No newline at end of file diff --git a/src/main/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheck.java b/src/main/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheck.java new file mode 100644 index 000000000..5c98da71a --- /dev/null +++ b/src/main/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheck.java @@ -0,0 +1,347 @@ +package org.openstreetmap.atlas.checks.validation.linear.edges; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.openstreetmap.atlas.checks.base.BaseCheck; +import org.openstreetmap.atlas.checks.flag.CheckFlag; +import org.openstreetmap.atlas.exception.CoreException; +import org.openstreetmap.atlas.geography.Heading; +import org.openstreetmap.atlas.geography.Location; +import org.openstreetmap.atlas.geography.PolyLine; +import org.openstreetmap.atlas.geography.Segment; +import org.openstreetmap.atlas.geography.atlas.items.AtlasObject; +import org.openstreetmap.atlas.geography.atlas.items.Edge; +import org.openstreetmap.atlas.geography.atlas.walker.OsmWayWalker; +import org.openstreetmap.atlas.tags.FootTag; +import org.openstreetmap.atlas.tags.FootwayTag; +import org.openstreetmap.atlas.tags.HighwayTag; +import org.openstreetmap.atlas.tags.LayerTag; +import org.openstreetmap.atlas.tags.SidewalkLeftTag; +import org.openstreetmap.atlas.tags.SidewalkRightTag; +import org.openstreetmap.atlas.tags.SidewalkTag; +import org.openstreetmap.atlas.tags.oneway.OneWayTag; +import org.openstreetmap.atlas.utilities.collections.Iterables; +import org.openstreetmap.atlas.utilities.configuration.Configuration; +import org.openstreetmap.atlas.utilities.scalars.Angle; +import org.openstreetmap.atlas.utilities.scalars.Distance; + +import avro.shaded.com.google.common.collect.Range; +import avro.shaded.com.google.common.collect.Ranges; + +/** + * This check flags when sidewalk=* tags are used on a highway that any separately mapped + * sidewalk(s) are not consistent with the highway’s sidewalk tags. + * + * @author Vladimir Lemberg + */ +public class SeparateSidewalkTagCheck extends BaseCheck +{ + private static final String INSTRUCTION_FORMAT = "Way {0,number,#} is tagged as sidewalk={1} but separately mapped sidewalks were detected that are not consistent with the way's sidewalk tag. Verify that the sidewalk tag for this way is correct and consistent with separately mapped ways for the entirety of the way."; + private static final List FALLBACK_INSTRUCTIONS = Collections + .singletonList(INSTRUCTION_FORMAT); + // default distance (meters) for searching separate sidewalk around the edge + private static final Double SIDEWALK_SEARCH_DISTANCE_DEFAULT = 15.0; + // default edge length (meters) + private static final Double EDGE_LENGTH_DEFAULT = 20.0; + // heading degree range to ensure that separate sidewalk is more or less parallel to the highway + private static final Range HEADING_DEGREE_RANGE = Ranges.closed(-20.0, 20.0); + private static final String MAXIMUM_HIGHWAY_DEFAULT = HighwayTag.PRIMARY.toString(); + // alternative separate sidewalk mapping tag value: + // https://wiki.openstreetmap.org/wiki/Key:sidewalk:left + private static final String ALTERNATIVE_SIDEWALK_TAG_VALUE = "separate"; + private final Distance searchDistance; + private final Distance defaultEdgeLength; + private final HighwayTag maximumHighwayType; + + public SeparateSidewalkTagCheck(final Configuration configuration) + { + super(configuration); + this.searchDistance = configurationValue(configuration, "sidewalk.search.distance", + SIDEWALK_SEARCH_DISTANCE_DEFAULT, Distance::meters); + this.defaultEdgeLength = configurationValue(configuration, "edge.length", + EDGE_LENGTH_DEFAULT, Distance::meters); + this.maximumHighwayType = this.configurationValue(configuration, "maximum.highway.type", + MAXIMUM_HIGHWAY_DEFAULT, str -> Enum.valueOf(HighwayTag.class, str.toUpperCase())); + } + + @Override + public boolean validCheckForObject(final AtlasObject object) + { + return object instanceof Edge && !this.isFlagged(object.getOsmIdentifier()) + && ((Edge) object).isMainEdge() && HighwayTag.isCarNavigableHighway(object) + && this.validSidewalkFilter((Edge) object); + } + + @Override + protected Optional flag(final AtlasObject object) + { + final Edge edge = (Edge) object; + final Location edgeMidPoint = edge.start().getLocation().midPoint(edge.end().getLocation()); + final String sidewalkTagValue = this.getSeparateSidewalkTagValue(edge); + final Set separatedSidewalks = Iterables.stream(edge.getAtlas() + .edgesIntersecting(this.closestSegmentToPoint(edge.asPolyLine(), edgeMidPoint) + .middle().boxAround(this.searchDistance))) + .filter(this::validFootwayFilter).collectToSet(); + int rightSidewalkCount = 0; + int leftSidewalkCount = 0; + + if (!separatedSidewalks.isEmpty()) + { + for (final Edge sidewalk : separatedSidewalks) + { + final Segment closestSidewalkSegment = this + .closestSegmentToPoint(sidewalk.asPolyLine(), edgeMidPoint); + + if (!this.isCrossing(edge.asPolyLine(), sidewalk.asPolyLine()) + && LayerTag.areOnSameLayer(edge, sidewalk)) + { + if (this.isRightOf(edge.asPolyLine(), closestSidewalkSegment.middle())) + { + rightSidewalkCount++; + } + else + { + leftSidewalkCount++; + } + } + } + if (this.isSidewalkTaggingMismatch(sidewalkTagValue, rightSidewalkCount, + leftSidewalkCount)) + { + return this.generateFlag(edge, sidewalkTagValue); + } + + } + return Optional.empty(); + } + + @Override + protected List getFallbackInstructions() + { + return FALLBACK_INSTRUCTIONS; + } + + /** + * Find the closest line {@link Segment} to provided location. + * + * @param line + * {@link PolyLine} one to check + * @param location + * {@link Location} one to check + * @return the closest line segment to location. + */ + private Segment closestSegmentToPoint(final PolyLine line, final Location location) + { + final PolyLine tLine = new PolyLine(location); + return line.segments().stream() + .min(Comparator.comparingDouble(s -> s.shortestDistanceTo(tLine).asMeters())) + .orElseThrow(() -> new CoreException("Unable to get a Segment {}", line)); + } + + /** + * Generate and return flag for separately mapped sidewalk if tags are not consistent with the + * highway’s sidewalk tags. + * + * @param edge + * edge to flag + * @param sidewalkTagValue + * separate sidewalk tag value + * @return an optional {@link CheckFlag} object + */ + private Optional generateFlag(final Edge edge, final String sidewalkTagValue) + { + super.markAsFlagged(edge.getOsmIdentifier()); + return Optional.of(this.createFlag(new OsmWayWalker(edge).collectEdges(), + this.getLocalizedInstruction(0, edge.getOsmIdentifier(), sidewalkTagValue))); + } + + /** + * Return sidewalk tag value. Also mapping alternative sidewalk tagging to preferred. + * https://wiki.openstreetmap.org/wiki/Key:sidewalk + * + * @param edge + * edge to get sidewalk tag values. + * @return separate sidewalk tag value. + */ + @SuppressWarnings("squid:S3655") + private String getSeparateSidewalkTagValue(final Edge edge) + { + // preferred way of mapping sidewalks + if (edge.getTag(SidewalkTag.KEY).isPresent()) + { + return edge.getTag(SidewalkTag.KEY).get(); + } + + // alternative way of mapping sidewalk + if (edge.getTag(SidewalkLeftTag.KEY).isPresent() + && ALTERNATIVE_SIDEWALK_TAG_VALUE.equals(edge.getTag(SidewalkLeftTag.KEY).get()) + && (edge.getTag(SidewalkRightTag.KEY).isPresent() + && "no".equals(edge.getTag(SidewalkRightTag.KEY).get()) + || edge.getTag(SidewalkRightTag.KEY).isEmpty())) + { + return "left"; + } + + if (edge.getTag(SidewalkRightTag.KEY).isPresent() + && ALTERNATIVE_SIDEWALK_TAG_VALUE.equals(edge.getTag(SidewalkRightTag.KEY).get()) + && (edge.getTag(SidewalkLeftTag.KEY).isPresent() + && "no".equals(edge.getTag(SidewalkLeftTag.KEY).get()) + || edge.getTag(SidewalkLeftTag.KEY).isEmpty())) + { + return "right"; + } + + if (edge.getTag(SidewalkLeftTag.KEY).isPresent() + && ALTERNATIVE_SIDEWALK_TAG_VALUE.equals(edge.getTag(SidewalkLeftTag.KEY).get()) + && edge.getTag(SidewalkRightTag.KEY).isPresent() + && ALTERNATIVE_SIDEWALK_TAG_VALUE.equals(edge.getTag(SidewalkRightTag.KEY).get())) + { + return "both"; + } + return null; + } + + /** + * Verifies that separate sidewalk and highway are within acceptable heading degree range (more + * or less parallel). + * + * @param headingOne + * {@link Heading} one to check + * @param headingTwo + * {@link Heading} to check. + * @return {@code true} if both heading are within acceptable heading degree range + */ + private boolean isAcceptableHeading(final Heading headingOne, final Heading headingTwo) + { + final int primeMeridian = 180; + return HEADING_DEGREE_RANGE.contains(headingOne.asDegrees() - headingTwo.asDegrees()) + || HEADING_DEGREE_RANGE.contains(headingOne.asDegrees() + - (Math.abs(primeMeridian - headingTwo.asDegrees()))); + } + + /** + * Verifies if given {@link PolyLine} and {@link PolyLine} are crossing + * + * @param lineCrossed + * {@link PolyLine} being crossed + * @param crossingItem + * {@link PolyLine} crossing + * @return whether given {@link PolyLine} and {@link PolyLine}'s intersections are actual + * {@link Location}s for both items + */ + private boolean isCrossing(final PolyLine lineCrossed, final PolyLine crossingItem) + { + return !lineCrossed.intersections(crossingItem).isEmpty() + || lineCrossed.overlapsShapeOf(crossingItem) + || !this.isAcceptableHeading( + Objects.requireNonNull(lineCrossed.overallHeading().orElse(null)), + Objects.requireNonNull(crossingItem.overallHeading().orElse(null))); + } + + /** + * Check if {@link Edge} is a dual carriageway road. + * + * @param edge + * {@link Edge} to be checked + * @return {@code true} if {@link Edge} is dual carriageway. + */ + private boolean isDualCarriageWay(final Edge edge) + { + final Optional highwayTag = HighwayTag.highwayTag(edge); + final Optional onewayTag = OneWayTag.tag(edge); + return highwayTag.isPresent() && onewayTag.isPresent() + && highwayTag.get().isMoreImportantThanOrEqualTo(this.maximumHighwayType) + && "YES".equals(onewayTag.get().toString()); + } + + /** + * Check if a location is to the right of a line. + * + * @param line + * The line to compare the location to + * @param location + * The location + * @return {@code true} if the location is to the right of the line. + */ + private boolean isRightOf(final PolyLine line, final Location location) + { + final PolyLine locationLine = new PolyLine(location); + final Segment closest = line.segments().stream() + .min(Comparator.comparingDouble(s -> s.shortestDistanceTo(locationLine).asMeters())) + .orElse(null); + if (closest != null) + { + final PolyLine testLine = new PolyLine(closest.first(), closest.last(), location); + final Angle difference = testLine.headingDifference().orElse(null); + return difference != null && difference.asDegrees() > 0; + } + return false; + } + + private boolean isSidewalkTaggingMismatch(final String sidewalkTagValue, + final int rightSidewalkCount, final int leftSidewalkCount) + { + switch (sidewalkTagValue) + { + // sidewalk=right but separate sidewalks on left or both sides are detected + case "right": + return leftSidewalkCount > 0; + // sidewalk=left but separate sidewalks on right or both sides are detected + case "left": + return rightSidewalkCount > 0; + // sidewalk=both but separate sidewalk on left or ride side is detected. + case "both": + return rightSidewalkCount < 1 || leftSidewalkCount < 1; + default: + throw new CoreException("Unknown sidewalk tag value {}", sidewalkTagValue); + } + } + + /** + * Helper function for filtering {@link Edge}s. This is detecting that {@link Edge} is + * separately mapped sidewalk https://wiki.openstreetmap.org/wiki/Sidewalks or designated + * pedestrian road https://wiki.openstreetmap.org/wiki/Key:foot. + * + * @param edge + * Edge to examine + * @return true if {@link Edge} is passed validation. + */ + @SuppressWarnings("squid:S3655") + private boolean validFootwayFilter(final Edge edge) + { + return edge.isMainEdge() + && (edge.getTag(HighwayTag.KEY).isPresent() + && "footway".equals(edge.getTag(HighwayTag.KEY).get()) + && edge.getTag(FootwayTag.KEY).isPresent() + && "sidewalk".equals(edge.getTag(FootwayTag.KEY).get())) + || (edge.getTag(FootTag.KEY).isPresent() + && edge.getTag(FootTag.KEY).get().matches("yes|designated")); + } + + /** + * Helper function for filtering {@link Edge}s. This is to detect {@link Edge} sidewalk tag + * existence with other + * + * @param edge + * Edge to examine + * @return {@code true} if {@link Edge} sidewalk tag meet the criteria. + */ + @SuppressWarnings("squid:S3655") + private boolean validSidewalkFilter(final Edge edge) + { + return (edge.getTag(SidewalkTag.KEY).isPresent() + && edge.getTag(SidewalkTag.KEY).get().matches("left|right|both") + || edge.getTag(SidewalkLeftTag.KEY).isPresent() && ALTERNATIVE_SIDEWALK_TAG_VALUE + .equals(edge.getTag(SidewalkLeftTag.KEY).get()) + || edge.getTag(SidewalkRightTag.KEY).isPresent() && ALTERNATIVE_SIDEWALK_TAG_VALUE + .equals(edge.getTag(SidewalkRightTag.KEY).get())) + && !this.isDualCarriageWay(edge) + && edge.asPolyLine().length().asMeters() >= this.defaultEdgeLength.asMeters() + && !edge.isClosed(); + } +} diff --git a/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTest.java b/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTest.java new file mode 100644 index 000000000..e2df1f274 --- /dev/null +++ b/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTest.java @@ -0,0 +1,234 @@ +package org.openstreetmap.atlas.checks.validation.linear.edges; + +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; + +/** + * Tests for {@link SeparateSidewalkTagCheck} + * + * @author vladlemberg + */ + +public class SeparateSidewalkTagCheckTest +{ + @Rule + public SeparateSidewalkTagCheckTestRule setup = new SeparateSidewalkTagCheckTestRule(); + + @Rule + public ConsumerBasedExpectedCheckVerifier verifier = new ConsumerBasedExpectedCheckVerifier(); + + private Configuration configuration = ConfigurationResolver.inlineConfiguration( + "{\"SeparateSidewalkTagCheck\": {\"edge.length\": 20.0,\"sidewalk.search.distance\": 15.0,\"maximum.highway.type\": \"primary\"}}"); + + @Test + public void testInvalidClosedWayRightFootwayLeft() + { + this.verifier.actual(this.setup.getInvalidHighwayClosedWaySidewalkLeftSide(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testInvalidHighwayLeftSidewalkRight() + { + this.verifier.actual(this.setup.getInvalidHighwayLeftSidewalkRight(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayLeftSidewalkRightAlternativeMapping() + { + this.verifier.actual(this.setup.getInvalidHighwayLeftSidewalkRightSideAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayLeftSidewalkRightAlternativeMapping2() + { + this.verifier.actual(this.setup.getInvalidHighwayLeftSidewalkRightSideAlternativeMapping2(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayRightFootwayLeft() + { + this.verifier.actual(this.setup.getInvalidHighwayRightFootwayLeft(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayRightSidewalkLeft() + { + this.verifier.actual(this.setup.getInvalidHighwayRightSidewalkLeft(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayRightSidewalkLeftAlternativeMapping() + { + this.verifier.actual(this.setup.getInvalidHighwayRightSidewalkLeftAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayRightSidewalkLeftAlternativeMapping2() + { + this.verifier.actual(this.setup.getInvalidHighwayRightSidewalkLeftAlternativeMapping2(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidHighwayRightSidewalkLeftReverseHeading() + { + this.verifier.actual(this.setup.getInvalidHighwayRightSidewalkLeftReverseHeading(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidSidewalkBothSameSide() + { + this.verifier.actual(this.setup.getInvalidSidewalkBothSameSide(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidSidewalkBothSidesAlternativeMapping() + { + this.verifier.actual(this.setup.getInvalidSidewalkBothSideAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidSidewalkBothSidesLeftMissing() + { + this.verifier.actual(this.setup.getInvalidSidewalkBothSideLeftMissing(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidSidewalkBothSidesRightMissing() + { + this.verifier.actual(this.setup.getInvalidSidewalkBothSideRightMissing(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.globallyVerify(flags -> Assert.assertEquals(1, flags.size())); + } + + @Test + public void testInvalidSidewalkDualCarriageWay() + { + this.verifier.actual(this.setup.getInvalidSidewalkLHighwayDualCarriageWay(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testInvalidSidewalkEdgeDefaultLength() + { + this.verifier.actual(this.setup.getInvalidSidewalkLHighwayShotEdge(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testNoSidewalk() + { + this.verifier.actual(this.setup.getNoSidewalk(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testSidewalkCrossing() + { + this.verifier.actual(this.setup.getSidewalkCrossing(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testSidewalkDifferentLayer() + { + this.verifier.actual(this.setup.getSidewalkDifferentLayer(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testSidewalkHeadingOutsideDegreeRange() + { + this.verifier.actual(this.setup.getSidewalkHeadingOutsideDegreeRange(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testSidewalkSharingLocation() + { + this.verifier.actual(this.setup.getSidewalkSharingLocation(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkBothSides() + { + this.verifier.actual(this.setup.getValidSidewalkBothSide(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkBothSidesAlternativeMapping() + { + this.verifier.actual(this.setup.getValidSidewalkBothSideAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkLeftSide() + { + this.verifier.actual(this.setup.getValidSidewalkLeftSide(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkLeftSideAlternativeMapping() + { + this.verifier.actual(this.setup.getValidSidewalkLeftSideAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkRightSide() + { + this.verifier.actual(this.setup.getValidSidewalkRightSide(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } + + @Test + public void testValidSidewalkRightSideAlternativeMapping() + { + this.verifier.actual(this.setup.getValidSidewalkRightSideAlternativeMapping(), + new SeparateSidewalkTagCheck(this.configuration)); + this.verifier.verifyEmpty(); + } +} diff --git a/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTestRule.java b/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTestRule.java new file mode 100644 index 000000000..4e6d6d2ea --- /dev/null +++ b/src/test/java/org/openstreetmap/atlas/checks/validation/linear/edges/SeparateSidewalkTagCheckTestRule.java @@ -0,0 +1,560 @@ +package org.openstreetmap.atlas.checks.validation.linear.edges; + +import org.openstreetmap.atlas.geography.atlas.Atlas; +import org.openstreetmap.atlas.utilities.testing.CoreTestRule; +import org.openstreetmap.atlas.utilities.testing.TestAtlas; +import org.openstreetmap.atlas.utilities.testing.TestAtlas.Edge; +import org.openstreetmap.atlas.utilities.testing.TestAtlas.Loc; +import org.openstreetmap.atlas.utilities.testing.TestAtlas.Node; + +/** + * {@link SeparateSidewalkTagCheck} data generator + * + * @author vladlemberg + */ +public class SeparateSidewalkTagCheckTestRule extends CoreTestRule +{ + private static final String HIGHWAY_1 = "37.3485228,-121.9449555"; + private static final String HIGHWAY_2 = "37.3490966,-121.9433543"; + private static final String HIGHWAY_3 = "37.34855, -121.94487"; + private static final String SIDEWALK_RIGHT_1 = "37.34839,-121.94506"; + private static final String SIDEWALK_RIGHT_2 = "37.34874,-121.94408"; + private static final String SIDEWALK_LEFT_1 = "37.34858,-121.94512"; + private static final String SIDEWALK_LEFT_2 = "37.34886,-121.94427"; + private static final String SIDEWALK_LEFT_3 = "37.34874, -121.94524"; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "-1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk=right" }) }) + private Atlas noSidewalk; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkRightSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:right=separate", "sidewalk:left=no" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkRightSideAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=left" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkLeftSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:left=separate", "sidewalk:right=no" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkLeftSideAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=both" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), + @Edge(id = "1000000003", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkBothSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:right=separate", "sidewalk:left=separate" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), + @Edge(id = "1000000003", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas validSidewalkBothSideAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayRightSidewalkLeft; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:right=separate", "sidewalk:left=no" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayRightSidewalkLeftAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:right=separate" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayRightSidewalkLeftAlternativeMapping2; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_2), + @Loc(value = SIDEWALK_LEFT_1) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayRightSidewalkLeftReverseHeading; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2), @Loc(value = HIGHWAY_1) }, tags = { + "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayClosedWaySidewalkLeftSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "foot=yes" }) }) + private Atlas invalidHighwayRightFootwayLeftSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=trunk", "oneway=yes", + "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidSidewalkLHighwayDualCarriageWay; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_3)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_3) }, tags = { "highway=residential", "sidewalk=right" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidSidewalkLHighwayShotEdge; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=left" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayLeftSidewalkRightSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:left=separate", "sidewalk:right=no" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayLeftSidewalkRightSideAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:left=separate" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas invalidHighwayLeftSidewalkRightSideAlternativeMapping2; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=both" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), }) + private Atlas invalidSidewalkBothSideLeftMissing; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=both" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), }) + private Atlas invalidSidewalkBothSideRightMissing; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { + @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", + "sidewalk:right=separate", "sidewalk:left=separate" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), }) + private Atlas invalidSidewalkBothSideAlternativeMapping; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=both" }), + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), + @Edge(id = "-1000000002", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }), + @Edge(id = "1000000003", coordinates = { @Loc(value = SIDEWALK_RIGHT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "foot=designated" }) }) + private Atlas invalidSidewalkBothSameSide; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + // sidewalk sharing location with highway + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas sidewalkCrossing; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + // sidewalk sharing location with highway + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = SIDEWALK_LEFT_2) }, tags = { "highway=footway", + "footway=sidewalk", "layer=1" }) }) + private Atlas sidewalkDifferentLayer; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_3)), + @Node(coordinates = @Loc(value = SIDEWALK_RIGHT_2)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + // sidewalk sharing location with highway + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_3), + @Loc(value = SIDEWALK_RIGHT_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas sidewalkHeadingOutsideDegreeRange; + + @TestAtlas( + // nodes + nodes = { @Node(coordinates = @Loc(value = HIGHWAY_1)), + @Node(coordinates = @Loc(value = HIGHWAY_2)), + @Node(coordinates = @Loc(value = SIDEWALK_LEFT_1)) }, + // edges + edges = { @Edge(id = "1000000001", coordinates = { @Loc(value = HIGHWAY_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=residential", "sidewalk=right" }), + // sidewalk sharing location with highway + @Edge(id = "1000000002", coordinates = { @Loc(value = SIDEWALK_LEFT_1), + @Loc(value = HIGHWAY_2) }, tags = { "highway=footway", + "footway=sidewalk" }) }) + private Atlas sidewalkSharingLocation; + + public Atlas getInvalidHighwayClosedWaySidewalkLeftSide() + { + return this.invalidHighwayClosedWaySidewalkLeftSide; + } + + public Atlas getInvalidHighwayLeftSidewalkRight() + { + return this.invalidHighwayLeftSidewalkRightSide; + } + + public Atlas getInvalidHighwayLeftSidewalkRightSideAlternativeMapping() + { + return this.invalidHighwayLeftSidewalkRightSideAlternativeMapping; + } + + public Atlas getInvalidHighwayLeftSidewalkRightSideAlternativeMapping2() + { + return this.invalidHighwayLeftSidewalkRightSideAlternativeMapping2; + } + + public Atlas getInvalidHighwayRightFootwayLeft() + { + return this.invalidHighwayRightFootwayLeftSide; + } + + public Atlas getInvalidHighwayRightSidewalkLeft() + { + return this.invalidHighwayRightSidewalkLeft; + } + + public Atlas getInvalidHighwayRightSidewalkLeftAlternativeMapping() + { + return this.invalidHighwayRightSidewalkLeftAlternativeMapping; + } + + public Atlas getInvalidHighwayRightSidewalkLeftAlternativeMapping2() + { + return this.invalidHighwayRightSidewalkLeftAlternativeMapping2; + } + + public Atlas getInvalidHighwayRightSidewalkLeftReverseHeading() + { + return this.invalidHighwayRightSidewalkLeftReverseHeading; + } + + public Atlas getInvalidSidewalkBothSameSide() + { + return this.invalidSidewalkBothSameSide; + } + + public Atlas getInvalidSidewalkBothSideAlternativeMapping() + { + return this.invalidSidewalkBothSideAlternativeMapping; + } + + public Atlas getInvalidSidewalkBothSideLeftMissing() + { + return this.invalidSidewalkBothSideLeftMissing; + } + + public Atlas getInvalidSidewalkBothSideRightMissing() + { + return this.invalidSidewalkBothSideRightMissing; + } + + public Atlas getInvalidSidewalkLHighwayDualCarriageWay() + { + return this.invalidSidewalkLHighwayDualCarriageWay; + } + + public Atlas getInvalidSidewalkLHighwayShotEdge() + { + return this.invalidSidewalkLHighwayShotEdge; + } + + public Atlas getNoSidewalk() + { + return this.noSidewalk; + } + + public Atlas getSidewalkCrossing() + { + return this.sidewalkCrossing; + } + + public Atlas getSidewalkDifferentLayer() + { + return this.sidewalkDifferentLayer; + } + + public Atlas getSidewalkHeadingOutsideDegreeRange() + { + return this.sidewalkHeadingOutsideDegreeRange; + } + + public Atlas getSidewalkSharingLocation() + { + return this.sidewalkSharingLocation; + } + + public Atlas getValidSidewalkBothSide() + { + return this.validSidewalkBothSide; + } + + public Atlas getValidSidewalkBothSideAlternativeMapping() + { + return this.validSidewalkBothSideAlternativeMapping; + } + + public Atlas getValidSidewalkLeftSide() + { + return this.validSidewalkLeftSide; + } + + public Atlas getValidSidewalkLeftSideAlternativeMapping() + { + return this.validSidewalkLeftSideAlternativeMapping; + } + + public Atlas getValidSidewalkRightSide() + { + return this.validSidewalkRightSide; + } + + public Atlas getValidSidewalkRightSideAlternativeMapping() + { + return this.validSidewalkRightSideAlternativeMapping; + } +}