11. Spatiala relationer

Hittills har vi bara använt spatiala funktioner som mäter (ST_Area, ST_Length), serialiserar (ST_GeomFromText) eller deserialiserar (ST_AsGML) geometrier. Gemensamt för dessa funktioner är att de bara fungerar på en geometri i taget.

Spatiala databaser är kraftfulla eftersom de inte bara lagrar geometri, utan också har möjlighet att jämföra relationer mellan geometrier.

Frågor som ”Vilka är de närmaste cykelställen till en park?” eller ”Var är korsningarna mellan tunnelbanelinjer och gator?” kan bara besvaras genom att jämföra geometrier som representerar cykelställen, gator och tunnelbanelinjer.

OGC-standarden definierar följande uppsättning metoder för att jämföra geometrier.

11.1. ST_Equals

ST_Equals(geometry A, geometry B) testar den spatiala likheten mellan två geometrier.

_images/st_equals.png

ST_Equals returnerar TRUE om två geometrier av samma typ har identiska x,y-koordinatvärden, dvs. om den andra formen är lika (identisk) med den första formen.

Låt oss först hämta en representation av en punkt från vår tabell nyc_subway_stations. Vi tar bara posten för ”Broad St”.

SELECT name, geom
FROM nyc_subway_stations
WHERE name = 'Broad St';
   name   |                      geom
----------+---------------------------------------------------
 Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141

Sedan kopplar du tillbaka geometrirepresentationen till ett ST_Equals-test:

SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(
  geom,
  '0101000020266900000EEBD4CF27CF2141BC17D69516315141');
Broad St

Observera

Representationen av punkten var inte särskilt läsbar för människor (0101000020266900000EEBD4CF27CF2141BC17D69516315141) men det var en exakt representation av koordinatvärdena. För ett test som jämlikhet är det nödvändigt att använda de exakta koordinaterna.

11.2. ST_Intersects, ST_Disjoint, ST_Crosses och ST_Overlaps

ST_Intersects, ST_Crosses och ST_Overlaps testar om geometriernas inre delar skär varandra.

_images/st_intersects.png

ST_Intersects(geometry A, geometry B) returnerar t (TRUE) om de två formerna har något gemensamt utrymme, dvs. om deras gränser eller inre skär varandra.

_images/st_disjoint.png

Motsatsen till ST_Intersects är ST_Disjoint(geometry A , geometry B). Om två geometrier är disjunkta skär de inte varandra, och vice versa. I själva verket är det ofta effektivare att testa ”not intersects” än att testa ”disjoint” eftersom intersects-testerna kan indexeras spatialt, medan disjoint-testet inte kan det.

_images/st_crosses.png

För jämförelser av multipunkt/polygon, multipunkt/linjestring, linjestring/linjestring, linjestring/polygon och linjestring/multipolygon returnerar ST_Crosses(geometry A, geometry B) t (TRUE) om skärningen resulterar i en geometri vars dimension är ett mindre än den maximala dimensionen för de två källgeometrierna och skärningsmängden är inre i båda källgeometrierna.

_images/st_overlaps.png

ST_Overlaps(geometry A, geometry B) jämför två geometrier med samma dimension och returnerar TRUE om deras korsningspunkt resulterar i en geometri som skiljer sig från båda men som har samma dimension.

Låt oss ta vår tunnelbanestation på Broad Street och bestämma dess grannskap med hjälp av funktionen ST_Intersects:

SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(583571 4506714)
SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(geom, ST_GeomFromText('POINT(583571 4506714)',26918));
        name        | boroname
--------------------+-----------
 Financial District | Manhattan

11.3. ST_Touches

ST_Touches testar om två geometrier rör vid varandra vid sina gränser, men inte skär varandra i sina inre delar

_images/st_touches.png

ST_Touches(geometry A, geometry B) returnerar TRUE om någon av geometriernas gränser skär varandra eller om endast en av geometriernas inre delar skär den andras gräns.

11.4. ST_Within och ST_Contains

ST_Within och ST_Contains testar om en geometri är helt inom den andra.

_images/st_within.png

ST_Within(geometry A , geometry B) returnerar TRUE om den första geometrin är helt inom den andra geometrin. ST_Within testar för det exakt motsatta resultatet av ST_Contains.

ST_Contains(geometry A, geometry B) returnerar TRUE om den andra geometrin är helt innesluten av den första geometrin.

11.5. ST_Distance och ST_DWithin

En mycket vanlig GIS-fråga är ”hitta alla saker inom avstånd X från de här andra sakerna”.

ST_Distance(geometry A, geometry B) beräknar det kortaste avståndet mellan två geometrier och returnerar det som en float. Detta är användbart för att faktiskt rapportera tillbaka avståndet mellan objekt.

SELECT ST_Distance(
  ST_GeometryFromText('POINT(0 5)'),
  ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
3

För att testa om två objekt befinner sig inom ett visst avstånd från varandra ger funktionen ST_DWithin ett indexaccelererat sant/falskt-test. Detta är användbart för frågor som ”hur många träd finns det inom en buffert på 500 meter från vägen?”. Du behöver inte beräkna en faktisk buffert, du behöver bara testa avståndsrelationen.

_images/st_dwithin.png

Med hjälp av vår Broad Street tunnelbanestation igen kan vi hitta gatorna i närheten (inom 10 meter från) tunnelbanestationen:

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
        geom,
        ST_GeomFromText('POINT(583571 4506714)',26918),
        10
      );
     name
--------------
   Wall St
   Broad St
   Nassau St

Och vi kan verifiera svaret på en karta. Broad St-stationen ligger faktiskt i korsningen mellan Wall, Broad och Nassau Streets.

_images/broad_st.jpg

11.6. Funktionslista

ST_Contains(geometri A, geometri B): Returnerar sant om och endast om inga punkter i B ligger i utsidan av A, och minst en punkt i insidan av B ligger i insidan av A.

ST_Crosses(geometri A, geometri B): Returnerar TRUE om de angivna geometrierna har vissa, men inte alla, inre punkter gemensamt.

ST_Disjoint(geometri A , geometri B): Returnerar SANT om geometrierna inte ”korsar varandra spatialt” - om de inte delar något utrymme tillsammans.

ST_Distance(geometri A, geometri B): Returnerar det 2-dimensionella cartesiska minimiavståndet (baserat på spatial ref) mellan två geometrier i projicerade enheter.

ST_DWithin(geometri A, geometri B, radie): Returnerar sant om geometrierna ligger inom det angivna avståndet (radien) från varandra.

ST_Equals(geometri A, geometri B): Returnerar sant om de givna geometrierna representerar samma geometri. Riktning ignoreras.

ST_Intersects(geometri A, geometri B): Returnerar TRUE om geometrierna/geografin ”spatialt korsar varandra” - (delar någon del av utrymmet) och FALSE om de inte gör det (de är disjunkta).

ST_Overlaps(geometri A, geometri B): Returnerar SANT om geometrierna delar utrymme, har samma dimension, men inte är helt inneslutna av varandra.

ST_Touches(geometri A, geometri B): Returnerar SANT om geometrierna har minst en punkt gemensamt, men deras interiörer inte korsar varandra.

ST_Within(geometri A , geometri B): Returnerar sant om geometrin A är helt inuti geometrin B