Přehled vybraných prostorových funkcí a operátorů¶
Operátory¶
Mezi nejpoužívanější operátory patří:
&&
- překryv minimálních ohraničujících obdélníků<#>
- vzdálenost minimálních ohraničujících obdélníků<->
- vzdálenost centroidů
Poznámka
Více informací v dokumentaci PostGIS.
Konstruktory¶
Kostruktory jsou funkce vytvářející v PostGISu nové geometrické objekty.
ST_GeomFromText geometrie z WKT.
ST_GeomFromGML, ST_GeomFromWKB, ST_Point, …
K vytvoření geometrie lze použít kromě funkcí PostGISu i přetypování z WKT:
SELECT
'SRID=5514; POLYGON((0 0,0 1,1 1,1 0,0 0))'::geometry(POLYGON, 5514);
Poznámka
Více informací v dokumentaci PostGIS.
Výstupy¶
Funkce umožňující převod geometrie do jiné reprezentace.
Rozměr geometrie¶
ST_Area plocha.
ST_Perimeter obvod.
ST_Length délka.
Další operace nad geometrií¶
ST_ExteriorRing obvodová hranice.
ST_Dump rozdělí multipart geometrii.
ST_Polygonize zaplochování.
ST_ConvexHull konvexní obal.
ST_Translate posun.
ST_Buffer obalová zóna.
ST_SetSRID nastaví SRID (ID souřadnicového systému)
…
Vzájemná poloha dvou geometrií¶
ST_Relate devítiprvková matice.
ST_Intersects existuje průnik (i jeden bod).
SELECT
ST_Intersects(
'POLYGON((0 0,0 1,1 1,1 0,0 0))'::geometry
, ST_Translate('POLYGON((0 0,0 1,1 1,1 0,0 0))'::geometry,1,1)
);
ST_Disjoint, ST_Overlaps, ST_Crosses, ST_Within, ST_DWithin, ST_Touches
Geometrické operace¶
ST_Intersection průnik.
ST_Difference rozdíl.
ST_SymDifference symetrický rozdíl.
Agregace¶
ST_Union sjednocení.
Praktické ukázky¶
Jak vypsat všechny tabulky s geometrií¶
Nejdříve si ukážeme, jak rychle zjistit, které tabulky v databázi obsahují prostorová data.
Tuto informaci získáme z pohledu geometry_columns. Ten zobrazuje data ze systémových tabulek (data o typech a omezeních) a přehledně je zobrazuje.
Poznámka
Ve verzích PostGIS 1.x byl geometry_columns definován jako tabulka a nikoliv jako pohled.
Jeho struktura je následující:
Sloupec |
Typ |
Uložení |
---|---|---|
f_table_catalog |
character varying(256) |
extended |
f_table_schema |
character varying(256) |
extended |
f_table_name |
character varying(256) |
extended |
f_geometry_column |
character varying(256) |
extended |
coord_dimension |
integer |
plain |
srid |
integer |
plain |
type |
character varying(30) |
extended |
Poznámka pro pokročilé
PostGIS definuje pohled geometry_columns následovně:
SELECT current_database()::character varying(256) AS f_table_catalog,
n.nspname::character varying(256) AS f_table_schema,
c.relname::character varying(256) AS f_table_name,
a.attname::character varying(256) AS f_geometry_column,
COALESCE(NULLIF(postgis_typmod_dims(a.atttypmod), 2)
, postgis_constraint_dims(n.nspname::text, c.relname::text, a.attname::text)
, 2) AS coord_dimension,
COALESCE(NULLIF(postgis_typmod_srid(a.atttypmod), 0)
, postgis_constraint_srid(n.nspname::text, c.relname::text, a.attname::text)
, 0) AS srid,
replace(replace(COALESCE(NULLIF(upper(postgis_typmod_type(a.atttypmod)),
'GEOMETRY'::text)
, postgis_constraint_type(n.nspname::text, c.relname::text,
a.attname::text)::text
, 'GEOMETRY'::text), 'ZM'::text, ''::text), 'Z'::text,
''::text)::character varying(30) AS type
FROM pg_class c,
pg_attribute a,
pg_type t,
pg_namespace n
WHERE t.typname = 'geometry'::name
AND a.attisdropped = false AND a.atttypid = t.oid AND
a.attrelid = c.oid AND c.relnamespace = n.oid
AND (c.relkind = 'r'::"char" OR c.relkind = 'v'::"char" OR
c.relkind = 'm'::"char" OR c.relkind = 'f'::"char")
AND NOT pg_is_other_temp_schema(c.relnamespace)
AND NOT (n.nspname = 'public'::name AND c.relname = 'raster_columns'::name)
AND has_table_privilege(c.oid, 'SELECT'::text);
Provedeme jednoduchý dotaz do tohoto pohledu.
SELECT
*
FROM geometry_columns
WHERE f_table_schema = 'dibavod';
Vybíráme tedy všechny záznamy vztažené k tabulkám ze schématu dibavod.
Výsledek může vypadat například takto:
f_table_catalog | gismentors
f_table_schema | dibavod
f_table_name | povodi_iii
f_geometry_column | geom
coord_dimension | 2
srid | 5514
type | MULTIPOLYGON
...
Jednoduchý atributový dotaz¶
Vyberte parcely ze schématu ruian_praha:
s kódem ochrany 26 (pozemek určený k plnění funkcí lesa)
s druhem pozemku 10 (les)
Poznámka
Nezapomeneme zkontrolovat, zda je sloupec, který dotazujeme, oindexován.
SELECT * FROM ruian_praha.parcely WHERE druhpozemkukod = 10;
SELECT * FROM ruian_praha.parcely WHERE druhpozemkukod = 26;
Vyberte stavební objekty ze schématu ruian_praha vybavené
plynem
výtahem a obarvěte je podle počtu podlaží
SELECT * FROM ruian_praha.stavebniobjekty
WHERE pripojeniplynkod IS NOT NULL;
SELECT * FROM ruian_praha.stavebniobjekty
WHERE vybavenivytahemkod IS NOT NULL;
Jednoduchý prostorový dotaz¶
Vypiště název obce a její rozlohu v hektarech
SELECT
nazev
, ST_Area(geom)/1e4 AS rozloha
FROM ruian.obce
ORDER BY nazev;
Zobrazte obce větší než 130 ha
SELECT
*
FROM ruian.obce
WHERE ST_Area(geom)/1e4 > 130;
Nasymbolizujte vrstvu ruian.obce podle poměru rozlohy a čtvrtiny obvodu na druhou.
SELECT ogc_fid
, nazev
, geom
, ST_Area(geom) / power( ST_Perimeter(geom)/4, 2) AS pomer
FROM ruian.obce;
Atributový JOIN¶
Obarvěte obce (ruian.obce)
podle počtu obyvatel (csu_sldb.sldb)
počtu obyvatel na kilometr čtvereční
SELECT
ogc_fid, o.nazev, geom, vse1111/(ST_Area(geom)/1e6) pocet_obyv_na_km
FROM ruian.obce o
JOIN csu_sldb.sldb s ON
s.uzcis = '43' --obce
AND s.uzkod = o.kod
order by vse1111/(ST_Area(geom)/1e6)
Obarvěte ORP (ruian.orp)
podle zastoupení jasanu (slhp.slhp)
SELECT o.ogc_fid
, o.nazev
, o.geom
, s.plocha_proc
FROM ruian.orp o
JOIN slhp.slhp s
ON s.orp_kod = o.kod
WHERE drevina = 'jasan'
Prostorový JOIN¶
Vyberte obce, na jejichž území je požární stanice.
SELECT o.nazev
FROM ruian.obce o
JOIN osm.pozarni_stanice p ON ST_Within(p.geom, o.geom)
GROUP BY o.kod, o.nazev;
Najděte obce, na jejichž území leží více než jedna požární stanice.
SELECT o.nazev, count(*)
FROM ruian.obce o
JOIN osm.pozarni_stanice p ON ST_Within(p.geom, o.geom)
GROUP BY o.kod, o.nazev
HAVING count(*) > 1
ORDER BY count(*) DESC;
Na území které obce leží nejvíce požárních stanic?
SELECT o.nazev, count(*)
FROM ruian.obce o
JOIN osm.pozarni_stanice p ON ST_Within(p.geom, o.geom)
GROUP BY o.kod, o.nazev
ORDER BY count(*) DESC
LIMIT 1;
Vyberte parcely v Praze, které leží na MZCHU.
BEGIN;
CREATE TABLE jelen.parcely_mzchu AS
SELECT * FROM ruian_praha.parcely p
WHERE EXISTS (
SELECT * FROM aopk.maloplosna_chranena_uzemi m
WHERE ST_Intersects(p.geom, m.geom)
);
ALTER TABLE jelen.parcely_mzchu ADD PRIMARY KEY (ogc_fid);
CREATE INDEX ON jelen.parcely_mzchu USING GIST(geom);
COMMIT;
Které z nich nemají správně kód způsobu ochrany?
Najděte v Praze budovy ohrožené stoletou vodou.
Buffer¶
Vytvořte obalovou zónu s tloušťkou klesající s řádem kolem vodních toků (dibavod.vodni_toky)
--vybere povodi Jizery pomoci rekurze
CREATE TABLE jizera.povodi_jizery AS
WITH RECURSIVE povodi_jizery AS (
SELECT
* , 1 rad
FROM dibavod.vodni_toky
WHERE tok_id = 110740000100
UNION ALL
SELECT
v.*, j.rad + 1
FROM dibavod.vodni_toky v
JOIN povodi_jizery j
ON j.tok_id = v.tokrec_id
)
SELECT row_number() over() rid, * FROM povodi_jizery;
Poznámka pro pokročilé
BEGIN;
CREATE TABLE jelen.jize (ogc_fid serial primary key,
geom geometry(LINESTRING, 5514));
INSERT INTO jelen.jize (geom)
SELECT (ST_Dump(geom)).geom FROM
(
SELECT ST_Union(geom) geom FROM jizera.povodi_jizery
) uni
;
CREATE INDEX ON jize USING gist(geom);
ALTER TABLE jize ADD rad smallint, ADD parent int;
UPDATE jize
SET parent = 0, rad = 1 WHERE ogc_fid = 2040;
DO $$
DECLARE i int;
BEGIN
WHILE (SELECT count(*) FROM jize WHERE rad IS NULL) > 0
LOOP
UPDATE jize j
SET rad = r.rad+1, parent = r.ogc_fid
FROM jize r
WHERE r.rad IS NOT NULL
AND j.rad IS NULL
AND ST_Touches(j.geom, r.geom)
;
RAISE NOTICE '%', count(*) FROM jize WHERE rad IS NULL;
END LOOP;
END
$$;
COMMIT;
SELECT
rid
, ST_Buffer(geom, 90-(rad * 10)) geom
FROM jizera.povodi_jizery;
Agregace¶
Vytvořte mapu POU (pověřené obce) z vrstvy obcí.
SELECT
ST_Union(geom) geom
, poukod
FROM ruian.obce
GROUP BY poukod;
Prostorové analýzy¶
Obarvěte katastrální území podle toho, kolik procent území je v NP
SELECT
katuze.*
, COALESCE (
(ST_Area(ST_Intersection(katuze.geom, vzchu.geom))/
ST_Area(katuze.geom)) * 100
, 0) v_np
FROM
ruian.katastralniuzemi katuze
LEFT JOIN
(
SELECT
k.ogc_fid
, ST_Union(vzchu.geom) geom
FROM
ruian.katastralniuzemi k
JOIN aopk.velkoplosna_chranena_uzemi vzchu
ON vzchu.geom && k.geom
AND vzchu.kat = 'NP'
GROUP BY k.ogc_fid
) vzchu
USING(ogc_fid)