PostGIS

A HupWiki-ből...

A PostGIS egy kiegészítő csomag a PostgreSQL-hez. A program alapvetően az OGC SQL alapú adatbáziskezelők térinformatikai funkciói számára kidolgozott ajánlásának (Simple Features SQL) megfelelően működik, tehát egy szabványos eszközről van szó. (A MySQL 4.1-es verziójában megjelenő térinformatikai funkciók ugyanezt a szabványt alkalmazzák.)

Tartalomjegyzék

A legfontosabb dolgok, amiket a PostGIS tud:

  • térképi adatok tárolása 'geometry' típusú mezőkben
  • egy sor függvény és operátor ezen mezők kezelésére (terület/kerület/hossz számítás, halmazműveletek, övezet generálás, topológiai vizsgálatok, generalizálás, stb.)
  • vetületek kezelése a PROJ4 program segítségével
  • GIST típusú térbeli index alkalmazása, hogy nagyobb méretű állományok esetében is hatékonyan lehessen térképi adatok alapján keresni vagy egyéb lekérdezéseket végezni.
  • Az 1.1.0 verziótól kezdődően megjelent a topológiai modell (kezdetleges) támogatása

A PostGIS-es kiegészítéssel rendelkező PostgreSQL adatbázisokat kezelni tudjuk például a QGIS térinformatikai programmal, vagy az UMN Mapserver segítségével internetes térképek hátterét is szolgáltathatják. Jól használható eszköz olyan térinformatikai rendszerekben, ahol több felhasználónak kell egyszerre hozzáférni az adatokhoz, akár módosítás szándékával is.

A PostGIS telepítése

Régebbi verzióknál a letöltött programot a PostgreSQL contrib könyvtára alá kellett kicsomagolni. Belépve az így létrejövő könyvtárba ki kellett adnunk a make parancsot a program lefordításához, majd rootként egy make installt a telelpítéshez. A fordítást megelőzően a Makefile.config állomány szerkesztésével tudtuk a programot konfigurálni.

Az 1.0.0-rc3 verziótól kezdődően a konfigurálást a máshonnan már jól ismert ./configure szkript megfelelő paraméterekkel való futtatásával végezhetjük el.

A beállítási lehetőségek közül a legfontosabb a GEOS és a PROJ programok használatának bekapcsolása és beállítása. Ezek alapban ki vannak kapcsolva, ezért ha olyan függvényeket akarunk használni (pl. a transform()-ot vetületi átszámításokra), melyekhez szükséges a fenti könyvtárak valamelyike, ne feledkezzünk meg erről a lépésről, amit a configure szkript --with-geos és a --with-proj kapcsolóival tudunk megtenni.

Az 1.1.0 verziótól teljesen átálltak az autoconf alapú konfigurációra. Szintén ettől (1.1.0) a verziótól kezdődően a program elérhető deb és rpm csomag formájában is. Azóta a PostGIS már a legtöbb nagyobb disztribúció részeként is elérhető, így telepítése és frissítése egyszerűen megoldható akár fordítás nélkül is.

A PostGIS hozzáadása egy adatbázishoz

Nem elég a PostGIS-t a fenti részben leírt módon telepíteni a gépünkre. A kiegészítő csomagot alkotó típusokat, függvényeket és operátorokat hozzá kell adni minden olyan adatbázishoz, ahol használni szeretnénk őket.

A PostGIS függvényeinek egy része C-ben, másik része plpgsql-ben íródott. Ennek következtében, ha eddig más okból kifolyólag nem tettük még meg, létre kell hozni a plpgsql nyelvet a kérdéses adatbázisban a createlang plpgsql adatbázis_neve shell paranccsal, vagy az SQL CREATE LANGUAGE parancsával.

Ezt követően futtathatjuk az adatbáziskezelővel az lwpostgis.sql állományban lévő utasításokat, melynek hatására létrejönnek a szükséges objektumok. Az lwpostgis.sql-t a $PREFIX/share könyvtárban találhatjuk meg. ($PREFIX a PostgreSQL telepítési könyvtára, pl. /usr/local vagy /usr/local/pgsql800)

Térképi elemet tartalmazó táblák létrehozása

A térképi elemeket tartalmazó oszlopot nem a CREATE TABLE paracs oszloplistájában kell hozzáadni a táblához, hanem az AddGeometryColumn függvény segítségével. Ez azért fontos, mert így létrejönnek a szükséges bejegyzések a geometry_columns táblában, ami egyes PostGIS funkciók és kliensprogramok helyes működése szempontjából fontos. Ha törölni szeretnénk a táblából egy térképi elemet, akkor ezt (az előbbihez hasonló megfontolásból) a DropGeometryColumn függvénnyel tegyük.

Egy térképi adatokat tartalmazó tábla létrehozása tehát a következőképpen néz ki:

 CREATE TABLE vezetekek (ID int4, anyag_kod char(5), atmero_mm int4);
 SELECT AddGeomertyColumn('vezetekek','geom',-1,'LINESTRING',2);

Az első paranccsal létrehoztuk a 'vezetekek' nevű táblát az attribútumadatok oszlopaival. A második sorban lévő SELECT parancs az AddGeometry függvény meghívásával hozzáad a 'vezetekek' táblához egy 'geom' nevezetű oszlopot, ahova majd a térképi elemek kerülhetnek. A térképi elemek leírásához használt koordinátarendszerhez nem tartozik vetületi leírás, amire a harmadik paraméterben található -1 érték utal. A térképi elemek típusa 'LINESTRING', vagyis vonallánc lesz. Az utolsó paraméterben lévő 2 a dimenziószámot jelenti. Ha 3 lenne itt, akkor az egyes alakjelző pontok helyzetét három koordinátával kellene megadnunk, vagyis tárolnánk a magasságukat is. A példában viszont csak kétdimenziós, síkbeli koordinátákat használunk az objektumok geometriájának meghatározásakor.

Térbeli (több dimenziós) indexek

Térbeli indexet hozhatunk létre egy tábla térképi elemeket tartalmazó oszlopához, meggyorsítva ezzel a lekérdezéseket olyan esetekben, amikor például az adatbázisból azokat az elemeket szeretnénk lekérdezni, melyek egy megadott területre esnek. Ezek a lekérdezések rendkívül gyakoriak, hiszen ilyen feladattal állunk szemben valahányszor ki akarjuk rajzolni egy ablakban egy terület térképének egy részletét. Térbeli index nélkül egy ilyen lekérdezéshez át kellene nézni a tábla valamennyi rekordját, mindet végigvizsgálva, hogy vajon tényleg a kérdéses területre esik-e az objektum. Ez nem valami hatékony megoldás, különösen nagyméretű táblák esetében.

A térbeli index segítségével a program egy előszűrést tud végezni, amivel gyorsan kiszórhatja azokat az elemeket, melyek a vizsgált területnek még a közelében sincsenek. A többdimenziós indexelésre többféle módszert fejlesztettek ki. A PostGIS ezek közül a GiST (Generalized Search Tree) algoritmust használja.

A PostgreSQL GIST indexek kezeléséért felelős kódját a 8.1-es sorozattól kezdődően a PostGIST fejlesztő Refraction Research támogatásával teljesen újraírták. Ennek köszönhetően egy sokkal hatékonyabban működő kódot kaptak, ami a régebbivel ellentétben már támogatja a soronkénti zárolást a GIST-el indexelt oszlopot tartalmazó táblákban.

Egy tábla indexelése térbeli adatok alapján a hagyományos indexek létrehozásához hasonlóan történik. A korábbi példát folytatva a következő parancsot kell kiadnunk:

 CREATE INDEX vez_geom_idx ON vezetekek USING GIST ( geom );

A nagyobb hatékonyság érdekében ajánlott a VACUUM ANALYZE parancs alkalmazása, valamint a PostgreSQL régebbi verzióinak (<8.0.0) esetében az UPDATE_GEOMETRY_STATS() függvény meghívása

Térképi adatok kezelése

Sorok beszúrása

Ha már lefordítottuk a PostGIS-t, hozzáadtuk egy adatbázishoz, ahol utána létrehoztunk térképi adatokat tartalmazó táblákat és utána még indexeltük is térképi adatok alapján, valószínűleg szeretnénk valahogyan feltölteni a táblákat adatokkal. Ezt az SQL INSERT INTO parancsával tehetjük meg. Ez eddig egyerű dolog volna, de hogyan adhatjuk meg a térképi elemeket? A PostGIS-ben erre többféle függvény alkalmazható, ezek egyike a GeomFromText(), melyet a következőképpen használhatunk:

 INSERT INTO vezetekek (ID, anyag_kod, atmero_mm, geom) VALUES
 (1, 'PVC', 150, GeomFromText('LINESTRING(102.15 541.32,110.08 597.29,130.07 610.88,135.45 620.32)', -1));

Mint az a példából is látszódik, a GeomFromText függvénynek két paramétere van. Az első szöveges adatként tartalmazza a geometria leírását WKT formátumban, a második pedig a koordináták vetületi rendszerének kódját adja meg.

Ha csak pontokat akarunk megadni, akkor alkalmazhatjuk az egyszerűbb MakePoint() függvényt is:

 INSERT INTO meghibasodas (ID, leiras, hely) VALUES
 (1, 'dugulás', MakePoint(140.25,530.64));

A térképi elemet tartalmazó oszlop itt most a 'hely' nevet viseli. A MakePoint() függvény két paramétere a két koordináta. A függvényt három paraméterrel meghívva lehetőségünk van a pont magasságának megadására is.

Lekérdezések

Ha fel vannak töltve a tábláink, lehetőségünk nyílik sokféle lekérdezésre. Néhány példa:

 SELECT Length(geom) FROM vezetekek WHERE ID=112;

A fenti módon kaphatjuk meg a 112-es azonosítójú vezeték hosszát.

 SELECT anyag_kod, atmero_mm, SUM(Length(geom)) FROM vezetekek
 GROUP BY anyag_kod, atmero_mm
 ORDER BY 1,2;

Ez a lekérdezés rendezve tartalmazza, hogy a különféle anyagú és átmérőjű vezetékekből hány méternyi van összesen a vizsgált hálózatban.

 SELECT telek.hrsz, COUNT(*), 100*area(telek.geom)/SUM(area(epulet.geom))
 FROM telek,epulet
 WHERE contains(telek.geom,epulet.geom)
 GROUP BY telek.hrsz, telek.geom
 ORDER BY 1;

Egy listában helyrajzi szám szerint rendezve megkapjuk, hogy az egyes telkeken hány épület áll, és hogy a telek hány százaléka van beépítve. A lekérdezés a contains() függvény miatt csak a GEOS támogatással lefordított PostGIS-ben használható.

A PostGIS-ben használható függvényekről és operátorokról bővebben a program dokumentációjában olvashatsz!

Vetületi rendszerek kezelése

A PostGIS a térképi elemek leírása mellett egy kódot is tárol, ami a vetületi rendszerre vonatkozik. Ez egy szám, aminek az értéke -1, ha a koordinátarendszer nem kapcsolódik semmilyen vetülethez (helyi rendszer), egyébként pedig a vetületi rendszernek a SPATIAL_REF_SYS táblában használt azonosítóját tartalmazza. Ezt a táblát a spatial_ref_sys.sql állományt futtatva tölthetjük fel adatokkal.

Ha a PostGIS-t PROJ támogatással fordítottuk, akkor vetületi átszámításokra is lehetőségünk nyílik a Transform() függvény segítségével. Erre egy egyszerű példa a következő:

 SELECT AsText(Transform(GeomFromText('POINT(600000 200000)',23700),32634));

Az eredmény pedig:

 POINT(302061.052648971 5224305.42083902)

A fenti példában egy EOV koordinátát számoltunk át UTM-be a PostGIS segítségével. A Transform() függvény első paramétere az átszámítandó térképi elem (a fenti példában a GeomFromText függvény eredménye), ami tartalmazza a vetületi rendszer a kódját is. A második paraméter annak a vetületi rendszernek a kódja, amibe át szeretnénk az adatokat számolni.

Adatok betöltése/kiírása (külső állományokkal)

A PostGIS csomaghoz tartozik egy shp2pgsql nevű program, aminek a segítségével az ArcView .shp állományait tudjuk átalakítani .sql állománnyá. Ezek az .sql állományok tartalmazzák a forrás állománynak megfelelő PostGIS/PostgreSQL tábla létrehozásához és feltöltéséhez szükséges SQL parancsokat, tehát csak futtatnunk kell őket a megfelelő adatbázisból.

Az shp2pgsql program használata a következőképpen néz ki:

 shp2pgsql [kapcsolók] shapefile [séma.]tábla

A fontosabb kapcsolók a következők:

  • -s <srid> Az alkalmazott vonatkozási (vetületi) rendszer kódja
  • -g <oszlopnév> A térképi adatokat tartalmazó oszlop neve
  • -I GiST index létrehozása

Az program kimenete azok az SQL utasítások, amelyek létrehoznak, majd adatokkal töltenek fel egy a shapefájlnak megfelelő táblát az adatbázisban. Célszerű ezért a kimenetet vagy egy fájlba átirányítani a későbbi felhasználás végett, vagy csővezetékkel átadni a psql parancsnak.

Létezik egy pgsql2shp nevű program is, amellyel a fordított irányú adatkonverziót végezhetjük. Egy PostGIS/PostgreSQL adatbázishoz kapcsolódva egy megadott tábla tartalmát tudjuk kiírni egy shape fájlba. Ezt a következőképpen tudjuk használni:

 pgsql2shp [kapcsolók] adatbázis [séma.]tábla

az adatbázishoz való kapcsolódást meghatározó kapcsolók:

  • -h <hoszt> A hely, ahol az adatbázis-szerver fut (IP cím vagy URL)
  • -p <port> A port, amin az adatbázis szerver fut (alapértelmezett a 5432)
  • -u <felhasználó> A felhasználó, akinek a nevében az adatbázis-szerverhez kapcsolódunk
  • -P <jelszó> A fenti felhasználó jelszava

egyéb kapcsolók:

  • -g <geom_oszlop> A táblának az az oszlopa, amelyben az objektum geometriáját leíró mezők találhatóak
  • -f <fájlnév> A létrehozandó .shp állomány neve

A parancssoros megoldáson túl léteznek különféle külsős programok az adatcsere grafikus felületen keresztül történő levezénylésére is. Az 1.4-es verziótól kezdődően maga a PostGIS is tartalmat egy GTK alapú shp2pgsql-gui programot, ami mint a nevéből is következik, .shp állományok tartalmának grafikus felületen keresztül történő beltöltését teszi lehetővé.

Raszter adatok kezelése

Jelenleg a PostGIS stabil kiadása nem tartalmaz semmiféle eszközt raszter adatok tárolására. Készülőben van azonban WKTRaster nevű kiegészítés, ami alkalmassá teszi majd erre.

Külső hivatkozások