From d375406a2f424fbf060ef1c204150ba02efa383d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sun, 7 Mar 2021 13:10:53 +0100 Subject: [PATCH 1/8] public transport - add tests about stops in routes - the order of the stops - the side of the street --- ...lyser_osmosis_relation_public_transport.py | 149 +++++++++++++++++- 1 file changed, 145 insertions(+), 4 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index b60c6ebf7..9e3117761 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -3,7 +3,7 @@ ########################################################################### ## ## -## Copyrights Frédéric Rodrigo 2016 ## +## Copyrights Frédéric Rodrigo 2016, Noémie Lehuby 2021 ## ## ## ## This program is free software: you can redistribute it and/or modify ## ## it under the terms of the GNU General Public License as published by ## @@ -118,7 +118,8 @@ relations.id, relation_members.member_type, ways.id AS mid, - relation_members.member_role as mrole, + relation_members.member_role AS mrole, + relation_members.sequence_id AS morder, ST_Transform(ways.linestring, {0}) AS geom FROM relations @@ -140,7 +141,8 @@ relations.id, relation_members.member_type, nodes.id AS mid, - relation_members.member_role as mrole, + relation_members.member_role AS mrole, + relation_members.sequence_id AS morder, ST_Transform(nodes.geom, {0}) AS geom FROM relations @@ -366,6 +368,133 @@ w_bs.id IS NULL """ +sql100 = """ +CREATE OR REPLACE FUNCTION generate_linestring_geom(route_id bigint) RETURNS geometry(MultiLineString, 4326) LANGUAGE PLPGSQL AS $$ +declare + f record; + full_way geometry(LineString, 4326); + last_roundabout geometry(LineString, 4326); +begin + for f in + select ways.id, ways.linestring AS geom from relation_members + join relations on + relations.id = relation_members.relation_id + JOIN ways ON + ways.id = relation_members.member_id + WHERE + relations.tags->'type' = 'route' AND + relation_members.member_type = 'W' AND + relation_members.member_role NOT IN ('stop', 'stop_exit_only', 'stop_entry_only', 'platform', 'platform_exit_only', 'platform_entry_only') AND + relations.tags->'route' IN ('train', 'subway', 'monorail', 'tram', 'bus', 'trolleybus', 'aerialway', 'ferry', 'coach', 'funicular', 'share_taxi', 'light_rail', 'school_bus') AND + (NOT relations.tags?(relations.tags->'route') OR relations.tags->(relations.tags->'route') != 'on_demand') AND + ST_NPoints(linestring) >= 2 + and relations.id = route_id + order by relation_members.sequence_id + loop + case + when full_way is null then + full_way := f.geom; + when st_endpoint(f.geom) = st_startpoint(f.geom) then + last_roundabout := f.geom; + when last_roundabout is not null then + case + when ST_Intersects(last_roundabout,st_startpoint(f.geom)) then + full_way:= ST_MakeLine(full_way,f.geom); + when ST_Intersects(last_roundabout,st_endpoint(f.geom)) then + full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); + else + return null; + end case; + last_roundabout = NULL; + when st_endpoint(full_way) = st_startpoint(f.geom) then + full_way:= ST_MakeLine(full_way,f.geom); + when st_endpoint(full_way) = st_endpoint(f.geom) then + full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); + when st_startpoint(full_way) = st_endpoint(f.geom) then + full_way:= ST_MakeLine(ST_Reverse(full_way),ST_Reverse(f.geom)); + when st_startpoint(full_way) = st_startpoint(f.geom) then + full_way:= ST_MakeLine(ST_Reverse(full_way),f.geom); + else + raise notice 'kapout'; + RAISE NOTICE 'full linestring: %', st_astext(st_makeline(full_way)); + return null; + end case; + end loop; + return full_way; +end; +$$; +""" + +sql101 = """ +CREATE TEMP TABLE route_linestring AS +SELECT id, + ST_Transform(generate_linestring_geom(id), {0}) AS geom +FROM relations +WHERE relations.tags->'type' = 'route' + AND relations.tags->'route' IN ('train', + 'subway', + 'monorail', + 'tram', + 'bus', + 'trolleybus', + 'aerialway', + 'ferry', + 'coach', + 'funicular', + 'share_taxi', + 'light_rail', + 'school_bus') + AND (NOT relations.tags?(relations.tags->'route') + OR relations.tags->(relations.tags->'route') != 'on_demand') +""" + +sql101b = """ +CREATE INDEX route_linestring_idx ON route_linestring USING gist(geom) +""" + +sql102 = """ +CREATE TEMP TABLE platform_that_can_project AS +( +SELECT route_linestring.id AS route_id, + stop_platform.member_type || stop_platform.mid AS stop_id, + stop_platform.geom AS stop, + ROW_NUMBER () OVER (PARTITION BY route_linestring.id + ORDER BY stop_platform.morder) AS stop_order, + ROW_NUMBER () OVER (PARTITION BY route_linestring.id + ORDER BY ST_LineLocatePoint(route_linestring.geom, stop_platform.geom)) AS projected_stop_order +FROM stop_platform +JOIN route_linestring ON route_linestring.id = stop_platform.id +WHERE stop_platform.mrole in ('platform', + 'platform_exit_only', + 'platform_entry_only') + AND stop_platform.member_type='N' + AND ST_LineLocatePoint(route_linestring.geom, ST_ClosestPoint(route_linestring.geom, stop_platform.geom)) <> 1 +) +""" + +sql102b = """ +CREATE INDEX platform_that_can_project_idx ON platform_that_can_project USING gist(stop) +""" + +sql103 = """ +SELECT DISTINCT ON (route_id) + platform_that_can_project.route_id, + ST_AsText(ST_Transform(platform_that_can_project.stop,4326)) AS geom +FROM platform_that_can_project +WHERE stop_order <> projected_stop_order +""" + +sql110 = """ +SELECT + platform_that_can_project.route_id, + platform_that_can_project.stop_id, + ST_AsText(ST_Transform(platform_that_can_project.stop, 4326)) +FROM platform_that_can_project +JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id +WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND + NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) +""" + class Analyser_Osmosis_Relation_Public_Transport(Analyser_Osmosis): requires_tables_common = ['highways'] @@ -393,6 +522,10 @@ def __init__(self, config, logger = None): self.classs[10] = self.def_class(item = 1260, level = 3, tags = ['public_transport'], title = T_('Stop position without platform nor bus stop'), fix = T_('A bus `public_transport=stop_position` without close `public_transport=platform` nor `highway=bus_stop`.')) + self.classs[11] = self.def_class(item = 1260, level = 3, tags = ['public_transport'], + title = T_('The stops may not be in the right order')) + self.classs[12] = self.def_class(item = 1260, level = 3, tags = ['public_transport'], + title = T_('The platform is not on the right side of the road')) self.callback10 = lambda res: {"class":1, "data":[self.relation_full, self.positionAsText]} self.callback20 = lambda res: {"class":2, "data":[self.relation_full, self.any_full, self.positionAsText]} @@ -406,6 +539,8 @@ def __init__(self, config, logger = None): self.callback80 = lambda res: {"class":8, "data":[self.relation_full, self.any_full, self.positionAsText]} self.callback90 = lambda res: {"class":9, "data":[self.relation_full, self.any_full, self.positionAsText]} self.callbackA0 = lambda res: {"class":10, "data":[self.node_full, self.positionAsText]} + self.callback100 = lambda res: {"class":11, "data":[self.relation_full, self.positionAsText]} + self.callback110 = lambda res: {"class":12, "data":[self.relation_full, self.any_full, self.positionAsText]} def analyser_osmosis_common(self): @@ -423,4 +558,10 @@ def analyser_osmosis_common(self): self.run(sql70, self.callback70) self.run(sql80, self.callback80) self.run(sql90, self.callback90) - self.run(sqlA0.format(self.config.options.get("proj")), self.callbackA0) + self.run(sql100) + self.run(sql101.format(self.config.options.get("proj"))) + self.run(sql101b) + self.run(sql102) + self.run(sql102b) + self.run(sql103, self.callback100) + self.run(sql110, self.callback110) From a258a934a8a5563efef647a67c7e923f608d1dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sun, 25 Apr 2021 17:15:06 +0200 Subject: [PATCH 2/8] public transport - bugfix on order of stops when the bus passes several times on the same street, the order of the projection on these segments are random. offset the linestring before the projection to split the multiple passages in opposite direction --- analysers/analyser_osmosis_relation_public_transport.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index 9e3117761..b147d19d4 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -415,8 +415,7 @@ when st_startpoint(full_way) = st_startpoint(f.geom) then full_way:= ST_MakeLine(ST_Reverse(full_way),f.geom); else - raise notice 'kapout'; - RAISE NOTICE 'full linestring: %', st_astext(st_makeline(full_way)); + -- RAISE NOTICE 'full linestring: %', st_astext(st_makeline(full_way)); return null; end case; end loop; @@ -461,13 +460,14 @@ ROW_NUMBER () OVER (PARTITION BY route_linestring.id ORDER BY stop_platform.morder) AS stop_order, ROW_NUMBER () OVER (PARTITION BY route_linestring.id - ORDER BY ST_LineLocatePoint(route_linestring.geom, stop_platform.geom)) AS projected_stop_order + ORDER BY ST_LineLocatePoint(ST_OffsetCurve(route_linestring.geom, -10), stop_platform.geom) DESC) AS projected_stop_order FROM stop_platform JOIN route_linestring ON route_linestring.id = stop_platform.id WHERE stop_platform.mrole in ('platform', 'platform_exit_only', 'platform_entry_only') AND stop_platform.member_type='N' + AND GeometryType(ST_OffsetCurve(route_linestring.geom, -10)) = 'LINESTRING' AND ST_LineLocatePoint(route_linestring.geom, ST_ClosestPoint(route_linestring.geom, stop_platform.geom)) <> 1 ) """ From 001ade05b438dfc6fc968e94c74ed1fee31bfbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sun, 25 Apr 2021 17:18:30 +0200 Subject: [PATCH 3/8] public transport - bugfix on side of street There are a lot of false positives on the first and last stops. Let's remove them from the analysis. --- .../analyser_osmosis_relation_public_transport.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index b147d19d4..517f5ddb3 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -490,9 +490,18 @@ platform_that_can_project.stop_id, ST_AsText(ST_Transform(platform_that_can_project.stop, 4326)) FROM platform_that_can_project -JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id +JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id +JOIN ( + SELECT + platform_that_can_project.route_id AS route_id, + MAX(platform_that_can_project.stop_order) AS last_platform + FROM platform_that_can_project + GROUP BY platform_that_can_project.route_id +) AS y ON platform_that_can_project.route_id = y.route_id WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND - NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) + NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) AND + platform_that_can_project.stop_order <> last_platform AND + platform_that_can_project.stop_order <> 1 """ class Analyser_Osmosis_Relation_Public_Transport(Analyser_Osmosis): From ac005cf9a14d029cd1373a6fd45795be2894b8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sun, 25 Apr 2021 17:19:12 +0200 Subject: [PATCH 4/8] public transport - bugfix on side of street only make sens for street served transport --- analysers/analyser_osmosis_relation_public_transport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index 517f5ddb3..65ecb4c1f 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -427,6 +427,7 @@ sql101 = """ CREATE TEMP TABLE route_linestring AS SELECT id, + relations.tags->'route' AS public_transport_mode, ST_Transform(generate_linestring_geom(id), {0}) AS geom FROM relations WHERE relations.tags->'type' = 'route' @@ -500,6 +501,7 @@ ) AS y ON platform_that_can_project.route_id = y.route_id WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) AND + route_linestring.public_transport_mode IN ('bus', 'trolleybus', 'coach', 'share_taxi', 'school_bus') AND platform_that_can_project.stop_order <> last_platform AND platform_that_can_project.stop_order <> 1 """ From acee77fa38bc0cef030ceec9d3b21083137800a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sun, 25 Apr 2021 17:29:39 +0200 Subject: [PATCH 5/8] public transport - lint --- ...lyser_osmosis_relation_public_transport.py | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index 65ecb4c1f..cb8576c53 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -370,14 +370,14 @@ sql100 = """ CREATE OR REPLACE FUNCTION generate_linestring_geom(route_id bigint) RETURNS geometry(MultiLineString, 4326) LANGUAGE PLPGSQL AS $$ -declare +DECLARE f record; full_way geometry(LineString, 4326); last_roundabout geometry(LineString, 4326); -begin - for f in - select ways.id, ways.linestring AS geom from relation_members - join relations on +BEGIN + FOR f IN + SELECT ways.id, ways.linestring AS geom FROM relation_members + JOIN relations ON relations.id = relation_members.relation_id JOIN ways ON ways.id = relation_members.member_id @@ -387,40 +387,40 @@ relation_members.member_role NOT IN ('stop', 'stop_exit_only', 'stop_entry_only', 'platform', 'platform_exit_only', 'platform_entry_only') AND relations.tags->'route' IN ('train', 'subway', 'monorail', 'tram', 'bus', 'trolleybus', 'aerialway', 'ferry', 'coach', 'funicular', 'share_taxi', 'light_rail', 'school_bus') AND (NOT relations.tags?(relations.tags->'route') OR relations.tags->(relations.tags->'route') != 'on_demand') AND - ST_NPoints(linestring) >= 2 - and relations.id = route_id - order by relation_members.sequence_id - loop - case - when full_way is null then + ST_NPoints(linestring) >= 2 AND + relations.id = route_id + ORDER BY relation_members.sequence_id + LOOP + CASE + WHEN full_way is null THEN full_way := f.geom; - when st_endpoint(f.geom) = st_startpoint(f.geom) then + WHEN st_endpoint(f.geom) = st_startpoint(f.geom) THEN last_roundabout := f.geom; - when last_roundabout is not null then - case - when ST_Intersects(last_roundabout,st_startpoint(f.geom)) then + WHEN last_roundabout is not null THEN + CASE + WHEN ST_Intersects(last_roundabout,st_startpoint(f.geom)) THEN full_way:= ST_MakeLine(full_way,f.geom); - when ST_Intersects(last_roundabout,st_endpoint(f.geom)) then + WHEN ST_Intersects(last_roundabout,st_endpoint(f.geom)) THEN full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); - else - return null; - end case; + ELSE + RETURN null; + END CASE; last_roundabout = NULL; - when st_endpoint(full_way) = st_startpoint(f.geom) then + WHEN st_endpoint(full_way) = st_startpoint(f.geom) THEN full_way:= ST_MakeLine(full_way,f.geom); - when st_endpoint(full_way) = st_endpoint(f.geom) then + WHEN st_endpoint(full_way) = st_endpoint(f.geom) THEN full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); - when st_startpoint(full_way) = st_endpoint(f.geom) then + WHEN st_startpoint(full_way) = st_endpoint(f.geom) THEN full_way:= ST_MakeLine(ST_Reverse(full_way),ST_Reverse(f.geom)); - when st_startpoint(full_way) = st_startpoint(f.geom) then + WHEN st_startpoint(full_way) = st_startpoint(f.geom) THEN full_way:= ST_MakeLine(ST_Reverse(full_way),f.geom); - else + ELSE -- RAISE NOTICE 'full linestring: %', st_astext(st_makeline(full_way)); - return null; - end case; - end loop; - return full_way; -end; + RETURN NULL; + END CASE; + END LOOP; + RETURN full_way; +END; $$; """ @@ -464,7 +464,7 @@ ORDER BY ST_LineLocatePoint(ST_OffsetCurve(route_linestring.geom, -10), stop_platform.geom) DESC) AS projected_stop_order FROM stop_platform JOIN route_linestring ON route_linestring.id = stop_platform.id -WHERE stop_platform.mrole in ('platform', +WHERE stop_platform.mrole IN ('platform', 'platform_exit_only', 'platform_entry_only') AND stop_platform.member_type='N' @@ -486,19 +486,19 @@ """ sql110 = """ -SELECT - platform_that_can_project.route_id, - platform_that_can_project.stop_id, +SELECT + platform_that_can_project.route_id, + platform_that_can_project.stop_id, ST_AsText(ST_Transform(platform_that_can_project.stop, 4326)) FROM platform_that_can_project -JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id +JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id JOIN ( - SELECT + SELECT platform_that_can_project.route_id AS route_id, MAX(platform_that_can_project.stop_order) AS last_platform - FROM platform_that_can_project + FROM platform_that_can_project GROUP BY platform_that_can_project.route_id -) AS y ON platform_that_can_project.route_id = y.route_id +) AS y ON platform_that_can_project.route_id = y.route_id WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) AND route_linestring.public_transport_mode IN ('bus', 'trolleybus', 'coach', 'share_taxi', 'school_bus') AND @@ -569,6 +569,7 @@ def analyser_osmosis_common(self): self.run(sql70, self.callback70) self.run(sql80, self.callback80) self.run(sql90, self.callback90) + self.run(sqlA0.format(self.config.options.get("proj")), self.callbackA0) self.run(sql100) self.run(sql101.format(self.config.options.get("proj"))) self.run(sql101b) From a6e5b3759ab969bb13b9345578e5e37e17c82f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sat, 1 May 2021 16:44:07 +0200 Subject: [PATCH 6/8] public transport - cut that freaking roundabout --- ...lyser_osmosis_relation_public_transport.py | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index cb8576c53..380dfac34 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -294,7 +294,7 @@ WHERE nodes.tags != ''::hstore AND nodes.tags?'public_transport' AND nodes.tags->'public_transport' = 'stop_position' AND - node_id is null; + node_id IS NULL; """ sql80 = """ @@ -392,30 +392,43 @@ ORDER BY relation_members.sequence_id LOOP CASE - WHEN full_way is null THEN + WHEN full_way IS NULL THEN full_way := f.geom; - WHEN st_endpoint(f.geom) = st_startpoint(f.geom) THEN + WHEN ST_EndPoint(f.geom) = ST_StartPoint(f.geom) THEN last_roundabout := f.geom; - WHEN last_roundabout is not null THEN + WHEN last_roundabout IS NOT NULL THEN CASE - WHEN ST_Intersects(last_roundabout,st_startpoint(f.geom)) THEN + WHEN ST_Intersects(last_roundabout,ST_StartPoint(f.geom)) THEN + CASE + WHEN ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)) > ST_LineLocatePoint(last_roundabout, ST_StartPoint(f.geom)) THEN + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)), 1)); + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, 0, ST_LineLocatePoint(last_roundabout, ST_StartPoint(f.geom)))); + ELSE + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)), ST_LineLocatePoint(last_roundabout, ST_StartPoint(f.geom)))); + END CASE; full_way:= ST_MakeLine(full_way,f.geom); - WHEN ST_Intersects(last_roundabout,st_endpoint(f.geom)) THEN + WHEN ST_Intersects(last_roundabout,ST_EndPoint(f.geom)) THEN + CASE + WHEN ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)) > ST_LineLocatePoint(last_roundabout, ST_EndPoint(f.geom)) THEN + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)), 1)); + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, 0, ST_LineLocatePoint(last_roundabout, ST_EndPoint(f.geom)))); + ELSE + full_way:= ST_MakeLine(full_way,ST_LineSubstring(last_roundabout, ST_LineLocatePoint(last_roundabout, ST_EndPoint(full_way)), ST_LineLocatePoint(last_roundabout, ST_EndPoint(f.geom)))); + END CASE; full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); ELSE - RETURN null; + RETURN NULL; END CASE; last_roundabout = NULL; - WHEN st_endpoint(full_way) = st_startpoint(f.geom) THEN + WHEN ST_EndPoint(full_way) = ST_StartPoint(f.geom) THEN full_way:= ST_MakeLine(full_way,f.geom); - WHEN st_endpoint(full_way) = st_endpoint(f.geom) THEN + WHEN ST_EndPoint(full_way) = ST_EndPoint(f.geom) THEN full_way:= ST_MakeLine(full_way,ST_Reverse(f.geom)); - WHEN st_startpoint(full_way) = st_endpoint(f.geom) THEN + WHEN ST_StartPoint(full_way) = ST_EndPoint(f.geom) THEN full_way:= ST_MakeLine(ST_Reverse(full_way),ST_Reverse(f.geom)); - WHEN st_startpoint(full_way) = st_startpoint(f.geom) THEN + WHEN ST_StartPoint(full_way) = ST_StartPoint(f.geom) THEN full_way:= ST_MakeLine(ST_Reverse(full_way),f.geom); ELSE - -- RAISE NOTICE 'full linestring: %', st_astext(st_makeline(full_way)); RETURN NULL; END CASE; END LOOP; From d2a94b18197434c4f6c78c923a2b69f73fd08f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sat, 1 May 2021 16:45:22 +0200 Subject: [PATCH 7/8] public transport - handle driving side --- .../analyser_osmosis_relation_public_transport.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index 380dfac34..b3af7b6f3 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -459,6 +459,7 @@ 'school_bus') AND (NOT relations.tags?(relations.tags->'route') OR relations.tags->(relations.tags->'route') != 'on_demand') + AND generate_linestring_geom(id) IS NOT NULL """ sql101b = """ @@ -482,7 +483,7 @@ 'platform_entry_only') AND stop_platform.member_type='N' AND GeometryType(ST_OffsetCurve(route_linestring.geom, -10)) = 'LINESTRING' - AND ST_LineLocatePoint(route_linestring.geom, ST_ClosestPoint(route_linestring.geom, stop_platform.geom)) <> 1 + AND ST_LineLocatePoint(route_linestring.geom, ST_ClosestPoint(route_linestring.geom, stop_platform.geom)) NOT IN (0, 1) ) """ @@ -513,7 +514,7 @@ GROUP BY platform_that_can_project.route_id ) AS y ON platform_that_can_project.route_id = y.route_id WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND - NOT ST_Intersects(ST_Buffer(route_linestring.geom,50,'side=right'), platform_that_can_project.stop) AND + NOT ST_Intersects(ST_Buffer(route_linestring.geom, 50, 'side={}'), platform_that_can_project.stop) AND route_linestring.public_transport_mode IN ('bus', 'trolleybus', 'coach', 'share_taxi', 'school_bus') AND platform_that_can_project.stop_order <> last_platform AND platform_that_can_project.stop_order <> 1 @@ -566,6 +567,10 @@ def __init__(self, config, logger = None): self.callback100 = lambda res: {"class":11, "data":[self.relation_full, self.positionAsText]} self.callback110 = lambda res: {"class":12, "data":[self.relation_full, self.any_full, self.positionAsText]} + if self.config.options.get("driving_side") == "left": + self.buffer_driving_side = "left" + else: + self.buffer_driving_side = "right" def analyser_osmosis_common(self): self.run(sql00) @@ -589,4 +594,4 @@ def analyser_osmosis_common(self): self.run(sql102) self.run(sql102b) self.run(sql103, self.callback100) - self.run(sql110, self.callback110) + self.run(sql110.format(self.buffer_driving_side), self.callback110) From 2b5d9ce3a2193cc0c7da4f7dbc04524f0abb9f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20Lehuby?= Date: Sat, 1 May 2021 20:43:47 +0200 Subject: [PATCH 8/8] PR review --- ...analyser_osmosis_relation_public_transport.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/analysers/analyser_osmosis_relation_public_transport.py b/analysers/analyser_osmosis_relation_public_transport.py index b3af7b6f3..1bd1a6986 100644 --- a/analysers/analyser_osmosis_relation_public_transport.py +++ b/analysers/analyser_osmosis_relation_public_transport.py @@ -475,7 +475,12 @@ ROW_NUMBER () OVER (PARTITION BY route_linestring.id ORDER BY stop_platform.morder) AS stop_order, ROW_NUMBER () OVER (PARTITION BY route_linestring.id - ORDER BY ST_LineLocatePoint(ST_OffsetCurve(route_linestring.geom, -10), stop_platform.geom) DESC) AS projected_stop_order + ORDER BY ST_LineLocatePoint(ST_OffsetCurve(route_linestring.geom, -10), stop_platform.geom) DESC) AS projected_stop_order, + (CASE + WHEN LEAD(stop_platform.morder, 1) OVER (PARTITION BY route_linestring.id + ORDER BY stop_platform.morder) IS NULL THEN 1 + ELSE 0 + END) AS is_last_platform FROM stop_platform JOIN route_linestring ON route_linestring.id = stop_platform.id WHERE stop_platform.mrole IN ('platform', @@ -506,17 +511,10 @@ ST_AsText(ST_Transform(platform_that_can_project.stop, 4326)) FROM platform_that_can_project JOIN route_linestring ON route_linestring.id = platform_that_can_project.route_id -JOIN ( - SELECT - platform_that_can_project.route_id AS route_id, - MAX(platform_that_can_project.stop_order) AS last_platform - FROM platform_that_can_project - GROUP BY platform_that_can_project.route_id -) AS y ON platform_that_can_project.route_id = y.route_id WHERE ST_DWithin(route_linestring.geom, platform_that_can_project.stop, 50) AND NOT ST_Intersects(ST_Buffer(route_linestring.geom, 50, 'side={}'), platform_that_can_project.stop) AND route_linestring.public_transport_mode IN ('bus', 'trolleybus', 'coach', 'share_taxi', 'school_bus') AND - platform_that_can_project.stop_order <> last_platform AND + platform_that_can_project.is_last_platform <> 1 AND platform_that_can_project.stop_order <> 1 """