L’analyse spatiale avec SQL:3-les fonctions de relation spatiale

Après les deux article introductifs,L’analyse spatiale avec SQL:1-Introduction, 2-les fausses idées reçues, voici, maintenant, la dizaine de fonctions de relation spatiale de Postgis (mais que vous trouverez aussi avec Spatialite). Comme dit précédemment, ce n’est qu’une toute petite partie des fonctions disponibles, mais c’est vraiment le noyau indispensable pour démarre l’analyse spatiale avec SQL.

Les types ou dimensions des géométries

Avant de voir les différentes fonctions il faut rappeler sur quoi nous allons travailler. Les différentes fonctions ont comme paramètres  deux géométries. Mais les géométries ne sont pas toutes de même type (on parle aussi de dimensions): nous avons trois types majeurs (point, ligne, surface) et trois type dérivés (multipoints, multilignes, multisurfaces). La distinction est importante car les fonctions fonctionnent sur la détermination, pour chaque entité (géométrie) de ce que l’on considère l’intérieur de l’entité et de ce que l’on considère l’extérieur. Pour une couche de polygones vous voyez tout de suite de quoi on parle et vous n’aurez aucun mal à distinguer l’intérieur  des polygones de leur extérieur.

Pour les points, ça commence à se corser car l’intérieur d’un point est un peu plus difficile à concevoir. Et ça devient presque métaphysique quand on parle de l’intérieur d’une entité multipoint.
Cette image peut représenter trois entités ponctuelles, dans le cas d’une couche de points, ou bien une seule entité constituée par trois points, dans le cas d’une couche multipoints. Mais dans les deux cas, l’intérieur est constitué par le ou les points seulement.

Par exemple, dans la figure suivante, est-ce que la ligne traverse la géométrie de la couche multipoint?

La réponse est NON. Pour traverse une géométrie, il faut qu’il y ait une partie commune « interne » aux deux géométries.

Dans la figure suivante, par contre, la réponse est OUI, la ligne traverse l’entité multipoint.

Vous aurez compris que l’intérieur d’une ligne est la ligne elle-même, comme pour les points.

On peut séparer les fonctions de relation spatiale en deux grands groupes: celles qui s’appliquent à tous les types de géométrie et ceux qui ne s’appliquent qu’à certains types.

Pour une description détaillée des fonctions, reportez vous à la documentation Postgis: https://postgis.net/docs/manual-1.5/reference.html#Spatial_Relationships_Measurements

Les fonctions applicables à tous les types de géométrie

Les fonction d’intersection, de différence,  de contenance ou de contenu et la fonction toucher acceptent dans les deux paramètres de la fonction n’importe quel type de géométrie de base ou multiple. On peut donc calculer l’intersection d’une couche multipoint avec un couche polyligne, de polygones et de multipolygones, etc.

st_Intersect

C’est la fonction la plus générique. Elle renvoie VRAI si l’intérieur d’une géométrie occupe la même place qu’un autre point intérieur de la deuxième géométrie, en d’autres termes si elles ont au moins un point de l’espace en commun. Si les autres fonctions telles que st_Crosses, st_Overlaps, st_touches, st_Within ou st_Contains retournent une valeur VRAI sur des géométries, st_Intersect retournera aussi une valeur VRAI.

L’exemple suivant montre le résultat de la requête permettant de trouver les parcelles qui sont affectées par une zone inondable de risque maximal:

SELECT parcelles.*
FROM parcelles,carto_risque
WHERE ST_Intersects(parcelles.geometry,carto_risque.geometry)
AND carto_risque.zone = ‘max’

Toute parcelle qui partage ne serait-ce qu’un point dans l’espace avec la zone inondable est sélectionnée.

st_Disjoint

Est la fonction inverse de st_intersect. Elle renvoie VRAI si l’intérieur d’une géométrie n’occupe pas la même place qu’un autre point intérieur de la deuxième géométrie, en d’autres termes si elles n’ont aucun point de l’espace en commun.

On obtient le même résultat qu’avec la commande st_intersects avec la requête:
SELECT parcelles.*
FROM parcelles,carto_risque
WHERE ST_Disjoint(parcelles.geometry,carto_risque.geometry)=false
AND carto_risque.zone = ‘max’

C’est un peu tiré par les cheveux de faire une requête inversée, mais si vous cherchez vraiment les géométries disjointes, il vaut mieux utiliser st_Intersects =false, car une requête utilisant st_intersect s’effectue avec les index spatiaux tandis que st_disjoint se fait en parcourant séquentiellement toutes les entités. les temps de réponse seront nettement différents!

st_Contains et st_Within

Ces deux fonctions testent si une géométrie est totalement à l’intérieur d’une autre. st_Within(geomA,geomB) retourne VRAI si la première géométrie (geomA) est complètement contenue dans l’autre (geomB).

st_Contains(geomA,geomB) retourne VRAI si la deuxième géométrie (geomB) est complètement contenue dans la première (geomA).

L’exemple suivant montre le résultat de la requête permettant de trouver les parcelles totalement incluses dans une zone inondable de risque maximal:

SELECT parcelles.*
FROM parcelles, carto_risque
WHERE ST_Within(parcelles.geometry, carto_risque.geometry)
AND carto_risque.zone = ‘max’

resultat de st_withinSeules les parcelles dont tous les points sont à l’intérieur de la zone inondable sont sélectionnées.

On obtient exactement le même résultat avec la requête

SELECT parcelles.*
FROM parcelles, carto_risque
WHERE ST_Contains(carto_risque.geometry, parcelles.geometry)
AND carto_risque.zone = ‘max’

st_Touches

Nous avons vu un exemple de cette fonction dans l’article précédent. Cette fonction retourne VRAI si les deux géométries ont au moins un point en commun mais que leurs intérieurs ne s’intersectent pas. En d’autres termes seuls les contours ont un ou plusieurs points en commun.

Les fonctions applicables selon le type de géométrie

st_Equals

St_Equals ne fonctionne que sur des géométries de même type. Il renvoie VRAI si les deux géométries partagent tous les points de l’espace, c’est à dire si toutes les coordonnées XY de la première géométrie sont identiques aux coordonnées de la deuxième. L’ordre des entités dans la couche n’intervient pas du tout dans la comparaison.

st_Crosses

St_Crosses ne s’applique pas à toutes les combinaisons de géométries. Elle s’applique aux combinaisons suivantes:

Les couches de points sont exclues. La fonction retourne VRAI si le résultat de l’intersection se retrouve à l’intérieur des deux géométries

Si on reprend notre exemple précédent, la figure suivante montre le résultat de la requête permettant de trouver les parcelles qui sont partiellement affectées par une zone inondable de risque maximal:

SELECT parcelles.*
FROM parcelles,carto_risque
WHERE ST_Overlaps(parcelles.geometry,carto_risque.geometry)
AND carto_risque.zone = ‘max’

Seules les parcelles qui ont des points à l’intérieur ET à l’extérieur de la zone inondable sont sélectionnées.

St_Distance

Contrairement aux autres fonctions, cette fonction ne renvoie pas VRAI ou FAUX mais la valeur de la plus petite distance calculée entre les deux géométries.

Si une partie (ou toute) de la géométrie de A se retrouve à l’intérieur de la géométrie B, la distance calculée sera 0.

L’exemple suivant montre le résultat de la requête permettant de trouver les parcelles situées à moins de 200 mètres d’une zone inondable de risque maximal:

SELECT parcelles.*
FROM parcelles,carto_risque
WHERE ST_Distance(parcelles.geometry,carto_risque.geometry) < 200
AND carto_risque.zone = ‘max’

Mais cette fonction est surtout utilisée pour calculer les distances entre géométries, car elle n’utilise pas les index spatiaux et fait un traitement séquentiel qui prend beaucoup plus de temps. Pour obtenir le même résultat que dans cette figure on utilise la fonction St_DWithin.

st_DWithin

La fonction prend la forme St_DWithin( geomA, geomB, Distance). Elle renvoie la valeur VRAI si la plus petite distance entre geomA et geomB est inférieure ou égale à Distance.

Pour l’exemple précédent la requête prend la forme:

SELECT parcelles.*
FROM parcelles,carto_risque
WHERE ST_Distance(parcelles.geometry,carto_risque.geometry,200)
AND carto_risque.zone = ‘max’

Et on obtient le même résultat cartographique.

Cette fonction est très utile pour répondre à une question telle que « Combien de parcelles se situent dans un buffer de 200 mètres autour de ce cours d’eau? ou de cette route? », sans avoir à calculer le buffer. On teste tout simplement la distance entre les géométries.

st_Covers et st_CoveredBy

J’ai laissé pour la fin ces deux fonctions qui sont presque équivalentes à st_Contains et st_Within. Le résultat sera presque toujours le même sauf dans certains cas très particuliers. C’est un peu tordu, mais il faut revenir à la notion de début de cet article, celle d’intérieur et extérieur d’une géométrie.

Quand nous avons un polygone, l’intérieur c’est l’espace contenu par les bords du polygone. Mais cette ligne imaginaire qui fait office de contour ne fait pas partie de l’intérieur, ni de l’extérieur non plus. C’est une limite.

Quand nous avons une ligne, même si elle n’a pas de dimension « épaisseur » on considère que la ligne est la zone « intérieure » de la géométrie.

Si nous avons par exemple une limite administrative de département, et cette limite correspond à une route qui est contenue dans une couche de polylignes, la fonction st_contains(polygone,ligne) va retourner FAUX car la zone intérieure de la ligne ne sera pas à l’intérieur du polygone (elle sera sur le contour).

La fonction st_Covers agit différemment. Elle trouvera que la limite du polygone « recouvre » le tronçon de route. La fonction st_CoveredBy cherche à savoir si la géométrie A et recouverte par la géométrie B et fonctionne de la même manière que st_Covers.

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *