#1 Fri 15 November 2013 17:24
- Razorbak
- Participant assidu
- Lieu: Clermont Ferrand
- Date d'inscription: 7 Oct 2007
- Messages: 505
[PostGis] Points contenus dans des polygones
Bonjour,
Je suis en train d'essayer de faire une requête permettant de sélectionner des chefs-lieux contenus dans des territoires. Puis je désire en faire une vue.
J'ai testé cette requête :
Code:
select A.insee_comm from adm.chl as A, adm.terri as B where ST_Within(A.geom, B.geom)
Mais le résultat est très long à arriver...
J'ai donc testé l'opérateur @ dans cette requête :
Code:
select A.insee_comm, A.geom @ B.geom as test from adm.chl as A, adm.terri as B where A.geom @ B.geom = true
C'est beaucoup plus rapide mais le résultat est faux, vu que l'on travaille sur les bbox.
Une idée ?
Merci et bon WE
Hors ligne
#2 Fri 15 November 2013 18:45
Re: [PostGis] Points contenus dans des polygones
Bonsoir,
les attributs géométriques des tables sont-ils bien indexés ?
Que donne le requête avec l’opérateur st_intersects() ?
Mathieu BOSSAERT
Association GeoRezo
Hors ligne
#3 Fri 15 November 2013 21:11
Re: [PostGis] Points contenus dans des polygones
Bonsoir,
L'utilisation de l'opérateur @ seul (et tous les autres aussi d'ailleurs &&, &<, etc) seront faux car ils utilisent les BBOX, donc il faut faire un deuxième passage. En réalité c'est ce que fait st_within() (ie ils utilisent les index donc les bbox puis fait un deuxième passage).
Par contre je ne sais pas quel opérateur est utilisé par st_within, peux être testé avec ST_DWithin et utiliser une distance de 0.000001 ?
Y.
Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !! - GeoRezo vous aide ? Aidez GeoRezo !
Hors ligne
#4 Mon 18 November 2013 16:45
- Fritsch
- Participant occasionnel
- Lieu: Paris
- Date d'inscription: 8 Nov 2006
- Messages: 32
Re: [PostGis] Points contenus dans des polygones
Comme à chaque fois avec ces questions d'optimisation : avez-vous mis au moins un index spatial sur l'une des deux géométries ?
Pouvez-vous poster ici le plan de requête ? (c'est le résultat de la requête avec EXPLAIN devant)
Emmanuel.
Dernière modification par Fritsch (Mon 18 November 2013 16:46)
Hors ligne
#5 Tue 19 November 2013 06:23
- ChristopheV
- Membre
- Lieu: Ajaccio
- Date d'inscription: 7 Sep 2005
- Messages: 3197
- Site web
Re: [PostGis] Points contenus dans des polygones
Bonjour,
J'ai donc testé l'opérateur @ dans cette requête :
Code:
select A.insee_comm, A.geom @ B.geom as test from adm.chl as A, adm.terri as B
where A.geom @ B.geom = true
Outre le fait que c'est un résultat approché comme vous le soulignez, la requête est un peu bizarre dans sa forme
Code:
select A.insee_comm, A.geom @ B.geom as test
va renvoyer une géométrie et un booléen.
de même
Code:
where A.geom @ B.geom = true
Le "=true" est inutile.
Concernant les fonctions postgis je ne connais pas leur code, mais il existe deux algorithmes principaux pour savoir si un point est à l'intérieur d'un polygone. Soit ce que je nommerai l'algo de la ligne de balayage (1) soit l'algo topologique (2).
1) : On parcours le polygone de bas en haut avec une ligne parallèle à l'axe des X et on vérifie si le point appartient aux intervalles résultant de l'intersection de cette ligne et du polygone.(on l'utilise pour de l'image).
2) On parcours le polygone selon ses sommets (les anneaux intérieurs étant orientés dans le sens inverse de l'anneau extérieur) et on vérifie que le point concerné est toujours du même coté avec une fonction du type EstAGauche() : boolean .
Ces deux algos dépendent du nombres de sommets du polygone.
En revanche avec l'utilisation de l'opérateur @ seuls les points appartenant à au moins deux BBox ont a subir une deuxième passe.
Christophe
L'avantage d'être une île c'est d'être une terre topologiquement close
Hors ligne
#6 Wed 20 November 2013 09:04
- Razorbak
- Participant assidu
- Lieu: Clermont Ferrand
- Date d'inscription: 7 Oct 2007
- Messages: 505
Re: [PostGis] Points contenus dans des polygones
Bonjour,
Pour répondre à une des interrogations, les index existent bien.
Finalement, j'ai testé autre chose et ça fonctionne :
Code:
WITH territoire AS ( SELECT geom FROM adm.territoire WHERE territoire = 'A' OR territoire = 'B' ) SELECT chl.gid, chl.insee_comm, chl.geom FROM adm.chl AS chl, territoire WHERE st_within(chl.geom, territoire.geom) AND territoire.geom && chl.geom;
En gros, j'ai fait un préfiltrage sur le territoire qui m'intéresse et par conséquent, qui me fait gagner du temps : résultat obtenu en à peine plus d'une seconde (contre 18 avant).
Merci et bonne journée
Hors ligne
#7 Wed 20 November 2013 16:20
- SANTANNA
- Moderateur
- Lieu: Angers
- Date d'inscription: 18 Jan 2008
- Messages: 3941
Re: [PostGis] Points contenus dans des polygones
Bonjour,
Etant donné que ST_WITHIN fait appel à la bbox, il me semble que ce n'est plus utile d'ajouter une comparaison de bbox avec
Code:
AND territoire.geom && chl.geom
Pour ce qui est des performances, je ne connais pas le nombre d'entités de la table adm.territoire ni la complexité de leur géométrie mais peut-être que finalement, le temps de requête n'était pas si énorme (A part la sous-sélection, on a pratiquement la même requête que celle du début).
Que vaut la même requête sans le préfiltrage sur les territoires par ex?
Code:
WITH territoire AS ( SELECT geom FROM adm.territoire ) SELECT chl.gid, chl.insee_comm, chl.geom FROM adm.chl AS chl, territoire WHERE st_within(chl.geom, territoire.geom);
Hors ligne
#8 Thu 21 November 2013 13:00
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostGis] Points contenus dans des polygones
Bonjour,
Pour ce genre de requetes, st_dwithin (distance within) est souvent plus rapide que st_within::
Code:
select chl.gid, chl.insee_comm, chl.geom from adm.chl AS chl, adm.territoire as t where t.territoire in ('A', 'B') and st_dwithin(t.geom, chl.geom, 0);
Hors ligne
#9 Mon 09 December 2013 10:26
- Razorbak
- Participant assidu
- Lieu: Clermont Ferrand
- Date d'inscription: 7 Oct 2007
- Messages: 505
Re: [PostGis] Points contenus dans des polygones
Bonjour,
Je reviens un peu tard sur ce post mais voici les résultats obtenus :
- avec la dernière requête de Nicolas Ribot : j'obtiens mes 7800 lignes en 19 secondes
- avec celle de Santanna : 17 secondes
- avec la requête de Santanna, mais en remplaçant le ST_Within par ST_Dwithin : 19 secondes
Du coup, bizarrement, ST_Within est plus rapide sur ce coup ?
Sinon, en prenant une couche "Territoire" avec des entités plus petites, comme les communes au lieu des régions par exemple (et donc des bbox à la fois plus petites et nombreuses), la requête est beaucoup plus rapide : moins de 2 secondes, que ce soit avec ST_Within ou ST_DWithin.
Pour le coup, ST_Dwithin est légèrement plus efficace mais ça se joue à un chouilla...
Merci en tout cas et bonne journée
Hors ligne
#10 Mon 09 December 2013 11:31
- Cornet Jérémie
- Participant assidu
- Lieu: Nouméa
- Date d'inscription: 6 Apr 2008
- Messages: 229
Re: [PostGis] Points contenus dans des polygones
Bonjour,
Si tu as peu de territoires dans ta recherche, a mon avis, une sous-requête dans le where sera le plus rapide.
Code:
SELECT chl.gid, chl.insee_comm, chl.geom FROM adm.chl AS chl WHERE ST_WHITHIN( the_geom, (SELECT ST_COLLECT(the_geom) FROM adm.territoire WHERE territoire IN('A','B') ) );
Hors ligne
#11 Mon 09 December 2013 14:04
- Razorbak
- Participant assidu
- Lieu: Clermont Ferrand
- Date d'inscription: 7 Oct 2007
- Messages: 505
Re: [PostGis] Points contenus dans des polygones
Bonjour Jérémie,
Je viens de tester ta requête (car j'ai effectivement seulement 2 territoires mais assez grands) que j'ai dû modifier car st_within tout court me renvoyait une erreur ("Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported").
Je suis donc passé en st_dwithin.
Mais elle se termine en 38 secondes.
Hors ligne