Viktigt

Översättning är en gemenskapsinsats du kan gå med i. Den här sidan är för närvarande översatt till 100.00%.

16.5. Lektion: Geometri Konstruktion

I det här avsnittet ska vi gå lite djupare in på hur enkla geometrier konstrueras i SQL. I verkligheten kommer du förmodligen att använda ett GIS som QGIS för att skapa komplexa geometrier med hjälp av deras digitaliseringsverktyg, men att förstå hur de formuleras kan vara praktiskt när du skriver frågor och förstår hur databasen är uppbyggd.

** Målet med denna lektion: ** För att bättre förstå hur man skapar rumsliga enheter direkt i PostgreSQL / PostGIS.

16.5.1. Skapa linjestring

Vi går tillbaka till vår databas address och ser till att vår gatutabell stämmer överens med de andra, dvs. att den har en begränsning för geometrin, ett index och en post i tabellen geometry_columns.

16.5.2. Prova själv: ★★☆

  • Modifiera tabellen streets så att den har en geometrikolumn av typen ST_LineString.

  • Glöm inte att göra den åtföljande uppdateringen av tabellen med geometrikolumner!

  • Lägg också till en begränsning för att förhindra att geometrier läggs till som inte är LINESTRINGS eller null.

  • Skapa ett spatialt index på den nya geometrikolumnen

Låt oss nu infoga en linjestring i vår gatutabell. I det här fallet kommer vi att uppdatera en befintlig gatupost:

update streets
set geom = 'SRID=4326;LINESTRING(20 -33, 21 -34, 24 -33)'
where streets.id=2;

Ta en titt på resultaten i QGIS (du kan behöva högerklicka på gatuskiktet i panelen ”Skikt” och välja ”Zooma till skiktets omfattning”)

Skapa nu några fler gatuposter - några i QGIS och några från kommandoraden.

16.5.3. Skapa polygoner

Att skapa polygoner är lika enkelt. En sak att komma ihåg är att polygoner per definition har minst fyra hörnpunkter, där den sista och den första är samlokaliserade:

insert into cities (name, geom)
values ('Tokyo', 'SRID=4326;POLYGON((10 -10, 5 -32, 30 -27, 10 -10))');

Observera

En polygon kräver dubbla parenteser runt sin koordinatlista; detta för att du ska kunna lägga till komplexa polygoner med flera områden som inte är sammankopplade. Exempelvis

insert into cities (name, geom)
values ('Tokyo Outer Wards',
        'SRID=4326;POLYGON((20 10, 20 20, 35 20, 20 10),
                           (-10 -30, -5 0, -15 -15, -10 -30))'
        );

Om du följde det här steget kan du kontrollera vad det gjorde genom att ladda in stadsdatasetet i QGIS, öppna dess attributtabell och välja den nya posten. Notera hur de två nya polygonerna beter sig som en polygon.

16.5.4. Övning: Koppla samman städer med människor

För denna övning ska du göra följande:

  • Ta bort alla data från din personaltabell.

  • Lägg till en kolumn med främmande nyckel i people som refererar till primärnyckeln i tabellen cities.

  • Använd QGIS för att fånga några städer.

  • Använd SQL för att infoga några nya personposter och se till att varje post har en tillhörande gata och stad.

Ditt uppdaterade personschema bör se ut ungefär så här:

\d people

Table "public.people"
   Column   |         Type          |                      Modifiers
 -----------+-----------------------+--------------------------------------------
  id        | integer               | not null
            |                       | default nextval('people_id_seq'::regclass)
  name      | character varying(50) |
  house_no  | integer               | not null
  street_id | integer               | not null
  phone_no  | character varying     |
  geom      | geometry              |
  city_id   | integer               | not null
Indexes:
  "people_pkey" PRIMARY KEY, btree (id)
  "people_name_idx" btree (name)
Check constraints:
  "people_geom_point_chk" CHECK (st_geometrytype(geom) =
                       'ST_Point'::text OR geom IS NULL)
Foreign-key constraints:
  "people_city_id_fkey" FOREIGN KEY (city_id) REFERENCES cities(id)
  "people_street_id_fkey" FOREIGN KEY (street_id) REFERENCES streets(id)

16.5.5. En titt på vårt schema

Vid det här laget bör vårt schema se ut så här:

../../../_images/final_schema.png

16.5.6. Prova själv: ★★★★

Skapa stadsgränser genom att beräkna det minsta konvexa skrovet av alla adresser för den staden och beräkna en buffert runt det området.

16.5.7. Åtkomst till underobjekt

Med SFS-Model-funktionerna har du en mängd olika alternativ för att komma åt underobjekt till SFS-geometrier. Om du vill välja den första vertexpunkten för varje polygongeometri i tabellen myPolygonTable, måste du göra det på följande sätt:

  • Omvandla polygongränsen till en linjestring:

    select st_boundary(geom) from myPolygonTable;
    
  • Välj den första toppunkten på den resulterande linjesträngen:

    select st_startpoint(myGeometry)
    from (
        select st_boundary(geom) as myGeometry
        from myPolygonTable) as foo;
    

16.5.8. Databehandling

PostGIS stöder alla OGC SFS/MM standardkonforma funktioner. Alla dessa funktioner börjar med ST_.

16.5.9. Klippning

Om du vill klippa ut en del av dina data kan du använda funktionen ST_INTERSECT(). För att undvika tomma geometrier, använd:

where not st_isempty(st_intersection(a.geom, b.geom))
../../../_images/qgis_001.png
select st_intersection(a.geom, b.geom), b.*
from clip as a, road_lines as b
where not st_isempty(st_intersection(st_setsrid(a.geom,32734),
  b.geom));
../../../_images/qgis_002.png

16.5.10. Bygga geometrier från andra geometrier

Från en given punkttabell vill du generera en linjestring. Ordningen på punkterna definieras av deras id. En annan ordningsmetod kan vara en tidsstämpel, t.ex. den som du får när du registrerar waypoints med en GPS-mottagare.

../../../_images/qgis_006.png

Om du vill skapa en linjestring från ett nytt punktlager som heter ”points” kan du köra följande kommando:

select ST_LineFromMultiPoint(st_collect(geom)), 1 as id
from (
  select geom
  from points
  order by id
) as foo;

För att se hur det fungerar utan att skapa ett nytt lager kan du också köra kommandot på lagret ”people”, även om det naturligtvis inte skulle vara särskilt meningsfullt att göra det i verkligheten.

../../../_images/qgis_007.png

16.5.11. Rengöring av geometri

Du kan få mer information om detta ämne i den här bloggposten.

16.5.12. Skillnader mellan tabeller

För att upptäcka skillnaden mellan två tabeller med samma struktur kan du använda PostgreSQL-nyckelordet EXCEPT:

select * from table_a
except
select * from table_b;

Resultatet blir att du får alla poster från tabell_a som inte finns lagrade i tabell_b.

16.5.13. Bordsytor

Du kan definiera var postgres ska lagra sina data på disken genom att skapa tablespaces:

CREATE TABLESPACE homespace LOCATION '/home/pg';

När du skapar en databas kan du sedan ange vilket tablespace som ska användas, t.ex:

createdb --tablespace=homespace t4a

16.5.14. Sammanfattningsvis

Du har lärt dig hur du skapar mer komplexa geometrier med hjälp av PostGIS-satser. Tänk på att detta främst är för att förbättra din tysta kunskap när du arbetar med geoaktiverade databaser via en GIS-frontend. Du behöver vanligtvis inte ange dessa satser manuellt, men att ha en allmän uppfattning om deras struktur kommer att hjälpa dig när du använder ett GIS, särskilt om du stöter på fel som annars verkar kryptiska.