Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions SQL/Code brut + commentaires/Code Parking simplification.sql
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
Copy link
Copy Markdown
Owner

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

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
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem, pas besoin de retransformer en EPSG: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
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem

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
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem, pas besoin de retransformer en EPSG:4326

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)

31 changes: 31 additions & 0 deletions SQL/Code brut + commentaires/Code building simplification.sql
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;

59 changes: 59 additions & 0 deletions SQL/Code brut + commentaires/Code displacement only linestring.sql
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);
Loading