Рекурсивный запрос PostGIS - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь превратить все кольцевые развязки в городе в простые перекрестки / перекрестки (o -> +). Поскольку я использую OpenStreetMap для исходной топологии, некоторые обходные пути представляют собой не круг, а просто сегменты круга (например: https://www.openstreetmap.org/#map = 18 / 43.34516 / -8.41536 ).

На практике проблема в том, что мне нужен центроид каждой кольцевой развязки, и я получаю его почти во всех случаях, но иногда я получаю несколько центроидов для одной и той же кольцевой развязки (центроиды арок, нет полной кольцевой развязки).

I достигли этого:

select f.osm_id as fid, (select ST_CENTROID(ST_Buffer(ST_UNION(way),1)) as r_geom
                      from planet_osm_line d 
                      where st_intersects(f.way, d.way) and junction = 'roundabout') as rotonda 
from planet_osm_line f 
where junction like 'roundabout';

Но это не решает проблему, а только уменьшает ее. Я не получаю полный круг, просто его большие сегменты.

Так что я думаю, что мне нужен рекурсивный запрос, чтобы сделать это, пока количество найденных геометрий не останется прежним (полный круг). Любые идеи о том, как построить этот запрос?

1 Ответ

0 голосов
/ 07 апреля 2020

Я искал что-то вроде этого (надеюсь, это поможет другим нуждающимся):

create table no_roundabouts as 
with recursive roundabout(geom) as (--Recursive function to build closed circled roundabouts even with roundabouts mapped as differents arches.
  SELECT ST_TRANSFORM(way,3857)
  FROM planet_osm_line ways --Get all segments tagged as 'roundabout'
  WHERE ways.junction = 'roundabout'
UNION ALL
  SELECT ST_TRANSFORM(ST_UNION(ways.way, roundabout.geom),3857)
  FROM roundabout, planet_osm_line ways -- Compose segments building greater arches of the roundabout until we have the full circle (My_segment + a touching segment that is no contained in my segment)
  WHERE ways.junction = 'roundabout' and ST_INTERSECTS(roundabout.geom, ways.way) and not ST_CONTAINS(roundabout.geom, ways.way)
)
SELECT * FROM roundabout;

alter table no_roundabouts add column id bigserial; -- Add id to each line
delete from no_roundabouts a -- Delete repeated roundabouts generated during recursion
where exists (select geom from no_roundabouts b where ST_CONTAINS(b.geom, a.geom) and b.id > a.id);

--select count(*) from no_roundabouts WHERE ST_IsClosed(geom) = false;
update no_roundabouts set geom = ST_LINEMERGE(geom) where ST_ISCLOSED(geom) is false --Force closed roundabouts

-- Query replacing roundabouts with crossroads (linking each way in and out with the centroid of the roundabout)
SELECT ST_TRANSFORM(ST_ADDPOINT(y.way, ST_CENTROID(x.geom), 0),4326) 
FROM no_roundabouts x JOIN planet_osm_line y ON ST_INTERSECTS(y.way, x.geom) 
WHERE y.highway is not null and ST_INTERSECTS(x.geom, st_pointn(y.way,1)) and ST_CONTAINS(x.geom, y.way) = false
UNION
SELECT ST_TRANSFORM(ST_ADDPOINT(y.way, ST_CENTROID(x.geom), -1),4326) 
FROM no_roundabouts x JOIN planet_osm_line y ON ST_INTERSECTS(y.way, x.geom) 
WHERE y.highway is not null and ST_INTERSECTS(x.geom, ST_POINTN(y.way,-1)) and ST_CONTAINS(x.geom, y.way) = false;
...