-
Notifications
You must be signed in to change notification settings - Fork 4
Modification buildings, motorways, railways, bridges pour OpenArdenneMap #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| WITH /*bbox AS ( | ||
| SELECT ST_Transform( | ||
| ST_MakeEnvelope( | ||
| 5.05, -- longitude Ouest | ||
| 49.78, -- latitude Sud | ||
| 5.10, -- longitude Est | ||
| 49.82, -- latitude Nord | ||
| 4326 -- système de coordonnées WGS84 | ||
| ), | ||
| 31370 -- Projection métrique (Web Mercator), on en aura besoin à cause de la future création de buffer | ||
| ) AS zone -- ici on créer une zone d'étude (plus précisement dans la ville de Bouillon pour étudier les parkings) | ||
| ),*/ | ||
|
|
||
| parkings_campings AS ( | ||
| SELECT -- sélection des parkings et campings OSM situés dans la zone d'étude | ||
| osm_id, -- identifiant unique OpenStreetMap | ||
| ST_MakeValid(way) AS geom -- si un parking a une géométrie un peu cassée, avec cette ligne elle est corrigée pour éviter des bugs plus tard | ||
| FROM planet_osm_polygon, bbox | ||
| WHERE ( | ||
| amenity = 'parking' -- selection Parkings | ||
| OR tourism = 'camp_site' -- selection Campings | ||
| ) | ||
| /*AND ST_Intersects( | ||
| way, | ||
| bbox.zone -- uniquement ceux qui intersect la zone de Bouillon | ||
| )*/ | ||
| ), | ||
|
|
||
| service_roads AS ( | ||
| SELECT | ||
| ST_MakeValid(way) AS geom -- réparation des routes au cas ou il y aurait des bugs | ||
| FROM planet_osm_line, bbox | ||
| WHERE highway = 'service' -- Routes de type et qui ont le tag "service", pas les autoroutes et nationales | ||
| /* AND ST_Intersects( | ||
| way, | ||
| bbox.zone )*/ -- routes uniquement présente dans la zone de bouillon | ||
| ), | ||
|
|
||
| parking_with_roads AS ( --- creation table temporaire + fusion des parkings/campings avec leurs routes de service associées | ||
| SELECT | ||
| p.osm_id, -- Identifiant du parking/camping en sortie | ||
|
|
||
| ST_Union( -- création d'une géom unique qui integre le parking et les routes | ||
| ARRAY[ -- permet d'avoir plusieurs geoms dans le ST_union | ||
| p.geom, -- Géométrie du parking ou camping finale sera plusieurs choses d'ou l'union 1. ici d'abord le parking | ||
|
|
||
| COALESCE( -- on récupère des portions de routes qui se trouvent dans un buffer de 5 mètres autour du parking et avec le ST_union on fait une forme qui lie à la fois le parking et à la fois les routes trouvées autours*/ | ||
| ST_Union( | ||
| ST_Intersection( | ||
| r.geom, | ||
| ST_Buffer(p.geom, 5) -- zone d'influence du parking, on ne prend que la route qui est "utile" au parking et qui se retrouve donc dans un buffer de 5m autour | ||
| ) | ||
| ), | ||
| p.geom -- valeur de secours si aucune route n'existe, on reprend le parking lui même | ||
| ) | ||
| ] --- tableau des geom fermés | ||
| ) AS geom --- geom finale par parking | ||
| FROM parkings_campings p | ||
|
|
||
| LEFT JOIN service_roads r -- Jointure spatiale avec les routes de service proches, permet de voir si les routes "service" passent à moins de 3m d'un parking | ||
| ON ST_Intersects( | ||
| p.geom, | ||
| ST_Buffer(r.geom, 3) -- Tolérance spatiale de 3 mètres, si une route "service" passe à moins de 3m du parking, on considère qu'elle en fait partie | ||
| ) | ||
|
|
||
| GROUP BY p.osm_id, p.geom -- agregation pour fusionner les parkings et les routes qui leurs sont associés | ||
| ) | ||
|
|
||
| SELECT | ||
| osm_id AS cid, -- on renomme l'identifiant pour la couche finale | ||
| ST_SimplifyPreserveTopology( -- ici on va nettoyer la géométrie | ||
| ST_Buffer( | ||
| geom, | ||
| 2, -- Buffer de 2 mètres, permet d'arrondir les bords du parkings | ||
| 'join=round' | ||
| ), | ||
| 1 -- permet de simplifier et de lisser le résultat pour ne pas juste avoir un cercle "parfait" tout en gardant le côté arrondi amener par le buffer | ||
| ) AS geom | ||
| FROM parking_with_roads | ||
|
|
||
|
|
||
| WHERE geom IS NOT NULL | ||
| AND NOT ST_IsEmpty(geom); -- exclusion des géométries nulles ou vides |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| --- ROAD | ||
|
|
||
| WITH base AS ( | ||
|
|
||
| -- Sélection des autoroutes avec une référence | ||
| SELECT | ||
| ST_Transform(way, 3857) AS geom, -- Passage en projection métrique | ||
| ref -- Identifiant de l’axe routier | ||
| FROM planet_osm_line | ||
| WHERE highway = 'motorway' -- Autoroutes uniquement | ||
| AND highway NOT LIKE '%_link' -- Exclusion des bretelles | ||
| AND ref IS NOT NULL -- Référence obligatoire | ||
| ), | ||
|
|
||
| polygons AS ( | ||
|
|
||
| -- Construction d’un polygone par référence routière | ||
| SELECT | ||
| ref, | ||
| ST_Subdivide( -- découpage des polygones trop grands ou complexes permettant de facilité les calculs | ||
| ST_UnaryUnion( -- tout les polygones collectionnés sont combinés en une seule géom (polygone) = création d'une forme continue | ||
| ST_Collect( -- regroupe les buffers en une seule collection = traite tout les segments de la route comme un ensemble | ||
| ST_Buffer( -- création d'un buffer autour de chaque ligne (ici de 25m) | ||
| ST_Simplify(geom, 2), -- Réduction de la complexité de la geom sans trop changer la forme originale | ||
| 25 | ||
| ) | ||
| ) | ||
| ), | ||
| 5000 -- taille maximale des polygones subdivisés pour limiter la complexité | ||
| ) AS poly | ||
|
|
||
| FROM base | ||
| GROUP BY ref -- toute les geoms sont regroupés par ref routieres | ||
| ) | ||
|
|
||
| -- Extraction de l’axe central des polygones | ||
| SELECT | ||
| row_number() OVER () AS id, -- Identifiant unique pour QGIS | ||
| ref, | ||
| ST_Transform( -- conversion de la projection en projection d'affichage 4326 | ||
|
||
| ST_LineMerge( -- fusion des segments d’axe médian en une seule ligne continue | ||
| CG_ApproximateMedialAxis(poly) -- création d'une ligne centrale au milieu des polygones | ||
| ), | ||
| 4326 | ||
| ) AS geom | ||
| FROM polygons | ||
|
|
||
| -- Exclusion des géométries vides | ||
| WHERE NOT ST_IsEmpty(poly); | ||
|
|
||
|
|
||
| ----------------------------------------- | ||
|
|
||
| --- RAILWAYS | ||
|
|
||
| WITH base AS ( | ||
| SELECT | ||
| ST_Transform(way, 3857) AS geom, -- transformation en projection métrique (Web Mercator) pour les calculs de distance | ||
|
||
| name -- selection du nom de la ligne ferroviaire | ||
| FROM planet_osm_line | ||
| WHERE railway = 'rail' -- on ne garde que les rails | ||
| AND service IS NULL -- exclusion des rails de service ou industriels + des tunnels + des ponts | ||
| AND (tunnel IS NULL OR tunnel = 'no') | ||
| AND (bridge IS NULL OR bridge = 'no') | ||
| ), | ||
|
|
||
| polygons AS ( | ||
| SELECT | ||
| name, -- regroupe par nom de ligne | ||
| ST_Subdivide( -- decoupe les polygones trop gros ou complexes en morceaux plus petits pour faciliter les calculs | ||
| ST_UnaryUnion( -- tout les polygones collectionnés sont combinés en une seule géom (polygone) | ||
| ST_Collect( -- regroupe tous les buffers d’une même ligne en une collection | ||
| ST_Buffer( -- création d’un buffer autour de la ligne (ici 6m) | ||
| ST_Simplify(geom, 1.5), -- réduction de la complexité de la geom sans trop changer la forme originale | ||
| 6 | ||
| ) | ||
| ) | ||
| ), | ||
| 3000 -- taille maximale des polygones subdivisés pour limiter la complexité | ||
| ) AS poly | ||
| FROM base | ||
| GROUP BY name | ||
| ) | ||
|
|
||
| SELECT | ||
| row_number() OVER () AS id, -- selection de l'id unique pour chaque ligne | ||
| name, -- selection du nom de la ligne ferroviaire | ||
| ST_Transform( -- conversion en projection 4326 (latitude/longitude) pour la visualisation | ||
|
||
| ST_LineMerge( -- fusion des segments d’axe médian en une seule ligne continue | ||
| CG_ApproximateMedialAxis(poly) -- creation d'une ligne central au milieu des polygones | ||
| ), | ||
| 4326 | ||
| ) AS geom | ||
| FROM polygons | ||
| WHERE NOT ST_IsEmpty(poly) -- On exclut les polygones vides (au cas où la fusion ou le buffer échoue) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| WITH clustered AS ( | ||
| SELECT | ||
| way, -- Sélection des géométries de bâtiments | ||
| ST_ClusterDBSCAN(way, eps := 10, minpoints := 1) OVER () AS cid -- Attribution d'un identifiant de cluster selon la proximité spatiale, eps = distance max entre deux batiments pour les considérer comme un même cluster | ||
| -- et minpoint = un cluster peut etre formé même avec 1 seul élément. | ||
| FROM planet_osm_polygon | ||
| WHERE building IS NOT NULL -- On conserve uniquement des polygones de bâtiments | ||
| /*AND way && ST_Transform( | ||
| ST_MakeEnvelope(5.63, 49.71, 5.68, 49.75, 4326), -- Limitation du traitement à la zone d'étude (ici à la commune de Habay) | ||
| 3857 | ||
| )*/ | ||
| ) | ||
|
|
||
| -- Fusion et généralisation des bâtiments par cluster | ||
| SELECT | ||
| cid, | ||
| ST_Simplify( -- simplification des batiments finaux | ||
| ST_Union( -- fusion des batiments appartenant à un même cluster | ||
| ST_MakeValid(way) -- permet d'avoir des géometries valides | ||
| ), | ||
| 1.5 -- en fonction de l'échelle, cette valeur peut changer, à l'échelle d'une ville on a une simplification qui reste précise | ||
| ) AS geom | ||
|
|
||
| FROM clustered | ||
|
|
||
| -- Suppression des entités sans cluster | ||
| WHERE cid IS NOT NULL | ||
|
|
||
| -- Création d'un polygone final par cluster | ||
| GROUP BY cid; | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| WITH | ||
| -- 1. On définit la zone en 3857 (le SRID de tes données planet_osm_line) | ||
| zone AS ( | ||
| SELECT ST_Transform(ST_MakeEnvelope(5.72, 50.57, 5.80, 50.60, 4326), 3857) AS geom | ||
| ), | ||
| -- 2. Obstacles (Rivières et Rails) --> ici on recupere les obstacles pour les routes ATTENTION on ne prend en compte que les éléments "ligne" | ||
| obstacles AS ( | ||
| SELECT way as geom | ||
| FROM planet_osm_line | ||
| WHERE (waterway IS NOT NULL OR railway = 'rail') -- garde uniquement rail et rivières de la table et dans la zone définie auparavant | ||
| AND ST_Intersects(way, (SELECT geom FROM zone)) | ||
| ), | ||
| -- 3. Points des routes éclatés -- objectif transformer les lignes en une serie de points + chaque point sera pris individuellement pour voir s'il est ou non proche d'un obstacle | ||
|
|
||
| points_eclates AS ( | ||
| SELECT | ||
| r.osm_id, | ||
| (ST_DumpPoints(r.way)).path as pt_path, -- pt_path va donner la position du point dans la ligne et st_dump va decouper la ligne en points | ||
| (ST_DumpPoints(r.way)).geom as pt_geom -- geom du point individuel (les coordonées du pts) | ||
| FROM planet_osm_line r | ||
| WHERE r.highway IS NOT NULL | ||
| AND (r.bridge IS NULL OR r.bridge = 'no') -- exclusion des ponts (vu qu'ils passent au dessus il n'y a donc pas de conflit) | ||
| AND ST_Intersects(r.way, (SELECT geom FROM zone)) | ||
| ), | ||
| -- 4. Recherche de l'obstacle et déplacement (en mètres car le 3857 utilise le mètre) | ||
| calcul_deplacement AS ( | ||
| SELECT | ||
| p.osm_id, | ||
| p.pt_path, -- position du point dans la ligne | ||
| CASE | ||
| WHEN ST_DWithin(p.pt_geom, obs.geom, 15) THEN -- ici on vérifie si le point se situe 15m d'un obstacle, si oui alors il y a conflit | ||
| ST_Translate( --si il y a conflit alors : déplacement du point | ||
| p.pt_geom, -- ici on prend le point à déplacer | ||
| sin(ST_Azimuth(ST_ClosestPoint(obs.geom, p.pt_geom), p.pt_geom)) * 12, -- On pousse de 12m le point le plus proche de l'obstacle en X | ||
| cos(ST_Azimuth(ST_ClosestPoint(obs.geom, p.pt_geom), p.pt_geom)) * 12 -- on pousse de 12m le point le plus proche de l'obstacle en Y | ||
| ) | ||
| ELSE p.pt_geom -- sinon on conserve le point originel | ||
| END as geom_p | ||
| FROM points_eclates p | ||
| LEFT JOIN LATERAL ( -- Lateral join permet pour chaque point de chercher et trouver l'obstacle le plus proche (recherche personalisée pour chaque point, alors que le join normal va en general relier les points avec tout les obstacles possibles | ||
| SELECT geom FROM obstacles | ||
| ORDER BY p.pt_geom <-> geom -- <-> = operateur de distance postgis, il va calculer la distance entre les deux geoms | ||
| LIMIT 1 -- garde que l'obstacle le plus proche | ||
| ) obs ON true -- jointure toujours vraie | ||
| ), | ||
| -- 5. Reconstruction des lignes | ||
| lignes_reconstruites AS ( | ||
| SELECT | ||
| osm_id, | ||
| ST_MakeLine(geom_p ORDER BY pt_path)::geometry(LineString, 3857) as geom -- reconnecte les points en une ligne dans l'ordre original de la route en forcant un type de geom = ligne | ||
| FROM calcul_deplacement | ||
| GROUP BY osm_id -- groupement pour refaire la route | ||
| ) | ||
| -- 6. Résultat final pour QGIS | ||
| SELECT | ||
| CAST(ROW_NUMBER() OVER() AS INT) as qgis_id, | ||
| osm_id, | ||
| geom | ||
| FROM lignes_reconstruites; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| WITH snapped AS ( | ||
| SELECT | ||
| highway, | ||
| ST_Snap(way, ST_Collect(way), 1) AS snapped_way -- ST_Snap ajuste chaque ligne pour qu'elle s'aligne sur les autres à moins de 1 unité, cela aura pour effet: | ||
| -- si deux lignes sont très proches (moins de 1 unité), leurs points finaux seront déplacés pour qu’elles se connectent parfaitement, éliminant les gaps ou décalages minimes | ||
| FROM planet_osm_line | ||
| WHERE bridge NOT IN ('0','no','') -- On ne garde que les ponts actifs | ||
| AND highway IN ('path','cycleway','footway','pedestrian','steps','bridleway','boardwalk') | ||
| GROUP BY highway, way -- regroupe les lignes pour faire fonctionner le collect | ||
| ), | ||
|
|
||
| clusters AS ( -- regroupement des lignes qui se touchent ou s'intersectent | ||
| SELECT | ||
| unnest(ST_ClusterIntersecting(snapped_way)) AS cluster_geom -- ST_ClusterIntersecting crée des groupes de lignes connectées, au cas ou des lignes ne serait pas une seule ligne en provenant de osm | ||
| -- et unnest permet de transformer ces clusters en lignes individuelles pour traitement | ||
| FROM snapped | ||
| ), | ||
|
|
||
| merged AS (-- fusion et nettoyage des lignes de chaque cluster | ||
| SELECT | ||
| row_number() OVER () AS geom_id, -- ID unique pour chaque ligne fusionnée | ||
| ST_RemoveRepeatedPoints( -- va supprimer les points consécutifs identiques ou très proches (tolérance 0.001) | ||
| ST_LineMerge(ST_Union(cluster_geom)), 0.001 -- ST_LineMerge combine les segments en une seule ligne continue + ST_Union fusionne toutes les lignes d'un cluster | ||
| ) AS geom_clean, | ||
| ST_Length(ST_LineMerge(ST_Union(cluster_geom))) AS length_way -- Calcul de la longueur totale de la ligne fusionnée | ||
| FROM clusters | ||
| GROUP BY cluster_geom | ||
| ) | ||
|
|
||
| -- sélection finale des colonnes utiles | ||
| SELECT | ||
| geom_id, -- Identifiant unique | ||
| geom_clean AS geom, -- Géométrie finale nettoyée et fusionnée | ||
| length_way -- Longueur de la ligne | ||
| FROM merged; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| DROP MATERIALIZED VIEW IF EXISTS view_belgium_bridges_snapped_3857; | ||
|
|
||
| CREATE MATERIALIZED VIEW view_belgium_bridges_snapped_3857 AS | ||
| WITH snapped AS ( | ||
| SELECT | ||
| highway, | ||
| ST_Snap(ST_Transform(way, 3857), ST_Collect(ST_Transform(way, 3857)), 1) AS snapped_way | ||
| FROM planet_osm_line | ||
| WHERE bridge NOT IN ('0','no','') | ||
| AND highway IN ('path','cycleway','footway','pedestrian','steps','bridleway','boardwalk') | ||
| GROUP BY highway, way | ||
| ), | ||
|
|
||
| clusters AS ( | ||
| SELECT | ||
| unnest(ST_ClusterIntersecting(snapped_way)) AS cluster_geom | ||
| FROM snapped | ||
| ), | ||
|
|
||
| merged AS ( | ||
| SELECT | ||
| row_number() OVER () AS geom_id, | ||
| ST_RemoveRepeatedPoints( | ||
| ST_LineMerge(ST_Union(cluster_geom)), 0.001 | ||
| ) AS geom_clean, | ||
| ST_Length(ST_LineMerge(ST_Union(cluster_geom))) AS length_way | ||
| FROM clusters | ||
| GROUP BY cluster_geom | ||
| ) | ||
|
|
||
| SELECT | ||
| geom_id, | ||
| geom_clean::geometry(Geometry, 3857) AS geom, | ||
| length_way | ||
| FROM merged; | ||
|
|
||
| -- Index spatial | ||
| CREATE INDEX idx_be_bridges_snapped_geom ON view_belgium_bridges_snapped_3857 USING GIST (geom); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| DROP MATERIALIZED VIEW IF EXISTS view_belgium_buildings_clustered; | ||
|
|
||
| CREATE MATERIALIZED VIEW view_belgium_buildings_clustered AS | ||
| WITH base_data AS ( | ||
| SELECT | ||
| ST_Transform(way, 3857) AS way | ||
| FROM planet_osm_polygon | ||
| WHERE building IS NOT NULL | ||
| AND building NOT IN ('church', 'chapel', 'cathedral', 'religious') | ||
| ), | ||
| clustered AS ( | ||
| SELECT | ||
| way, | ||
| ST_ClusterDBSCAN(way, eps := 10, minpoints := 1) OVER () AS cid | ||
| FROM base_data | ||
| ) | ||
| SELECT | ||
| cid AS id, | ||
| ST_Simplify( | ||
| ST_Union( | ||
| ST_MakeValid(way) | ||
| ), | ||
| 1.5 | ||
| )::geometry(Geometry, 3857) AS geom | ||
| FROM clustered | ||
| WHERE cid IS NOT NULL | ||
| GROUP BY cid; | ||
|
|
||
| -- Index spatial pour que ça trace sur la carte | ||
| CREATE INDEX idx_be_buildings_clustered_geom ON view_belgium_buildings_clustered USING GIST (geom); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il n'y a pas besoin ici de transformer en EPSG:3857. C'est déjà le CRS de la BD OSM