PostGIS kullanarak yol kavşaklarını belirleme


17

Yolların birbiriyle nerede kesiştiğini belirlemeye ve bu kesişimde, kesişmeyi oluşturan yolların sayısı ile bir noktaya değinmeye çalışıyorum.

resim açıklamasını buraya girin

Bunu başarmak için ST_NumPoints kullanmanın bir yolu olup olmadığını merak ediyordum ama ne yapmam gerektiğini tam olarak anlayamıyorum . Ne yaptım hatları aşağıdaki kodu kullanarak kesiştiği noktaların bir tablo oluşturmaktır:

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

Bunu bir yol örneğinde çalıştırırsam aşağıdaki nokta ızgarasını alırım (yollar gösterim için gösterilir):

resim açıklamasını buraya girin

Noktalardan birini incelersem, üst üste yığılmış birçok nokta olduğunu görürüm:

resim açıklamasını buraya girin

Buradaki GID yol kimliğidir, ancak neden çok fazla nokta olduğunu anlamıyorum. Merkezi bir yol kavşağı için 4 puan sayıldığını anlayabiliyorum, ancak burada 12 puan var. PostGIS'te bu hesaplamayı yapmanın daha iyi bir yolu var mı?

Yanıtlar:


21

Gruplandırırsanız, yalnızca benzersiz puanlar almalısınız.

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

Sadece bir uyarı, geometriye göre gruplama, geometrinin kendisi değil, geometrinin bbox'ına göre gruplandırma ile sonuçlanır. Puanlarla uğraşırken bu önemli değil. Neredeyse. Bboxlar, teorik olarak özdeş olmayan iki noktayı birlikte gruplamaya yol açabilen noktanın kendisinden daha az hassasiyete sahiptir.
Nicklas Avén

Teşekkürler NicklasAvén. Bbox karşılaştırması ne kadar hassas? Bu kullanım durumu için yeterli olmasını beklerdim.
underdark

1
Teşekkürler @underdark. Kesişen çizgilerin sayısını nasıl sayabileceğimi biliyor musunuz? COUNT()Böyle birkaç kombinasyon denedim COUNT(ST_Touches(..))ve COUNT(ST_Intersection(..))ancak tüm değerleri olduğu gibi çalışmıyor gibi görünüyor 12.
djq

@underdark, evet kesinlikle yeterli, bu yüzden "teoride" yazdım. Kutu float4'te ve noktanın koordinatları çift kesinliktedir. Böylece kutu ST_Point (1.000001,1.0) ve ST_Point (1.000002,1.0) için aynı görünecektir (En azından benim sistemimde, sadece denedim. Kutu ve gerçek geometri arasındaki bu fark, bir süredir geliştirici listesinde bir tartışma olmuştur.
Nicklas Avén

@AlexOs tarafından önerilen modifikasyonu inceleyin gis.stackexchange.com/a/151277/3195
Martin F

6

Bu beklediğinizden biraz daha hileli. Çünkü çiftlerden daha fazla ilişkiyi analiz etmenin iyi bir yolu yoktur. Bir işleve üç satır koyamaz ve hepsinin kesişip kesişmediğini soramazsınız.

Ancak, en azından bir yaklaşım önce geçişleri bulmak, daha sonra her geçişte kaç yolun temas ettiğini kontrol etmek olabilir (hepsi aynı sorguda yapılabilir).

Yollarınız birbirine mükemmel bir şekilde bağlanıyorsa ve bir geçişten geçen yol yoksa, böyle bir şey yapabilirsiniz (test edilmedi):
unutulmuş grup maddesiyle düzenlenmiş (hala test edilmemiştir):

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;

Yollar doğru şekilde bağlanmazsa ve / veya bazı yollar bir geçişten geçerse daha karmaşıktır.

HTH

Nicklas


Merhaba @ Nicklas, bunu çalıştırmak için alamıyorum. İki iç madde düzgün çalışır; yerine distinct_crosspoints ,roadstablo adımı ( roads_test) ile değiştirmeli miyim ? Bunu denedim ama sonra geombelirsiz olmakla ilgili bir hata var .
djq

1
@celenius, Üzgünüm, grup maddesini unuttum. Ayrıca, ekstra bir seviyeye belirgin olmanıza gerek olmadığını da görüyorum. Sadece doğrudan kavşağa koyabilirsiniz. Underdarks cevabı altındaki tartışmaya göre, Distinct'in grupla aynı davranışa sahip olduğunu unutmayın.
Nicklas Avén

Sorgunun çalışmasını sağlamak için Nicklas yanıtına differentt_crosspoints.geom ekledim. Şimdi benim için çalışıyor.
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)
    ;

A çizgisi (id 1) B çizgisini (id 2) geçerse ihtiyacımız olan bir kavşak noktasıdır. Ancak B çizgisi de A çizgisini aynı noktada keser. Ancak bu noktaya iki kez ihtiyacımız yok. Bu yüzden kullanmak a.gid < b.gid yerinea.gid != b.gid

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.