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 Thu 22 May 2014 22:52

Elsane
Juste Inscrit !
Date d'inscription: 8 Jul 2009
Messages: 9

intersect n couches

Bonjour,

j'aimerais savoir si quelqu'un a déjà effectué une ST_intersects sur plusieurs couches à la fois ou une piste à creuser ?

Merci

Hors ligne

 

#2 Fri 23 May 2014 09:43

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Bonjour Elsane,

Vous voulez dire plusieurs tables intersectant une seule et même table?
Si c'est le cas, je fais aussi face à la même question. Pour l'instant j'ai essayer de créer une fonction pl/pgsql suivante:

Code:

CREATE OR REPLACE FUNCTION test2(out nom_table text, OUT id_littoral text, out geom_littoral geometry ) RETURNS SETOF record
LANGUAGE plpgsql
AS
$BODY$
DECLARE
  tables record;
BEGIN
  FOR tables IN SELECT DISTINCT tablename FROM pg_tables where tablename 
         IN 
        (
        (select tablename from pg_tables where schemaname ='france' and tablename in (SELECT f_table_name FROM geometry_columns where f_table_name not like '%_t' and f_table_name not like 'france_littoral' and f_table_name not like 'box%' and f_table_name not like 'rast%'))
        ) 
    AND pg_tables.schemaname='france'  
  LOOP
    nom_table := tables.tablename;
   Execute 'select '||quote_ident (tables.tablename)||'.id from france_littoral,' ||quote_ident(tables.tablename)||' WHERE st_intersects('|| quote_ident (tables.tablename)||'.the_geom_box, france_littoral.the_geom_wgs84) ;'
      Into id_littoral;
   Execute 'select france_littoral.the_geom_wgs84 from france_littoral, '||quote_ident (tables.tablename)|| ' where st_intersects('||quote_ident(tables.tablename)||'.the_geom_box, france_littoral.the_geom_wgs84);'
      Into geom_littoral;
    RETURN NEXT;
  END LOOP;
END
$BODY$;

La fonction me donne un résultat mais pas celui escompté, en revanche même si le résultat de la requête est à discuté, il m'effectue bien un ST_intersect sur plusieurs couches. plusieurs couches.
J'espère avoir pu vous mettre sur une piste.

Hors ligne

 

#3 Fri 23 May 2014 10:03

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: intersect n couches

Bonjour,

Quel type d'intersection souhaitez-vous réaliser ? Une couche avec toutes les autres qui seraient fusionnées ? Une combinatoire de tous les cas possible ? Les couches ont des types de geom différents ?

Suivant le résultat escompté et le type géométriques des couches en jeu, il y a plusieurs approches:
Union de tous les objets des n couches (en conservant les sources et id originaux) puis intersection avec la couche de référence, par ex.

Nicolas

Hors ligne

 

#4 Fri 23 May 2014 10:26

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Bonjour,

Pour ma part le résultat espéré serait d'avoir dans la couches  d'intersection de référence, les id et le noms de toutes les tables qui l'intersectent. Est-ce possible?
Désolé de profiter du poste d'Elsane pour poser ma question mais j'avoue faire face au même problème...

Hors ligne

 

#5 Fri 23 May 2014 10:37

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

De plus j'aurais une autre question.

Suivant le résultat escompté et le type géométriques des couches en jeu, il y a plusieurs approches:
Union de tous les objets des n couches (en conservant les sources et id originaux) puis intersection avec la couche de référence, par ex.


Il est donc possible de regrouper toutes les tables géométriques (point, polyligne, multipoint, polygone...) en une seul table? 
Merci.

Stych

Hors ligne

 

#6 Fri 23 May 2014 11:27

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: intersect n couches

Oui tout a fait:

Suivant ce qui est le plus convenable dans votre contexte, une fonction (comme celle que vous avez faite) ou une requete SQL avec préparation d'une table de synthèse sont possibles:

Avec une table regroupant les geoms des autres tables:

Code:

create table all_geoms as (
    select id as id_source, 'table1' as source, geom
    from table1
 UNION
    select id as id_source, 'table2' as source, geom
    from table2
  UNION
...
);

Création d'un index spatial sur cette table.

Puis interrogation de tous les objets qui intersectent la table de référence:

Code:

select fl.id, a.id_source, a.source
france_littoral fl, all_geoms a
where st_intersects(fl.geom, a.geom);

Nicolas

Hors ligne

 

#7 Fri 23 May 2014 16:58

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Re,

Merci pour votre réponse Nicolas.
J'ai pu ainsi réaliser une fusion de toutes mes tables de manière plus ou moins dynamique en passant par une fonction.
Puis j'ai réaliser mon St_intersects avec ma couche de référence en faisant un "CREATE OR REPLACE VIEW" en faisant bien attention de récupérer la colonne géométrique de ma table de référence.
Mais la vue ne peux pas s'afficher dans mon client carto(Qgis) et Qgis me dit que ma couche est non valide...

Est ce quelqu'un à déjà été confronté à ce genre de problème?

Bon week end à vous!!
Stych.

Hors ligne

 

#8 Fri 23 May 2014 21:33

Elsane
Juste Inscrit !
Date d'inscription: 8 Jul 2009
Messages: 9

Re: intersect n couches

Pas de soucis Stych,

je suis tout à fait dans le même cas de figure que toi à savoir récupérer les id et noms des tables intersectées, et avec des géométries différentes.

Peux-tu me mettre ta fonction qui fusionne dynamiquement des tables ?

Elsane

Hors ligne

 

#9 Sat 24 May 2014 12:58

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3807

Re: intersect n couches

Bonjour,

Il est donc possible de regrouper toutes les tables géométriques (point, polyligne, multipoint, polygone...) en une seul table?
Merci.


En effet, c'est possible mais il faut garder en mémoire que toutes les fonctions de Postgis ne sont pas adaptées à toutes les géométries et donc bien savoir quel usage et quel traitement on veut faire de cette table pour en comprendre les résultats ou messages d'erreur.

Mais la vue ne peux pas s'afficher dans mon client carto(Qgis) et Qgis me dit que ma couche est non valide...


Pour pouvoir afficher une table dans QGIS, deux conditions requises:
- un identifiant unique de type integer dans la table, ce qui ne devrait pas être le cas ici avec la fusion de toutes ces couches. Ca peut se faire en ajoutant un champ dans la requete d'intersection avec row_number() OVER () as num
- un type identique de géométrie (pas de mélange autorisé entre ligne, polygone, point). cf point précédent.

Hors ligne

 

#10 Mon 26 May 2014 13:19

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Salut,

Code:

--drop function table_union();
CREATE OR REPLACE FUNCTION france.table_union () RETURNS table (gid bigint,id varchar, nom_donnee varchar, the_geom geometry)  
language plpgsql
as
$BODY$
DECLARE
 tables record;
BEGIN
  FOR tables IN SELECT tablename FROM pg_tables where tablename 
         IN 
        (select tablename from pg_tables where schemaname ='france' and tablename in (SELECT f_table_name FROM geometry_columns where f_table_name not like '%_t' and f_table_name not like 'france_littoral' and f_table_name not like 'box%' and f_table_name not like 'rast%'))
  LOOP
  return query Execute 'select row_number() over(order by id) as gid ,id,  nom_donnee, the_geom_wgs84  from '||quote_ident (tables.tablename)||';' 
    RETURN ;
  END LOOP;
END
$BODY$;

Elsane, voici la fonction qui me permet de fusionner mes tables et de récupérer les champs désirés et leurs géométries.
Ensuite je crée une vue en intersectant cette tables et ma couche de référence, en ne récupérant que la géométrie de ma couche de référence pour pouvoir ensuite visualiser mon résultat dans un client carto. Mais pour l'instant cette dernière étape me pose toujours problème. 

Santana, merci pour ton intervention.
La fonction me récupère mes id de toutes mes tables, qui est une concaténation du nom des tables + leurs gid. Logiquement l'identifiant est unique est cela marche parfaitement sur les autre vues. Dans le doute j'ai tout de même utilisé row_number() over() comme tu me l'a indiqué, mais rien n'a changé. Qgis bloque sur la première couche de ma vue et me dit qu'elle n'existe pas... Pourtant les géométries récupérée sont les géométries de ma couches de référence. Donc un seul et même type de géométrie.
Je continue de chercher et posterais une solution quand j'aurais réussis à résoudre le problème.

Stych

Dernière modification par Stych (Mon 26 May 2014 13:21)

Hors ligne

 

#11 Mon 26 May 2014 14:42

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3807

Re: intersect n couches

Bonjour,
Stych, tu passes par quelle interface pour ouvrir ta vue dans QGIS? DBManager, Parcourir ou ouvrir une table PG? Quelle version de QGIS?
Quand dans PG, tu fais un "select st_isvalidreason(geom) from mavue", il te renvoie que de la géométrie valide?

En regardant ta fonction, je me demande si le row_number()over() ne va pas itérer couche par couche, ce qui fait qu'en sortie on risque d'avoir des numéros non uniques (venant de différentes couches). A vérifier sur ta donnée. Je me trompe peut-être.
Quand j'en parlais, c'était plutôt à insérer dans la requête vérifiant l'intersection.
Mais bizarre qu'il accepte tes vues si tu me dis que la clé primaire n'est pas integer. La doc de QGIs en parle juste dans la section au dessus de ce lien

Hors ligne

 

#12 Mon 26 May 2014 15:27

Elsane
Juste Inscrit !
Date d'inscription: 8 Jul 2009
Messages: 9

Re: intersect n couches

Bonjour  Stych,

peux-tu m'expliquer à quoi te sert "row_number() over(order by id) as gid"

Merci !

Hors ligne

 

#13 Tue 27 May 2014 10:50

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Bonjour,

Elsane:
La fonction row_number() over() devrait me permettre de récupérer un identifiant unique de type integer. En gros il me numérote mes lignes de 1 à n lignes. Elle me servait surtout à récupérer un identifiant que Qgis pourrait interpréter comme clés primaire. Selon tes besoins elle ne t'es pas forcément indispensable.

Santanna:
Merci pour ta réponse. Pour ouvrir mes table j'utilise l'outil 'ajouter une couche Postgis'. J'ai réalisé un st_validreason comme tu me la conseillé, et le résultat en sorti me confirme bien que mes géométries sont toutes valides.
J'ai aussi enlevé row_number()over() de ma fonction et je l'ai plutôt placé dans la création de ma vue. En analysant cette même vue via un select, chaque lignes de ma tables sont numéroté de 1 à n lignes. Donc un identifiant unique et de type integer.

Lors de l'importation de mes vues vers qgis j'ai pu récupérer les messages d'erreurs suivant:

Code:

Requête erronée : SELECT DISTINCT CASE WHEN upper(geometrytype("the_geom_wgs84")) IN ('POINT','MULTIPOINT','POINTM','MULTIPOINTM') THEN 'POINT' WHEN upper(geometrytype("the_geom_wgs84")) IN ('LINESTRING','MULTILINESTRING','LINESTRINGM','MULTILINESTRINGM') THEN 'LINESTRING' WHEN upper(geometrytype("the_geom_wgs84")) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM') THEN 'POLYGON' END, st_srid("the_geom_wgs84") FROM "france"."table_liste" a retourné 7 [ERREUR:  la relation « mnt_alentour_emprise » n'existe pas
LINE 1: select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_em...
                                                     ^
QUERY:  select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_emprise;
CONTEXT:  fonction PL/pgsql france.table_union(), ligne 9 Ã  RETURN QUERY
]
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Requête erronée : SELECT * FROM "france"."table_intersect" LIMIT 1 a retourné 7 [ERREUR:  la relation « mnt_alentour_emprise » n'existe pas
LINE 1: select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_em...
                                                     ^
QUERY:  select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_emprise;
CONTEXT:  fonction PL/pgsql france.table_union(), ligne 9 Ã  RETURN QUERY
]
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Impossible d'accéder à la relation "france"."table_intersect".
Le message d'erreur de la base de données est :
ERREUR:  la relation « mnt_alentour_emprise » n'existe pas
LINE 1: select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_em...
                                                     ^
QUERY:  select id,  nom_donnee, the_geom_wgs84  from mnt_alentour_emprise;
CONTEXT:  fonction PL/pgsql france.table_union(), ligne 9 à RETURN QUERY

SQL : SELECT * FROM "france"."table_intersect" LIMIT 1

Apparemment, pour Qgis mes table n'existe pas. Je trouve cela vraiment bizarre puisque dans postgis, la fonction marche et mes vues issues de cette fonction me retournent les bons résultats.
Quelqu'un aurait une idée de la provenance du problème?

Dernière modification par Stych (Tue 27 May 2014 10:52)

Hors ligne

 

#14 Tue 27 May 2014 15:22

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Re bonjour,

Je reviens vers vous pour apporter une nouvelle vision du problème, et aussi un semblant de solution.
Il semblerais que créer une vue en allant piocher des coordonnées dans une autre vue ne soit pas faisable, ou plutôt si, Postgis le fait sans problème, mais Qgis ne sait pas le prendre en compte.
J'ai donc du créer une table dans postgis issue de cette intersection et là tout fonctionne !
Mais cela ne fait que déplacer mon problème puisque mon opération d'intersection n'est plus dynamique...
@Elsane, si tu fais face au même cas que moi, as tu trouvé quelques pistes?

Dernière modification par Stych (Tue 27 May 2014 15:27)

Hors ligne

 

#15 Tue 27 May 2014 16:42

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1536

Re: intersect n couches

Bonjour,

Si, QGis sait afficher des vues PostGIS contenant des geometries. Il faut pour cela que la vue contienne un type geometrique unique, et que ce type ne soit pas "GEOMETRY" mais un type plus précis (point, ligne...)

Hmm attention a la confusion: vous avez créé une fonction qui renvoie des lignes, mais ce n'est pas une vue ni une table matérialisée.

Si vous voulez travailler avec une table, je vous invite à la créer dans la fonction, et pas a retourner les lignes.
Si vous préférez une vue, utilisez la fonction pl/pgsql pour générer le SQL de la vue, style:

create view toto as (
select id, geom from table1
UNION
select id, geom from table2
UNION
...
)

Puis executez le code SQL généré par la fonction.

Si la vue ou table nouvellement créée contient des géométries hétérogènes, je ne suis pas sur que QGIs sache la lire. OpenJump, autre SIG OpenSource, sait le faire. Mais il est moins riche que QGis.

Si la vue/table ne contient qu'un seul type d'objet (POLYGONE par ex), vous pouvez caster le champs geometry en un type polygone: geom::geometry(Polygon, 2154) (si le SRID de la couche est 2154)

Dans ce cas, la table ou vue sera automatiquement enregistrées dans les métadonnées de Postgis (vue geoemtry_columns) et qgis saura l'afficher.

Nicolas

Hors ligne

 

#16 Tue 27 May 2014 17:19

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Bonjour Nicolas,

Postgis n'est effectivement pas capable de lire une table avec des géométries hétérogène. Cependant ce n'est pas mon cas puisque je ne garde que les géométries de ma couches de référence que j'utilise lors de mon découpage.

Pour la fonction(), j'ai oublié de préciser que je créait une vue en récupérant le résultat de ma fonction, désolé

Code:

create or replace view table_liste as 
select * from fonction();

Puis je créait une vue à partir de cette vue et de ma couche d'intersection... de quoi s'embrouiller.

En revanche je n'ai pas essayer de créer une table via ma fonction directement. J'essaierais et tiendrais à jour le poste.
Mais la table issue de cette fonction sera t'elle mise à jour dynamiquement?
En tout cas merci pour vos piste de réflexions.

Stych.

Dernière modification par Stych (Tue 27 May 2014 17:20)

Hors ligne

 

#17 Tue 27 May 2014 17:55

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3807

Re: intersect n couches

Bonjour,

Il semblerais que créer une vue en allant piocher des coordonnées dans une autre vue ne soit pas faisable, ou plutôt si, Postgis le fait sans problème, mais Qgis ne sait pas le prendre en compte.


Pas d'accord. J'utilise au quotidien QGIS avec des vues PG qui sont des combinaisons (le fameux UNION qu'évoque Nicolas) de tables et de vues. Ça ne pose pas de problème, pour autant que les conditions que j'avais déjà listées soient respectées (identifiant unique numérique et un "type" de géométrie).

Pour ce qui est des fonctions, je ne suis pas très à l'aise donc je laisse Nicolas en parler. Mais une fois la fonction table_union effectuée, arrives-tu à ouvrir cette table dans QGIS (avant toute opération d'intersection)?

J'ai réalisé un st_validreason comme tu me la conseillé, et le résultat en sorti me confirme bien que mes géométries sont toutes valides.


Désolé mais ce que j'aurais plutôt dû te faire checker c'est la géométrie des entités. Que donne un "select distinct st_geometrytype(geom) from matable"?

-- EDIT--
Désolé Stych si des éléments de réponse sont déjà dans ton précédent message. J'ai tardé à envoyer mon message et n'ai pas pensé à actualiser la fenêtre avant l'envoi. sad

Dernière modification par SANTANNA (Tue 27 May 2014 18:23)

Hors ligne

 

#18 Wed 28 May 2014 13:14

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

Salut,

Pas de soucis Santanna wink

Non, pour moi la fonction table_union() n'a pas vocation à être ouverte sur Qgis. Elle ne me sert qu'à 'fusionner' toutes mes tables (géométriques) en une seul, puis je crée une vue qui récupère les résultats de ma fonction. De plus cette table cette table possède plusieurs type de géométrie, et ne peut donc pas s'ouvrir dans Qgis comme vous me l'avez indiquez.

J'ai réalisé un st_geometrytype sur mes vues issues par la suite de mon intersections et il me retourne bien qu'un seul type de géométrie.

Ce que je trouve étrange c'est qu'avec la même requête d'intersection, que j'utilise pour réaliser mes vues et table d'intersection, Qgis ne réagis pas de la même façon. Il ouvre les tables mais pas les vues. Elles ont pourtant toutes les deux tous les paramètres nécessaire à l'ouverture d'une couche postgis dans Qgis.
Au regard de vos réponse, je pense que le problème vient peut être de ma fonction...
Mais je continue de chercher.
Merci pour toutes vos précisions big_smile

Stych

Dernière modification par Stych (Wed 28 May 2014 13:19)

Hors ligne

 

#19 Wed 28 May 2014 13:34

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3807

Re: intersect n couches

Salut,
Tu passes par quelle interface pour ouvrir tes couches dans QGIS? Si c'est par le menu vecteur > Ajouter une couche PG, parfois, dans la liste des tables, QGIs n'arrive pas à identifier quel champ fait office de ID ou de geom et il faut explicitement les lui indiquer. Regarde peut-être par là.

Hors ligne

 

#20 Wed 28 May 2014 17:14

Stych
Participant occasionnel
Date d'inscription: 24 Mar 2014
Messages: 15

Re: intersect n couches

J'ai finalement compris pourquoi Qgis ne voulait pas ouvrir mes vues.
J'avais oublié de spécifier mon schéma dans le lequel mes tables ce trouvent.

Code:

  FOR tables IN SELECT tablename FROM pg_tables where tablename 
         IN 
        (select tablename from pg_tables where schemaname ='france' and

Avec le FOR je lui dis bien de récupérer mes table dans le bon schéma, mais par la suite,

Code:

return query Execute 'select row_number() over(order by id) as gid ,id,  nom_donnee, the_geom_wgs84  from '||quote_ident (tables.tablename)||';'

le return query m'effectue bêtement la requête avec les tables spécifier dans la boucle FOR mais sans savoir dans quel schémas elles se trouvent.
J'ai donc rajouter 'france.' dans le return query afin que lors de l'import de Qgis, le chemin des tables soient bien renseignés.
Je ne sait pas si c'est réellement la bonne explication, mais c'est en tout cas la seul que j'ai trouvé.

Code:

--drop function table_union();
CREATE OR REPLACE FUNCTION france.table_union () RETURNS table (gid bigint,id varchar, nom_donnee varchar, the_geom geometry)  
language plpgsql
as
$BODY$
DECLARE
 tables record;
BEGIN
  FOR tables IN SELECT tablename FROM pg_tables where tablename 
         IN 
        (select tablename from pg_tables where schemaname ='france' and tablename in (SELECT f_table_name FROM geometry_columns where f_table_name not like '%_t' and f_table_name not like 'france_littoral' and f_table_name not like 'box%' and f_table_name not like 'rast%'))
  LOOP
  return query Execute 'select row_number() over(order by id) as gid ,id,  nom_donnee, the_geom_wgs84  from france.'||quote_ident (tables.tablename)||';' 
    RETURN ;
  END LOOP;
END
$BODY$;

Merci pour votre aide en tout cas wink

Hors ligne

 

Pied de page des forums

Powered by FluxBB