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

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#1 Thu 03 July 2014 12:20

Erwan
Membre
Lieu: BZH
Date d'inscription: 17 Feb 2006
Messages: 79

[postgis] Récupération de valeur entre 2 couches

Bonjour,

Voici ma problématique :
Je souhaite renseigner automatiquement pour chaque tronçon de canalisation AEP le code insee et le nom de la commune correspondant.

J'utilise pour cela deux fonctions postgis
- calcul du point central du segment "canalisation" (fonction PointOnSurface) car un tronçon de canalisation peut être à cheval sur deux communes
- intersection entre ce point et le polygone commune (fonction st_intersects)

Si la requête (select...) fonctionne seule avec une valeur test (gckey = identifiant), l'inclusion dans la fonction trigger ne fonctionne pas.


Code:

CREATE OR REPLACE FUNCTION aep.cana_insee_i()
  RETURNS trigger AS
$BODY$ 
BEGIN 
    IF NEW."gckey" is not null then
    
    NEW."cana_insee" = (select co.com_insee_varchar from aep.canalisation as ca, commune as co where ca.gckey = NEW."gckey" and st_intersects(PointOnSurface(NEW."geometrie"), co.geometrie) is true);
    NEW."cana_commune" = (select co.com_lib_maj from aep.canalisation as ca, commune as co where ca.gckey = NEW."gckey" and st_intersects(PointOnSurface(NEW."geometrie"), co.geometrie) is true);

    END IF;
    return NEW;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION aep.cana_insee_i() OWNER TO postgres;



-- Trigger: trg_cana_insee_i on aep.canalisation

-- DROP TRIGGER trg_cana_insee_i ON aep.canalisation;

CREATE TRIGGER trg_cana_insee_i
  BEFORE INSERT
  ON aep.canalisation
  FOR EACH ROW
  EXECUTE PROCEDURE aep.cana_insee_i();

R1

Hors ligne

 

#2 Thu 03 July 2014 13:39

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

Re: [postgis] Récupération de valeur entre 2 couches

Bonjour,

Plusieurs remarques:

• Dans un trigger BEFORE, la ligne courante n'est pas encore insérée dans la base: on ne peut pas comparer la valeur NEW."gckey" avec ca.gckey si ce champ gckey est nouveau lors de l'insertion.
Dans votre cas, il ne faut pas refaire un lien sur la table canalisation, qui est concernée par le trigger, mais directement utiliser la table commune et la geometrie qui arrive dans le trigger.
Une seule requete est necessaire pour cela et vous pouvez stocker les deux colonnes qui vous interessent directement dans les deux variables:

Code:

select co.com_insee_varchar, co.com_lib_maj 
from commune as co 
where st_intersects(st_lineInterpolatePoint(NEW."geometrie", 0.5), co.geometrie)
into NEW."cana_insee", NEW."cana_commune";

• La méthode st_PointOnSurface (attention, PointOnSurface, sans le prefixe, est un vieux nom qu'il ne faut plus utiliser) marche pour des surfaces, normalement wink
Postgis la supporte sur des lignes en renvoyant le milieu, mais pas sur que ce comportement soit pérenne entre les versions. Pour avoir le milieu d'une ligne, il faut mieux utiliser st_lineLocatePoint(line.geom, 0.5).

• Etes vous sûr que le milieu de la canalisation est le bon critère pour trouver la commune d'appartenance ? Ne peut-il pas y avoir des cas ou 90% de la canalisation est dans une commune mais son milieu dans une autre ? Le pourcentage de longueur de la canalisation par commune ne serait-il pas plus pertinent ? (ca dépend grandement de vos données)

Nicolas

Hors ligne

 

#3 Thu 03 July 2014 17:59

Erwan
Membre
Lieu: BZH
Date d'inscription: 17 Feb 2006
Messages: 79

Re: [postgis] Récupération de valeur entre 2 couches

Nicolas,

Merci pour ces remarques très intéressantes.

Cordialement
R1


R1

Hors ligne

 

#4 Fri 04 July 2014 12:34

Erwan
Membre
Lieu: BZH
Date d'inscription: 17 Feb 2006
Messages: 79

Re: [postgis] Récupération de valeur entre 2 couches

bonjour,

Si la requête fonctionne très bien (j'utilise st_geometryN car mon linéaire est en multilinestring)

Code:

select co.com_insee_varchar, co.com_lib_maj from commune co, aep.canalisation ca where st_intersects(st_line_interpolate_point(st_GeometryN(ca.geometrie,1), 0.5), co.geometrie)

, la récupération des deux variables NEW."cana_insee", NEW."cana_commune" via into ne fonctionne pas

Cordialement


R1

Hors ligne

 

#5 Fri 04 July 2014 14:12

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

Re: [postgis] Récupération de valeur entre 2 couches

Bonjour,

Ca ne marche que dans le code du trigger.

Vous pouvez poster le code de la fonction du trigger ainsi que sa definition ?
Quel est le message d'erreur ?

Nicolas

Hors ligne

 

#6 Fri 04 July 2014 17:07

Erwan
Membre
Lieu: BZH
Date d'inscription: 17 Feb 2006
Messages: 79

Re: [postgis] Récupération de valeur entre 2 couches

Code:

-- Trigger: trg_maj_cana_insee_com on aep.canalisation

-- DROP TRIGGER trg_maj_cana_insee_com ON aep.canalisation;

CREATE TRIGGER trg_maj_cana_insee_com
  AFTER INSERT OR UPDATE
  ON aep.canalisation
  FOR EACH ROW
  EXECUTE PROCEDURE aep.maj_cana_insee_com();




- Function: aep.maj_cana_insee_com()

-- DROP FUNCTION aep.maj_cana_insee_com();

CREATE OR REPLACE FUNCTION aep.maj_cana_insee_com()
  RETURNS trigger AS
$BODY$ 


BEGIN 
    IF NEW."geometrie" is not null then
    
    select co.com_insee_varchar, co.com_lib_maj from commune as co where st_intersects(st_line_interpolate_point(st_GeometryN(NEW."geometrie",1), 0.5), co.geometrie) into NEW."cana_insee", NEW."cana_commune";

    END IF;
    return NEW;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION aep.maj_cana_insee_com() OWNER TO postgres;

R1

Hors ligne

 

#7 Mon 07 July 2014 13:36

Erwan
Membre
Lieu: BZH
Date d'inscription: 17 Feb 2006
Messages: 79

Re: [postgis] Récupération de valeur entre 2 couches

Je n ai pas de message d erreur sur le codage précédent mais rien ne se passe. Comme si la variable new restait vide.


R1

Hors ligne

 

#8 Mon 07 July 2014 14:02

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

Re: [postgis] Récupération de valeur entre 2 couches

Bonjour,

Oui normal: vous avez changé la définition du trigger en AFTER INSERT OR UPDATE, au lieu de BEFORE:

Un trigger défini AFTER agit une fois que la donnée a ete insérée ou mise a jour en base, on ne peut donc plus toucher a la ligne concernée a travers NEW.

Nicolas

Hors ligne

 

Pied de page des forums

Powered by FluxBB