Eesti gravitatsioonikaardi loomine OSM teede põhjal on huvitav ja mitmetahuline ülesanne. Siin on, kuidas seda saab teha:

---

### 🧭 **Mis on gravitatsioonikaart?**

Gravitatsioonikaart (või **liiklusgravitatsiooni mudel**) ei tähenda füüsikalist gravitatsiooni, vaid **ruumilist mudelit, mis näitab, kui tõenäoliselt inimesed liiguvad ühest punktist teise**, arvestades teedevõrku, kaugust, ligipääsetavust ja sihtkohtade atraktiivsust.

---

### 🛠️ **Kuidas luua gravitatsioonikaart OSM teede põhjal?**

#### 1. **Impordi OSM teed PostGIS andmebaasi**

- Kasuta `osm2pgsql`, nagu sul juba on.
- Tee eraldi tabel `osm_roads`, mis sisaldab ainult teid (`highway IS NOT NULL`).

#### 2. **Loo teede võrgustik**

- Kasuta `pgRouting` PostGISis, et luua graaf teede ühendustest.
- Vajalikud väljad: `source`, `target`, `cost`, `reverse_cost`.

#### 3. **Defineeri sihtkohad ja lähtekohad**

- Näiteks: linnad, asulad, koolid, tööpiirkonnad (võib võtta OSMist või HOTOSM-ist).

#### 4. **Rakenda gravitatsioonimudelit**

- Klassikaline mudel:  
    $$T_{ij} = \frac{P_i \cdot P_j}{D_{ij}^2}$$ Kus:
    - $(T_{ij})$ = liikumise intensiivsus punktide $(i)$ ja $(j)$ vahel
    - $(P_i, P_j)$ = lähtekoha ja sihtkoha "mass" (nt rahvaarv, töökohtade arv)
    - $(D_{ij})$ = kaugus (või aeg) teedevõrgus

#### 5. **Visualiseeri tulemus**

- Kasuta `QGIS` või `Python` (nt `matplotlib`, `geopandas`) gravitatsioonivälja visualiseerimiseks.

---

### 📜 **Skriptide ja töövoo pakkumine**

Kas soovid, et:

- Aitan luua **pgRouting graafi** sinu OSM teede põhjal?
- Koostan **Python-skripti**, mis arvutab gravitatsioonivälja ja visualiseerib selle?
- Loome **väiksemate piirkondade jaoks** eraldi kaardid?

Anna teada, millise osa soovid kõigepealt automatiseerida või visualiseerida, ja ma koostan vastava skripti!

Et luua pgRouting graaf sinu OSM teede andmete põhjal, tuleb järgida järgmisi samme. Allpool on täielik **bash-skript + SQL**, mis:

1. **Valmistab teetabeli** (`osm_roads`) OSM andmetest.
2. **Lisab vajalikud veerud** pgRoutingu jaoks.
3. **Käivitab `pgr_createTopology`**, et luua graaf.

---

### 📝 **1. Bash-skript: `create_pgrouting_graph.sh`**

```bash
#!/usr/bin/env bash

# Ühenduse andmed
destination_host='localhost'
destination_port='5432'
destination_user='osm'
destination_password='osm'
destination_dbname='data'
destination_schema='aaa_osm'
table_name='osm_roads'

export PGPASSWORD=${destination_password}
CONNECTION_NAME="-h ${destination_host} -p ${destination_port} -d ${destination_dbname} -U ${destination_user}"

# Loome pgRoutingu jaoks sobiva teetabeli
psql ${CONNECTION_NAME} <<EOF
DROP TABLE IF EXISTS ${destination_schema}.${table_name};

CREATE TABLE ${destination_schema}.${table_name} AS
SELECT
  osm_id,
  name,
  highway,
  ST_Length(way) AS cost,
  ST_Length(way) AS reverse_cost,
  way AS geom
FROM
  ${destination_schema}.osm_line
WHERE
  highway IS NOT NULL
  AND way IS NOT NULL;

-- Lisame pgRoutingu jaoks vajalikud veerud
ALTER TABLE ${destination_schema}.${table_name}
  ADD COLUMN id SERIAL PRIMARY KEY,
  ADD COLUMN source INTEGER,
  ADD COLUMN target INTEGER;

-- Loome ruumiindeksi
CREATE INDEX idx_${table_name}_geom ON ${destination_schema}.${table_name} USING GIST (geom);
EOF

# Käivitame pgRouting topoloogia loomise
psql ${CONNECTION_NAME} -c "SELECT pgr_createTopology('${destination_schema}.${table_name}', 0.0001, 'geom', 'id');"
```

---

### 📦 **Kasutamine**

1. Salvesta see failina `create_pgrouting_graph.sh`
2. Tee see käivitatavaks:

```bash
chmod +x create_pgrouting_graph.sh
```

3. Käivita:

```bash
./create_pgrouting_graph.sh
```

---

### 📌 Märkused

- `cost` ja `reverse_cost` on mõlemad määratud teelõigu pikkuse järgi. Soovi korral saab lisada ka kiiruspiiranguid või tee tüübi põhiseid kaalusid.
- `0.0001` on topoloogia tolerants kraadides (umbes 11 m). Seda saab vajadusel muuta.

---

Kas soovid, et lisaksin ka **liiklusklasside põhise kaaluarvutuse** (nt `motorway` = 1, `residential` = 5 jne)? Või soovid kohe edasi minna **gravitatsioonimudeli** arvutamisega?

Suurepärane! Lisame nüüd liiklusklasside põhised kaalud, et pgRouting arvestaks erinevate teetüüpide erinevat "kulu" (cost). See võimaldab näiteks eelistada kiirteid ja vältida väiksemaid tänavaid.

---

### 🛣️ **Liiklusklasside kaalud (näide)**

|`highway` tüüp|`cost` kordaja|
|---|---|
|motorway|1|
|trunk|1.2|
|primary|1.5|
|secondary|2|
|tertiary|2.5|
|residential|3|
|service|4|
|track|5|
|footway/path|10|

---

### 📝 **Täiendatud Bash-skript: `create_pgrouting_graph_weighted.sh`**

```bash
#!/usr/bin/env bash

# Ühenduse andmed
destination_host='localhost'
destination_port='5432'
destination_user='osm'
destination_password='osm'
destination_dbname='data'
destination_schema='aaa_osm'
table_name='osm_roads'

export PGPASSWORD=${destination_password}
CONNECTION_NAME="-h ${destination_host} -p ${destination_port} -d ${destination_dbname} -U ${destination_user}"

# Loome pgRoutingu jaoks sobiva teetabeli koos kaaludega
psql ${CONNECTION_NAME} <<EOF
DROP TABLE IF EXISTS ${destination_schema}.${table_name};

CREATE TABLE ${destination_schema}.${table_name} AS
SELECT
  osm_id,
  name,
  highway,
  way AS geom,
  ST_Length(way) *
    CASE
      WHEN highway = 'motorway' THEN 1
      WHEN highway = 'trunk' THEN 1.2
      WHEN highway = 'primary' THEN 1.5
      WHEN highway = 'secondary' THEN 2
      WHEN highway = 'tertiary' THEN 2.5
      WHEN highway = 'residential' THEN 3
      WHEN highway = 'service' THEN 4
      WHEN highway = 'track' THEN 5
      WHEN highway IN ('footway', 'path', 'cycleway') THEN 10
      ELSE 6
    END AS cost,
  ST_Length(way) *
    CASE
      WHEN highway = 'motorway' THEN 1
      WHEN highway = 'trunk' THEN 1.2
      WHEN highway = 'primary' THEN 1.5
      WHEN highway = 'secondary' THEN 2
      WHEN highway = 'tertiary' THEN 2.5
      WHEN highway = 'residential' THEN 3
      WHEN highway = 'service' THEN 4
      WHEN highway = 'track' THEN 5
      WHEN highway IN ('footway', 'path', 'cycleway') THEN 10
      ELSE 6
    END AS reverse_cost
FROM
  ${destination_schema}.osm_line
WHERE
  highway IS NOT NULL
  AND way IS NOT NULL;

-- Lisame pgRoutingu jaoks vajalikud veerud
ALTER TABLE ${destination_schema}.${table_name}
  ADD COLUMN id SERIAL PRIMARY KEY,
  ADD COLUMN source INTEGER,
  ADD COLUMN target INTEGER;

-- Loome ruumiindeksi
CREATE INDEX idx_${table_name}_geom ON ${destination_schema}.${table_name} USING GIST (geom);
EOF

# Käivitame pgRouting topoloogia loomise
psql ${CONNECTION_NAME} -c "SELECT pgr_createTopology('${destination_schema}.${table_name}', 0.0001, 'geom', 'id');"
```

---

### ✅ Kasutamine

1. Salvesta see failina `create_pgrouting_graph_weighted.sh`
2. Tee see käivitatavaks:

```bash
chmod +x create_pgrouting_graph_weighted.sh
```

3. Käivita:

```bash
./create_pgrouting_graph_weighted.sh
```

---

Kas soovid nüüd edasi liikuda **gravitatsioonimudeli arvutamise ja visualiseerimisega** väiksemate piirkondade jaoks?

Et kasutada **administratiivpiirkondi** hilisemas **gravitatsioonimudeli analüüsis** (nt teedevõrkude, liikuvus- või ligipääsetavusuuringutes), on vaja igale piirkonnale määrata **kaal** (attractiveness weight). Kaalud võivad põhineda näiteks:

---

### 📊 **1. Kaalude tüübid – mida kasutada**

Tüüpilised kaalud administratiivpiirkondade jaoks:

|Kaalutüüp|Allikas / meetod|
|---|---|
|**Elanike arv** (populatsioon)|Statistikaamet, ruudustik, OSM tagid|
|**Töökohtade arv**|Registreeritud töökohad või ettevõtted|
|**Teenuste hulk**|Koolid, haiglad, poed, OSM POI|
|**Pindala**|`ST_Area(geom)`|
|**Hõive/rahvastikutihedus**|Pop / Area|
|**Ligipääsetavus keskusesse**|Keskmine tee pikkus või aeg keskpunkti|
|**Majandusaktiivsus**|Kaubandus- ja teenindusasutuste loendus|

---

### ⚙️ **2. Kuidas lisada kaal PostGIS-andmebaasi**

Oletame, et sul on juba tabel `ardok_polygons`, millel on `relation_id`, `name`, `admin_level`, `geom`.

#### Näide: kaalu arvutamine elanike arvu põhjal

Kui sul on näiteks statistikaameti ruudustik või andmed eraldi tabelis (nt `population_grid`), millel on `geom` ja `population`, võid kasutada järgmist:

```sql
ALTER TABLE public.ardok_polygons ADD COLUMN weight_pop double precision;

UPDATE public.ardok_polygons p
SET weight_pop = sub.total_pop
FROM (
  SELECT
    a.relation_id,
    SUM(g.population) AS total_pop
  FROM public.ardok_polygons a
  JOIN public.population_grid g
    ON ST_Intersects(a.geom, g.geom)
  GROUP BY a.relation_id
) AS sub
WHERE p.relation_id = sub.relation_id;
```

---

### 🧠 Alternatiiv: kaal OSM andmetest

Kui sul pole statistikaandmeid, saad kasutada ka nt POI arvu OSM andmetes:

```sql
ALTER TABLE public.ardok_polygons ADD COLUMN weight_poi integer;

UPDATE public.ardok_polygons p
SET weight_poi = sub.poi_count
FROM (
  SELECT
    a.relation_id,
    COUNT(poi.*) AS poi_count
  FROM public.ardok_polygons a
  JOIN public.osm_pois poi
    ON ST_Intersects(a.geom, poi.geom)
  GROUP BY a.relation_id
) AS sub
WHERE p.relation_id = sub.relation_id;
```

---

### 🛰️ **3. Kaalude kasutamine gravitatsioonimudelis**

Gravitatsioonimudelites kasutatakse üldiselt kujul:

```
Interaction_ij = (Weight_i * Weight_j) / f(distance_ij)
```

kus `Weight` võib olla:

- `population`, `jobs`, `poi_count`, `GDP`, jne,
    
- ja `f(distance)` – näiteks `distance^2`, `exp(distance)`, vms.
    

Saad selleks luua `OD`-tabeli (origin-destination paarid), mis sisaldab kõigi piirkondade vahelisi kaugusi ning liita kaalud mõlema poole kohta.

---

### 🔧 4. Praktiline töövoog

**Soovituslik pipeline:**

1. **Lisa `weight_pop`, `weight_poi`, `area_km2`, `pop_density`** jms veerud tabelisse `ardok_polygons`.
    
2. **Loo OD-paaride tabel** (piirkondade omavahelised kaugused).
    
3. **Kasuta `psql`, QGIS, Python või R** gravitatsioonimudeli rakendamiseks.
    
4. **Analüüsi tulemusi** näiteks piirkondliku liikuvuse modelleerimiseks.
    

---

### 📌 Küsin üle:

- Kas Sul on **statistikaameti andmeid** (nt rahvastiku ruudustik)?
    
- Kas soovid **konkreetset SQL-skripti** gravitatsioonikaalude arvutamiseks ja salvestamiseks?
    
- Kas gravitatsioonimudel on sul **plaanitud PostgreSQL/PostGIS-s sees**, või toimub see **Pythonis/R-is**?
    

Kui vastad, saan anda veel täpsemad soovitused.

Tabeli `osm_pois` (Points of Interest) loomine sõltub sellest, kuidas sa OSM andmeid töötled – näiteks kas kasutad `osm2pgsql`, `imposm`, `osmium` või teed käsitööna SQL-ga. Kuna sul juba on `osm2pgsql` põhine töövoog (kasutades Lua skripti), siis soovitan luua POI-tabeli `osm2pgsql` kaudu.

---

## 🧭 1. **POI tabeli loomine osm2pgsql Lua skriptis**

Lisa oma olemasolevasse Lua-faili (nt `ardok_administrative.lua` kõrvale või samasse) järgmine definitsioon, et luua `osm_pois` tabel, kuhu salvestatakse OSM-i objektid, millel on huvipakkuvad tag’id (nt `amenity`, `shop`, `tourism`, `office`, jms).

### 📄 **osm_pois.lua** (või lisa olemasolevasse Lua-skripti):

```lua
local schema = os.getenv("PGSCHEMA") or "public"

local tables = {}

tables.pois = osm2pgsql.define_node_table(
  'osm_pois',
  {
    { column = 'name', type = 'text' },
    { column = 'type', type = 'text' },
    { column = 'tags', type = 'jsonb' },
    { column = 'geom', type = 'point', not_null = true }
  },
  {
    schema = schema,
    proj = 3301
  }
)

function osm2pgsql.process_node(object)
  local tags = object.tags
  local poi_type = tags.amenity or tags.shop or tags.tourism or tags.office or tags.leisure

  if not poi_type then
    return
  end

  tables.pois:insert({
    name = tags.name,
    type = poi_type,
    tags = tags,
    geom = object:as_point()
  })
end
```

---

## 🚀 2. **Käivita `osm2pgsql` koos selle Lua-skriptiga**

```bash
osm2pgsql --create \
  --database your_database \
  --output=flex \
  --style=osm_pois.lua \
  your.osm.pbf
```

Või kui kombineerid selle oma olemasoleva skriptiga (nt `ardok_administrative.lua`), võid need funktsioonid panna ühte faili, ja `osm2pgsql` loeb mõlemat korraga.

---

## 🛠️ 3. **Tabeli sisu (näide)**

|name|type|tags (jsonb)|geom|
|---|---|---|---|
|"Rimi"|"shop"|`{ "shop": "supermarket" }`|POINT(...)|
|"Kohvik"|"amenity"|`{ "amenity": "cafe" }`|POINT(...)|

---

## 📌 4. **Alternatiiv: luua käsitsi SQL-ga**

Kui sa **ei kasuta `osm2pgsql`** ja soovid lihtsalt PostGIS-is POI-tabelit testimiseks, võid selle luua käsitsi:

```sql
CREATE TABLE public.osm_pois (
  id serial PRIMARY KEY,
  name text,
  type text,
  tags jsonb,
  geom geometry(Point, 3301)
);
```

Ja siis lisada sinna andmeid käsitsi või mõne OSM-tööriistaga (`overpass`, `osmium`, jms).

---

## 🧠 Soovitused

- Kui töötled suurt piirkonda ja vajad ka POI-de värskendamist, kasuta kindlasti `osm2pgsql` koos `--append` või `--update` režiimiga.
    
- Kui soovid ainult teatud tüüpi POI-sid (nt `hospital`, `school`), lisa vastav filter `process_node` funktsiooni.
    

---

Soovi korral võin aidata ka:

- kombineeritud skriptiga, mis lisab POI-d olemasolevale relatsioonide töötlusele,
    
- päringutega, mis seovad `osm_pois` ja `ardok_polygons` (nt `ST_Intersects` abil kaalu arvutamiseks).