Je suis confronté à un défi avec PostGIS que je n'arrive pas à comprendre. Je sais que je peux résoudre ce problème en utilisant un langage de programmation (et c'est mon plan de sauvegarde), mais j'aime vraiment résoudre ce problème dans PostGIS. J'ai essayé de chercher, mais je n'ai pas trouvé de réponses qui correspondent à mon problème, c'est peut-être parce que je ne suis pas sûr de mes termes de recherche, alors s'il vous plaît excusez-le et dirigez-moi dans la bonne direction car il y a bien une réponse.
Mon problème est le suivant:
- J'ai une table avec des polygones mixtes / multi-polygones
- Chaque (multi) polygone a un attribut qui le classe (priorité)
- Chaque polygone a également une valeur que j'aimerais connaître
- J'ai une zone de recherche (polygone)
- Pour ma zone de requête, je veux trouver la zone couverte par chaque valeur de polygone
Exemple:
Disons que j'ai les trois polygones représentés en rouge, vert et indigo ici:
Et que le petit rectangle bleu est mon polygone de requête
De plus, les attributs sont
geom | rank | value
-------|------|----
red | 3 | 0.1
green | 1 | 0.2
indigo | 2 | 0.2
Ce que je veux, c'est sélectionner ces géométries, de sorte que le plus haut rang (vert) remplisse toute la zone qu'il peut (c'est-à-dire l'intersection entre mon géom de requête et ce géom), puis le plus haut suivant (indigo) remplit l'intersection entre le géom de requête et le geom MOINS le déjà couvert) etc.
J'ai trouvé cette question: utiliser ST_Difference pour supprimer les fonctionnalités qui se chevauchent? mais il ne semble pas faire ce que je veux.
Je peux moi-même comprendre comment calculer des zones et autres, donc une requête qui me donne les trois géométries décrites dans la deuxième image est très bien!
Informations supplémentaires: - Ce n'est pas un grand tableau (~ 2000 lignes) - il peut y avoir zéro ou plusieurs chevauchements (pas seulement trois) - il peut ne pas y avoir de polygones dans ma zone de requête (ou seulement dans certaines parties) - i ' m exécuter postgis 2.3 sur postgres 9.6.6
Ma solution de secours consiste à faire une requête comme celle-ci:
SELECT
ST_Intersection(geom, querygeom) as intersection, rank, value
FROM mytable
WHERE ST_Intersects(geom, querygeom)
ORDER by rank asc
Et puis "couper" itérativement des parties des géométries dans le code. Mais, comme je l'ai dit, j'aimerais vraiment le faire dans PostGIS
WITH RECURSIVE ...
Réponses:
Je pense que cela fonctionne.
C'est une fonction de fenêtrage, obtenant la différence entre l'intersection de chaque intersection de géométries avec la zone de requête et l'union des géométries précédentes.
La fusion est nécessaire car l'union des géométries précédentes pour la première géométrie est nulle, ce qui donne un résultat nul, au lieu de ce qui est souhaité.
Je ne sais pas cependant comment cela fonctionne. Mais puisque ST_Union et ST_Intersection sont marqués comme immuables, ce n'est peut-être pas si mal.
la source
Un peu d'une approche différente à cela. Il y a une mise en garde que je ne sais pas comment cela évoluera en termes de performances, mais sur une table indexée, cela devrait être correct. Il fonctionne à peu près comme la requête de Nicklas (un peu plus lent?), Mais la mesure sur un si petit échantillon est lourde.
Il semble beaucoup plus laid que la requête de Nicklas, mais il évite la récursivité dans la requête.
la source
Depuis que je bavarde,
WITH RECURSIVE
je vais ajouter une réponse rapide et sale en l'utilisant.Cela fonctionne à peu près aussi bien que la solution de @ NicklasAvén sur trois Polygones, impossible à tester lors d'une mise à l'échelle.
Dans l'état actuel des deux solutions, celle-ci présente un petit avantage par rapport à l'autre: si, par exemple, le polygone avec rang = 2 est contenu par celui de rang = 1 , les
...WHERE GeometryType = 'POLYGON'
filtres disparaissent alors qu'autrement il y aura unGEOMETRYCOLLECTION EMPTY
(j'ai changé la géométrie du polygone respectif dans ma solution en conséquence pour donner un exemple; cela est également vrai pour d'autres cas où aucune intersection avec la différence n'est trouvée). Cependant, cela est facilement inclus dans les autres solutions et pourrait même ne pas être préoccupant.la source