이것이 나의 완전한 해결책입니다. 분할을 수행하기위한 일종의 해킹이 필요합니다. 나는를 사용하여 선상의 점 (방법, OSM 용어 사용) ST_ClosestPoint
을 얻은 다음 아주 작은 거리로 버퍼링하여 분할이 실제로 작동하도록합니다. 그렇지 않으면 부정확 / 반올림 오류로 인해 분할이 방지되었습니다.
이것은 버퍼링 때문에 포인트 당 각 라인에 두 개의 스플릿을 생성한다는 문제가 있습니다. 나중에 사용하기 시작했습니다. 나중에 선 외부에있는 원래 점에 가장 가까운 분할 지점 사이를 라우팅했으며 이는 라인 버퍼 교차점의 두 분할 지점 중 하나 일 수 있습니다.
OSM 데이터를 다운로드하여 Postgres에 임포팅하기 시작했습니다.
CITY="MY_CITY"
BBOX="-46.6003,-23.7362,-46.4806,-23.5965"
wget --progress=dot:mega -O "$CITY.osm" "http://www.overpass-api.de/api/xapi?*[bbox=${BBOX}][@meta]"
# create database
createdb my_database
# add extensions
psql -d my_database -c "CREATE EXTENSION postgis;"
psql -d my_database -c "CREATE EXTENSION pgrouting;"
# import osm data to postgres database
osm2pgrouting \
-f MY_CITY.osm \
-d my_database \
-U user
# load points into db
shp2pgsql -I -s 4326 points_to_split_ways.shp public.points_to_split_ways | psql -d my_database
버퍼를 사용하여 방법 나누기 :
WITH pts_ways AS (
-- get nearest way for each point we want to split the ways by
SELECT s.gid AS pt_id, ws.gid AS way_gid, s.geom AS pt_geom, ws.the_geom AS way_geom FROM points_to_split_ways s
CROSS JOIN LATERAL
(
SELECT w.gid, w.the_geom
FROM ways w
ORDER BY s.geom <-> w.the_geom LIMIT 1
) AS ws
), pts_on_ways AS (
-- "move" these points to be on top of the ways
SELECT pt_id, way_gid, ST_ClosestPoint(way_geom, pt_geom) as geom
FROM pts_ways
), ways_without_pts AS (
-- get the ways that don't have any points on them
SELECT the_geom as the_geom, gid as way_gid FROM ways
WHERE gid NOT IN (SELECT way_gid FROM pts_ways)
)
SELECT
way_gid as old_id,
-- we need to build a new unique ID, because split ways will share the old ID
row_number() over(order by way_gid) as gid,
-- this is the split way geometry
the_geom
FROM (
SELECT
way_gid,
-- split the ways and dump into indiviudal segments
(ST_Dump(ST_Split(line_geom, pt_geom))).geom AS the_geom
FROM (
(SELECT the_geom as line_geom, gid FROM ways) AS lines
LEFT JOIN
-- HACK: use a buffer to fix imprecisions / rounding errors
-- this will generate one extra splitting per point (each buffer will intersect each way twice)
-- but it's ok for our purposes
-- also, collect them grouped by the way to handle cases where there are multiple points on the same way
(SELECT ST_Collect(ST_Buffer(geom, 0.000001)) as pt_geom, way_gid FROM pts_on_ways GROUP BY way_gid) AS pts
ON lines.gid = pts.way_gid
) AS tmp1
-- union the ways without points, otherwise you'd get only the ones that were split
UNION ALL
SELECT way_gid, the_geom FROM ways_without_pts
) AS tmp2;
pgrouting으로 라우팅에 필요한 토폴로지를 작성하십시오.
SELECT UpdateGeometrySRID('ways_split','the_geom', 4326);
SELECT find_srid('public','ways_split','the_geom');
ALTER TABLE ways_split ADD COLUMN "source" integer;
ALTER TABLE ways_split ADD COLUMN "target" integer;
ALTER TABLE ways_split ADD PRIMARY KEY (gid);
ALTER TABLE ways_split ADD CONSTRAINT ways_source_fkey FOREIGN KEY (source) REFERENCES ways_split_vertices_pgr (id) MATCH FULL;
ALTER TABLE ways_split ADD CONSTRAINT ways_target_fkey FOREIGN KEY (target) REFERENCES ways_split_vertices_pgr (id) MATCH FULL;
SELECT pgr_createTopology('ways_split', 0.00001, 'the_geom', 'gid', clean := TRUE);
SELECT pgr_analyzeGraph('ways_split', 0.000001, the_geom := 'the_geom', id := 'gid');