Рекурсивный запрос PostGIS на основе линейного подключения

9

У меня проблемы с запросом. У меня есть сеть строк, каждая из которых имеет значение в столбце n_type. Это может быть одним из нескольких вариантов. Я хотел бы создать новую таблицу, которая группирует любые строки линий того же типа и которые образуют непрерывную линию.

Перед:

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

После:

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

Вот что у меня так далеко. Он возвращает результаты, но они не имеют никакого смысла - типы не совпадают, и он возвращает слишком много функций.

Также обратите внимание, что я определил «непрерывную» как любую линию в пределах 5 футов от соседа и встречающуюся под углом менее 30 градусов.

WITH RECURSIVE all_links (i, pk_uid, n_type, geom) AS (
    SELECT  1 AS i,
            pk_uid,
            n_type,
            geom
    FROM    network
    WHERE   n_type != 'none'

    UNION ALL

    SELECT  a.i + 1,
            b.pk_uid,
            b.n_type,
            b.geom
    FROM    network b, all_links a
    WHERE   b.n_type = a.n_type
    AND     b.geom <#> a.geom <= 5  --lines are continuous if within 5 feet of neighbor
    AND     ABS( DEGREES( 3*pi() - st_azimuth(st_startpoint(a.geom),st_endpoint(a.geom)) + st_azimuth(st_startpoint(b.geom),st_endpoint(b.geom)))::int % 360 - 180) <= 30 )  --only take links within 30 degrees of the same angle

SELECT i, n_type, ST_Union(the_geom) FROM all_links GROUP BY i, n_type

Я предположил, что рекурсивный запрос - это путь, но я счастлив, что оказался неправ в этом. Рекурсивы немного трудно уловить.

Изменить: я должен также добавить, что я уже пытался агрегировать с использованием ST_Union и ST_Linemerge, а затем выводить результат. Это своего рода работает, но не учитывает пересечения> 30 градусов и также не может соблюдать пятифутовый допуск для подключения.

spencerrecneps
источник
Не углубляясь вглубь этого, пара наблюдений. Вам нужно будет объединить a.geom и b.geom в предложении select. Вы, вероятно, должны убедиться, что вы не пытаетесь присоединиться к одной линии с самим собойa.pk_uid != b.pk_uid
MickyT
@ MickyT спасибо. Я должен был упомянуть, что могу выполнить объединение в последнем предложении SELECT, но на данный момент только что выбрал *, чтобы я мог видеть все результаты. Я изменю свой фрагмент кода, чтобы показать, как он в конечном итоге должен выглядеть.
spencerrecneps
Рекурсивные запросы трудно уловить. Лол и +1
Джон Пауэлл
Беглый взгляд показывает, что у вас могут быть проблемы с вашим базовым / якорным запросом. Вам нужно выбрать начальную точку для каждой строки, A, B, C и т. Д., Которую вы затем строите в рекурсивной части. Возможно, вам нужно добавить какой-то порядок в запрос привязки (возможно, в направлении x или y, направление - трудно узнать, не видя данных). Я сломал бы это и удостоверился бы, что я сначала получил разумные начальные точки, прежде чем продолжить с рекурсивной частью. Я недавно использовал рекурсивный запрос, чтобы найти полосы во временных рядах, и как только я правильно определил опорные точки, остальное было легко (иш)
Джон Пауэлл
@dbaston. Хороший вопрос, но вы также можете сделать это с помощью рекурсивного запроса, но не у всех это установлено.
Джон Пауэлл

Ответы:

1

Ваше решение, по крайней мере, пропускает предварительный заказ линейных компонентов, как сказал Джон Барса.

Я бы сказал, что рекурсивные запросы очень и очень трудно поддается поиску.

Вы должны попытаться повторить поведение ST_Linemerge в новой функции базы данных. Сначала я бы попытался взглянуть на источник реализации ST_Linemerge и повторить его, чтобы получить 30-градусный угол.

Чтобы отбросить из агрегата сегменты, которые не находятся под углом <30 градусов, вы должны сравнить их ВНУТРИ цикла агрегации.

rpcavaco
источник