Oblicz równoległe linie wzdłuż linii środkowej w PostGIS

10

W mojej bazie danych PostgreSQL mam ulicę (środkową linię drogi) i buduję tabele wielokątów. Przykładowy scenariusz wygląda następująco:

Przykładowy scenariusz

Problem:

Muszę obliczyć równoległe linie wzdłuż ulicy na przecięciu 50 m bufora wokół ulicy i najbliższego wielokąta budynku po obu stronach. Pożądany scenariusz wyjściowy to:

Pożądany scenariusz wyjściowy

Co próbowałem:

Moje podejście było następujące:

 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

Oto moja próba:

    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

Problem z powyższym kodem polega na tym, że nie zwraca on równoległych linii zgodnie z pożądanym wyjściem, tj. Generowane są równoległe linie na wszystkich przecięciach wielokątów zamiast na przecięciu najbliższych wielokątów.

EDIT_1:

Rzeczywiste wyjście powyższego kodu to:

kod_wyjściowy

Podczas gdy na powyższym wyjściu wymagane są tylko żółte równoległe linie (przesunięcie krzywych do najbliższych wielokątów po obu stronach ulicy):

wymagane wiersze rzeczywistej mocy wyjściowej

Czy ktoś może mi zasugerować, jak uzyskać pożądaną wydajność?

Khajlk
źródło
Czy możesz również dodać obraz rzeczywistej wydajności? Pomaga w zrozumieniu problemu.
plandeka
@tilt: Zredagowałem pytanie. Właśnie dodałem rzeczywistą moc wyjściową i wymagane równoległe linie w rzeczywistej mocy wyjściowej.
khajlk
Problem jest bardziej złożony niż myślisz. Chcecie dowiedzieć się, po której stronie ulicy znajdują się domy. Tylko wtedy możesz znaleźć najbliższy po obu stronach. Oto post, który ma przykładowy kod do znalezienia właściwej strony: gis.stackexchange.com/questions/156578/…
tilt
W rzeczywistości mogą zdarzyć się przypadki, gdy budynki znajdują się tylko po jednej stronie (nazwałbym to wyjątkami). Mógłbym zmodyfikować swój kod, aby obsługiwał wyjątki, gdy będę w stanie osiągnąć pożądany wynik. Powyżej nadal widać wielokąty budowlane po obu stronach. W tym momencie moim wymaganiem jest uzyskanie równoległych linii po obu stronach ulicy (takich jak te pokazane na rysunku). Jeśli chodzi o twój link, mógłbym użyć przykładowego kodu, aby poprawić mój powyższy kod prawdopodobnie później.
khajlk
Widzę tylko, że bufor jest zbędny. Możesz po prostu użyć stdwithin i użyć 50 jako odległości. (Wybierz ulice, budynki, w których st_dwithin (ulice, budynki, 50))
jbalk

Odpowiedzi:

1

Jeśli zmodyfikowałeś odległość CTE w następujący sposób:

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

wówczas dla każdej ulicy zwracana byłaby tylko najkrótsza odległość i w tej odległości generowana byłaby jedna para linii przesunięcia.

Andy Harfoot
źródło
Dziękuję za sugestię. Przetestuję to i sprawdzę, czy daje oczekiwany rezultat. Przekopałem się, aby rozwiązać ten problem. Odkryłem jeden szalony pomysł: aby zacząć od 1 m bufora wokół ulicy i programowo zwiększać bufor ORAZ szukać budynków po obu stronach, aż liczba budynków wyniesie 2, a następnie zwróć tę odległość bufora jako szerokość ulicy. Ostatecznym celem wszystkich powyższych ćwiczeń.
khajlk
To prawda, że ​​przy użyciu Twojej sugestii generowana jest tylko jedna para przesunięć. Jednak wciąż brakuje żółtych równoległych linii pokazanych powyżej :(
khajlk,