#1 Sun 29 March 2020 22:16
- preliator
- Participant assidu
- Date d'inscription: 17 Nov 2018
- Messages: 433
[PostGis] Créer des centroides (couche bâtis de OSM)
Bonjour à tous,
Je travaille actuellement sur des polygones représentant les maisons dans un département (plus de 100 000 entités) . Cette donnée provient d'Open Street Map.
Dans cette couche de polygones, je voudrais créer un champ qui indique la distance minimale au plus proche voisin, pour faire une étude sur l'isolement des maisons. Pour cet exercice, je pensais me baser sur les centroides des polygones.
Malheureusement (ou heureusement !), cette couche de bâtiment est très précise et de nombreux bâtiments sont découpés en plusieurs polygones. De ce fait, je me retrouve avec plusieurs centroides pour un seul même bâtiment, ce qui biaise mes calculs.
Comme par exemple, sur cette image : https://zupimages.net/viewer.php?id=20/13/tg4m.png
Je me demandais donc s'il existait un moyen, sur PostGis, de créer UN seul centroide pour ces bâtiments qui se touchent, ou alors s'il existait un outil sur QGis pour regrouper ces polygones qui se touchent en une seule entité.
Merci.
Dernière modification par preliator (Sun 29 March 2020 22:22)
Hors ligne
#2 Mon 30 March 2020 11:07
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostGis] Créer des centroides (couche bâtis de OSM)
Bonjour,
Pkoi calculer des centroids pour avoir la distance entre objets ?
Ca sera faux dans certains cas (batiments en U, batiment avec cour, etc. (le centroid ne tombant pas dans le pg pour ces cas. IL faut mieux prendre st_pointOnSurface pour cela)
Calculez directement la distance la plus proche, elle sera 0 si le batiment en touche un autre ! (utilisez l'operateur distance KNN <-> pour cela, et surtout pas st_distance(geom, geom), qui prendrait un temps fou.
Sinon, pour regrouper des objets qui se touchent, plusieurs facons:
st_union(geom) => tous les objets qui se touchent seront unis en un seul objet, ou plus rapide:
st_clusterINtersecting: ca renvoie un tableau de geometryCollection contenant tous les objets qui se touchent, st_UnaryUnion pour avoir l'union de ces objets.
Mais dans le cas que vous décrivez, ca me parait inutile.
Nicolas
Hors ligne
#3 Mon 30 March 2020 15:26
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: [PostGis] Créer des centroides (couche bâtis de OSM)
Un exemple de SQL pour
regrouper les objets qui se touchent (st_clusterIntersecting),
en faire un polygone unique (st_unaryUnion),
croiser cette couche avec elle même pour trouver le plus proche voisin (t.geom <-> t2.geom),
croiser avec les batiments pour faire un lien entre chaque cluster de batiments et les batiments qui le composent (array_agg(id),
fabriquer une geom qui est la plus petite distance entre deux clusters de batiments (st_shortestLine) :
Image: https://zupimages.net/viewer.php?id=20/14/095n.png
En rose: cluster, id du cluster (générée avec WITH ORDINALITY), en gris, id des batiments, en vert: distance mini entre les objets (en m)
Code:
with tmp as ( select st_clusterintersecting(geom) as arr from batiment ), tmp1 as ( select u.ordinality as idcluster, u as geom from tmp, unnest(tmp.arr) with ordinality as u ), tmp2 as ( select t.idcluster, t2.idcluster as idcluster2, t2.dist, st_unaryunion(t.geom) as geom, t2.geom as geom2 from tmp1 t cross join lateral ( select b.idcluster, b.geom <-> t.geom as dist, b.geom from tmp1 b where b.idcluster != t.idcluster order by b.geom <-> t.geom limit 1 ) as t2 ) select t.idcluster, t.idcluster2, dist, array_agg(b.id) as id_batiments, st_shortestline(t.geom, t.geom2) as geomline from tmp2 t join batiment b on st_contains(t.geom, st_pointonsurface(b.geom)) group by 1,2,3,5; idcluster idcluster2 dist id_batiments 1 3 49.8 {1} 2 3 97.2 {2} 3 1 49.8 {3,4,5,6,7,8} 4 2 176. {9} 5 6 78.3 {10,13} 6 7 41.7 {11} 7 6 41.7 {12} 8 1 99.1 {14} 9 8 100. {15}
Avec une vraie grosse table de batiments, il faut passer par des tables intermédiaires et créer des index spatiaux qui vont bien (geom, st_pointOnSurface(geom), ...) pour optimiser la requête.
Nico
Dernière modification par Nicolas Ribot (Wed 01 April 2020 10:01)
Hors ligne
#4 Tue 31 March 2020 21:52
- preliator
- Participant assidu
- Date d'inscription: 17 Nov 2018
- Messages: 433
Re: [PostGis] Créer des centroides (couche bâtis de OSM)
Je vous dis un grand merci pour votre réponse cela résout mon problème en plus de m'apporter de nouveaux outils à apprendre !
Hors ligne