Kết nối các điểm (điểm dừng xe buýt), không nằm trên đường (LINESTRING), với mạng?


9

Tôi cần kết nối các điểm dừng xe buýt (điểm) với một lớp mạng (dữ liệu OSM). Các điểm dừng xe buýt này không nằm trực tiếp trên các tuyến (xem ảnh chụp màn hình) cũng như không nên di chuyển vị trí của chúng. Tôi sử dụng PostGIS, pgrouting và QGIS và mạng đã có thể định tuyến được với các cột nguồn và đích, v.v.

nhập mô tả hình ảnh ở đây

Chủ yếu tôi muốn làm hai việc sau đó:

  1. Lấy khoảng cách giữa các điểm dừng xe buýt bằng cách sử dụng phân tích đường đi ngắn nhất.
  2. Tạo isochrones với khoảng cách đi bộ từ trạm xe buýt bằng mạng OSM.

Để có được các giá trị chính xác, điều cần thiết là việc định tuyến 'bắt đầu' và 'dừng' gần nhất với các điểm dừng xe buýt. Trong nhiều trường hợp, nút hiện tại gần nhất sẽ ở quá xa để có được giá trị chính xác. Nhưng không nên định tuyến đến vị trí điểm thực tế của trạm xe buýt. Trong ví dụ của tôi trên hình bạn có thể thấy cách định tuyến giữa các điểm dừng sẽ như thế nào.

Có khả năng tự động chèn các nút mới vào mạng (LINESTRING) gần nhất với các điểm dừng xe buýt hay có thể bắt đầu định tuyến trên một loại 'điểm giả' được đặt chỉ cho truy vấn (tương tự như đường đi plugin đồ thị trong QGIS nào)?

Câu trả lời:


5

Phần đầu tiên của giải pháp là đây:

SELECT a.id, ST_Closestpoint(ST_Collect(b.geom_way), a.geom) AS geom 
FROM point_table a, line_table b
GROUP BY a.id, a.geom;

Điều này sẽ đưa các busstops vào các đường của mạng lưới đường như bạn có thể thấy trong hình và hoạt động khá dễ dàng.

nhập mô tả hình ảnh ở đây

Tiếp theo tôi sẽ cố gắng phân chia các dòng tại vị trí của các điểm. Sau khi tách các dòng tôi muốn sử dụng lại pgr_createTopology. Sau đó, có thể tạo một truy vấn để tìm ra các nút gần nhất với busstops, đây sẽ là các nút mới được tạo của tôi tại 'splitpoint'.

Tôi sẽ biết ơn nếu ai đó có gợi ý cho tôi cách phân chia dòng dõi với các tính năng điểm trong postgis, vì sau khi tôi xem xét các câu hỏi tương tự, dường như không có một giải pháp dễ dàng nào cho điều đó vào lúc này.


ST_Split (Somethingtocut, blade)
simplexio

1
thêm nhận xét vì tôi hoàn toàn không kiểm tra điều này, cú pháp có thể sai ... ... chọn *, st_split (a.lg, a.pg) từ (select *, lines.g dưới dạng lg, points.geom là pg từ các điểm tham gia các dòng trên ST_intersect (p.geom, l.geom)) với tư cách là một bộ sưu tập trả lại tách ra, do đó bạn vẫn cần phải lấy tất cả các dòng ra khỏi nó ...
Simplexio

2

Đây là giải pháp đầy đủ của tôi. Nó liên quan đến một loại hack để thực hiện việc phân tách: Tôi lấy điểm trên các dòng (cách, sử dụng thuật ngữ OSM) bằng cách sử dụng ST_ClosestPoint, và sau đó đệm chúng theo một khoảng cách rất nhỏ để thực hiện việc chia tách thực sự hoạt động. Mặt khác, lỗi không chính xác / làm tròn đã ngăn cản việc chia tách.

Điều này có vấn đề là nó tạo ra hai phần tách trên mỗi dòng trên mỗi điểm (vì bộ đệm). Đối với việc sử dụng của tôi, điều này là tốt, vì sau này tôi đã định tuyến giữa các điểm phân tách gần nhất với các điểm ban đầu, nằm ngoài đường và nó có thể là một trong hai điểm phân tách của giao lộ bộ đệm dòng.

Tôi đã bắt đầu bằng cách tải xuống dữ liệu OSM và đưa nó vào 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

Tách các cách sử dụng bộ đệm:

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;

Tạo cấu trúc liên kết cần thiết để định tuyến với 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');

Suy nghĩ đầu tiên của tôi là bộ đệm. Nhưng nếu bạn có thể nhận được 'khoảng cách đến gần nhất', hãy đệm số tiền đó, tạo một điểm tại giao điểm đó ... thì bạn có thể tạo một đường thẳng với các điểm cuối bao gồm điểm ban đầu của bạn và điểm 'gần nhất' với điểm đó.
Mox

1

Vì tôi đang thực hiện một nhiệm vụ tương tự, tôi chỉ muốn nói về cách tiếp cận mà tôi hiện đang sử dụng. Điều này sử dụng GRASS GIS, nhưng theo như các thử nghiệm của tôi với PostGIS, việc thêm nhiều điểm mới vào LineStrings hiện tại bằng cách chia các LineStrings tại các vị trí tương ứng là khá phức tạp - mặc dù tôi chắc chắn có một giải pháp thuận tiện.

Bây giờ tôi đã sử dụng v.netchức năng GRASS GIS bằng tùy chọn này connect. Chỉ cần chọn input vector line layerpoints layer. Có tùy chọn để bắt các điểm đến điểm gần nhất trên các đường hoặc để tạo các kết nối mới giữa điểm gần nhất trên đường và điểm mới.

Đây là một hình ảnh trước và sau. Ở phía bên phải, đối với mỗi điểm của lớp điểm, một nút trên mạng đường được thêm vào: nhập mô tả hình ảnh ở đây

Sau đó trong PostGIS, sau khi tạo ..._vertices_pgrbảng của bạn ra khỏi mạng lưới, chỉ cần gán điểm của bạn cho đỉnh gần nhất để bạn có thể sử dụng chúng trong các yêu cầu định tuyến của mình. Đối với tác vụ này, bạn có thể sử dụng ST_ClosestPointhàm như được thực hiện bởi @ Setrawork trong câu trả lời của mình.

Nhược điểm của phương pháp này là:

  • việc kết nối các điểm với các đường phải được thực hiện trong GRASS GIS
  • các tuyến đường được tính toán có thể bao gồm nhiều thành phần (tùy thuộc vào số lượng điểm mới được thêm vào)
  • không thể bổ sung các điểm mới

Cách tiếp cận này hoạt động tốt nếu bạn có một số điểm xác định sẽ được thêm vào mạng lưới đường (như trong ví dụ về câu hỏi với các điểm dừng xe buýt).

Nếu ai đó có thể cung cấp một ví dụ hoạt động bằng PostGIS, tôi rất muốn đọc về điều đó!


0

Có một bài viết thảo luận về một vấn đề tương tự, bạn có thể thấy bài đăng đó tại địa điểm sau: http://osdir.com/ml/qgis-user-gis/2011-11/msg00220.html


Đây chỉ là một phần của một giải pháp khả thi, bởi vì sau khi chụp các điểm vào các dòng, các điểm nằm trực tiếp trên các dòng, nhưng chúng vẫn không phải là một phần của mạng.
Setrawork

Nếu bạn đang mong đợi nhận được một câu trả lời cung cấp cho bạn tất cả các yêu cầu của bạn, bạn có thể thất vọng. Điều này có thể giúp bạn đi được một nửa, sau đó bạn có thể tập trung vào phần khác mà bạn đang thiếu.
Ryan Garnett

Tôi nghĩ bạn đúng Ryan. Tôi đã quản lý để bắt các điểm vào các dòng, vì vậy bước tiếp theo sẽ là tìm hiểu làm thế nào để phân chia linestrings với các điểm trong postgis. Cảm ơn vì sự giúp đỡ của bạn!
Setrawork

Rất vui vì tôi có thể giúp. Có những công cụ sẽ phân chia một dòng với một điểm, nhưng tôi sẽ tiếp tục tìm kiếm một tùy chọn trong PostGIS. Chúc may mắn
Ryan Garnett

@ Setrawork bạn có thể muốn xem tùy chọn PostGIS sau (ST_Split) postgis.net/docs/ST_Split.html . Bạn có thể chia một dòng với một điểm, đây là lời giải thích từ PostGIS: Hàm hỗ trợ chia một dòng theo điểm, một dòng theo từng dòng, một đa giác theo dòng. Các hình học trả về luôn luôn là một bộ sưu tập.
Ryan Garnett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.