-
Notifications
You must be signed in to change notification settings - Fork 81
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
Conversation
…Fixed )'s in validCheckForObject.
…g names, changed congig defaults to use tag classes, refactored Math.abs() to Edge.isMasterEdgeId().
…fig minimum.highway.type to residential
…linear to checks.validation.tag, updated javadocs.
… moved boolean checks around
{ | ||
for (final Area area : object.getAtlas() | ||
.areas(area -> Validators.isOfType(area, LandUseTag.class, LandUseTag.MILITARY) | ||
|| Validators.hasValuesFor(area, MilitaryTag.class))) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 LineItem
s. As far as I am aware, LineItem
s 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 Location
s 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.
There was a problem hiding this comment.
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())) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 Edge
s and Line
s. That way you can iterate military areas first and mark Edge
s and Line
s.
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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)) }, |
There was a problem hiding this comment.
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"; |
There was a problem hiding this comment.
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))) |
There was a problem hiding this comment.
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())) |
There was a problem hiding this comment.
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.
@Bentleysb sorry for the long merge delays, can you fix the conflicting files and we'll go ahead and merge |
* 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
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:
highway
tag is present and above a minimum priorityaccess
tag is present with a value ofno
access=no
, such aspublic_transport=yes
landuse=military
ormilitary=*
tagThis PR includes flag logic, configuration, unit tests, and documentation.
OSM Example:
Way id:28957025 has the
access=no
tag without any supporting tags, such aspublic_transport=yes
.