Requête récursive PostGIS basée sur la connectivité de ligne

9

J'ai du mal avec une requête. J'ai un réseau de chaînes de lignes, chacune avec une valeur dans la colonne n_type. Cela peut être l'une d'une poignée d'options. Je voudrais générer un nouveau tableau qui regroupe toutes les chaînes de lignes qui sont du même type et qui forment une ligne continue.

Avant:

entrez la description de l'image ici

Après:

entrez la description de l'image ici

Voici ce que j'ai jusqu'à présent. Il renvoie des résultats mais ils n'ont aucun sens - les types ne correspondent pas et retournent trop de fonctionnalités.

Veuillez également noter que j'ai défini «continu» comme toute ligne à moins de 5 pieds de son voisin et se rencontrant à moins d'un angle de 30 degrés.

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

J'ai supposé qu'une requête récursive était la voie à suivre, mais je suis heureux d'avoir tort. Les récursifs sont un peu difficiles à comprendre.

Edit: je dois également ajouter que j'ai déjà essayé d'agréger à l'aide de ST_Union et ST_Linemerge, puis de vider le résultat. Cela fonctionne un peu, mais ne tient pas compte des intersections de> 30 degrés et ne peut pas non plus respecter la tolérance de cinq pieds pour la connectivité.

spencerrecneps
la source
Sans creuser profondément, quelques observations. Vous devrez unir a.geom et b.geom dans votre clause select. Vous devriez probablement vous assurer que vous n'essayez pas de joindre une ligne à elle-même aveca.pk_uid != b.pk_uid
MickyT
@MickyT merci. J'aurais dû mentionner que je peux faire l'union dans la dernière clause SELECT mais pour le moment je viens de sélectionner * pour que je puisse voir tous les résultats. Je vais modifier mon extrait de code pour montrer à quoi il devrait finalement ressembler.
spencerrecneps
Les requêtes récursives sont difficiles à gérer. Lol et +1
John Powell
Un rapide coup d'œil suggère que vous pourriez avoir des problèmes avec votre requête de base / d'ancrage. Vous devez sélectionner le point de départ pour chaque ligne, A, B, C, etc., que vous créez ensuite dans la partie récursive. Il est possible que vous deviez ajouter une sorte de classement à la requête d'ancrage (peut-être en x ou y, direction - difficile à connaître sans voir les données). Je décomposerais cela et m'assurerais que j'obtenais des points de départ raisonnables avant de continuer avec la partie récursive. J'ai utilisé une requête récursive pour trouver des séquences dans les séries chronologiques récemment, et une fois que les points d'ancrage ont été correctement identifiés, le reste a été facile (ish)
John Powell
@dbaston. Bon point, mais vous pouvez également le faire avec une requête récursive, et tout le monde ne l'a pas encore installé.
John Powell

Réponses:

1

Votre solution manque, au moins, une précommande de composants de ligne comme l'a dit John Barça.

Je dirais que les requêtes récursives sont très, très difficiles à gérer.

Vous devez essayer de répliquer le comportement ST_Linemerge dans une nouvelle fonction de base de données. J'essaierais d'abord de regarder la source d'une implémentation de ST_Linemerge et de la répliquer, en la modifiant pour produire la contraction d'angle de 30 degrés.

Pour éliminer de l'agrégation les segments qui ne sont pas à un angle <30 degrés, vous devez les comparer À L'INTÉRIEUR d'une boucle d'agrégation.

rpcavaco
la source