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 06 April 2017 08:08

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

[POSTGIS] : Polygone Z

Bonjour,

Je reviens vers vous car je suis confronté à un cas auquel je n'avais pas pensé (mais pourtant logique)
J'ai des polygones Z (triangles) qui peuvent être découpés par des lignes (création de nouveaux polygones). Cette découpe me crée de nouveaux polygones Z (interpolés au niveau de la découpe), or dans ma petite tête je pensais pouvoir récupérer la valeur de la courbe de découpe dans mon polygone Z facilement.
Exemple :
triangle Z avec des sommets à 1-3-3.5 et un courbe (type courbe orographique d'une valeur de 2) qui coupe mon triangle. Les  2polygones créés auront pour sommet 1-2.1-2.1-2.1-2.1-1 et 2.1-2.1-2.1-2.1-3-3.5-2.1 (2.1 étant les points de la courbe de découpe avec une valeur interpolée).
J'espère être clair?

Je me pose une question comment forcer mes polygones à avoir la valeur 2 à la place de la valeur 2.1.
Doit-on utiliser un st_force_3d, mais comment récupérer cette valeur 2? (sachant que j'ai également des courbes de 5-10...)? La doc ne précise pas trop de chose à ce sujet!
Doit-on recréer des polygones en s'appuyant sur les noeuds que l'on peut créer ?

D'après vous quel(s) serait(ent) la méthode la plus simple, la plus éfficace?

D'avance merci

Dernière modification par Ted (Thu 06 April 2017 08:08)

Hors ligne

 

#2 Thu 06 April 2017 14:19

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

Re: [POSTGIS] : Polygone Z

Bonjour,

Une approche pourrait etre de dumper les points des deux polygones issus du split triangle/courbe (pg_split), puis de comparer ces points avec les points de la courbe et les points de l'intersection de la courbe avec le polygone (pt_check).

Pour les points des pg_split qui correspondent aux points pt_check, fabriquer un nouveau pt avec comme Z le Z de la courbe,
pour les autres points de pg_split: conserver les points tels quels.

Ensuite, reconstruire les polygones pg_split à partir des listes de points.

En SQL:

les CTE triange et courbe créent les géometries.
La CTE split construit les deux polygones en splittant le triangle par la courbe. On dump pour obtenir les deux triangles en deux lignes.
La CTE check_pt construit la liste des points de controle:
    • points de la courbe dumpés.
    • points de l'intersection de la courbe avec le contour du triangle.
La CTE dump_split dump les points (sommets) des deux polygones issus du split.
La CTE swapz fait un Left Join entre ces sommets de polygones et les points check: si le point du pg est proche du point check => on force le Z de la courbe, sinon, on garde le point du pg.
Enfin, la requete finale reconstruit les deux polygones à partir de leurs points:

Code:

with triangle as (
  select 'a'::text as id, 'POLYGON((0 0 3.5, 2 0 3, 1 2 1, 0 0 3.5))'::geometry(polygonZ, 0) as geom
), courbe as (
    select 1::int as id, 'LINESTRING(0 0.8 2, 1 0.8 2, 2 0.8 2)'::geometry(linestringZ, 0) as geom
), split as (
    SELECT
      t.id as idt,
      c.id as idc,
      st_dump(st_split(t.geom, c.geom)) AS d
    FROM triangle t, courbe c
), check_pt as (
  SELECT t.id as idt, c.id as idc,
    (st_dump(st_intersection(st_boundary(t.geom), c.geom))).geom AS geom
  FROM triangle t, courbe c

  UNION ALL
    select null::text as idt, id as idc, (st_dumppoints(geom)).geom
  from courbe
), dmp_split as (
    SELECT
      idt,
      idc,
      (d).path                AS id_split,
      st_dumppoints((d).geom) AS dp
    FROM split s
), swapz as (
    SELECT
      d.id_split,
      (d.dp).path as ptpath,
      c.idc,st_Z(st_pointN(courbe.geom, 1)),
      CASE WHEN c.idc IS NULL
        THEN (d.dp).geom
      ELSE st_makePoint(st_X((d.dp).geom), st_y((d.dp).geom), st_Z(st_pointN(courbe.geom, 1))) END AS newgeom
    FROM courbe, dmp_split d LEFT JOIN check_pt c ON st_dwithin((d.dp).geom, c.geom, 0.001)
) select s.id_split[1] as id,
  st_makepolygon(st_makeLine(s.newgeom ORDER BY s.id_split[1], s.ptpath[2])) as geom
from swapz s
group by s.id_split[1];

En image: a gauche, les 2 pg, avec coord Z affichée, avec interpolation du Z par rapport a la courbe
a droite: résultat de la requete avec Z swappés pour les points concernés

Nicolas


Fichier(s) joint(s) :
Pour accéder aux fichiers vous devez vous inscrire.

Hors ligne

 

#3 Thu 06 April 2017 19:11

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Merci Nicolas,

Je teste ça ce soir.
Juste pour info, tu es parti du principe que ma ligne était une ligne 3d?

Dans mon cas la valeur du Z est dans un champ attributaire. En même temps, avec l'exemple fourni, tu ne pouvais pas deviner. Je creuse ta requête.

Encore merci

Hors ligne

 

#4 Thu 06 April 2017 21:33

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Nicolas,

Je viens de lancer la requête en amenanageant pour mes donnees(multilines donc nécessité de st_dump).
Mais la requête est lancée depuis 30 minutes (je de test pour les polygones, une dizaine et toutes les lignes) et rien ne sort, je trouve cela long !

Est-ce normal ?
À+
Ted

Hors ligne

 

#5 Fri 07 April 2017 11:35

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Bonjour,

Ma requête a planté :-(
Le problème ne viendrait-il pas du trop grand nombre de points sur mes lignes?

D'avance merci

Hors ligne

 

#6 Fri 07 April 2017 12:47

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1159

Re: [POSTGIS] : Polygone Z

Salut,

difficile de vous aider si vous ne donnez pas plus d'informations,
comme la requête que vous avez utilisez par exemple, vu que
que vous avez adapté la requête de Nicolas,
ainsi que ce que la façon dont la requête a planté.

Hors ligne

 

#7 Fri 07 April 2017 14:15

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

Re: [POSTGIS] : Polygone Z

Bonjour,

Oui, j'avais considéré que vous vouliez récupérer la valeur Z de la ligne.

Et effectivement, comme le dit tumasgui, pensez a indiquer la requete qui pose probleme, eventuellement la version/plateforme de postgis et le message d'erreur.


Dans mon exemple, attention: 1 seule ligne, un seul triangle. Si vous avez remplacé ces parties par des requetes sur vos tables, alors ca fait un produit cartésien (tous les triangles x toutes les lignes) => très long, voire ~ infini s'il y a bcp de données.

Dans un cas réel, il vous faudra croiser ces deux tables et gérer les eventuels liens n-m entre triangles et courbes.

Nicolas

Hors ligne

 

#8 Fri 07 April 2017 15:05

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Bonjour,

Voici le sql modifié (enfin pas trop, en fonction des messages d'erreur que j'avais).

Code:

with triangle as (
  select id_triangle, geometryexplose as geom from test_interpo."7123_TRIANGLE_DISTINCT_Sel"
), courbe as (
    select id, (st_dump(geom)).geom as geom test_interpo."7123_DEPCNT_Arc"
), split as (
    SELECT
      t.id as idt,
      c.id as idc,
      st_dump(st_split(t.geom, c.geom)) AS d
    FROM triangle t, courbe c
), check_pt as (
  SELECT t.id as idt, c.id as idc,
    (st_dump(st_intersection(st_boundary(t.geom), c.geom))).geom AS geom
  FROM triangle t, courbe c

  UNION ALL
    select row_number() over() as idt, id as idc, (st_dumppoints(geom)).geom
  from courbe
), dmp_split as (
    SELECT
      idt,
      idc,
      (d).path                AS id_split,
      st_dumppoints((d).geom) AS dp
    FROM split s
), swapz as (
    SELECT
      d.id_split,
      (d.dp).path as ptpath,
      c.idc,st_Z(st_pointN(courbe.geom, 1)),
      CASE WHEN c.idc IS NULL
        THEN (d.dp).geom
      ELSE st_makePoint(st_X((d.dp).geom), st_y((d.dp).geom), st_Z(st_pointN(courbe.geom, 1))) END AS newgeom
    FROM courbe, dmp_split d LEFT JOIN check_pt c ON st_dwithin((d.dp).geom, c.geom, 0.001)
) select s.id_split[1] as id,
  st_makepolygon(st_makeLine(s.newgeom ORDER BY s.id_split[1], s.ptpath[2])) as geom
from swapz s
group by s.id_split[1];

Problème potentiel : mes lignes ne sont pas "Z", c'est un champ qui le détermine
Plantage : la requête a tourné toute la nuit, pour me dire que "votre PC ne répond pas".

A+
Ted

Hors ligne

 

#9 Thu 13 April 2017 08:04

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Bonjour,

Je reviens vers vous car j'ai avancé. J'y suis allé étape par étape (plus facile pour ma petite tête et un pour un débutant).

Donc je vous indique mes requêtes successives :
1ère requête découpage de mes triangles par des surfaces s'appuyant sur mes courbes :

Code:

  create table "test_interpo"."tmppolyg7123seldepare" as select distinct
row_number() over() as idpoly,D.drval1,D.drval2,  T.id_triangle, D.id as id,

  st_collectionextract(st_intersection(D.geom, T.geometryexplose),3) as geom
        From "test_interpo"."7123_DEPARE_Polygon" D inner join
"test_interpo"."7123_TRIANGLE_DISTINCT_sel" T on st_intersects(D.geom,
T.geometryexplose);

Puis création des points de chaque polygone nouvellement créé (requête trouvée sur internet et adaptée à mon besoin) :

Code:

create table "test_interpo"."node2update" as WITH t AS -- Transfor polygons in sets of points
    (SELECT idpoly,id_triangle,
            st_dumppoints(geom) AS dump
     FROM "test_interpo"."tmppolyg7123seldepare"),
f AS -- Get the geometry and the indexes from the sets of points
    (SELECT t.idpoly,t.id_triangle,
           (t.dump).path[1] AS part,
           (t.dump).path[3] AS vertex,
           (t.dump).geom AS geom
     FROM t)
-- Get all points filtering the last point for each geometry part
SELECT row_number() OVER () AS gid, -- Creating a unique id
       f.idpoly,
       f.id_triangle,
       f.part,
       f.vertex,
       ST_X(f.geom) as x, -- Get point's X coordinate
       ST_Y(f.geom) as y, -- Get point's Y coordinate
       ST_Z(f.geom) as z,
       f.geom::geometry('POINTZ',4326) as geom -- make sure of the resulting geometry type
FROM f ;

création des noeuds de mes courbes (pour récupérer leurs valeurs) :

Code:

drop table if exists "test_interpo"."Node2_Valdco" cascade;
 Create table
"test_interpo"."Node2_Valdco"
as
select N.*, L.valdco as Valdco
from
"test_interpo". "node2update" N inner join "test_interpo". "7123_DEPCNT_Arc" L
on st_dwithin (N.geom, L.geom,0.0000001);
 
-- noeuds polygone seulement les sondes
drop table if exists "test_interpo"."node2_SOUNDG" cascade;
create table "test_interpo". "node2_SOUNDG" as
select distinct n.* from "test_interpo"."node2update" n inner join "test_interpo". "7123_SOUNDG_UWTRO" s
 on   st_dwithin(n.geom,s.geom,0.00000001);
 
 
--Reconstitution table Node a jour des bons Z
drop table if exists "test_interpo"."Node2Z" cascade;
create table  "test_interpo"."Node2Z" as

select  gid,id_triangle, part, idpoly, vertex,x,y,z, st_setsrid((st_makepoint(st_X(geom),st_y(geom),valdco)),4326) geom

from   "test_interpo"."Node2_Valdco"

union all

select gid,id_triangle, part, idpoly, vertex,x,y,z,st_setsrid((st_makepoint(st_X(geom),st_y(geom),st_z(geom))),4326) from "test_interpo". "node2_SOUNDG";

Maintenant, je suis à l'étape de reconstruction de mes polygones voici ma piste :

Code:

select st_makepolygon(st_makeline(geom)) from
(SELECT idpoly,
             count(gid)
       FROM test_interpo."Node2Z"
       GROUP BY idpoly order by idpoly) as polyg inner join (SELECT idpoly,
            geom
       FROM test_interpo."Node2Z") t on  polyg.idpoly=t.idpoly

Mais comme vous vous en doutez, ça ne fonctionne pas! Il me dit que ma ligne n'est pas fermée. Après, vérification, dans ma table, j'ai bien pour chaque point son idpoly, son ordre (1 à n), mais je n'arrive pas à boucler sur le premier point ;-(. LE problème vient de là je pense.

Je ne vois pas comment faire, une idée?

D'avance merci

Hors ligne

 

#10 Thu 13 April 2017 09:51

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Re,

J'ai trouvé une piste fourni par Nicolas, en utilisant les array_ag, je pense que cela pourrait m'aider.
Voici le lien du post : https://georezo.net/forum/viewtopic.php?pid=253372

Code:

with array_points as (
    select array_agg(t.the_geom) as arr
    from ma_couche_points t
    ORDER BY t.valeur
) select st_makepolygon( st_makeline( (arr ) ) 
from array_points;

Je vais creuser.

Hors ligne

 

#11 Thu 13 April 2017 11:31

Ted
Participant assidu
Date d'inscription: 16 Jan 2007
Messages: 181

Re: [POSTGIS] : Polygone Z

Finalement,

Je fais un Up, car à première vue j'ai réussi. Bon j'ai du modifier une de mes requêtes initiales (cas d'une même courbe coupant plusieurs fois le même triangle).

Code:

drop table if exists "T067"."tmppolyg067seldepare" cascade;
  create table "T067"."tmppolyg067seldepare" as select distinct
D.drval1,D.drval2,  T.id_triangle, D.id as id,

  (st_dump(st_collectionextract(st_intersection(D.geom, T.geometryexplose),3))).geom as geom
        From "T067"."067_DEPARE_Polygon" D inner join
"T067"."067_TRIANGLE_DISTINCT_sel" T on st_intersects(D.geom,
T.geometryexplose);
alter table "T067"."tmppolyg067seldepare"add column idpoly bigserial;

Et pour construire mes polygones, je suis parti sur ça : st_convexhull

Code:

--reconstruire polygone
 create table "T067"."Newpoly" as select idpoly, st_convexhull( st_collect(geom) ) as geom, st_asewkt(st_convexhull( st_collect(geom) ))

from 
 "T067"."Node2Z" group by idpoly order by idpoly ;

Dites-moi si cela vous semble correct?

Ted

Hors ligne

 

Pied de page des forums

Powered by FluxBB