20. Funktioner för geometrikonstruktion

Alla funktioner som vi har sett hittills arbetar med geometrier ”som de är” och returnerar

  • analyser av objekten (ST_Length(geometry), ST_Area(geometry)),

  • serialiseringar av objekten (ST_AsText(geometry), ST_AsGML(geometry)),

  • delar av objektet (ST_RingN(geometry,n)) eller

  • sant/falskt-test (ST_Contains(geometry,geometry), ST_Intersects(geometry,geometry)).

”Geometry constructing functions” tar geometrier som indata och matar ut nya former.

20.1. ST_Centroid / ST_PointOnSurface

Ett vanligt behov när man skapar en spatial fråga är att ersätta en polygonfunktion med en punktrepresentation av funktionen. Detta är användbart för spatiala sammanfogningar (som diskuteras i Polygon/Polygon Joins) eftersom användning av ST_Intersects(geometry,geometry) på två polygonlager ofta resulterar i dubbelräkning: en polygon på en gräns kommer att korsa ett objekt på båda sidor; om den ersätts med en punkt måste den vara på den ena eller andra sidan, inte båda.

  • ST_Centroid(geometry) returnerar en punkt som ligger ungefär på inmatningsargumentets masscentrum. Denna enkla beräkning är mycket snabb, men ibland inte önskvärd, eftersom den returnerade punkten inte nödvändigtvis ligger i själva objektet. Om inmatningsobjektet har en konvexitet (föreställ dig bokstaven ”C”) är det inte säkert att den returnerade centroiden ligger i objektets inre.

  • ST_PointOnSurface(geometry) returnerar en punkt som garanterat befinner sig inuti inmatningsargumentet. Detta gör den mer användbar för att beräkna ”proxypunkter” för spatiala sammanfogningar.

_images/centroid.jpg
-- Compare the location of centroid and point-on-surface for a concave geometry

SELECT ST_Intersects(geom, ST_Centroid(geom)) AS centroid_inside,
       ST_Intersects(geom, ST_PointOnSurface(geom)) AS pos_inside
FROM (VALUES
    ('POLYGON ((30 0, 30 10, 10 10, 10 40, 30 40, 30 50, 0 50, 0 0, 0 0, 30 0))'::geometry)
  ) AS t(geom);
 centroid_inside | pos_inside
-----------------+------------
 f               | t

20.2. ST_Buffer

Buffringsoperationen är vanlig i GIS-arbetsflöden och finns även tillgänglig i PostGIS. ST_Buffer(geometry,distance) tar in ett buffertavstånd och en geometrityp och matar ut en polygon med en gräns som ligger buffertavståndet bort från indatageometrin.

_images/st_buffer.png

Om US Park Service till exempel ville införa en marin trafikzon runt Liberty Island skulle de kunna bygga en 500 meter buffertpolygon runt ön. Liberty Island är ett enda folkräkningsblock i vår tabell nyc_census_blocks, så vi kan enkelt extrahera och buffra det.

-- Make a new table with a Liberty Island 500m buffer zone
CREATE TABLE liberty_island_zone AS
SELECT ST_Buffer(geom,500)::geometry(Polygon,26918) AS geom
FROM nyc_census_blocks
WHERE blkid = '360610001001001';
_images/liberty_positive.jpg

Funktionen ST_Buffer accepterar även negativa avstånd och bygger inskrivna polygoner inom polygonala ingångar. För linjer och punkter får du bara en tom retur.

_images/liberty_negative.jpg

20.3. ST_Intersection

En annan klassisk GIS-operation - ”overlay” - skapar en ny täckning genom att beräkna korsningspunkten mellan två överlagrade polygoner. Den resulterande polygonen har egenskapen att alla polygoner i någon av föräldrarna kan byggas genom att slå samman polygoner i den resulterande polygonen.

Funktionen ST_Intersection(geometry A, geometry B) returnerar det spatiala område (eller den linje eller punkt) som de båda argumenten har gemensamt. Om argumenten är disjunkta returnerar funktionen en tom geometri.

-- What is the area these two circles have in common?
-- Using ST_Buffer to make the circles!

SELECT ST_AsText(ST_Intersection(
  ST_Buffer('POINT(0 0)', 2),
  ST_Buffer('POINT(3 0)', 2)
));
_images/intersection.jpg

20.4. ST_Union

I det föregående exemplet korsade vi geometrier och skapade en ny geometri som hade linjer från båda ingångarna. Funktionen ST_Union gör det omvända; den tar ingångar och tar bort gemensamma linjer. Det finns två former av funktionen ST_Union:

  • ST_Union(geometry, geometry): En version med två argument som tar in två geometrier och returnerar den sammanslagna unionen. Till exempel ser vårt exempel med två cirklar från föregående avsnitt ut så här när du ersätter intersektionen med en union.

    -- What is the total area these two circles cover?
    -- Using ST_Buffer to make the circles!
    
    SELECT ST_AsText(ST_Union(
      ST_Buffer('POINT(0 0)', 2),
      ST_Buffer('POINT(3 0)', 2)
    ));
    
    _images/union.jpg
  • ST_Union([geometry]): En aggregerad version som tar in en uppsättning geometrier och returnerar den sammanslagna geometrin för hela gruppen. Aggregatet ST_Union kan användas med SQL-satsen GROUP BY för att skapa noggrant sammanslagna delmängder av grundläggande geometrier. Det är ett mycket kraftfullt verktyg.

Som ett exempel på ST_Union-aggregering kan vi ta vår tabell nyc_census_blocks. Censusgeografin är noggrant konstruerad så att större geografier kan byggas upp från mindre. Så vi kan skapa en karta över folkräkningstrakter genom att slå samman de kvarter som bildar varje trakt (vilket vi gör senare i Skapa en tabell över folkräkningsområden). Eller så kan vi skapa en länskarta genom att slå samman block som faller inom varje län.

För att utföra sammanslagningen, notera att den unika nyckeln blkid faktiskt innehåller information om geografierna på högre nivå. Här är de delar av nyckeln för Liberty Island som vi använde tidigare:

360610001001001 = 36 061 000100 1 001

36     = State of New York
061    = New York County (Manhattan)
000100 = Census Tract
1      = Census Block Group
001    = Census Block

Så vi kan skapa en länskarta genom att slå samman alla geometrier som delar samma första 5 siffror i deras blkid. Ha tålamod; detta är beräkningsmässigt dyrt och kan ta en minut eller två.

-- Create a nyc_census_counties table by merging census blocks
CREATE TABLE nyc_census_counties AS
SELECT
  ST_Union(geom)::Geometry(MultiPolygon,26918) AS geom,
  SubStr(blkid,1,5) AS countyid
FROM nyc_census_blocks
GROUP BY countyid;
_images/union_counties.png

Ett områdestest kan bekräfta att vår fackliga verksamhet inte har förlorat någon geometri. Först beräknar vi ytan för varje enskilt folkbokföringsblock och summerar dessa ytor grupperade efter folkbokföringslänets id.

SELECT SubStr(blkid,1,5) AS countyid, Sum(ST_Area(geom)) AS area
FROM nyc_census_blocks
GROUP BY countyid
ORDER BY countyid;
 countyid |       area
----------+------------------
 36005    | 110196022.906506
 36047    | 181927497.678368
 36061    | 59091860.6261323
 36081    | 283194473.613692
 36085    | 150758328.111199

Sedan beräknar vi arean för var och en av våra nya länspolygoner från länstabellen:

SELECT countyid, ST_Area(geom) AS area
FROM nyc_census_counties
ORDER BY countyid;
 countyid |       area
----------+------------------
 36005    | 110196022.906507
 36047    | 181927497.678367
 36061    | 59091860.6261324
 36081    | 283194473.593646
 36085    | 150758328.111199

Samma svar! Vi har framgångsrikt byggt en NYC county-tabell från våra data om folkbokföringsblock.

20.5. Funktionslista

ST_Centroid(geometri): Returnerar en punktgeometri som representerar masscentrum för indatageometrin.

ST_PointOnSurface(geometry): Returnerar en punktgeometri som garanterat befinner sig i det inre av indatageometrin.

ST_Buffer(geometri, distance): För geometri: Returnerar en geometri som representerar alla punkter vars avstånd från denna geometri är mindre än eller lika med distance. Beräkningar görs i det spatiala referenssystemet för denna geometri. För geografi: Använder ett omslag för planar transformation.

ST_Intersection(geometri A, geometri B): Returnerar en geometri som representerar den delade delen av geomA och geomB. Geografi-implementeringen gör en transform till geometri för att göra korsningen och sedan transformera tillbaka till WGS84.

ST_Union(): Returnerar en geometri som representerar punktuppsättningens union av geometrierna.

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

substring(sträng [från int] [för int]): PostgreSQL-strängfunktion för att extrahera delsträng som matchar SQL reguljärt uttryck.

sum(uttryck): PostgreSQL-aggregeringsfunktion som returnerar summan av poster i en uppsättning poster.