Identifikasi persimpangan jalan menggunakan PostGIS

17

Saya mencoba mengidentifikasi di mana jalan berpotongan satu sama lain, dan membuat titik di persimpangan ini, dengan jumlah jalan yang membentuk persimpangan terdaftar.

masukkan deskripsi gambar di sini

Saya bertanya-tanya apakah ada cara menggunakan ST_NumPoints untuk mencapai ini, tetapi saya tidak tahu apa yang harus saya lakukan. Apa yang telah saya lakukan adalah membuat tabel poin di mana garis-garis berpotongan menggunakan kode berikut:

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);

Jika saya menjalankan ini pada sampel jalan saya mendapatkan kotak titik berikut (jalan ditunjukkan untuk ilustrasi):

masukkan deskripsi gambar di sini

Jika saya memeriksa salah satu poin, saya melihat bahwa ada banyak poin yang saling menumpuk:

masukkan deskripsi gambar di sini

GID di sini adalah ID jalan, tapi saya tidak mengerti mengapa ada beberapa poin. Saya bisa mengerti 4 poin dihitung untuk persimpangan jalan pusat, tetapi ada 12 poin yang tercantum di sini. Apakah ada cara yang lebih baik untuk melakukan perhitungan ini di PostGIS?

djq
sumber

Jawaban:

21

Jika Anda mengelompokkan, Anda hanya akan mendapatkan poin unik.

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)
;
underdark
sumber
Hanya pemberitahuan, pengelompokan berdasarkan geometri menghasilkan pengelompokan berdasarkan bbox geometri, bukan geometri itu sendiri. Itu tidak masalah ketika berhadapan dengan poin. Hampir saja. Bbox memiliki ketelitian yang lebih rendah daripada titik itu sendiri yang secara teori dapat menyebabkan pengelompokan dua titik bersama yang tidak identik.
Nicklas Avén
Terima kasih @ NicklasAvén. Seberapa tepat perbandingan Bbox? Saya berharap itu sudah cukup untuk kasus penggunaan ini.
underdark
1
Terima kasih @ underdark. Apakah Anda tahu bagaimana saya bisa menghitung jumlah garis yang berpotongan? Saya sudah mencoba beberapa kombinasi COUNT()seperti COUNT(ST_Touches(..))dan COUNT(ST_Intersection(..))tetapi ini sepertinya tidak berhasil karena semua nilainya 12.
djq
@ Sunderdark, ya itu benar-benar cukup, itu sebabnya saya menulis "dalam teori". Kotak di float4 dan koordinat titik dalam presisi ganda. Jadi kotak akan terlihat sama untuk ST_Point (1.000001,1.0) dan ST_Point (1.000002,1.0) (Setidaknya di sistem saya, saya baru saja mencoba. Ini mengelompokkan poin-poin ke bersama-sama). Perbedaan ini antara kotak dan geometri nyata telah menjadi diskusi untuk beberapa waktu di dev-list.
Nicklas Avén
Lihat @AlexOs menyarankan modifikasi gis.stackexchange.com/a/151277/3195
Martin F
6

Ini sedikit lebih rumit dari yang Anda duga. Itu karena tidak ada cara yang baik dalam menganalisis hubungan untuk lebih dari pasangan. Anda tidak dapat menempatkan tiga baris ke dalam fungsi dan bertanya apakah semuanya berpotongan.

Tapi, setidaknya satu pendekatan bisa menjadi yang pertama menemukan penyeberangan, lalu periksa berapa banyak jalan yang bersinggungan di setiap penyeberangan (semua bisa dilakukan dalam permintaan yang sama).

Jika jalan Anda terhubung dengan sempurna satu sama lain, dan tidak ada jalan yang melewati persimpangan, maka Anda dapat melakukan sesuatu seperti ini (tidak diuji):
diedit dengan klausa grup yang terlupakan (masih belum diuji):

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;

Jika jalan tidak terhubung dengan benar dan / atau beberapa jalan melewati persimpangan, itu lebih rumit.

HTH

Nicklas

Nicklas Avén
sumber
Hai @Nicklas, saya tidak bisa menjalankan ini. Dua klausa dalam bekerja dengan baik; haruskah saya mengganti distinct_crosspoints ,roadsdengan nama tabel saya ( roads_test)? Saya memang mencobanya tetapi kemudian mendapat kesalahan tentang geommenjadi ambigu.
djq
1
@celenius, Maaf saya lupa klausa grup. Saya juga melihat bahwa Anda tidak perlu membedakan pada level tambahan. Anda bisa langsung meletakkannya di persimpangan. Perhatikan bahwa Distinct memiliki perilaku yang sama dengan grup sesuai dengan diskusi di bawah jawaban underdarks.
Nicklas Avén
Saya menambahkan differ_crosspoints.geom ke Nicklas jawaban untuk menjalankan kueri. Sekarang bekerja untuk saya.
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)
    ;

Jika garis A (id 1) melintasi garis B (id 2) itu adalah titik persimpangan yang kita butuhkan. Tetapi garis B juga melintasi garis A pada titik yang sama. Tetapi kita tidak membutuhkan poin ini dua kali. Itu sebabnya saya menggunakan a.gid < b.gid sebagai gantinyaa.gid != b.gid

Alex Os
sumber