Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
82 changes: 82 additions & 0 deletions SQL/Code brut + commentaires/Code Parking simplification.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
WITH /*bbox AS (
SELECT ST_Transform(
ST_MakeEnvelope(
4.84,
50.43,
4.92,
50.49,
4326
),
3857 ) AS zone -- ici on créer une zone d'étude (plus précisement dans la ville de Namur pour étudier les parkings) + ST_Transform pas besoin d'etre effectuée
),*/

parkings_campings AS (
SELECT -- sélection des parkings et campings OSM situés dans la zone d'étude
osm_id,
ST_MakeValid(way) AS geom -- reparation parking au cas ou il y aurait des bugs
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 Namur
)*/
),

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 qui ont le tag "service"
/* AND ST_Intersects(
way,
bbox.zone )*/ -- routes uniquement présente dans la zone de Namur
),

parking_with_roads AS ( --- creation table temporaire + fusion des parkings/campings avec leurs routes de service associées
SELECT
p.osm_id,

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,

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 si aucune route n'existe, on reprend le parking lui même
)
] -- tableau des geoms fermées
) 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) -- 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,
ST_SimplifyPreserveTopology( -- ici on va nettoyer la géométrie
ST_Buffer(
geom,
2, -- le buffer de 2 mètres permet d'arrondir les bords du parkings
'join=round'
),
1 -- permet de simplifier le résultat pour ne pas juste avoir un cercle "parfait" tout en gardant le côté arrondi amené 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,86 @@
--- ROAD

WITH base AS (

-- Sélection des autoroutes avec une référence
SELECT
ref
FROM planet_osm_line
WHERE highway = 'motorway'
AND highway NOT LIKE '%_link' -- pas de bretelles prises en compte
AND ref IS NOT NULL
),

polygons AS (
SELECT
ref,
ST_Subdivide( -- découpage des polygones trop grands ou complexes permettant de facilité les calculs (taille max 5000)
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
) 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,
ref,
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
)
FROM polygons

-- Exclusion des géométries vides
WHERE NOT ST_IsEmpty(poly);


-----------------------------------------

--- RAILWAYS

WITH base AS (
SELECT
name
FROM planet_osm_line
WHERE railway = 'rail'
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 (ici 3000)
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
) AS poly
FROM base
GROUP BY name
)

SELECT
row_number() OVER () AS id,
name,
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
)
FROM polygons
WHERE NOT ST_IsEmpty(poly) -- On exclut les polygones vides (au cas où la fusion ou le buffer échoue)

29 changes: 29 additions & 0 deletions SQL/Code brut + commentaires/Code building simplification.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
WITH clustered AS (
SELECT
way, -- sélection des géométries de bâtiments
ST_ClusterDBSCAN(way, eps := 10, minpoints := 1) OVER () AS cid -- 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
)*/
)

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
) AS geom

FROM clustered

WHERE cid IS NOT NULL -- Suppression des entités sans cluster

GROUP BY cid; -- création d'un polygone par cluster


60 changes: 60 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,60 @@
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.25, 49.74, 5.32, 49.79, 4326), 3857) AS geom
),*/ -- pas obligatoire le ST_Transform et MakeEnvelope mais si travail sur une petite zone alors utile (ici zone de Herbeumont)

-- 2. On recupere les obstacles pour les routes ATTENTION on ne prend en compte que les éléments "ligne" (ici chemins de fers et rivières)
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. 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 normalement pas de conflit)
AND ST_Intersects(r.way, (SELECT geom FROM zone))
),
-- 4. recherche de l'obstacle (rivière ou rails) et déplacement
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 décalages minimes
FROM planet_osm_line
WHERE bridge NOT IN ('0','no','')
AND highway IN ('path','cycleway','footway','pedestrian','steps','bridleway','boardwalk')
GROUP BY highway, way -- regroupe les lignes pour faire fonctionner le ST_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 être traitée
FROM snapped
),

merged AS (-- fusion et nettoyage des lignes de chaque cluster
SELECT
row_number() OVER () AS geom_id,
ST_RemoveRepeatedPoints( -- va supprimer les points consécutifs identiques ou très proches
ST_LineMerge(ST_Union(cluster_geom)), 0.001 -- ST_LineMerge combine les segments en une seule ligne continue + ST_Union va fusionner toutes les lignes d'un cluster
) AS geom_clean,
ST_Length(ST_LineMerge(ST_Union(cluster_geom))) AS length_way
FROM clusters
GROUP BY cluster_geom
)

-- sélection finale des colonnes utiles
SELECT
geom_id,
geom_clean AS geom,
length_way
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