PostGIS'te paralel bir çizgiyi orta çizgi boyunca hesaplayın


10

PostgreSQL veritabanımda sokak (yol merkez hattı) ve bina çokgen tablolarım var. Örnek senaryo aşağıdaki gibidir:

Örnek senaryo

Sorun:

Caddenin etrafındaki 50 metrelik tamponun kesişim noktasında ve her iki tarafta en yakın bina poligonunun kesiştiği yerde paralel çizgiler hesaplamam gerekiyor. İstenen çıktı senaryosu:

İstenen çıktı senaryosu

Ne denedim:

Benim yaklaşımım:

 1) Generate 50m buffer around street layer
 2) get the intersection of buffer and polygons
 3) Compute the distance
 4) Draw offset curves (parallel lines) at both sides of street layer
 5) Merge both curves to get parallel lines at the intersection

İşte benim girişimim:

    WITH street_buffer AS (
     SELECT
      street.gid street_id,
      street.geom street_geom,
      ST_Buffer(street.geom, 50, 'endcap=square join=round') geom1,
      building.geom  geom2  
     FROM street
     LEFT JOIN building on ST_DWithin(building.geom, street.geom, 50)
     ORDER BY street_id
    ),
    selected_buildings AS (
     SELECT
      street_id,
      street_geom,
      ST_Intersection(geom1, geom2) geom
     FROM street_buffer
    ),
    distance AS (
     SELECT 
      street_id,
      street_geom,
      ST_Distance(street_geom, geom) as dist
     FROM selected_buildings 
    ),
    curves AS (
     SELECT 
      street_id,
      ST_OffsetCurve(ST_LineMerge(street_geom), dist) as curve1,
      ST_OffsetCurve(ST_LineMerge(street_geom), -dist) as curve2
     FROM distance
     ORDER BY street_id
    )
    SELECT 
     street_id,
     ST_Union(curve1, curve2) geom 
    FROM curves
    ORDER BY street_id

Yukarıdaki kodla ilgili sorun, istenen çıktıya göre paralel çizgiler döndürmemesi, yani en yakın çokgenlerin kesişimi yerine tüm çokgen kavşaklarında paralel çizgiler üretilmesidir.

EDIT_1:

Yukarıdaki kodun gerçek çıktısı:

code_output

Yukarıdaki çıktıda sadece sarı paralel çizgiler (sokağın her iki tarafındaki en yakın çokgenlere ofset eğrileri) gereklidir:

gerçek çıktıda gerekli satırlar

Birisi bana istenen çıktıyı nasıl alacağımı önerebilir mi?


Gerçek çıktının görüntüsünü de ekleyebilir misiniz? Sorunun anlaşılmasına yardımcı olur.
eğin

@tilt: Soruyu düzenledim. Sadece gerçek çıkışı ve gerçek çıkışa gerekli paralel hatları ekledim.
khajlk

Sorun düşündüğünüzden daha karmaşık. Ondan önce evlerin sokağın hangi tarafında olduğunu bulmalısınız. Ancak o zaman her iki tarafta da en yakını bulabilirsiniz . İşte doğru tarafı bulmak için örnek kod içeren bir yazı: gis.stackexchange.com/questions/156578/…
eğim

Gerçekte, binaların sadece bir tarafta olduğu durumlar olabilir (buna istisna diyorum). İstediğim çıktıya ulaşabildiğimde istisnaları işlemek için kodumu değiştirebilirim. Yukarıda, her iki tarafta da çokgenler inşa ettiğini görüyorsunuz. Bu noktada ihtiyacım, sokağın her iki tarafında paralel çizgiler elde etmektir (şekilde gösterdiğim gibi). Bağlantınızla ilgili olarak, yukarıdaki kodumu muhtemelen daha sonra geliştirmek için örnek kodu kullanabilirim.
khajlk

Gördüğüm bir şey, tamponun gereksiz olduğu. Sadece stdwithin ve mesafe olarak 50 kullanabilirsiniz. (Sokakları seçin, st_dwithin olan binalar (sokaklar, binalar, 50))
jbalk

Yanıtlar:


1

CTE mesafesini aşağıdaki gibi değiştirdiyseniz:

distance AS (
 SELECT 
  street_id,
  street_geom,
  MIN(ST_Distance(street_geom, geom)) as dist
 FROM selected_buildings
 GROUP BY street_id, street_geom
)

her bir sokak için yalnızca en kısa mesafe döndürülür ve bu mesafede bir çift ofset çizgisi oluşturulur.


Öneri için teşekkürler. Test edeceğim ve beklenen sonuç verip vermediğini göreceğim. Bu sorunu gidermek için araştırıyorum. Çılgın bir fikir keşfettim: Caddenin etrafında 1 m tamponla başlamak ve arabelleği programlı olarak artırmak ve bina sayısı 2 olana kadar her iki tarafta bina aramak için, bu tampon mesafesini sokak genişliği olarak döndürün. Yukarıdaki tüm egzersizlerin nihai amacı.
khajlk

Öneriniz kullanılarak yalnızca bir çift ofset üretildiği doğrudur. Ancak, yukarıda gösterilen sarı paralel çizgiler hala eksik :(
khajlk
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.