a-b-street / osm2lanes Goto Github PK
View Code? Open in Web Editor NEWA common library and set of test cases for transforming OSM tags to lane specifications
Home Page: https://a-b-street.github.io/osm2lanes/
License: Apache License 2.0
A common library and set of test cases for transforming OSM tags to lane specifications
Home Page: https://a-b-street.github.io/osm2lanes/
License: Apache License 2.0
https://github.com/a-b-street/osm2lanes/blob/main/osm2lanes/src/transform/tags_to_lanes/modes/non_motorized.rs is in a very messy state right now.
I suggest removing anything not needed to pass tests.
Most of Lyon breaks without this support, eg, https://www.openstreetmap.org/way/113485483. Reminder to self to add a test and start to work on this
Improve the website UI to hint that the tags in text form are editable.
The website https://a-b-street.github.io/osm2lanes/ has a "OSM Way ID", but it would be easier to select this from a slippy map.
Just starting a place where we can discuss ideas with @tyrasd about tackling openstreetmap/iD#387
Inputting in https://a-b-street.github.io/osm2lanes/
highway=residential
cycleway=track
auto-fills to
cycleway:both=lane
cycleway:left:oneway=-1
cycleway:right:oneway=yes
highway=residential
lanes=2
lanes:backward=1
lanes:forward=1
shoulder=no
sidewalk=no
Now, where does the cycle lane come from?
It looks like some cycleway=opposite*
tagging is not understood. This is the "old" method how to tag cycleways that have cyclist contraflow in oneway streets, but it is (still) used a lot and will likely never completely go away.
The table below assumes a country with right-hand traffic. Note that the sides flip if oneway=-1
and if it is in a country with left-hand traffic.
input | current output | expected output | comment |
---|---|---|---|
|
|
oneway=yes
cycleway:left=lane
cycleway:left:oneway=-1
+ oneway:bicycle=no |
The tag can be inferred from |
|
Conversion Error: unsupported: 'cycleway=opposite without oneway=yes oneway:bicycle=no' |
oneway=yes
+ cycleway:left=no
+ oneway:bicycle=no |
It is not an error if they are not tagged explicitly as these can be unambiguously be inferred from |
|
(nothing?) |
+ oneway=yes
+ cycleway:left=track
+ cycleway:left:oneway=-1
+ oneway:bicycle=no |
|
|
(nothing?) |
+ oneway=yes
+ cycleway:left=share_busway
+ cycleway:left:oneway=-1
+ oneway:bicycle=no |
That cycleway tagging refers to a busway that is itself not tagged can be considered incomplete / erronous tagging, however, that's not the point |
Note: Follow-up of this ticket would be to consider it invalid/ambiguos tagging if the cycleway=opposite*
tagging contradicts with other tagging, e.g. cycleway=opposite + oneway=no
or cycleway=opposite + oneway=yes + oneway:bicycle=yes
or cycleway=opposite_lane + oneway=yes + cycleway:left=track
etc.
oneway=-1
means that the road is a oneway to the opposite direction in which the way is drawn. E.g. if the road is drawn for North to South, it would be a oneway from South to North.
The last test in A/B Street has the following specification:
(
"https://www.openstreetmap.org/way/335668924",
vec!["lanes=1", "sidewalk=none"],
DrivingSide::Right,
"SddS",
"vv^^",
),
Why do we assume two traffic lanes here?
A recent ping reminded me to update my local A/B-Streets install. Browsing around my city in A/B-Street, which is always a pleasure, I got to see some bidirectional cycleways, which in fact are single direction only. Eg. https://www.openstreetmap.org/way/25745877 has a lane for cyclists contra-flow motorists. Its tagging looks like polished with StreetComplete, still I consider the tagging accurate and complete, if not over-complete.
In A/B-Street, the "opposite-lane" (an old-fashioned osm jargon) for cyclists renders as a bidirectional cycle-way, where in reality, it is just a narrow cycle-only-lane contra the one-way. Cyclists going the motorist-one-way direction are to use the carriageway just as usual.
The OSM-Wiki is silent about directionality in such cases. I asked on the new forum, but only got on response from somebody, sharing the same background that I operate on ;) Is this different in e.g. Seattle? Or, are there just no tiles/presets for that? Or …
Each (non-separator) lane on an OSM way must have a width.
See: https://wiki.openstreetmap.org/wiki/Key:width#Width_of_streets
In the unlikely event that all of the relevant width:carriageway
, cycleway:<side>:width
, parking:lane:<side>:width
, shoulder:width
, lanes:width
are specified, we could have a trivial implementation. This is rarely the case, so we must assume incomplete information.
Locale (the region specific encoding of highway construction conventions) will be used to infer the width of each lane.
As this is constant for a given road, we will treat this and the resulting widths as constant in our requirements and algorithms.
When no width is given, the locale is used to determine typical widths of the lanes in the road.
If tags for certain lanes are provided (e.g. cycleway:<side>:width
), the defaults can be replaced.
width=*
or width:carriageway=*
When a total width is given, we have the strict requirement to fill that width.
In the simple case, we could use the same method as above, and then scale all the lanes by the same factor to reach this requirement. However (depending on the locale) it is reasonable to imagine situations where this is insufficient. For example, bus lanes are unlikely to expand beyond a maximum width, shrinking footpaths will take precedence over shrinking travel lanes, there is a minimum size for a parallel parking bay, etc.
One proposal could be to model the following parameters per locale:
Width {
min_width: Option<Metre>,
default_width: Option<Metre>,
max_width: Option<Metre>,
}
The lanes are still scaled together to meed the width, but will staurate at their minimum or maximum.
In situations where the width constraints cannot be met, an error may be thrown.
As more tags are provided (e.g. cycleway:<side>:width
), the calculation above can be further constrained.
Consumers may not want osm2lanes to guess what the width should be, so this should be a config option.
When a lane width has been inferred with no guarantee of correctness, it should be excluded from the proposed/normalized/roundtrip OSM tags.
This may require an internal representation of the data:
enum DataWithConfidence {
Direct, // Stated in a tag
Calculated, // Other tags, when combined, can be used to calculate this
Locale, // Not known for sure, so based on locale
Default, // Locale has no standard, so defaults are used
Unknown, // Unknown
}
We ignore situations where the OSM tags are contradictory.
The current implementation does a single direct assignment of the lanes (excluding separators) and all their parameters.
Options:
"Simple"
Assign the default width first, and as a post processing step apply the above algorithm to mutate the widths.
This has the downside that information from other tags cannot be added on the preceding step
"Builder"
A LaneBuilder
struct is passed around instead of a Lane
, upon which properties like maximum and minimum widths may be set.
At the end, a LaneBuilder.lane(self)
is called to return the API Lane
.
This would allow for more future flexibility when building lanes across multiple "passes".
Downside: this will be a bit of work to rewrite the current implementation.
My idea for surfacing the provenance of values in the output to the user, and providing clarity and control for the round-trip problem is this: Let the user configure if and when osm2lanes should guess details, instead of annotating every detail with its provenance.
If osm2lanes always guesses and annotates data, the chance that the user needs to process the output to filter out guesses that they don't want is high. If the level of guessing is customisable, it is likely that one of the options is exactly what they want:
Tagging every value in every entry in the output will turn the resulting JSON into a wall of text in no time, and I am not looking forward to any part of that experience.
The same tags can be converted in different modes, and the user can compare between the two outputs to make more nuanced decisions.
I feel like this will be easier to implement than tracking provenance, especially if we come up with guesses that have nock-on effects in the rest of the parsing process (such as arbitrarily resolving conflicts). There will be no need to keep track of all the values that have been effected by the guess, while the user can still figure out what was assumed.
When fetching ways by way ID in the website, there is a small delay waiting on overpass. It would be a better interface if this active wait was communicated to the user.
A loading animation would be nice, but the simple solution would be to change the button text to "Loading...".
I'd vote for the second, since it seems less work.
Should we use https://json-schema.org or switch to protocol buffers or similar?
First thing is the set of lane types, and how we want to add details to some of them. For instance, we could have parallel_parking
and diagonal_parking
... or type = parking, parking_type = parallel
. If we used protos, we could be more precise and show that the parking_type
field is only valid when type = parking
by using oneof. Any preferences?
The next major question on my mind is whether to represent a bus/transit-only lane, or instead list access/usage restrictions. We could just say "travel lane" with some subset of [motor vehicle, high-occupancy vehicle, public transit, taxi] allowed.
I also don't want to get too bogged down in deciding things that're pretty quick to switch in the code, but I'm not convinced blindly following A/B Street's current schema is the right choice.
It says:
osm2lanes-cli
- CLI toolBut the actual is named:
osm2lanes-bin
Support aromatic check for Kotlin implementation.
If ways are close together, e.g. a road and an adjacent cyclepath, one may not be selectable.
This is because overpass returns the ways within 10m in no particular order:
https://github.com/a-b-street/osm2lanes/blob/main/osm2lanes/src/overpass.rs#L146
As far as I know, there is no overpass API to do what we want (find the nearest), so we may need to do a linear search of all line segments in the geometries of all returned ways to find which one is the closest to the queried point.
cargo run way 240294912
https://www.openstreetmap.org/way/240294912
osm2lanes/src/transform/tags_to_lanes/lane.rs:205:33
It would be good to have an ordered list of tags (key + val) used in ways, such that we can prioritize support.
We can then make milestones tracking our coverage of all tags used in >1% of ways, then 0.1% of ways, etc.
e.g. https://taginfo.openstreetmap.org/tags/oneway=yes is used in 1.77% of ways.
I think it would be good to share country-related metadata with other tools.
For example, we could fork https://github.com/streetcomplete/StreetComplete/blob/master/res/country_metadata into a different repo, and then include it both here and in streetcomplete as a compile time dependency to determine locale specific data.
Complication: https://github.com/streetcomplete/StreetComplete/blob/master/COPYING this license is incompatible with ours as far as I know.
Either we need to rewrite this from scratch, or discuss licensing with the StreetComplete maintainer.
https://www.openstreetmap.org/way/485926026
{"cycleway": "track", "cycleway:left": "track", "cycleway:left:width": "1.25", "cycleway:right": "lane", "cycleway:right:width": "1.25", "highway": "trunk", "lcn": "yes", "maxspeed": "30 mph", "name": "Wilmslow Road", "parking:lane:both": "no_parking", "ref": "A6010", "surface": "asphalt"})
unsupported: 'cycleway=* with any cycleway:* values
Just noting an error I keep spotting. Will add a test and dig into the problem
A large part of contributing to OSM goes through the wiki.
This tool should be mentioned there somehow.
It looks like some busway=opposite_lane
tagging is not interpreted correctly.
The table below assumes a country with right-hand traffic. Note that the sides flip if oneway=-1
and if it is in a country with left-hand traffic.
input | current output | expected output |
---|---|---|
|
|
oneway=yes
- lanes=1
- busway:both=lane
+ busway:left=lane |
|
|
- lanes=2
+ oneway=-1
+ busway:right=lane |
The current test case suite lacks bus lanes, cycleway separators, and probably other cases. I can generate a JSON test case for every single OSM way in a region using the Rust implementation. Then run the Python/Kotlin implementation against them, look for discrepancies, and boil down to the simplest test cases.
On the current website (https://a-b-street.github.io/osm2lanes/) you will notice that a tag of lanes=6
becomes lanes=5
!
This is clearly a bug.
Start by making a test case that fails:
https://github.com/a-b-street/osm2lanes/blob/main/data/tests.yml
And then try to find out how to fix it!
Looking at https://a-b-street.github.io/osm2lanes/ I see
sidewalk=both
workssidewalk:left=yes
workssidewalk:right=yes
workssidewalk:both=yes
does not work, yetAFAIK, for all currently accepted tags(*) the the :both
tagging is supported whenever there is a :left|right
version and the version of the tag without a side is an implicit :both
.
*) I know of one exception, which is the WIP separation schema https://wiki.openstreetmap.org/wiki/Proposed_features/cycleway:separation
If no side is given, the side towards the strongest traffic user is meant by default (usually towards a road with motor vehicles – in countries with right-hand traffic usually on the left-hand side of the cycle path).
(PS: I suggest commenting on that proposal in case you find this too complex for data consumers to handle; I tried to raise this issue before, but with little success :-))
Of topic: Are issues like this helpful? Or is it better to wait for a while and test once you are happy with a release?
Reading #79, I was wondering what a similar ticket would look like for an easier tagging topic (than width), like surface
(and very similarly smoothness
).
Each lane should have a fallback or direct(ly taggeg) surface tag. Including separator-"lanes".
surface
and smoothness
from StreetComplete https://docs.google.com/spreadsheets/d/1-JiRgPPSByqyt7qQagFYJ3O7OvVh2DTJY_2-x9oeExs/edit#gid=0smoothness
Gallery https://wiki.openstreetmap.org/wiki/Key:smoothness/GalleryWhat tags to consider…?
sidewalk:<Side|None>:surface
paving_stones
in Germany, I would sayparking:lane:<Side>:surface
highway=*
.surface
cycleway:<Side|none>:surface
highway=*
.surface
This has different fallbacks IMO, that is why I list it separately. Only PBL could fall back to the highway-surface IMO, but those are not mapped explicitly via one tag, so we have no way of identifying them.
cycleway:<Side|none>:surface
paving_stones
in Germany, I would say – at least for the existing, old infrastructure we have now. In Berlin the mobility law defines asphalt
for new cycleways AFAIK.The combination highway=cycleway + surface=*
has 750,000 objects https://taginfo.openstreetmap.org/tags/highway=cycleway#combinations.
highway=
.surface
track
> ground
asphalt
in GermanyFor a local analysis, I used this mapping to provide fallback values for missing data: https://github.com/FixMyBerlin/osm-scripts/blob/main/ZESPlus/Highways-SurfaceData/utils/assumedSmoothnessBasedOnHighway.ts#L3-L24. However, this is part of a script that adds smoothness
values to all highways using multiple layer of fallbacks, so that is what it is optimized for.
To complete this list, I should look at the types of buffer and other lanes, that osm2lanes creates …
I will update this based on feedback and what comes to mind later.
See https://wiki.openstreetmap.org/wiki/Key:cycleway:lane
It looks like cycleway=shared_lane
is also not understood.
See the discussion in #185.
Note: I don't actually notice this on my desktop, but I do on my laptop...
I would like the examples and particularly syntax highlighting to be loaded lazily.
Tagging like
cycleway=no + cycleway:left=track
cycleway=track + cycleway:left=no
cycleway:both=lane+ cycleway:right=track
should report an error.
I.e. wherever cycleway:both
/ cycleway
contradicts with the cycleway:<direction>
tag
This tagging is ambiguous and either one of these tags must be a mistake (or both).
We have a British and Dutch example on the website. I am looking for suggestions for ways in other country that are good examples.
A good example is:
At the time of writing, there is a python, kotlin, and rust implementation intending to cover the same functionality.
This issue tracks the development of a strategy on what language bindings and implementations to support, how to support them, and how to track their capabilities. (There were other discussions, but this is to regroup them).
The readme states
This repo is currently just for starting this experiment. No license chosen yet.
https://github.com/a-b-street/osm2lanes#osm2lanes
I just wanted to add this issue to not miss the point when the experiment becomes a project that should have a license …
I have now started a very minimal prototype in https://github.com/a-b-street/osm2lanes/tree/web_editor to make a new web app that lets people select an OSM way, see the rendered lanes in a cross-section view, edit those lanes (adding, deleting, reordering, modifying width, etc), generate the OSM tags for the changes, and upload to OSM. This is a step towards making it easier to edit lane data in OSM.
@BudgieInWA and I discussed some of the complications that'll come up. Two of the big ones:
When a road is split into multiple parallel ways, what do we do? The lane editor as I'm building it operates on a single way. We could maybe ask the user to draw a line and select all of the ways they want to edit, then present a unified cross section across all of them, and make it very clear which way is getting edited. Of course it won't be that simple, so to start, my goal is just to handle simple cases where one way corresponds to the "entire" road.
The left-to-right order of the draggable lane cards of course depends how the way in OSM is oriented. We need to display the way on the map and make it clear what's happening. Even better, leverage osm2streets + some rendering to draw the lanes on the 2D map at the same time.
I'm building using vanilla JS, which is new to me (this is a learning project!).
When I get something minimally decent open, I'll open a PR -- hopefully a few days if I can keep dodging other responsibilities. :)
https://www.openstreetmap.org/way/200596577
panicked at 'called
Option::unwrap()on a
None value', osm2lanes/src/transform/tags_to_lanes/mod.rs:418:80
Relevant line is let backward_edge = lane_to_edge_separator(self.backward_outside().unwrap());
Start by adding a test case, then figure out what went wrong
cargo run way 1005922755
yields "error": "unimplemented: highway=living_street"
(https://www.openstreetmap.org/way/1005922755)
Few thoughts:
With all the indirections around error transformations, it's not easy to spot the place in the source that's actually deciding this tag isn't implemented. I searched for unimplemented_tag
, and the 3 places don't seem relevant. Should we consider one of the error handling crates that adds a bit of context of file + line number of the "thrown" error?
I'd add a test case, except I don't know what we want to infer about highway=living_street
(the access=destination
doesn't seem relevant). Standard 1 travel lane and sidewalk each side?
This one's interesting, because someone has fixed the upstream data since then. It causes a panic now, so I'll definitely add a test case.
https://www.openstreetmap.org/way/102917976 is now fixed, but in my old copy:
<way id="102917976" version="15" timestamp="2021-07-08T22:56:38Z" changeset="0">
<nd ref="1487927529"/>
<nd ref="7085519171"/>
<nd ref="8523528017"/>
<nd ref="3629413438"/>
<nd ref="4273741094"/>
<tag k="bicycle" v="designated"/>
<tag k="cycleway" v="lane"/>
<tag k="highway" v="secondary"/>
<tag k="lanes" v="5"/>
<tag k="lanes:backward" v="1"/>
<tag k="lanes:both_ways" v="1"/>
<tag k="lanes:forward" v="3"/>
<tag k="maxspeed" v="3025 mph"/>
<tag k="name" v="South Royal Brougham Way"/>
<tag k="name_1" v="State Route 519"/>
<tag k="surface" v="asphalt"/>
<tag k="tiger:cfcc" v="A31"/>
<tag k="tiger:county" v="King, WA"/>
<tag k="tiger:name_base" v="Royal Brougham"/>
<tag k="tiger:name_base_1" v="State Route 519"/>
<tag k="tiger:name_direction_prefix" v="S"/>
<tag k="tiger:name_type" v="Way"/>
<tag k="turn:lanes:backward" v="right"/>
<tag k="turn:lanes:both_ways" v="left"/>
</way>
/home/dabreegster/.cargo/git/checkouts/osm2lanes-0a9401f46878d04a/df0e7bb/osm2lanes/src/transform/tags_to_lanes/separator/semantic.rs:27:18
Something less dutch...
In honor of @dabreegster 's current neighbours, I was thinking:
https://www.openstreetmap.org/way/201619353
https://www.google.nl/maps/@51.4944808,-0.1225736,3a,75y,101.15h,63.33t/data=!3m6!1e1!3m4!1srm9HZspurzms6jqE4ZK0cg!2e0!7i16384!8i8192
Look at that sorry excuse for a bicycle lane!
I will need to add parking:condition:both=no_stopping
upstream to get the red colour.
An interesting road with bus lanes, cycle lanes, and electric vehicle lanes.
It breaks today without warning: the bus lane is sandwiched between 2 car lanes, and the roundtrip has bus:lanes=|||designated||||
As of writing, the input is:
bicycle:lanes=||designated
bus:lanes=|designated|
cycleway:right=lane
cycleway:right:width=2
electric_vehicle:lanes=|no|
highway=trunk
lanes=3
maxspeed=40
motor_vehicle:lanes=|no|no
name=Dronning Eufemias gate
oneway=yes
placement=right_of:1
ref=E 18
surface=asphalt
surface:colour:lanes=||red
width:lanes=3|3|2
wikidata=Q11966089
The roundtrip is:
bus:lanes=|||designated||||
cycleway:right=lane
cycleway:right:oneway=yes
highway=trunk
lanes=3
maxspeed=40
oneway=yes
shoulder=no
sidewalk=no
https://wiki.openstreetmap.org/wiki/Tags
A key type, at its simplest it could be a &'static str
or String
. See also: https://lib.rs/crates/kstring.
&'static str
s.Add
trait implemented to support :
joined keys (i.e. A + B + C == "a:b:c"
)A value type, at its simplest it could be a &'static str
or String
.
Trait implemented to support ;
joined keys.
The result should also resemble an iterable.
Example: [A, B, C].into() == "a;b;c"
.
Support interaction mimicking a HashMap
or BTreeMap
<K, V>
, for example:
fn get<Q>(&self, key: &Q) -> Option<V>
fn is<Q, U>(&self, key: &Q, value: &U) -> bool
fn is_any<Q, W>(&self, key: &Q, values: &W) -> bool
Arguments of type Q
should be possible directly from a &'static str
, .e.g. tags.get("highway")
.
Support access as a tree structure, for :
separated keys.
Example:
// foo:bar:baz=toto
tags.tree().get("foo").unwrap().get("bar").unwrap().is("baz", "toto")
In addition to the constraints on the key (see kstring):
foo:bar
using foo
will be O(N).:
split cost when not needed, i.e. get("foo" + "bar")
must not allocate a String("foo:bar")
which is then .split_once(':')
.For now, this should replace https://github.com/a-b-street/osm2lanes/tree/main/rust/osm2lanes/src/tag.
Once proven, a separate crate should be made.
We could have a simple webpage hosted on github pages where you copy in an OSM way's key/values, press a button, and get the JSON lanes output. Internally it can use Javascript and call the Rust implementation, compiled to WASM.
Next steps after that could be a Leaflet or Mapbox map, where you click on a way, we query Overpass for the nearest way and its tags, and do the same thing.
And then from there, maybe consider some kind of rendering/visualization, just for a single road.
I want to propose that dividers be represented internally by their semantics, instead of their visual/physical manifestation, and be translated into specific markings in a separate step. My initial feeling is that it would shift most or all locale dependent questions about dividers out of the tag parsing step, into its own divider to markings step. Providing the divider semantics in the output would also be useful for users.
Dividers would be broadly categorised something like:
with additional semantic properties such as
dividers_to_markings
A separate function concerned with just the problem of converting semantic dividers to markings in the context of a given road would be a easier for new contributors to contribute to, which would be valuable for capturing global nuances. (I would be interested to see how static the mappings turn out to be.)
Having the markings be a separate step would also be a useful to allow additional information to be added to the road after examing the semantics. E.g. I have two connected OSM ways: 2 lanes into 3 lanes. I get the semantic lane info, compare them and decide that first lane in the 3 lane way is an added lane. I annotate the appropriate divider as "merging" before getting markings, and receive a beautifully appropriate dotted line (here in Oz).
Exposing the function as part of the API would also be a good way to query the lane marking database, because describing a situation from scratch in the output schema is much easier than describing it in the OSM schema!
Given that different locales might have different width markings for the same semantic divider, semantic dividers would have zero width: their markings fit within the the width(s) of the adjacent lane(s). (I'm not even sure this isn't how it already works). This is how I would prefer to receive osm2lanes output in semantic mode as a user.
This makes the "median" divider the odd one out, as the only divider with width of its own. Perhaps this suggest that the median itself should be a "lane" like a shoulder or a verge. One benefit is that the markings that divide the road from the median can be described too. In Australia, a median will often have a continuous solid line surrounding it, even as it transitions from a solid colour to a raised median to a diagonal hatching. The following output to describe the median would make sense to me:
{"type": "travel_lane", "direction": "forward"},
{"type": "separator", "markings": [{"style": "solid_line"}]},
{"type": "median", "kind": "raised"}, // or "colored" or "striped" or whatever
{"type": "separator", "markings": [{"style": "solid_line"}]},
{"type": "travel_lane", "direction": "backward"},
Medians are not well represented in OSM at the moment (divider=
is the best I could find), but that is no reason not to represent then in this schema.
By far the most common problem I'm seeing with real data is more than one bus lanes scheme used. One example is https://www.openstreetmap.org/way/679636490. Glancing at this, I can't help feeling like though it uses two schemes, they both agree -- there's exactly 1 backwards lane and it's bus-only.
For #71, I'll probably be tactical in the short-term, detect these cases, and just arbitrarilyish rip out keys for one of the schemes. But I had another idea -- if we could parse each bus scheme independently, clone the road builder, and "try out" both schemes, then we could check if the results match. If so, just a warning about redundant tags could suffice -- no need to totally give up?
https://www.openstreetmap.org/way/185226351 (an alleyway) and https://www.openstreetmap.org/way/742718564 (a larger road with a center turn lane) both come up as
{
"type": "travel",
"direction": "both",
"designated": "motor_vehicle",
}
I'm starting to think center turn lanes are some edge case. They're not really travel lanes; you generally can't just drive through one of them in either directions. (Or they become a regular turn lane close to the intersection and cease to be a shared turn lane.)
I want to distinguish these two cases in A/B Street. In the short-term I can detect the difference based on the total number of lanes, but I'm wondering if we should consider a type = shared_turn
or something
Support the bus lanes scheme as described in https://wiki.openstreetmap.org/wiki/Bus_lanes#The_lanes:psv.3D.2A_scheme
Add tests to https://github.com/a-b-street/osm2lanes/blob/main/data/tests.yml#L559
Then add the implementation to https://github.com/a-b-street/osm2lanes/blob/main/rust/osm2lanes/src/transform/tags_to_lanes/bus.rs#L111
Good first issue: self contained rust business logic implementation, with examples to copy from https://github.com/a-b-street/osm2lanes/blob/main/rust/osm2lanes/src/transform/tags_to_lanes/bus.rs
osm2lanes is nearly at a point where I'd like to make A/B Street take a dependency on it and remove the original copy of the osm2lanes logic. Just writing down some notes about how to transition, not sure when I'll have time to tackle this.
The steps are probably:
@tordanik today expressed interest for OSM2World. I just want to start a place where we can have further discussion and track the process of looking into Rust -> JVM bindings.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.