PostGIS çokgen kenar analizi (yönlendirme, kenar uzunluğu)


9

CBS dünyasında ve özellikle PostGIS'te yeniyim, bu yüzden cevap açık görünüyorsa lütfen affedersiniz ...

Birkaç bina üzerinde analiz yapmak istiyorum. İlgilendiğim bir şey, cephe yüzeyleri ve ilgili yönelim. Aşağıdaki resimde gösterildiği gibi, bir dizi çokgen içinde tüm kenarların uzunluk ve (normal) yönüne sahip olmak istiyorum. Örnekte sadece bir yüzeyi vurguladım.

resim açıklamasını buraya girin

Bir sonuç tablosu şöyle görünebilir:

building_id | edge_id | orientation | edge_length
-------------------------------------------------
      1     |    1    |     315     |    10.0
      1     |    2    |      45     |     7.0
      1     |   ...   |     ...     |     ...

Ancak, sonucu daha sonraki işlemler için saklamanın akıllı bir yolu olup olmadığından emin değilim (örneğin kenardan bir sonraki binaya olan mesafeyi hesaplayın, vb.). Benim sorum iki yönlü:

  1. Çokgenin kenarlarını analiz edebilen etkili bir PostGIS işlevi var mı? Doğal bir PostGIS fonksiyonu yoksa alternatif olarak Python tabanlı bir yaklaşımla ilgilenirim.
  2. Çokgenler farklı sayıda kenara sahip olabileceğinden, sonucu bir PostGIS tablosunda depolamanın akıllıca bir yolu nedir?

2
İlk önce çokgenin segmentlerini oluşturun: stackoverflow.com/questions/7595635/… Ardından başlangıç ​​noktası ve bitiş noktası koordinatları x1, y1 ve x2, y2 ve daha sonra ST_Azimuth (ST_Startpoint (geometriler), ST_Endpoint (geometriler)) sütunlara gitmelidir. . ( postgis.org/docs/ST_Azimuth.html )
Tamas Kosa

1
@TamasKosa: İyi bir yanıtın özüne sahipsiniz. Neden bire genişletmiyoruz? Ayrıca, normaller için azimutların +/- pi / 2'ye ihtiyacı vardır.
Martin F

1
@TamasKosa Bu benim de düşündüğüm bir yaklaşım. ST_ExteriorRing kullanın ve sonra azimutları dediğiniz gibi alın. Binaların farklı sayıda kenarı olabileceğinden sonuçları ideal olarak nasıl saklayabilirim? Yukarıda tarif ettiğim gibi bir tabloda mı? MartinF'ye katılıyorum, bu neredeyse bir cevap;)
n1000

Sadece merak ediyorum, neden normaller istiyorsun ... güneşe maruz kalma?
Martin F

1
Sorunuzun ilk kısmı cevaplandı - ST_Dumppoints ve ST_Azimuth'u kullanabilirsiniz. Çıktı için uzamsal elemanlar olmadığından, ikinci bölüm için, bulduğunuz gibi polygonID ve edge_id'e bir bağlantı düşünürdüm.
John Powell

Yanıtlar:


10

Dün ayrıntılarıyla oluşturmak için zamanım yoktu ... Çözümümü 4 adımda görün:

CREATE OR REPLACE VIEW bd_segment AS
SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) AS sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) AS ep
    FROM
       -- extract the individual linestrings
       (SELECT (ST_Dump(ST_Boundary(the_geom))).geom
       FROM bd) AS linestrings;

CREATE OR REPLACE VIEW bd_segment_geom AS
SELECT sp, ep, st_makeline(sp, ep) 
FROM bd_segment;

CREATE OR REPLACE view bd_segment_id AS 
SELECT bd.gid, row_number() 
    OVER (order by bd.gid), degrees(st_azimuth(ff.sp, ff.ep)-1.57079633) AS az_deg,
    ST_LENGTH(ff.st_makeline) , ff.st_makeline FROM bd_segment_geom ff
JOIN bd ON st_touches(ff.st_makeline, bd.the_geom)
GROUP BY bd.gid, ff.sp, ff.ep, ff.st_makeline;

UPDATE bd_segment_id
SET az_deg = az_deg + 360
WHERE az_deg < 0;

Son sorgu st_touches kullanarak uzamsal birleştirme ile bina kimlikleri verir. Umarım yardımcı olur. Güncelleme - qgis'de çözüm şöyle görünür: resim açıklamasını buraya girin


1
Etkileyici! Çalıştırdım. Çok teşekkür ederim! Çok sayıda bina ile biraz yavaşlar. Azimutlar şu anda normal değil. Bunu nasıl ele alacağınız hakkında bir fikriniz var mı? Çokgenin "dış" tarafını nasıl bulacağımdan emin değilim.
n1000

1
radyandaki azimuta şu şekilde 90 derece ekleyin: derece (st_azimuth (ff.sp, ff.ep) +1.57079633). Bazen 360'tan büyük değerler oluşturur. Ancak bir güncelleme sorgusu ile bunları değiştirebilirsiniz. Statik bir görünüm olarak kullanmak istiyorsanız, "MALZEME GÖRÜNÜMÜ OLUŞTURUN" oluşturun ve ilk seferde yavaş olmayacaktır.
Tamas Kosa,

2
Pek değil. Kuzeyin 0 ° olduğu varsayıldığında, bu çokgen / binanın içine doğru normal görüntüyü verecektir (ekran görüntünüzde de görüldüğü gibi). Ama haklısın - basit bir UPDATEhile yapmalı. Bu harika çözüm için tekrar teşekkürler. Kabul etmeden önce başka cevaplar ortaya çıkarsa birkaç gün daha bekleyeceğim.
n1000

1
Ne olmuş ST_ForceRHR? Bu cevap aslında iyi görünüyor.
Jakub Kania

@ JakubKania Bir ST_ForceRHRçözüm bulmaya çalıştım ama başarılı olamadım . İpuçları için müteşekkir olur ... DenedimST_Dump(ST_Boundary(ST_ForceRHR(the_geom)))
n1000
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.