Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid Access Tag Check #46

Merged
merged 35 commits into from
Jun 26, 2018
Merged

Invalid Access Tag Check #46

merged 35 commits into from
Jun 26, 2018

Conversation

Bentleysb
Copy link
Collaborator

This check flags Edges and Lines where the access tag is invalid due to an improper use or lack of supporting tags.

To be flagged all of the following must be true:

  • A highway tag is present and above a minimum priority
  • An access tag is present with a value of no
  • There are no supporting tags for access=no, such as public_transport=yes
  • The Edge or Line is not in an Area or Relation with a landuse=military or military=* tag

This PR includes flag logic, configuration, unit tests, and documentation.

OSM Example:
Way id:28957025 has the access=no tag without any supporting tags, such as public_transport=yes.

Bentleysb added 29 commits May 10, 2018 08:37
…g names, changed congig defaults to use tag classes, refactored Math.abs() to Edge.isMasterEdgeId().
…linear to checks.validation.tag, updated javadocs.
{
for (final Area area : object.getAtlas()
.areas(area -> Validators.isOfType(area, LandUseTag.class, LandUseTag.MILITARY)
|| Validators.hasValuesFor(area, MilitaryTag.class)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is iterating over all the areas. Please use a method like areasIntersecting that would limit the search.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with using areasIntersecting is that it requires a polygon, and this check is working with LineItems. As far as I am aware, LineItems can be converted to polygons by either using their bounding box, or by connecting there first and last nodes. If this was done, false negatives could result if a road that would be flagged was near a military tagged area.
areasCovering could be used, but would require iteration over all the Locations in the polyline of a LineItem. That is the best option I can come up with. I would love to hear if there is an even better alternative that you can think of.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LineItem has a method called bounds, which will give you a Polygon. You can retrieve areas intersecting that and filter them down. e.g. atlas.areasIntersecting(line.bounds(), area -> (line.intersects(areaPolygon) || areaPolygon.fullyGeometricallyEncloses(line.asPolyLine())) && (Validators.isOfType(area, LandUseTag.class, LandUseTag.MILITARY) || Validators.hasValuesFor(area, MilitaryTag.class))).

You should alsoe cache the result of object.asPolyLine(), because that method would be returning a new PolyLine object per call.

for (final Relation relation : object.getAtlas().relations(
relation -> (Validators.isOfType(relation, LandUseTag.class, LandUseTag.MILITARY)
|| Validators.hasValuesFor(relation, MilitaryTag.class))
&& relation.isMultiPolygon()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again this method is iterating over all the relations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, unfortunately, does not seem to have as easy a fix as with areas. There does not appear to be an equivalent to areasCovering for relations. The only thing I could find was relationsWithEntitiesIntersecting. Using this would create false positive flags for anything that was completely contained in a relation, if I am not mistaken. I do not see an alternative to iterating over all relations, but would love to consider anything you might be able to come up with. I only need to test multipolygon relations for the intersection or containment of the current check object.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment please. Retrieve relations intersecting line bounds and then filter them down.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the guidance. Your solution for areas is great. Unfortunately, it does not work in the case of relations. Using relationsWithEntitiesIntersecting will create false positive flags for items with bounds that are completely contained by the relation.

Example:
https://www.openstreetmap.org/way/251110595 contained by
https://www.openstreetmap.org/relation/7437523

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iterating over each and every relation should be avoided.

You can further filter relations returned from relationsWithEntitiesIntersecting method. That method accepts a second optional parameter: Predicate<Relation>. Something like:

object.getAtlas().relationsWithEntitiesIntersecting(object.bounds(), relation -> (Validators.isOfType(relation, LandUseTag.class, LandUseTag.MILITARY) || Validators.hasValuesFor(relation, MilitaryTag.class) && relation.isMultiPolygon()))

should give multi polygon relations with intersecting entities. Then MultiPolygon could be created from relation and checked for intersection.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this should be avoided, but after all this I do not see an alternative. I thank you very much for all your suggestions, unfortunately, the use of relationsWithEntitiesIntersecting will create false positive flags. The LineItems in question do not intersect any of the members of the military relations that contain them, even when the bounds of the LineItems are used. Thus, no relations are passed to the predicate for further filtering.

To completely substitute this loop, there would need to be a method that checks for containment of an item in a relation, not intersection.

As another example:
Unit test accessNoInHighwayEdgesLanduseMilitaryRelation simulates this scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but that sounds like a problem in atlas - possibly missing an API that could check for intersection against the relation altogether. Feel free to create an issue on atlas project, document it here and then move forward. False positives are acceptable. However, iterating over all relations should be avoided given that the number of relations in an Atlas could be huge and such iteration will be repeated potentially for each Edge in the same Atlas.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, you can edit this check to go through military areas rather than Edges and Lines. That way you can iterate military areas first and mark Edges and Lines.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing atlas relation method issue: Relation Covering Method #137

* This check flags {@link Edge}s and {@link Line}s that include an access tag with a value of no,
* and does not have any supporting tags. Supporting tags declare what is or is not included in
* {@code access=no}. For example a supporting tag of {@code public_transport=yes} would mean only
* public transport vehicles are allowed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document the use of tags.filter configuration. Otherwise, this check's implementation doesn't have a direct use of the tag example mentioned above. It'd be confusing.

@Node(coordinates = @Loc(value = TEST_7)),
@Node(coordinates = @Loc(value = TEST_8)),
@Node(coordinates = @Loc(value = TEST_9)),
@Node(coordinates = @Loc(value = TEST_10)) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to create a node for each shape point in an edge. You only need nodes for edge's end points.

private static final String TEST_11 = "0.2,-0.1";
private static final String TEST_12 = "-0.2,-0.1";
private static final String TEST_13 = "-0.2,1.0";
private static final String TEST_14 = "0.2,1.0";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is OK to use these values, I'd suggest using locations that are closer to real life lat/long values.

{
for (final Area area : object.getAtlas()
.areas(area -> Validators.isOfType(area, LandUseTag.class, LandUseTag.MILITARY)
|| Validators.hasValuesFor(area, MilitaryTag.class)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LineItem has a method called bounds, which will give you a Polygon. You can retrieve areas intersecting that and filter them down. e.g. atlas.areasIntersecting(line.bounds(), area -> (line.intersects(areaPolygon) || areaPolygon.fullyGeometricallyEncloses(line.asPolyLine())) && (Validators.isOfType(area, LandUseTag.class, LandUseTag.MILITARY) || Validators.hasValuesFor(area, MilitaryTag.class))).

You should alsoe cache the result of object.asPolyLine(), because that method would be returning a new PolyLine object per call.

for (final Relation relation : object.getAtlas().relations(
relation -> (Validators.isOfType(relation, LandUseTag.class, LandUseTag.MILITARY)
|| Validators.hasValuesFor(relation, MilitaryTag.class))
&& relation.isMultiPolygon()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment please. Retrieve relations intersecting line bounds and then filter them down.

@jklamer
Copy link
Collaborator

jklamer commented Jun 26, 2018

@Bentleysb sorry for the long merge delays, can you fix the conflicting files and we'll go ahead and merge

@jklamer jklamer merged commit ec4e6c1 into osmlab:dev Jun 26, 2018
yiqingj pushed a commit to yiqingj/atlas-checks that referenced this pull request Oct 25, 2018
* public/dev: (37 commits)
  Check resource loader update/Global Polygon Filter (osmlab#52)
  Invalid Lanes Tag Check (osmlab#55)
  Conflicting Area Tag Combination check (osmlab#53)
  Invalid Access Tag Check (osmlab#46)
  Sharp Angle Check Enhancement (osmlab#56)
  Intersecting Building Check Enhancments (osmlab#48)
  Batch Size sized by numer of buckets, but never less than 100) (osmlab#54)
  Log time to execute message as info (osmlab#51)
  Building Road Intersection Enhancements (osmlab#41)
  Fixing issue that was causing exception in MapRouletteClient when Def… (osmlab#49)
  create required maproulette challenge json object for check configs without defaultPriority (osmlab#47)
  MalformedRoundabout Configuration Bug (osmlab#45)
  Waterbody And Island Size Check (osmlab#44)
  Malformed Roundabout Check (osmlab#42)
  Update README and gradlew (osmlab#43)
  One Member Relation Check (osmlab#40)
  Sink Island Check Enhancements (osmlab#36)
  Update flagged point (osmlab#39)
  Address Point Match Check Bug Fix (osmlab#38)
  Updating atlas-generator dependency
  ...

# Conflicts:
#	dependencies.gradle
#	gradle.properties
#	gradle/wrapper/gradle-wrapper.properties
#	src/main/java/org/openstreetmap/atlas/checks/base/BaseCheck.java
#	src/main/java/org/openstreetmap/atlas/checks/base/CheckResourceLoader.java
#	src/main/java/org/openstreetmap/atlas/checks/validation/points/AddressPointMatchCheck.java
#	src/test/java/org/openstreetmap/atlas/checks/base/CheckResourceLoaderTest.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants