Dane przestrzenne w PHP
-
Upload
michal-mackiewicz -
Category
Technology
-
view
2.035 -
download
2
Transcript of Dane przestrzenne w PHP
SystemyInformacji Przestrzennej
Dane przestrzenne
czyli
Jak nauczyć PHP geografii?
Michał Mackiewicz
Szczyrk, 25- 27.10.2013
www.gis-support.pl
SystemyInformacji Przestrzennej
fot. monokini / sxc.hu
SystemyInformacji Przestrzennej Tymczasem w internetach
SystemyInformacji Przestrzennej
Podnosimy poprzeczkę
SystemyInformacji Przestrzennej
Podnosimy poprzeczkę
„Znajdź wszystkie czynne sklepy monopolowe czynne w piątek po godzinie 19 nie dalej niż 5 km od hotelu Orle Gniazdo w Szczyrku”
SystemyInformacji Przestrzennej Grzechy główne
SpatialIsNotSpecial
SystemyInformacji Przestrzennej Ale co konkretnie jest „specjalne”?
●Typy danych●Relacje przestrzenne●Układy współrzędnych●Formaty przechowywania●Formaty wymiany
SystemyInformacji Przestrzennej Typy danych
Punkt (POINT)
Linia (LINESTRING)
Poligon (POLYGON)
Fot.gimnick /sxc/hu
Fot. linder6580 / sxc.hu
Fot. ColinBroug / sxc.hu
SystemyInformacji Przestrzennej Geometrie złożone
Poligon złożony (MULTIPOLYGON)
Linia złożona (MULTILINESTRING)
Rys. rybnik.eu
Rys. rzyjontko / Wikimedia Commons
SystemyInformacji Przestrzennej Geometrie non-simple albo invalid
Poligon z bagnetem
Samoprzecinająca się linia
SystemyInformacji Przestrzennej Relacje przestrzenne
rys. Krauss/Wikimedia Commons, CC-BY-SA
SystemyInformacji Przestrzennej Układy współrzędnych
● Współrzędne mogą być geograficzne albo płaskie● Istnieje bardzo wiele układów współrzędnych● Układy identyfikowane są przez kod EPSG, tzw. SRID● Układy można przeliczać (transformować) z użyciem
odpowiednich bibliotek
SystemyInformacji Przestrzennej Współrzędne geograficzne
South Pole
North Pole
Equator
Prime Meridian0
30
60-60
-30
90-90
0
30
-60
6090
-90
-30
180
-120
-150 150
120
o
o
oo
o
o
o
● Współrzędne sferyczne, jednostki - stopnie● Zakres od -90 do 90 (szerokość), -180 do 180 (długość)● Jednolite dla całego świata● Bardziej złożone obliczeniowo – uwzględnienie krzywizny Ziemi
SystemyInformacji Przestrzennej Współrzędne płaskie
● Współrzędne kartezjańskie, jednostki – metry / stopy● Liczby 6-9 cyfrowe, najczęściej wyłącznie dodatnie● (bardzo) wiele lokalnych układów● Proste obliczenia – bez uwzględnienia krzywizny
SystemyInformacji Przestrzennej Układ współrzędnych Google
● Współrzędne rysunku mapy w odwzorowaniu Merkatora● Ogromne zniekształcenia długości i powierzchni● Nadają się do renderowania map, ale nie do obliczeń
EPSG:900913EPSG:3785EPSG:3875
SystemyInformacji Przestrzennej PHP a dane przestrzenne
ZŁA WIADOMOŚĆ
Większość bibliotek przeznaczonych do pracy z danymi przestrzennymi ma bardzo słabe wsparcie dla PHP
DOBRA WIADOMOŚĆ
Większość potrzebnych operacji na danych przestrzennych można wykonać po stronie bazy danych
SystemyInformacji Przestrzennej Bazy danych dla geoinformacji
SQL
PostgreSQL + PostGISMS SQL Server (natywnie)SQLite + SpatiaLiteOracle (natywnie ograniczony zestaw funkcji, +Spatial)MySQL(natywnie)
NoSQL
MongoDB (2.4+ natywnie)CouchDB + GeoCouch
SystemyInformacji Przestrzennej Bazy danych dla geoinformacji
Typy przestrzenne
Funkcje przestrzenne
Indeksy przestrzenne
Specjalne typy kolumn dedykowane przechowywaniu geometrii
Specjalne funkcje np. do obliczania długości, powierzchni, wyszukiwania wg kryteriów przestrzennych, testowania relacji przestrzennych
Ułatwiają wyszukiwanie wg kryteriów przestrzennych
SystemyInformacji Przestrzennej Typy przestrzenne
Typ GEOMETRY
Typ GEOGRAPHY
Umożliwia przechowywanie geometrii w dowolnym układzie współrzędnych.Dane do obliczeń (np. maksymalna odległość) muszą być zadane w tych samych jednostkach, co układ współrzędnych.Dostępny w każdej bazie oferującej rozszerzenia przestrzenne
Umożliwia przechowywanie geometrii tylko w układzie współrzędnych geograficznych.Dane do obliczeń (np. maksymalna odległość) są zadawane w metrach.Dostępny w PostgreSQL + PostGIS, MS SQL Server
Wada: wolniejsze działanie, ograniczona liczba funkcji przestrzennych
SystemyInformacji Przestrzennej Funkcje przestrzenne
Przykłady:
Służą do operacji na typach GEOMETRY i GEOGRAPHYPodstawą jest specyfikacja OpenGIS SQL/MMNazwy funkcji są częściowo zunifikowane między różnymi DBMS i mają przedrostek ST_
● Funkcje pomiarów – ST_Length (zwraca długość), ST_Area (zwraca powierzchnię), ST_Extent (zwraca zasięg), ST_Distance (zwraca odległość między 2 geometriami)
● Funkcje testujące relacje przestrzenne – ST_Equals (czy geometrie są identyczne?), ST_Intersects (czy geometrie się przecinają?), ST_Disjoint (czy geometrie nie mają punktów wspólnych?)
● Funkcje tworzące nowe geometrie – ST_Buffer (strefa buforowa o zadanym promieniu), ST_Intersection (część wspólna z przecięcia 2 geometrii)
● Funkcje eksportu – ST_AsText (zwraca geometrię w postaci tekstowej), ST_AsKML (zwraca geometrię w formie zgodnej z Google Earth)
● Funkcje importu – ST_GeomFromText (tworzy geometrię na podstawie tekstu w formacie WKT), ST_MakePoint (tworzy geometrię punktu na podstawie pary współrzędnych x i y)
SystemyInformacji Przestrzennej Indeksy przestrzenne
PostGIS:
CREATE INDEX tabela1_gist ON tabela1(geom) USING gist;
SpatiaLite:
SELECT CreateSpatialIndex('tabela1','geom');
Służą do przyspieszenia wyszukiwania według kryteriów przestrzennych, np. w promieniu od zadanego punktu
SystemyInformacji Przestrzennej Forma zapisu w bazie
ATRYBUTY GEOMETRIA
Dane opisoweDowolne typy dopuszczone przez DBMS
Kształt obiektuTyp GEOMETRY/GEOGRAPHYDane binarne
Dodatkowe ograniczenia dot. typu geometrii i układu współrzędnychNieobowiązkowe w aplikacjach WEB, przydatne dla DesktopGIS
SystemyInformacji Przestrzennej Format wymiany: GeoJSON
● Prosty w użyciu i implementacji● Zgodny z bibliotekami WebGIS
(OpenLayers,Leaflet, Geo5)● Zgodny z aplikacjami DesktopGIS (np. QGIS)
i biblioteką GDAL/OGR● Opublikowany na GitHub automagicznie
zmienia się w mapę
SystemyInformacji Przestrzennej GeoJSON - struktura
{'type' : 'FeatureCollection','features' : [
{'type' : Feature,'properties' : {
'atrybut1' : 'wartość1','atrybut2' : 2,'atrybut3' : false},'geometry': {
'type' : 'Point', //LineString, Polygon, MultiPolygon etc.'coordinates' : []
}},// etc, etc...
]}
SystemyInformacji Przestrzennej GeoJSON – budowa w PHP
Haczyk:
Geometria musi być zapisana oddzielnie od atrybutów
Problemy z nim związane:
Trzeba znać nazwę kolumny z geometrią
Trzeba przekształcić geometrię z bazy na format zgodny z specyfikacją GeoJSON
SystemyInformacji Przestrzennej Rozpoznanie kolumny z geometrią
Rozwiązanie 1. Zawsze trzymać się konwencji
Kolumnę geometrii zwykło się nazywać „geom” albo „the_geom” (stara konwencja)
Rozwiązanie 2. Uczynić nazwę kolumny geometrii definiowalną
Podanie nazwy kolumny geometrii jako jednego z parametrów zapytania do serwera i odczytanie z $_GET / $_POST
Rozwiązanie 3. Skorzystać z systemowej tabeli/widoku geometry_columns
Wymaga dodatkowego zapytania do bazy. Nie należy korzystać z information_schema ponieważ rozpoznaje geometrię jako typ USER_DEFINED – możliwa kolizja
SystemyInformacji Przestrzennej
Przetworzenie geometrii z bazy na GeoJSON
Rozwiązanie 1. Skorzystanie z funkcji ST_AsGeoJSON (tylko PostGIS)
Rozwiązanie 2. Konwersja po stronie PHP
● Eksport funkcją ST_AsText (dostępna w PostGIS, MySQL, SQL Server, SpatiaLite) i własna funkcja parsowania
● Eksport funkcją ST_AsBinary (PostGIS, MySQL, SQL Server, SpatiaLite) i konwersja biblioteką geoPHP
● Użycie geoPHP bez funkcji eksportu (tylko PostGIS)
SystemyInformacji Przestrzennej
Co zrobić z wynikiem ST_AsGeoJSON?
Rozwiązanie 1.
Rozwiązanie 2.
SystemyInformacji Przestrzennej geoPHP
●Biblioteka na podwójnej licencji (Modified BSD albo GPL)●Nie ma dodatkowych zależności●Może wykorzystać moduł GEOS – wówczas dysponuje rozszerzonym zestawem funkcji●Możliwa integracja z Drupalem●Umożliwia:
● Odczyt i zapis geometrii w formatach tekstowych i WKB/EWKB (wewnętrzny PostGIS)
● Obliczanie długości i powierzchni● Obliczanie centroidu i zasięgu (bounding box)● Sprawdzenie układu współrzędnych● Rozbijanie geometrii złożonych na proste● Rozbijanie geometrii poligonowych i liniowych na punkty
http://github.com/phayes/geoPHP
SystemyInformacji Przestrzennej GeoPHP – użycie z PostGIS
$sql = 'SELECT * FROM poi LIMIT 1';$row = $pdo->query($sql)->fetch();
//geometria pobrana bezpośrednio z bazy jest zakodowana w postaci HEX
$wkb = hex2bin($row['geom']);
$geophpGeom = geoPHP::load($wkb,'ewkb');$exporter = new GeoJSON();$geojsonArray = $exporter->getArray($geophpGeom);
Założenia:Instancja PDO o nazwie $pdo, tryb pobierania danych FETCH_ASSOCKolumna geometrii o nazwie geom
SystemyInformacji Przestrzennej
GeoPHP – użycie z funkcją ST_AsBinary()
$sql = 'SELECT nazwa,adres,ST_AsBinary(geom) AS geom FROM poi LIMIT 1';$row = $pdo->query($sql)->fetch();
//geometria pobrana bezpośrednio z bazy jest zakodowana w postaci HEX
$wkb = hex2bin($row['geom']);
$geophpGeom = geoPHP::load($wkb,'wkb');$exporter = new GeoJSON();$geojsonArray = $exporter->getArray($geophpGeom);
Założenia:Instancja PDO o nazwie $pdo, tryb pobierania danych FETCH_ASSOCKolumna geometrii o nazwie geom
SystemyInformacji Przestrzennej Kompletny skrypt (prawie DBMS-agnostic)
require_once('geoPHP/geoPHP.inc');$pdo = new PDO('pgsql:host=localhost;port=5432;dbname=gis;user=geo;password=***');$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$sql = 'SELECT nazwa,adres,ST_AsBinary(geom) AS geom FROM poi';$rs = $pdo->query($sql)->fetchAll();
$geojson = ['type'=>'FeatureCollection','features'=>[]];
foreach($rs as $row) {$wkb = hex2bin($row['geom']); $geophpGeom = geoPHP::load($wkb,'wkb');$exporter = new GeoJSON();$geojsonArray = $exporter->getArray($geophpGeom);unset($row['geom']);$feature = ['type'=>'Feature','geometry'=>$geojsonArray,'properties'=>[]];foreach($row as $key=>$value) {
$feature['properties'][$key] = $value;}array_push($geojson,$feature);
}
header('Content-type: application/json');echo json_encode($geojson);
SystemyInformacji Przestrzennej Zapis geometrii z GeoJSON
$geojson = json_decode($_POST['geojson'],true);foreach($geojson['features'] as $feature) {
$geojsonGeom = $feature['geometry'];$attributes = $feature['properties'];$geophpGeom = geoPHP::load($geojsonGeom,'json');$wkbGeom = geoPHP::out($geophpGeom,'wkb');$hexHeom = bin2hex($wkbGeom);$columns = implode(',',array_keys($attributes));$values = array_values($attributes);$str = str_repeat('?,',count($values)).”ST_GeomFromWKB('$hexGeom',4326)”;$sql = „INSERT INTO tabela($columns,geom) VALUES($valueString)”;$stmt = $pdo->prepare($sql);$result = $stmt->execute($values);
}
SystemyInformacji Przestrzennej
Zapis geometrii z pary współrzędnych
$x = $_POST['x'];$y = $_POST['y'];$info = $_POST['info'];
//dla PostGIS
$sql = INSERT INTO poi(info,geom) VALUES('$info',ST_SetSRID(ST_MakePoint($x,$y),4326));
//dla pozostałych
$sql = INSERT INTO poi(info,geom) VALUES('$info',ST_GeomFromText('POINT($x $y)',4326);
SystemyInformacji Przestrzennej Format KML
Do użycia w Google Maps / Earth
Najważniejsze różnice:● Zapis atrybutów w postaci HTML● Opcjonalne dołączenie stylu
Pozyskiwanie z bazy danych:
PostGIS – funkcja ST_AsKML(geom)
Pozostałe – metoda geoPHP::out($geophpGeom,'kml')
Włączenie fragmentu surowego XML do DOM
Więcej informacji - https://developers.google.com/kml/articles/phpmysqlkml
SystemyInformacji Przestrzennej
…no dobrze, ale gdzie jest ten sklep monopolowy?
Poszukiwanie w promieniu – ST_DWithin(geometria,promień) – tylko PostGIS
SELECT * FROM poi WHERE type='alcohol' AND open_till > 19 AND ST_DWithin(
geom,ST_GeomFromText('POINT(19.02456,49.72074)',4326),5000);
SystemyInformacji Przestrzennej Więcej zasobów
●http://www.postgis.org●http://geophp.net●http://gis.stackexchange.com●http://www.bostongis.com
SystemyInformacji Przestrzennej
Dziękuję za uwagę.