iD icon indicating copy to clipboard operation
iD copied to clipboard

A bridge or tunnel should not suffice to stop warnings about crossing ways

Open jleedev opened this issue 1 year ago • 3 comments

URL

No response

How to reproduce the issue?

  1. Draw two crossing ways, one with highway=residential and bridge=yes, one with waterway=river.
  2. Draw two crossing ways with different layer but neither bridge nor tunnel.

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:

Screenshot 2024-12-25 15 19 02Screenshot 2024-12-25 15 18 57Screenshot 2024-12-25 15 18 53Screenshot 2024-12-25 15 18 49

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

jleedev avatar Dec 25 '24 20:12 jleedev

for reference, this is from the wiki:

Bridges should have a layer=*, for simple crossings almost always layer=1 but 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?!

tyrasd avatar Jan 07 '25 10:01 tyrasd

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

Image

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.

homersimpsons avatar Apr 13 '25 21:04 homersimpsons

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.

homersimpsons avatar Apr 27 '25 21:04 homersimpsons