Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Printemps des cartes 2024

#1 Wed 21 September 2016 10:44

vincent52
Participant occasionnel
Date d'inscription: 21 Sep 2016
Messages: 15

QGIS 2.14.6: Intersection trop lourde

Bonjour,

j'aimerais connaitre la surface d'intersection entre deux shapes assez lourds, le premier avec 3000 entités (polygones) et l'autre avec environ 30 000 (Registre parcellaire graphique) polygones. Lorsque je lance l'intersection sous QGIS, le logiciel ne répond plus et rien ne se passe au bout d'un quart d'heure. J'ai donc éssayé de faire l'intersection sous spatialite (ST_intersection) mais l'opération est interminable également. J'aimerais donc utiliser l'index spatial R tree (qui permet de gagner en temps de calcul) mais je ne maîtrise pas complètement... J'ai lu ce tutoriel : gaia-gis.it/spatialite-2.4.0-4/spatialite-cookbook-fr/ ainsi que ce site https://sites.google.com/site/sgbdspati … -multiples. Par exemple dans le second site, le code indique "ST_multi" mais je ne sais pas à quoi cela correspond...

Si vous avez une solution sous QGIS ou Spatialite, je suis preneur...

Merci d'avance et bonne journée

PS : j'ai vérifié et corrigé la géométrie des deux couches

Dernière modification par vincent52 (Wed 21 September 2016 14:00)

Hors ligne

 

#2 Thu 22 September 2016 01:14

Mathieu Denat
Participant actif
Lieu: Montpellier
Date d'inscription: 5 May 2010
Messages: 110

Re: QGIS 2.14.6: Intersection trop lourde

Bonsoir,

Je connais pas spatialite, mais ce que vous cherchez à faire est assez simple avec PostGIS et j'ai l'impression que les fonctions sont similaires.
Je vous propose donc quelques infos (qui fonctionnent sous PostGIS) qu'il faudra peut être adapter pour qu'elles fonctionnent avec Spatialite.

Dans un premier temps vous pouvez optimiser votre requête en utilisant des index spatiaux et en forçant leur utilisation (avec une clause WHERE).
De ce que j'ai compris c'est ce que cherchez à faire en utilisant R*tree.

Pour ce qui est de la fonction ST_Multi, d'après les références Spatialite ( http://www.gaia-gis.it/spatialite-2.4.0 … l-2.4.html ), elle renvoie une géométrie multiple (multipolygone) plutôt qu'une géométrie simple (polygone).
Ça peut être utile si le résultat de votre intersection génère des multipolygones (à ma connaissance, il n'est pas utile de se préoccuper de la "multiplicité" des polygones avec PostGIS) je ne sais pas si c'est utile avec Spatialite.

À ce propos l'auteur précise:

Un point important: la contrainte GeometryType( st_multi( st_intersects() ) )="MULTIPOLYGON" permet de ne sélectionner que les intersections de type polygon/multipolygon. En effet, l'intersection peut sortir des (multi) lignes/points.


En clair, il convertit l'ensemble des entités résultants en multi-entités (j'imagine que c'est moins gourmand que de convertir le résultat de l'intersection en entités simples (à se faire confirmer par quelqu'un de + calé), puis il sélectionne uniquement les multipolygones pour ne pas créer d'erreurs (puisque la surface d'une ligne ou d'un point est nulle).

Sous PostgreSQL (et donc PostGIS) les clauses WHERE (et les jointures) utilisent les index.
Il suffit donc d'ajouter une clause WHERE (ou une jointure) utilisant les index spatiaux à votre requête pour l'optimiser.
Je sais qu'il existe des méthodes optimiser votre clause WHERE avec PostgreSQL en testant l'existence d'un objet (WHERE EXISTS (SELECT ...)), mais je laisserai des personnes plus compétentes préciser.
Côté requête avec PostGIS ça donnerait un truc comme ça (il faudra peut-être adapter un peu pour Spatialite!).

Code:

SELECT SUM(ST_Area(ST_Intersection(couche.geom, cadastre.geom))) AS "surface"
FROM couche, cadastre
WHERE ST_Intersects(couche.geom,cadastre.geom)

D'après votre second lien, il faut essayer quelque chose comme ça:

Code:

SELECT
    SUM(
          ST_Area(
            ST_Multi(
               ST_Intersection( t1.geometry,t2.geometry) ) ) ) AS surface
FROM couche t1, cadastre t2
WHERE
    ST_Intersects(t1.geometry,t2.geometry) 
AND
    GeometryType( 
        ST_Multi( ST_Intersection( t1.geometry,t2.geometry))
    ) = "MULTIPOLYGON"
AND
    t1.rowid IN (
        SELECT pkid
        FROM idx_t1_geometry
        WHERE
        pkid MATCH RtreeIntersects(
            MBRminX(t2.geometry),
            MBRminY(t2.geometry),
            MBRmaxX(t2.geometry),
            MBRmaxY(t2.geometry)
    )

La dernière clause WHERE semble comparer les bouding boxes de chaque polygone, c'est cette partie qui est censée optimiser la requête en utilisant les index spatiaux.
Tenez nous au courant et envoyez nous les erreurs si la requête n'est pas valide.
Et envoyez nous la requête qui n'aboutit pas car sans code il est difficile de débuguer!

Bonne soirée.


Mathieu
C'est en forgeant qu'on devient forgeron

Hors ligne

 

#3 Thu 22 September 2016 12:12

vincent52
Participant occasionnel
Date d'inscription: 21 Sep 2016
Messages: 15

Re: QGIS 2.14.6: Intersection trop lourde

Bonjour matmat et merci pour la réponse!

Alors je me suis dit que finalement il valait mieux attendre la fin du traitement afin de comparer les deux méthodes.
En utilisant le géotraitement intersection de Qgis j'obtiens finalement une surface totale de 146 954 ha (1h de traitement environ)
En utilisant spatialite (via l'index spatial), j'obtiens 146 451 ha (1h voire plus de traitement).

En fait ici l'utilisation des index spatiaux n'est pas justifiée car comme il est indiqué sur http://www.gaia-gis.it/spatialite-2.4.0 … rtree.html, "le cadre de sélection couvre quasiment toute la région". Donc dans tous les cas, l'opération est ultra lourde car il y a quasiment autant d'intersections que de parcelles (RPG avec environ 30 000 entités).

Je vous remercie pour le code, mais je tiens à préciser que sur les versions récentes de spatialite, la fonction Rtreeintersects ne fonctionne plus. Cette fonction est désormais simplifiée, voici le code que j'ai utilisé :

Code:

SELECT
    SUM(
          ST_Area(
            ST_Multi(
               ST_Intersection( t1.geom,t2.geom) ) ) ) AS surface
FROM t1, t2
WHERE
    ST_Intersects(t1.geom,t2.geom) 
AND
    GeometryType( 
        ST_Multi( ST_Intersection( t1.geom,t2.geom))
    ) = "MULTIPOLYGON"
AND
    t1.rowid IN (
       SELECT ROWID
 FROM SpatialIndex
 WHERE f_table_name = 't1'
 AND search_frame = t2.geom)

Le "nouveau" code pour utiliser l'index spatial est sur les 5 dernières lignes. J'ai trouvé cette info sur https://www.gaia-gis.it/spatialite-3.0. … Update.pdf. D'ailleurs je ne sais pas exactement à quoi correspond "f_table_name" (?)

En conclusion, je pense qu'il vaut mieux travailler à plus petite échelle...

Merci encore pour votre aide et bonne journée!!

Hors ligne

 

Pied de page des forums

Powered by FluxBB