A bridge or tunnel should not suffice to stop warnings about crossing ways
URL
No response
How to reproduce the issue?
- Draw two crossing ways, one with
highway=residentialandbridge=yes, one withwaterway=river. - Draw two crossing ways with different
layerbut neitherbridgenortunnel.
Actual:
Neither is caught by the validator.
Expected:
1 should be flagged: With the noted exceptions of indoor/corridor/building/etc, crossing ways (highway, waterway, railway) having the same layer is never correct: They should either intersect or have different layers.
2 should be flagged: If two highway/waterway/railway ways cross each other, it's a virtual certainty that one is a bridge or tunnel. Tagging just the layer is not enough.
Screenshot(s) or anything else?
Having a bridge at layer=0 cross a non-bridge at layer=0 may seem unambiguous, but it confuses rendering. Screenshots near https://www.openstreetmap.org/changeset/160586698 with Tracestrack Topo:
The sidewalk has layer=1; the highway has layer=0; the sidewalk casing obscures the roadway.
Which deployed environments do you see the issue in?
Released version at openstreetmap.org/edit, Development version at ideditor.netlify.app, RapiD version at mapwith.ai/rapid
What version numbers does this issue effect?
2.31.0
Which browsers are you seeing this problem on?
No response
for reference, this is from the wiki:
Bridges should have a
layer=*, for simple crossings almost alwayslayer=1but other values may be appropriate for complex crossings.
(iD automatically adds layer=1 for newly tagged bridges using the field in the presets.)
It is however not that uncommon to see ways with bridge=* and no layer tag (about 7%), so making the validation more strict would potentially lead to many warnings that are not necessarily "problematic situations" (one could argue that a bridge could imply a layer=1 value). :thinking: Perhaps situations like this would be better accounted for in an external quality assurance tool?!
I do not know if this is related, but I too believe that iD should flag them.
There is a maproulette challenge to fix such issues: https://maproulette.org/browse/projects/58349 but sometimes it is hard to figure where exactly is the issue when the highlighted way is rather long.
I had those 2 ways crossings:
-
highway=trunk,layer=1 -
bridge=yes,highway=secondary,layer=1
And iD would not report the issue because of the following line (if I'm correct):
https://github.com/openstreetmap/iD/blob/6a88fe3d40db6e37012abd177e8228532c50a803/modules/validations/crossing_ways.js#L97
I believe there could be a middle ground between too much false positives or no, we could flag intersection in the following cases:
const wayALayer<int|null> = ...;
const wayBLayer<int|null> = ...;
const isWayABridge<bool> = ...;
const isWayBBridge<bool> = ...;
const isWayATunnel<bool> = ...;
const isWayBTunnel<bool> = ...;
const intersect = wayALayer === wayBLayer
&& (
wayALayer !== null // They both have a layer property
|| (isWayABridge && isWayBBridge) // None of them have layer, both are bridge
|| (isWayATunnel && isWayBTunnel) // None of them have layer, both are tunnel
|| (!isWayABridge && !isWayBBridge && !isWayATunnel && !isWayBTunnel) // None of them have layer, both are nor tunnel nor bridge
);
This would ensure that if both layer are defined then they would be flagged as intersect. But if both ways does not have a layer then they will be flagged as intersect only if they are both bridge or both tunnel or both none of bridge nor tunnel.
Note that this is not handling the case layer=0 intersect with "no layer".
one could argue that a bridge could imply a layer=1 value
It is maybe safe to assume this in case there is no layer set, it is maybe even safer to assume that a bridge without layer is just above everything else. Note that the wiki says (https://wiki.openstreetmap.org/wiki/Key:bridge#Layers):
Bridges should have a layer=*
Hence maybe there should instead be 2 lints: one that requires a layer for bridge and one that check the intersection on that layer?
Note that for tunnel it is less clear about the layer https://wiki.openstreetmap.org/wiki/Key:tunnel
Looking at the sources
https://github.com/openstreetmap/iD/blob/6a88fe3d40db6e37012abd177e8228532c50a803/modules/validations/crossing_ways.js#L81
// level logic
// TODO: Add building logic
// don't flag crossing waterways and pier/highways
if (featureType1 === 'waterway' && featureType2 === 'highway' && tags2.man_made === 'pier') return true;
if (featureType2 === 'waterway' && featureType1 === 'highway' && tags1.man_made === 'pier') return true;
var layer1 = tags1.layer || null;
var layer2 = tags2.layer || null;
if (layer1 !== null && layer1 === layer2) return false; // If both have a layer defined
const isElement1Bridge = allowsBridge(featureType1) && hasTag(tags1, 'bridge');
const isElement2Bridge = allowsBridge(featureType2) && hasTag(tags2, 'bridge');
if (isElement1Bridge ^ isElement2Bridge) return true; // Either one is bridge, the other is not
const isElement1Tunnel = allowsTunnel(featureType1) && hasTag(tags1, 'tunnel');
const isElement2Tunnel = allowsTunnel(featureType2) && hasTag(tags2, 'tunnel');
if (isElement1Tunnel ^ isElement2Tunnel ) return true; // Either one is tunnel, the other is not
return (layer1 || '0') !== (layer2 || '0');
The above logic should lead to the following test cases:
| layer1 | layer2 | bridge1 | bridge2 | tunnel1 | tunnel2 | isLegitCrossing |
|---|---|---|---|---|---|---|
| 1 | 2 | (any) | (any) | (any) | (any) | yes |
| 1 | 1 | (any) | (any) | (any) | (any) | no |
| null | 1 | (any) | (any) | (any) | (any) | yes |
| null | null/0 | yes | yes | (any) | (any) | no |
| null | null/0 | yes | no | (any) | (any) | yes |
| null | null/0 | (any) | (any) | yes | yes | no |
| null | null/0 | (any) | (any) | yes | no | yes |
Note that I did not define some cases like tunnel + bridge on the same way.
one could argue that a bridge could imply a layer=1 value
For the record, I stumbled upon a proposal to share such default values between software that was rejected https://wiki.openstreetmap.org/wiki/Proposal:Default_layer_for_bridge_and_tunnel. So I believe that we should not implement such logic.