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

Line Diagram. Stops are shown twice. #190

Open
Hubert87 opened this issue Jan 23, 2015 · 7 comments

Comments

Projects
None yet
6 participants
@Hubert87
Copy link

commented Jan 23, 2015

Dear Developers.
I like the Line Diagram very much and it worked like a charm until I added "platforms" to the route-relations using PTv2.
In the case where a node (1) on the street is tagged with "public_transport=stop_position + bus=yes" and a node next to the street (2) has is tagged with "highway=bus_stop + public_transport=platform + bus=yes", the Line Diagram will show the stop twice (http://i.imgur.com/EdoEyDN.png).
The route-relation has node 1 as a member with role "stop" and the node 2 with the role "platform".
Right now, I have "fixed" this by separating "highway=bus_stop" and "public_transport=platform + bus=yes" into two nodes, and not adding the node with "highway=bus_stop" to the route-relation
This works, but I think it would be better if one could have "highway=bus_stop + public_transport=platform + bus=yes" in one node.
Thank you for your time.

@vincentxavier

This comment has been minimized.

Copy link

commented Jul 18, 2015

Maybe around https://github.com/drolbr/Overpass-API/blob/master/src/pt_diagrams/processed_input.cc#L354, you can process input to just select the nodes which are in the relation with the tag "stop" ?
I'm not enough fluent in C++ to try it by my self :-(

@Hubert87

This comment has been minimized.

Copy link
Author

commented May 6, 2016

I belief that the problem lies within

if ((key == "highway") && (value == "bus_stop"))

A fix could be to ignore the stop if its tagged on a platform. My best guess is that one would need to change Line 739 from

if ((key == "highway") && (value == "bus_stop"))
   is_stop = true;

to

if ((key == "highway") && (value == "bus_stop"))
{
   if ((key == "public_transport") && (value != "platform"))
      is_stop = true;
}

This would leave a gab if there is a node with "highway=bus_stop" + "pt=platform" but no node with "pt=stop_position". But that is IMHO more acceptable because it would result in a missing stop due to incomplete data.

@drolbr drolbr added the enhancement label Jun 4, 2016

@laurentriffard

This comment has been minimized.

Copy link

commented Feb 10, 2018

Hello,
The above proposition breaks PTv1 compatibility when relation is written in PTv1, and stop nodes are tagged with both "highway=bus_stop" and "pt=platform".

Here is a patch which may provide better results (hope so) :

diff --git a/src/pt_diagrams/processed_input.cc b/src/pt_diagrams/processed_input.cc
index 732ee610..ea1e2f82 100644
--- a/src/pt_diagrams/processed_input.cc
+++ b/src/pt_diagrams/processed_input.cc
@@ -857,7 +857,7 @@ void start(const char *el, const char **attr)
        relation.backward_stops.push_back(ref);
        relation.direction = Relation::BOTH;
       }
-      else
+      else if (role.substr(0, 8) != "platform")
       {
        relation.forward_stops.push_back(ref);
        relation.backward_stops.push_back(ref);

Rationale : I assume the relation is written either in PTv1 style or in PTv2 style.

  • in PTv1 relation, stop nodes (highway=bus_stop) are given role "backward", "forward", or empty. Just accept all these cases, don't change anything.
  • in PTv2 relation, stop nodes may be given role "stop" or "platform" (or stop_exit_only or stop_entry_only or platform_exit_only or platform_entry_only). empty role is forbidden for stops. In this case, I discard members with role "platform", assuming there is a member with role "stop" representing this stop.

This algorithm will break in two cases :

  • when a stop is represented with a "platform" member and no "stop" member. => the stop is not displayed at all.
  • when the "stop" member is a node tagged platform=stop_position but no name (name may be assigned to stop_area only). => the stop is displayed without name.

But it does solve the problem of double display, and helps to " not mapping for render "

@verdy-p

This comment has been minimized.

Copy link

commented Feb 10, 2018

This is not a problem of "mapping for render" but preserving compatibility where there are tags preserving v1 compatiblity even if there are also v2 tags for newer agents that are PTv2 aware.

So there will remain v1 stops still referenced by both v1 and v2 relations (for different lines not built compeltely at the same time with the same schema, but sharing the same stops): these v1 stops (bus_stop) are normally nodes beside the highway route and usually are given the v2 role "platform", but there are also cases where the v1 stops are nodes on the highway itself and given the v2 role "stop": this mixed case occurs because its difficult to migrate all lines at the same time from v1 to v2 including all the stops they may (and will frequently) share.

Yes a v1 relation should look for v1 nodes members only (with role "stop" only) which may thermselves have both a v1 tag (like highway=bus_stop) and v2 tag (public_transport=stop+others)

And yes a v2 relations should look for v2 nodes/ways/relations members (with roles "stop" or "platform" and their suffixed variants) which may also have both a v1 tag and a v2 tag...

What is essentially different between v1 and v2 is not these stops of platforms, but the fact that v2 routes (way members with empty/forward/backward roles) are normally not creating a bidirectional loop like in v1 but these routes are grouped in a route_master relation containing the various variants and directions.

But not also that forward/backward roles are still needed in v2 (single direction) because of tricky cases like lines that perform a local loop and return back by the same way they used before

  • either in the opposite direction:
>>>>>>>>>>>>>\  />>>>>>>>>>>>>>>>
              v^
              v^
              v^
             /  \
            v    ^
            v    ^
            \>>>>/
  • or sometimes in the same direction used twice:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        /       \
        ^       v
        ^       v
        ^       v
        \<<<<<<</

(note that I have not figured any stop/platform here, only the route effectively followed, along which there will be stops. These 2 cases is independant of the v1 or v2 schema used.

Using the roles "backward" and "forward" still allow reconstructing the complete route even when ways are not ordered (e.g. editing with iD), and then to know when stops/platforms may be reached along the route. Without these roles for route members, neither v1 or v2 will be abel to solve the problem, and you don''t know in which order the stops/platforms will be reached, and the addition on them of "entry_only" or "exit_only" is also insufficient to reply correctly.

Finally note that there exists routes that perform a circular travel: the start and end nodes of route member ways (when you reorder them correctly with the forward/backward roles which is easy in v2 but difficult in v1) are the same, and it is normally located near the first and last stop/platforms, which may be the same (no entry_only/exit_only) or different (but also they may not be restricted to entry_only/exit-only: people may remain in the bus to continue on the next loop circuit after its designated "terminus").

@verdy-p

This comment has been minimized.

Copy link

commented Feb 10, 2018

In summary, we need the coexistence of v1 and v2, even if v2 is more powerful and allows better disambiguation and more efficient automation (in v2 you can effectively know which stops will be deserved along the route, something impossible in v1 which mixes different services of the same "line" in a complex graph difficult to orient)

@verdy-p

This comment has been minimized.

Copy link

commented Feb 10, 2018

note also that even with v2, the case of circular loops does not allow to easily determine the direction of the line if nodes are unordered (as produced by the iD editor which does not preserve the order when editing).

Specifying a start node and end node on the route is not enough, you need to specify 3 nodes: one node should be the terminus, but you need two other nodes not located at the terminus (at start and end of the route) to specify the direction correctly. These three nodes may be chosen arbitrarily along the circular route and in fact do not need to be stop positions.

When there's a local loop (figures above) you need to specify the nodes of convergence/divergences and at least two nodes on that loop. But even in that case, nodes for stop positions will not say if it is used to service the platform on one side or the other (along the common part of the route taken twice). The only way is to append a numeric suffix (:1, :2, the exact value does not matter, only their relative numeric order...) to specify the exact order of platforms desserved. If you don't want that, then the routes with local loops/branches will need to be split in several unidirectional parts and you'll need to have a v2 "route" whose members are "route_section" relations.

Note that route_sections are also needing for tagging properties such as tarifings/zoning, or change of operator or responsible public network (e.g. in France we have RER train routes operated partly by SNCF or by RATP, and tarifing sections by "zone"; zoning also occurs on long distance lines where they go from one city (managed by a given local authority) to another (managed independantly by another authority, both authorities sharing the costs of exploitation, but allowing a section of the line to be used with their own tickets or subscriptions, and other sections requiring the purchase of additional tickets to the operator of the line)

So I we could expect new member types in v2 "route" relations to solve the last remaining problems, and "route section" relations would be useful to really indicate specific tagging for part of the roujte or solve geometric problems such as local branches and loops, or circular routes could be split in at least two sections with a clear direction.

But even with route sections (defined the same way as existing "route" relations, except that they cannot have any subdivision again in subsections), we need to number them to reconnect them correctly if their start (or end) node has more than 2 sections connected to them (starting or ending on that node). The role for including them in a "route" relation should be "section:1", "section:2"... (the value of the suffix does not matter, only their relative order, and the given indices should all be distinct and comparable as "lower than" or "greater than").

To avoid this numbering, the simplest way is to avoid splitting sections at their nodes of convergence/divergence, and allow distinct sections to have common ways. For example the route:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        /       \
        ^       v
        ^       v
        ^       v
        \<<<<<<</

can be represented as these two sections:

>>>>>>>>>>>>>>>>
                \
                v
                v
                v
             <<</
         >>>>>>>>>>>>>>>>>>>>>
        /        
        ^        
        ^        
        ^        
        \<<<< 

because you know the order followed if you specify the node starting the first section as being the start of the route.

But this trick will not work with circular route where you need to specify 3 distinct ordered nodes to determine the direction (with roles "from", "via1", "via2", given that the "to" node is generally the same as "from"). Note that these roles for ordered nodes does not mean they are necessarily stop positions with associated platforms.

In all cases

  • the first need is to determine the order of ways along all possible sections of a single route (each section is unidirectional, and cannot have the same way referenced multiple times as members, and it cannot reference multiple times the same "stop position", or the same "platform").
  • then the "stop positions" can be ordered along the route in the same order determined by the reconstructed and ordered route;
  • and then platforms can be associated with them (with the help of "stop_area" relations)

With these definitions (based on the addition of sections), we can now represent all routes, and we are no longer restricted to maintain a specific order for any members in any relation, and we facilitate the work in editors that won't need to worry about that when we split ways, or modify them locally, without even knowing anything about the current PT schema requirements (which are difficult to maintain and frequently broken): all relations within this schemes are unordered, only some roles are used to order sections when needed. We have all what is needed to manage zoning for travel prices/subscriptions, because sections can have their own tags (including dedicated names, operators, or change of accessibility tags, or changes of vehicle capacity for trains where some wagons will stay in the station and passengers must go to the remaining wagons).

Finally a "route" can contain a mix of:

  • way member without role (simple case): they form sections implicitly where they connect together, but cannot have the same way referenced multiple times as members.
  • "route_section" relation members, with an ordering role if needed (not needed in the simple case shown above if we've avoided to split sections on convergence/divergence nodes)
  • node members with roles "from", "to" (generally not needed, may be equal to "from", and so is undesirable, so "from" is enough), plus (only for circular routes) 2 nodes with the "via1", "via2" roles (specified as members in any order): these nodes are not necessarily stop positions, they may be at the bus/train depot where there's no passenger on board and no platform to wait, or on a service way, or on the loop of a roundaround with no bus stop on it.
  • "stop" members (in arbitrary order) (possibly suffixed with "_entry/exit_only")
  • "platform" members (in arbitrary order)

All these tricky cases have been currently ignored in the current PTv2 specs, this will require documentation. As they are needed in the cases the PTv2 schema does not work, there's no compatibility problem, it can remain in version 2 as a simple extension for these complex cases which are otherwise not representable, but a version 3 would focus on saying that the PTv3 schema no longer requires any strict ordering of members in "route" relations (no longer needed because PTv3 would necessarily support these sections), with PTv3 also adding the restriction: never twice the same member with the same role (and never twice the same member if "from", "via1" and "via2" nodes are distinct from stop positions, but just any nodes along the route which don't need any specific tagging). PTv3 would also deprecate the tags "from=name", "to=name" and "via=name" from routes (no longer needed at all, replaced by node members, and generally only one node member with role "from" for non-circular routes).

For rendering the routes in Overpass-API, the "from=name", "to=name" and "via=name" are also not needed: Overpass can infer them by following each route in the correct order and find all the effective stop positions through which the route goes, including the first and last one, and then taking the names of these stop positions (if not found there, the name of the associated "stop_area" relation, otherwise the name of the nearest "platform").

@mmd-osm

This comment has been minimized.

Copy link
Contributor

commented Feb 11, 2018

Not sure if you read this: #166 (comment)

The sketch_route tools have fallen out of focus. It is more likely that they would get a general overhaul before back in development.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.