Анализ ребер полигонов PostGIS (ориентация, длина ребер)

9

Я довольно новичок в мире ГИС и особенно в PostGIS, поэтому извините, если ответ кажется очевидным ...

Я хотел бы сделать анализ ряда зданий. Одна вещь, которая меня интересует, это их фасадные поверхности вместе с соответствующей ориентацией. Как показано на рисунке ниже, я хотел бы иметь длину и (нормальную) ориентацию всех ребер в серии многоугольников. В примере я выделил только одну поверхность.

введите описание изображения здесь

Таблица результатов может выглядеть так:

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

Однако я не уверен, что это разумный способ сохранить результат для дальнейшей обработки (например, рассчитать расстояние от края до следующего здания и т. Д.). Итак, мой вопрос состоит из двух частей:

  1. Существует ли эффективная функция PostGIS, которая может анализировать ребра многоугольника? В случае отсутствия встроенной функции PostGIS, я бы заинтересовался подходом на основе Python.
  2. Какой разумный способ сохранить результат в таблице PostGIS, поскольку полигоны могут иметь разное число ребер?
N1000
источник
2
Сначала создайте сегменты многоугольника: stackoverflow.com/questions/7595635/… Затем начальная точка и координаты конечной точки должны идти в столбцы, такие как x1, y1 и x2, y2 и чем ST_Azimuth (ST_Startpoint (геометрии), ST_Endpoint (геометрии)) , ( postgis.org/docs/ST_Azimuth.html )
Тамас Коса
1
@TamasKosa: У вас есть суть хорошего ответа. Почему бы не расширить его в один? Также для нормалей азимутам нужно +/- пи / 2.
Мартин Ф
1
@TamasKosa Это подход, о котором я тоже думал. Используйте ST_ExteriorRing, а затем получите азимуты, как вы говорите. Как бы я в идеале сохранил результаты, так как здания могут иметь разное количество ребер? В таблице, как я описал выше? Я согласен с MartinF, это почти ответ;)
n1000
Просто любопытно, а зачем тебе нормальные ... солнечные лучи?
Мартин Ф
1
На первую часть вашего вопроса ответили - вы можете использовать ST_Dumppoints и ST_Azimuth. Во второй части, поскольку в выводе нет пространственных элементов, я бы подумал, что ссылка на polygonID и edge_id, как у вас, будет найдена.
Джон Пауэлл

Ответы:

10

Вчера у меня не было времени, чтобы создать его в деталях ... Смотрите мое решение в 4 этапа:

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;

Последний запрос дает вам идентификаторы здания с пространственным объединением, используя st_touches. Надеюсь, поможет. Обновление - в qgis решение выглядит так: введите описание изображения здесь

Тамас Коса
источник
1
Впечатляет! Я получил это на работу. Спасибо огромное! Это становится немного медленным с большим количеством зданий. Азимуты не являются нормальными прямо сейчас. У вас также есть идея, как решить эту проблему? Я не уверен, как найти «внешнюю» сторону многоугольника.
19000 года
1
добавить 90 градусов к азимуту в радианах следующим образом: градусы (st_azimuth (ff.sp, ff.ep) +1.57079633). Иногда он генерирует значения, превышающие 360. Но с помощью запроса на обновление вы можете заменить их. Если вы хотите использовать в качестве статического представления, создайте «CREATE MATERIALIZED VIEW», и оно не будет медленным только в первый раз.
Тамас Коса
2
Не совсем. Предполагая, что север равен 0 °, это даст нормаль к внутренней части многоугольника / здания (как также видно на скриншоте). Но вы правы - простой UPDATEдолжен сделать свое дело. Еще раз спасибо за это отличное решение. Я буду ждать еще несколько дней, если появятся другие ответы, прежде чем принимать.
1915 года
1
Как насчет ST_ForceRHR? Этот ответ на самом деле кажется правильным.
Якуб Кания
@JakubKania Я пытался найти ST_ForceRHRрешение, но безуспешно . Был бы благодарен за подсказки ... Я попробовалST_Dump(ST_Boundary(ST_ForceRHR(the_geom)))
n1000