#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
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