9. Geometrier

9.1. Introduktion

I föregående avsnitt laddade vi en mängd olika data. Innan vi börjar leka med våra data kan vi ta en titt på några enklare exempel. I pgAdmin väljer du återigen databasen nyc och öppnar SQL-frågeverktyget. Klistra in detta exempel på SQL-kod i pgAdmins SQL Editor-fönster (ta bort all text som kan finnas där som standard) och kör sedan.

CREATE TABLE geometries (name varchar, geom geometry);

INSERT INTO geometries VALUES
  ('Point', 'POINT(0 0)'),
  ('Linestring', 'LINESTRING(0 0, 1 1, 2 1, 2 2)'),
  ('Polygon', 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
  ('PolygonWithHole', 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))'),
  ('Collection', 'GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))');

SELECT name, ST_AsText(geom) FROM geometries;
_images/start01.png

Exemplet ovan CREATE:ar en tabell (geometries) och INSERT:ar sedan fem geometrier: en punkt, en linje, en polygon, en polygon med ett hål och en samling. Slutligen SELECTAS de infogade raderna och visas i fönstret Output.

9.2. Metadatatabeller

I enlighet med specifikationen Simple Features for SQL (SFSQL) tillhandahåller PostGIS två tabeller för att spåra och rapportera om de geometrityper som finns tillgängliga i en viss databas.

  • Den första tabellen, spatial_ref_sys, definierar alla spatiala referenssystem som är kända för databasen och kommer att beskrivas mer i detalj senare.

  • Den andra tabellen (egentligen en vy), geometry_columns, innehåller en lista över alla ”features” (definierade som ett objekt med geometriska attribut) och de grundläggande detaljerna för dessa features.

_images/table01.png

Låt oss ta en titt på tabellen geometry_columns i vår databas. Klistra in det här kommandot i Query Tool som tidigare:

SELECT * FROM geometry_columns;
_images/start08.png
  • f_table_catalog, f_table_schema och f_table_name ger det fullständigt kvalificerade namnet på funktionstabellen som innehåller en given geometri. Eftersom PostgreSQL inte använder kataloger tenderar f_table_catalog att vara tom.

  • f_geometry_column är namnet på den kolumn som innehåller geometri - för funktionstabeller med flera geometrikolumner kommer det att finnas en post för varje.

  • coord_dimension och srid definierar geometrins dimension (2-, 3- eller 4-dimensionell) respektive identifieraren för det spatiala referenssystemet som hänvisar till tabellen spatial_ref_sys.

  • Kolumnen type definierar typen av geometri enligt beskrivningen nedan; hittills har vi sett typerna Point och Linestring.

Genom att fråga i denna tabell kan GIS-klienter och bibliotek avgöra vad de kan förvänta sig när de hämtar data och kan utföra all nödvändig projicering, bearbetning eller rendering utan att behöva inspektera varje geometri.

Observera

Har några eller alla dina ”NYC”-tabeller inte en ”srid” på 26918? Det är lätt att åtgärda genom att uppdatera tabellen.

ALTER TABLE nyc_neighborhoods
  ALTER COLUMN geom
  TYPE Geometry(MultiPolygon, 26918)
  USING ST_SetSRID(geom, 26918);

9.3. Representera objekt i den verkliga världen

Simple Features for SQL (SFSQL) specifikationen, den ursprungliga vägledande standarden för PostGIS-utveckling, definierar hur ett verkligt objekt representeras. Genom att ta en kontinuerlig form och digitalisera den med en fast upplösning uppnår vi en acceptabel representation av objektet. SFSQL hanterade endast 2-dimensionella representationer. PostGIS har utvidgat det till att omfatta 3- och 4-dimensionella representationer; nyligen har SQL-Multimedia Part 3 (SQL/MM) -specifikationen officiellt definierat sin egen representation.

Vår exempeltabell innehåller en blandning av olika geometrityper. Vi kan samla in allmän information om varje objekt med hjälp av funktioner som läser geometrimetadata.

  • ST_GeometryType(geometry) returnerar typen av geometri

  • ST_NDims(geometry) returnerar antalet dimensioner för geometrin

  • ST_SRID(geometry) returnerar geometrins identifieringsnummer för spatial referens

SELECT name, ST_GeometryType(geom), ST_NDims(geom), ST_SRID(geom)
  FROM geometries;
      name       |    st_geometrytype    | st_ndims | st_srid
-----------------+-----------------------+----------+---------
 Point           | ST_Point              |        2 |       0
 Polygon         | ST_Polygon            |        2 |       0
 PolygonWithHole | ST_Polygon            |        2 |       0
 Collection      | ST_GeometryCollection |        2 |       0
 Linestring      | ST_LineString         |        2 |       0

9.3.1. Punkter

_images/points.png

En spatial punkt representerar en enda plats på jorden. Denna punkt representeras av en enda koordinat (antingen 2-, 3- eller 4-dimensionell). Punkter används för att representera objekt när de exakta detaljerna, t.ex. form och storlek, inte är viktiga i målskalan. Till exempel kan städer på en världskarta beskrivas som punkter, medan en karta över en enskild stat kan representera städer som polygoner.

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Point';
POINT(0 0)

Några av de specifika spatiala funktionerna för att arbeta med punkter är:

  • ST_X(geometry) returnerar X-ordinaten

  • ST_Y(geometry) returnerar Y-ordinaten

Så vi kan läsa föreskrifterna från en punkt som denna:

SELECT ST_X(geom), ST_Y(geom)
  FROM geometries
  WHERE name = 'Point';

Tabellen New York City subway stations (nyc_subway_stations) är en datamängd som representeras av punkter. Följande SQL-fråga returnerar den geometri som är associerad med en punkt (i kolumnen ST_AsText).

SELECT name, ST_AsText(geom)
  FROM nyc_subway_stations
  LIMIT 1;

9.3.2. Linjesträngar

_images/lines.png

En linjestring är en väg mellan platser. Den har formen av en ordnad serie av två eller flera punkter. Vägar och floder representeras vanligtvis som linjestringar. En linjestring sägs vara sluten om den börjar och slutar på samma punkt. Den sägs vara enkel om den inte korsar eller rör vid sig själv (utom vid sina ändpunkter om den är sluten). En linjestring kan vara både sluten och enkel.

Gatunätet för New York (nyc_streets) laddades tidigare under workshopen. Denna dataset innehåller detaljer som namn och typ. En enda gata i verkligheten kan bestå av många linjestringar, som var och en representerar ett vägsegment med olika attribut.

Följande SQL-fråga returnerar den geometri som är associerad med en linjestring (i kolumnen ST_AsText).

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Linestring';
LINESTRING(0 0, 1 1, 2 1, 2 2)

Några av de specifika spatiala funktionerna för att arbeta med linjestrings är:

  • ST_Length(geometry) returnerar längden på linjesträngen

  • ST_StartPoint(geometry) returnerar den första koordinaten som en punkt

  • ST_EndPoint(geometry) returnerar den sista koordinaten som en punkt

  • ST_NPoints(geometry) returnerar antalet koordinater i linjesträngen

Så längden på vår linjestring är:

SELECT ST_Length(geom)
  FROM geometries
  WHERE name = 'Linestring';
3.41421356237309

9.3.3. Polygoner

_images/polygons.png

En polygon är en representation av ett område. Polygonens yttre gräns representeras av en ring. Denna ring är en linjestring som är både sluten och enkel enligt definitionen ovan. Hål inom polygonen representeras också av ringar.

Polygoner används för att representera objekt vars storlek och form är viktiga. Stadsgränser, parker, byggnaders fotavtryck eller vattendrag representeras ofta som polygoner när skalan är tillräckligt hög för att man ska kunna se deras yta. Vägar och floder kan ibland representeras som polygoner.

Följande SQL-fråga returnerar den geometri som är associerad med en polygon (i kolumnen ST_AsText).

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';

Observera

I stället för att använda ett =-tecken i vår WHERE-sats använder vi operatorn LIKE för att utföra en strängmatchningsoperation. Du kanske är van vid symbolen ``*`` som en ”glob” för mönstermatchning, men i SQL används symbolen ``%``, tillsammans med operatorn LIKE för att tala om för systemet att göra globbing.

POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))
POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))

Den första polygonen har bara en ring. Den andra har ett inre ”hål”. De flesta grafiksystem innehåller begreppet ”polygon”, men GIS-system är relativt unika genom att de tillåter polygoner att uttryckligen ha hål.

_images/polygons1.png

Några av de specifika spatiala funktionerna för att arbeta med polygoner är:

  • ST_Area(geometry) returnerar polygonernas area

  • ST_NRings(geometry) returnerar antalet ringar (vanligtvis 1, fler om det finns hål)

  • ST_ExteriorRing(geometry) returnerar den yttre ringen som en linjestring

  • ST_InteriorRingN(geometry,n) returnerar en angiven inre ring som en linjestring

  • ST_Perimeter(geometry) returnerar längden på alla ringar

Vi kan beräkna arean av våra polygoner med hjälp av areafunktionen:

SELECT name, ST_Area(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';
Polygon            1
PolygonWithHole    99

Observera att polygonen med ett hål har en area som är arean av det yttre skalet (en 10x10 kvadrat) minus arean av hålet (en 1x1 kvadrat).

9.3.4. Samlingar

Det finns fyra samlingstyper, som grupperar flera enkla geometrier i uppsättningar.

  • MultiPoint, en samling punkter

  • MultiLineString, en samling av linjestrings

  • MultiPolygon, en samling av polygoner

  • GeometryCollection, en heterogen samling av valfri geometri (inklusive andra samlingar)

Samlingar är ett annat koncept som förekommer mer i GIS-program än i generiska grafikprogram. De är användbara för att direkt modellera verkliga objekt som spatiala objekt. Hur kan man till exempel modellera en tomt som delas av en väg? Som en MultiPolygon, med en del på vardera sidan om körbanan.

_images/collection2.png

Vår exempelsamling innehåller en polygon och en punkt:

SELECT name, ST_AsText(geom)
  FROM geometries
  WHERE name = 'Collection';
GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))
_images/collection.png

Några av de specifika spatiala funktionerna för att arbeta med samlingar är:

  • ST_NumGeometries(geometry) returnerar antalet delar i samlingen

  • ST_GeometryN(geometry,n) returnerar den angivna delen

  • ST_Area(geometry) returnerar den totala ytan för alla polygonala delar

  • ST_Length(geometry) returnerar den totala längden för alla linjära delar

9.4. Inmatning och utmatning av geometri

I databasen lagras geometrierna på disk i ett format som endast används av PostGIS-programmet. För att externa program ska kunna infoga och hämta användbara geometrier måste de konverteras till ett format som andra program kan förstå. Lyckligtvis stöder PostGIS utmatning och konsumtion av geometrier i ett stort antal format:

  • Välkänd text (WKT)

    • ST_GeomFromText(text, srid) returnerar geometry

    • ST_AsText(geometry) returnerar text

    • ST_AsEWKT(geometry) returnerar text

  • Välkänd binär (WKB)

    • ST_GeomFromWKB(bytea) returnerar geometry

    • ST_AsBinary(geometry) returnerar bytea

    • ST_AsEWKB(geometry) returnerar bytea

  • Geographic Mark-up Language (GML)

    • ST_GeomFromGML(text) returnerar geometry

    • ST_AsGML(geometry) returnerar text

  • Keyhole Mark-up Language (KML)

    • ST_GeomFromKML(text) returnerar geometry

    • ST_AsKML(geometry) returnerar text

  • GeoJSON

    • ST_AsGeoJSON(geometry) returnerar text

  • Skalbar vektorgrafik (SVG)

    • ST_AsSVG(geometry) returnerar text

Den vanligaste användningen av en konstruktor är att omvandla en textrepresentation av en geometri till en intern representation:

Observera att vi förutom en textparameter med en geometrisk representation också har en numerisk parameter som anger geometrins SRID.

Följande SQL-fråga visar ett exempel på WKB-representation (anropet till encode() krävs för att konvertera den binära utdata till en ASCII-form för utskrift):

SELECT encode(
  ST_AsBinary(ST_GeometryFromText('LINESTRING(0 0,1 0)')),
  'hex');
01020000000200000000000000000000000000000000000000000000000000f03f0000000000000000

I den här workshopen kommer vi att fortsätta använda WKT för att säkerställa att du kan läsa och förstå de geometrier vi tittar på. Men för de flesta faktiska processer, t.ex. visning av data i en GIS-applikation, överföring av data till en webbtjänst eller bearbetning av data på distans, är WKB det format som ska väljas.

Eftersom WKT och WKB definierades i SFSQL-specifikationen hanterar de inte 3- eller 4-dimensionella geometrier. För dessa fall har PostGIS definierat formaten Extended Well Known Text (EWKT) och Extended Well Known Binary (EWKB). Dessa ger samma formateringsmöjligheter som WKT och WKB med den extra dimensionaliteten.

Här är ett exempel på en 3D-linjestring i WKT:

SELECT ST_AsText(ST_GeometryFromText('LINESTRING(0 0 0,1 0 0,1 1 2)'));
LINESTRING Z (0 0 0,1 0 0,1 1 2)

Observera att textrepresentationen ändras! Detta beror på att textinmatningsrutinen för PostGIS är liberal i vad den konsumerar. Den kommer att konsumera

  • hex-kodad EWKB,

  • utökad välkänd text, och

  • ISO-standard välkänd text.

På utdatasidan är funktionen ST_AsText konservativ och ger bara ut välkänd text enligt ISO-standard.

Förutom funktionen ST_GeometryFromText finns det många andra sätt att skapa geometrier från välkänd text eller liknande formaterade indata:

-- Using ST_GeomFromText with the SRID parameter
SELECT ST_GeomFromText('POINT(2 2)',4326);

-- Using ST_GeomFromText without the SRID parameter
SELECT ST_SetSRID(ST_GeomFromText('POINT(2 2)'),4326);

-- Using a ST_Make* function
SELECT ST_SetSRID(ST_MakePoint(2, 2), 4326);

-- Using PostgreSQL casting syntax and ISO WKT
SELECT ST_SetSRID('POINT(2 2)'::geometry, 4326);

-- Using PostgreSQL casting syntax and extended WKT
SELECT 'SRID=4326;POINT(2 2)'::geometry;

Förutom emitters för de olika formerna (WKT, WKB, GML, KML, JSON, SVG) har PostGIS också consumers för fyra (WKT, WKB, GML, KML). De flesta applikationer använder WKT- eller WKB-funktionerna för geometrisk skapande, men de andra fungerar också. Här är ett exempel som konsumerar GML och matar ut JSON:

SELECT ST_AsGeoJSON(ST_GeomFromGML('<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>'));
_images/represent-07.png

9.5. Casting från text

De WKT-strängar vi har sett hittills har varit av typen ’text’ och vi har konverterat dem till typen ’geometri’ med hjälp av PostGIS-funktioner som ST_GeomFromText().

PostgreSQL innehåller en kortformssyntax som gör att data kan konverteras från en typ till en annan, casting-syntaxen, oldata:: newtype. Så till exempel konverterar denna SQL en dubbel till en textsträng.

SELECT 0.9::text;

Mindre trivialt konverterar denna SQL en WKT-sträng till en geometri:

SELECT 'POINT(0 0)'::geometry;

En sak att notera om att använda casting för att skapa geometrier: om du inte anger SRID får du en geometri med okänd SRID. Du kan ange SRID med hjälp av det ”utökade” välkända textformuläret, som innehåller ett SRID-block längst fram:

SELECT 'SRID=4326;POINT(0 0)'::geometry;

Det är mycket vanligt att använda casting-notationen när man arbetar med WKT, samt kolumnerna geometry och geography (se Geografi).

9.6. Funktionslista

ST_Area: Returnerar ytans area om det är en polygon eller multipolygon. För typen ”geometry” är arean i SRID-enheter. För ”geography” är arean i kvadratmeter.

ST_AsText: Returnerar WKT-representationen (Well-Known Text) av geometrin/geografin utan SRID-metadata.

ST_AsBinary: Returnerar WKB-representationen (Well-Known Binary) av geometrin/geografin utan SRID-metadata.

ST_EndPoint: Returnerar den sista punkten i en LINESTRING-geometri som en POINT.

ST_AsEWKB: Returnerar WKB-representationen (Well-Known Binary) av geometrin med SRID-metadata.

ST_AsEWKT: Returnerar WKT-representationen (Well-Known Text) av geometrin med SRID-metadata.

ST_AsGeoJSON: Returnerar geometrin som ett GeoJSON-element.

ST_AsGML: Returnerar geometrin som ett GML version 2 eller 3 element.

ST_AsKML: Returnerar geometrin som ett KML-element. Flera varianter. Standardversion=2, standardprecision=15.

ST_AsSVG: Returnerar en geometri i SVG-sökvägsdata givet ett geometri- eller geografiobjekt.

ST_ExteriorRing: Returnerar en radsträng som representerar den yttre ringen i POLYGON-geometrin. Returnerar NULL om geometrin inte är en polygon. Fungerar inte med MULTIPOLYGON

ST_GeometryN: Returnerar den 1-baserade N:te geometrin om geometrin är en GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTICURVE eller MULTIPOLYGON. I annat fall returneras NULL.

ST_GeomFromGML: Tar som indata GML-representation av geometri och matar ut ett PostGIS-geometriobjekt.

ST_GeomFromKML: Tar som indata KML-representation av geometri och matar ut ett PostGIS-geometriobjekt

ST_GeomFromText: Returnerar ett specificerat ST_Geometry-värde från Well-Known Text representation (WKT).

ST_GeomFromWKB: Skapar en geometriinstans från en Well-Known Binary geometrirepresentation (WKB) och valfri SRID.

ST_GeometryType: Returnerar geometritypen för ST_Geometry-värdet.

ST_InteriorRingN: Returnerar den N:te inre linjära ringen i polygongeometrin. Returnerar NULL om geometrin inte är en polygon eller om det angivna N ligger utanför intervallet.

ST_Length: Returnerar geometrins 2d-längd om den är en linjesträng eller multilinjesträng. geometri är i enheter för spatial referens och geografi är i meter (standard sfäroid)

ST_NDims: Returnerar geometrins koordinatdimension som ett litet int. Värdena är: 2,3 eller 4.

ST_NPoints: Returnerar antalet punkter (vertexer) i en geometri.

ST_NRings: Om geometrin är en polygon eller multipolygon returneras antalet ringar.

ST_NumGeometries: Om geometrin är en GEOMETRYCOLLECTION (eller MULTI*) returneras antalet geometrier, annars returneras NULL.

ST_Perimeter: Returnerar längdmätningen av gränsen för ett ST_Surface- eller ST_MultiSurface-värde. (Polygon, Multipolygon)

ST_SRID: Returnerar den spatiala referensidentifieraren för ST_Geometry enligt definitionen i tabellen spatial_ref_sys.

ST_StartPoint: Returnerar den första punkten i en LINESTRING-geometri som en POINT.

ST_X: Returnerar X-koordinaten för punkten, eller NULL om den inte är tillgänglig. Indata måste vara en punkt.

ST_Y: Returnerar punktens Y-koordinat, eller NULL om den inte är tillgänglig. Indata måste vara en punkt.