Väga hea – sul on juba olemas põhjalik skript OSM-i maanteede (`ardok_highways`) töötlemiseks ning olemasolev Bash-põhine töövoog graafi (`links`, `nodes`) ja PGROUTING toe loomiseks. Allpool annan **kokkuvõtliku juhise ja parendatud SQL/Bash struktuuri**, et **luua teedevõrgu graaf `links` tabelist** kasutades sinu `ardok_highways` tabelit. --- ## ✅ **Eesmärk: Loo `links` ja `nodes` tabelid `ardok_highways` baasil** ### 1. **Lähteandmed** - Tabel: `${destination_schema}.ardok_highways` - Veerg: `geom` (LINESTRING, SRID 3301) - ID: `id` - Tee tüüp: `hwtype` --- ## 🧰 2. **Töövoog (kaasaegsem ja lihtsustatud)** ### 📦 a) `links` loomine ```sql DROP TABLE IF EXISTS ${destination_schema}.links CASCADE; CREATE TABLE ${destination_schema}.links AS WITH dumped_lines AS ( SELECT (ST_Dump(geom)).geom AS geom, id, hwtype FROM ${destination_schema}.ardok_highways ), unified AS ( SELECT ST_Union(geom) AS geom FROM dumped_lines ), split_lines AS ( SELECT (ST_Dump(ST_LineMerge(ST_Union(geom)))).geom AS geom FROM dumped_lines ), numbered AS ( SELECT ROW_NUMBER() OVER () AS id, geom FROM split_lines WHERE GeometryType(geom) = 'LINESTRING' ), attributed AS ( SELECT l.id, MIN(h.id) AS eid, h.hwtype, l.geom FROM numbered l JOIN ${destination_schema}.ardok_highways h ON ST_Intersects(h.geom, ST_LineSubstring(l.geom, 0.01, 0.99)) GROUP BY l.id, l.geom, h.hwtype ) SELECT * FROM attributed; ``` > See eemaldab kattuvad jooned, teeb need unikaalseks ja seob lähte-ID ja tüübi. --- ### 🧠 b) `nodes` loomine ```sql DROP TABLE IF EXISTS ${destination_schema}.nodes CASCADE; CREATE TABLE ${destination_schema}.nodes AS WITH all_nodes AS ( SELECT ST_StartPoint(geom) AS geom FROM ${destination_schema}.links UNION SELECT ST_EndPoint(geom) AS geom FROM ${destination_schema}.links ), distinct_nodes AS ( SELECT DISTINCT geom FROM all_nodes ) SELECT ROW_NUMBER() OVER () AS id, geom FROM distinct_nodes; CREATE INDEX IF NOT EXISTS ${pk}_nodes_geom_idx ON ${pk}.nodes USING GIST (geom); ``` --- ### 🔗 c) `links` täiendamine `source`, `target`, `cost` ```sql ALTER TABLE ${destination_schema}.links ADD COLUMN source bigint, ADD COLUMN target bigint, ADD COLUMN cost double precision, ADD COLUMN reverse_cost double precision DEFAULT -1; ``` ```bash BATCH_SIZE=10000 MAX_ID=$(psql -tA -c "SELECT max(id) FROM ${pk}.links;") for ((i=1; i<=MAX_ID; i+=BATCH_SIZE)); do END=$((i+BATCH_SIZE-1)) echo "Processing batch $i - $END" psql ${CONNECTION_NAME} -c " WITH link_batch AS ( SELECT * FROM ${pk}.links WHERE id BETWEEN $i AND $END ), nodes AS (SELECT * FROM ${pk}.nodes), link_data AS ( SELECT l.id, l.geom, n1.id AS source, n2.id AS target, ST_Length(l.geom) AS cost FROM link_batch l JOIN nodes n1 ON ST_DWithin(ST_StartPoint(l.geom), n1.geom, 0.01) AND ST_Distance(ST_StartPoint(l.geom), n1.geom) = 0 JOIN nodes n2 ON ST_DWithin(ST_EndPoint(l.geom), n2.geom, 0.01) AND ST_Distance(ST_EndPoint(l.geom), n2.geom) = 0 ) UPDATE ${pk}.links l SET source = d.source, target = d.target, cost = ROUND(d.cost::numeric, 1) FROM link_data d WHERE l.id = d.id;" done ``` --- ### ⚙️ d) PGROUTING ettevalmistus ```sql SELECT pgr_createVerticesTable('${destination_schema}.links', 'geom', 'source', 'target'); SELECT pgr_analyzeGraph('${destination_schema}.links', 0.001, the_geom := 'geom', id := 'id', source := 'source', target := 'target'); ``` --- ### 🏷️ e) Indeksid ja võtmed ```sql ALTER TABLE ${destination_schema}.links ADD PRIMARY KEY (id); CREATE INDEX ON ${destination_schema}.links USING GIST (geom); CREATE INDEX ON ${destination_schema}.links (source, target); ALTER TABLE ${destination_schema}.nodes ADD PRIMARY KEY (id); CREATE INDEX ON ${destination_schema}.nodes USING GIST (geom); ``` --- ## ✨ **Soovitused edasi:** - **Tee lisaveerg `is_main_road`** → kui `hwtype IN (...)` - **Lisa `travel_time = cost / average_speed`**, kui `maxspeed` olemas - **Kaalude lisamine gravitatsioonimudeliks** (vt eelmine vastus) --- ## 📌 Kui soovid: - bashi wrapper-funktsioon nagu `create_links` või `create_graph` - täiendatud versiooni PGROUTING analüüsiks - automaatset `reverse_cost` genereerimist (nt ühesuunaliste teede jaoks) ...anna teada – võin vormistada kõik struktureeritult skriptina. Siin on täiendatud SQL-töövoog, mis põhineb sinu `ardok_highways` → `links` → `nodes` süsteemil ning lisab järgmised 3 olulist veergu: --- ## ✅ **1. `is_main_road`** Märgib, kas teelõik kuulub põhi-/kõrval-/tugimaanteede hulka ## ✅ **2. `travel_time`** Aeg sekundites teelõigu läbimiseks, kui `maxspeed` on teada ## ✅ **3. `weight_pop`** Gravitatsioonianalüüsi kaal, impordituna piirkondade tabelist (eeldame, et `ardok_polygons` sisaldab veergu `weight_pop` ja `relation_id`) --- ## 🔧 **Muudatused `links` tabeli täiendamiseks** ### 📥 **Lisa uued veerud** ```sql ALTER TABLE ${destination_schema}.links ADD COLUMN is_main_road boolean, ADD COLUMN travel_time double precision, ADD COLUMN weight_pop double precision; ``` --- ### 🧠 **1. Märgista `is_main_road`** ```sql UPDATE ${destination_schema}.links SET is_main_road = TRUE WHERE hwtype IN ( 'motorway', 'motorway_link', 'trunk', 'trunk_link', 'primary', 'primary_link', 'secondary', 'secondary_link', 'tertiary', 'tertiary_link' ); ``` (ülejäänud jäävad `NULL` või `FALSE`) --- ### 🕓 **2. Arvuta `travel_time` sekundites** Eeldame, et `maxspeed` on km/h — teisendame m/s → s: ```sql UPDATE ${destination_schema}.links l SET travel_time = ROUND(l.cost / (NULLIF(h.maxspeed, 0) * 1000.0 / 3600.0), 1) FROM ${destination_schema}.ardok_highways h WHERE l.eid = h.id AND h.maxspeed IS NOT NULL; ``` > NB! `NULLIF` hoiab ära 0-ga jagamise. Kui `maxspeed` puudub, jääb `travel_time` `NULL`. --- ### 🌍 **3. Lisa gravitatsiooniline kaal `weight_pop`** Eeldame, et saad iga teelõigu lähima piirkonna `weight_pop` väärtuse: ```sql UPDATE ${destination_schema}.links l SET weight_pop = p.weight_pop FROM ${destination_schema}.ardok_administrative p WHERE ST_Intersects(l.geom, p.geom) AND p.weight_pop IS NOT NULL; ``` > Vajadusel võid kasutada ka `ST_ClosestPoint` vms, kui `ST_Intersects` annab mitu sobivat ala. Võin aidata ka `ST_DWithin + ORDER BY ST_Distance LIMIT 1` variandiga. --- ## 🧹 **Lisa indeksid uutele veergudele (soovituslik)** ```sql CREATE INDEX ON ${destination_schema}.links (is_main_road); CREATE INDEX ON ${destination_schema}.links (travel_time); CREATE INDEX ON ${destination_schema}.links (weight_pop); ``` --- ## 📊 **Kokkuvõte – mis sul nüüd on** |Veerg|Kirjeldus| |---|---| |`is_main_road`|TRUE, kui tee kuulub põhi-/kõrvalteede hulka| |`travel_time`|Läbimisaeg sekundites, kui maxspeed olemas| |`weight_pop`|Gravitatsioonianalüüsi "mass" piirkonnast| --- Kui soovid seda töövoogu bash-funktsioonina (nt `enhance_links()`), annan hea meelega ka struktureeritud `bash`-skripti versiooni. Võin lisada ka `weight_jobs`, `poi_count`, vms kui sul on täiendavaid andmeid.