Xác định các nút giao thông đường bộ bằng PostGIS


17

Tôi đang cố gắng xác định nơi các con đường giao nhau và để tạo một điểm tại giao lộ này, với số lượng đường tạo thành giao lộ được liệt kê.

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

Tôi đã tự hỏi nếu có một số cách sử dụng ST_NumPoints để đạt được điều này nhưng tôi không thể hiểu được những gì tôi nên làm. Những gì tôi đã làm là tạo một bảng các điểm trong đó các đường giao nhau bằng cách sử dụng mã sau đây:

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    a.gid
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom);

Nếu tôi chạy cái này trên một mẫu đường, tôi sẽ nhận được lưới các điểm sau (các đường được hiển thị để minh họa):

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

Nếu tôi kiểm tra một trong những điểm, tôi thấy rằng có nhiều điểm xếp chồng lên nhau:

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

GID ở đây là ID đường, nhưng tôi không hiểu tại sao có nhiều điểm. Tôi có thể hiểu 4 điểm được tính cho một ngã tư đường trung tâm, nhưng có 12 điểm được liệt kê ở đây. Có cách nào tốt hơn để thực hiện tính toán này trong PostGIS không?

Câu trả lời:


21

Nếu bạn nhóm, bạn sẽ chỉ nhận được điểm duy nhất.

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    Count(Distinct a.gid)
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom)
    AND a.gid != b.gid
GROUP BY
    ST_Intersection(a.geom, b.geom)
;

Chỉ cần một thông báo, nhóm theo hình học dẫn đến việc nhóm theo hộp của hình học, chứ không phải chính hình học. Điều đó không quan trọng khi xử lý điểm. Vâng, gần như vậy. Các hộp có độ chính xác thấp hơn chính điểm mà theo lý thuyết có thể dẫn đến việc nhóm hai điểm không giống nhau.
Nicklas Avén

Cảm ơn @ NicklasAvén. Làm thế nào chính xác là so sánh Bbox? Tôi hy vọng nó là đủ cho trường hợp sử dụng này.
underdark

1
Cảm ơn @underdark. Bạn có biết làm thế nào tôi có thể đếm số lượng đường đang giao nhau? Tôi đã thử một vài kết hợp COUNT()như COUNT(ST_Touches(..))COUNT(ST_Intersection(..))nhưng điều này dường như không hoạt động vì tất cả các giá trị là 12.
djq

@underdark, vâng, nó là hoàn toàn đủ, đó là lý do tại sao tôi đã viết "trên lý thuyết". Hộp nằm trong float4 và tọa độ của điểm có độ chính xác gấp đôi. Vì vậy, hộp sẽ trông giống nhau cho ST_Point (1.000001,1.0) và ST_Point (1.000002,1.0) (Ít nhất là tại hệ thống của tôi, tôi vừa thử. Nó nhóm các điểm lại với nhau). Sự khác biệt giữa hộp và hình học thực sự đã gây xáo trộn trong một thời gian tại danh sách dev.
Nicklas Avén

Xem @AlexOs đề xuất sửa đổi gis.stackexchange.com/a/151277/3195
Martin F

6

Đây là một chút khó khăn hơn bạn có thể mong đợi. Đó là bởi vì không có cách nào tốt trong việc phân tích các mối quan hệ cho nhiều hơn các cặp. Bạn không thể đặt ba dòng vào một hàm và hỏi xem tất cả chúng có giao nhau không.

Nhưng, ít nhất một cách tiếp cận có thể là trước tiên tìm đường giao nhau, sau đó kiểm tra xem có bao nhiêu con đường chạm vào mỗi đường giao nhau (tất cả đều có thể được thực hiện trong cùng một truy vấn).

Nếu các đường của bạn kết nối hoàn hảo với nhau và không có đường nào đi qua ngã tư, thì bạn có thể làm một cái gì đó như thế này (không được kiểm tra): được
chỉnh sửa với mệnh đề nhóm bị lãng quên (vẫn chưa được kiểm tra):

SELECT distinct_crosspoints.geom as crossing, array_agg(roads.gid), count(*) FROM
  (SELECT DISTINCT (geom) geom FROM 
    (SELECT ST_Intersection(a.geom, b.geom) geom 
     FROM roads a, roads b 
     WHERE ST_Intersects(a.geom, b.geom)
    ) all_crosspoints
   ) distinct_crosspoints
   ,roads 
 WHERE ST_Intersects(distinct_crosspoints.geom, roads.geom)
 GROUP BY distinct_crosspoints.geom;

Nếu đường không được kết nối đúng cách và / hoặc một số đường đi qua ngã tư thì sẽ phức tạp hơn.

HTH

Nicklas


Xin chào @Nicklas, tôi không thể chạy cái này. Hai mệnh đề bên trong hoạt động tốt; Tôi có nên thay thế distinct_crosspoints ,roadsbằng tên bảng của tôi ( roads_test) không? Tôi đã thử điều đó nhưng sau đó có một lỗi về geomviệc mơ hồ.
djq

1
@celenius, Xin lỗi tôi đã quên điều khoản nhóm. Tôi cũng thấy rằng bạn không cần phải phân biệt ở cấp độ cao hơn. Bạn chỉ có thể đặt nó trên giao lộ trực tiếp. Lưu ý rằng Phân biệt có hành vi tương tự như nhóm theo cuộc thảo luận dưới câu trả lời dưới.
Nicklas Avén

Tôi đã thêm câu trả lời differ_crosspoint.geom vào Nicklas để chạy truy vấn. Làm việc cho tôi bây giờ.
Frank

1
 CREATE TABLE test_points as
    SELECT      
        ST_Intersection(a.geom, b.geom),
        Count(Distinct a.gid)
    FROM
        roads as a,
        roads as b
    WHERE
        ST_Touches(a.geom, b.geom)
        AND a.gid < b.gid   /* !!! Changed "!=" for "<"  */
    GROUP BY
        ST_Intersection(a.geom, b.geom)
    ;

Nếu dòng A (id 1) vượt qua dòng B (id 2) thì đó là điểm giao nhau mà chúng ta cần. Nhưng dòng B cũng vượt qua dòng A trong cùng một điểm. Nhưng chúng ta không cần điểm này hai lần. Đó là lý do tại sao tôi đang sử dụng a.gid < b.gid thay vìa.gid != b.gid

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.