Dane przestrzenne w PHP

Post on 21-Jul-2015

2.035 views 2 download

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ę.