Viktigt
Översättning är en gemenskapsinsats du kan gå med i. Den här sidan är för närvarande översatt till 100.00%.
7. Geometrihantering
Råd
Kodsnuttarna på den här sidan behöver följande import om du befinner dig utanför pyqgis-konsolen:
1from qgis.core import (
2 QgsGeometry,
3 QgsGeometryCollection,
4 QgsPoint,
5 QgsPointXY,
6 QgsWkbTypes,
7 QgsProject,
8 QgsFeatureRequest,
9 QgsVectorLayer,
10 QgsDistanceArea,
11 QgsUnitTypes,
12 QgsCoordinateTransform,
13 QgsCoordinateReferenceSystem
14)
Punkter, linjestrengar och polygoner som representerar en rumslig egenskap kallas vanligen geometrier. I QGIS representeras de med klassen QgsGeometry
.
Ibland är en geometri i själva verket en samling enkla (endelade) geometrier. En sådan geometri kallas en flerdelsgeometri. Om den bara innehåller en typ av enkel geometri kallar vi den multipunkt, multilinjestring eller multipolygon. Till exempel kan ett land som består av flera öar representeras som en multipolygon.
Geometriernas koordinater kan vara i valfritt koordinatreferenssystem (CRS). När funktioner hämtas från ett skikt kommer associerade geometrier att ha koordinater i skiktets CRS.
Beskrivning och specifikationer av alla möjliga geometrier, konstruktioner och relationer finns tillgängliga i OGC Simple Feature Access Standards för avancerade detaljer.
7.1. Geometri Konstruktion
PyQGIS erbjuder flera alternativ för att skapa en geometri:
från koordinater
1gPnt = QgsGeometry.fromPointXY(QgsPointXY(1,1)) 2print(gPnt) 3gLine = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) 4print(gLine) 5gPolygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 1), 6 QgsPointXY(2, 2), QgsPointXY(2, 1)]]) 7print(gPolygon)
Koordinater anges med hjälp av klassen
QgsPoint
ellerQgsPointXY
. Skillnaden mellan dessa klasser är attQgsPoint
stöder M- och Z-dimensioner.En Polyline (Linjestring) representeras av en lista med punkter.
En polygon representeras av en lista med linjära ringar (dvs. slutna linjestringar). Den första ringen är den yttre ringen (gränsen), valfria efterföljande ringar är hål i polygonen. Observera att till skillnad från vissa program kommer QGIS att stänga ringen åt dig så att du inte behöver duplicera den första punkten som den sista.
Geometrier med flera delar går en nivå längre: multi-point är en lista med punkter, multi-linestring är en lista med linestrings och multi-polygon är en lista med polygoner.
från välkänd text (WKT)
geom = QgsGeometry.fromWkt("POINT(3 4)") print(geom)
från välkänd binär (WKB)
1g = QgsGeometry() 2wkb = bytes.fromhex("010100000000000000000045400000000000001440") 3g.fromWkb(wkb) 4 5# print WKT representation of the geometry 6print(g.asWkt())
7.2. Tillgång till geometri
Först bör du ta reda på geometritypen. Metoden wkbType()
är den som ska användas. Den returnerar ett värde från QgsWkbTypes.Type
uppräkning.
1print(gPnt.wkbType())
2# output: 1
3print(gLine.wkbType())
4# output: 2
5print(gPolygon.wkbType())
6# output: 3
Som ett alternativ kan man använda metoden type()
som returnerar ett värde från uppräkningen QgsWkbTypes.GeometryType
.
print(gLine.type())
# output: 1
Du kan använda funktionen displayString()
för att få en geometrityp som är läsbar för människor.
1print(QgsWkbTypes.displayString(gPnt.wkbType()))
2# output: 'Point'
3print(QgsWkbTypes.displayString(gLine.wkbType()))
4# output: 'LineString'
5print(QgsWkbTypes.displayString(gPolygon.wkbType()))
6# output: 'Polygon'
Det finns också en hjälpfunktion isMultipart()
för att ta reda på om en geometri är multipart eller inte.
För att extrahera information från en geometri finns det accessorfunktioner för varje vektortyp. Här är ett exempel på hur man använder dessa accessorer:
1print(gPnt.asPoint())
2# output: <QgsPointXY: POINT(1 1)>
3print(gLine.asPolyline())
4# output: [<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>]
5print(gPolygon.asPolygon())
6# output: [[<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>, <QgsPointXY: POINT(2 1)>, <QgsPointXY: POINT(1 1)>]]
Observera
Tuplerna (x,y) är inte riktiga tupler, de är QgsPoint
-objekt, värdena är tillgängliga med x()
och y()
-metoder.
För geometrier med flera delar finns liknande accessorfunktioner: asMultiPoint()
, asMultiPolyline()
och asMultiPolygon()
.
Det är möjligt att iterera över alla delar av en geometri, oavsett geometrins typ. T.ex.
geom = QgsGeometry.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
for part in geom.parts():
print(part.asWkt())
Point (0 0)
Point (1 1)
Point (2 2)
geom = QgsGeometry.fromWkt( 'LineString( 0 0, 10 10 )' )
for part in geom.parts():
print(part.asWkt())
LineString (0 0, 10 10)
gc = QgsGeometryCollection()
gc.fromWkt('GeometryCollection( Point(1 2), Point(11 12), LineString(33 34, 44 45))')
print(gc[1].asWkt())
Point (11 12)
Det är också möjligt att modifiera varje del av geometrin med QgsGeometry.parts()
-metoden.
1geom = QgsGeometry.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
2for part in geom.parts():
3 part.transform(QgsCoordinateTransform(
4 QgsCoordinateReferenceSystem("EPSG:4326"),
5 QgsCoordinateReferenceSystem("EPSG:3111"),
6 QgsProject.instance())
7 )
8
9print(geom.asWkt())
MultiPoint ((-10334726.79314758814871311 -5360105.10101194866001606),(-10462133.82917747274041176 -5217484.34365733992308378),(-10589398.51346861757338047 -5072020.35880533326417208))
7.3. Geometri Predikat och operationer
QGIS använder GEOS-biblioteket för avancerade geometrioperationer som geometripredikater (contains()
, intersects()
, …) och set-operationer (combine()
, difference()
, …). Den kan också beräkna geometriska egenskaper för geometrier, t.ex. area (för polygoner) eller längder (för polygoner och linjer).
Låt oss se ett exempel som kombinerar iterering över funktionerna i ett visst skikt och utförande av några geometriska beräkningar baserat på deras geometrier. Nedanstående kod kommer att beräkna och skriva ut arean och omkretsen för varje land i skiktet countries
i vårt QGIS-projekt för handledning.
Följande kod förutsätter att layer
är ett QgsVectorLayer
-objekt som har funktionstypen Polygon.
1# let's access the 'countries' layer
2layer = QgsProject.instance().mapLayersByName('countries')[0]
3
4# let's filter for countries that begin with Z, then get their features
5query = '"name" LIKE \'Z%\''
6features = layer.getFeatures(QgsFeatureRequest().setFilterExpression(query))
7
8# now loop through the features, perform geometry computation and print the results
9for f in features:
10 geom = f.geometry()
11 name = f.attribute('NAME')
12 print(name)
13 print('Area: ', geom.area())
14 print('Perimeter: ', geom.length())
1Zambia
2Area: 62.82279065343119
3Perimeter: 50.65232014052552
4Zimbabwe
5Area: 33.41113559136517
6Perimeter: 26.608288555013935
Nu har du beräknat och skrivit ut geometriernas area och omkrets. Du kanske dock snabbt märker att värdena är konstiga. Det beror på att areor och omkretsar inte tar hänsyn till CRS när de beräknas med hjälp av metoderna area()
och length()
från klassen QgsGeometry
. För en mer kraftfull beräkning av yta och avstånd kan klassen QgsDistanceArea
användas, som kan utföra ellipsoidbaserade beräkningar:
Följande kod förutsätter att layer
är ett QgsVectorLayer
-objekt som har funktionstypen Polygon.
1d = QgsDistanceArea()
2d.setEllipsoid('WGS84')
3
4layer = QgsProject.instance().mapLayersByName('countries')[0]
5
6# let's filter for countries that begin with Z, then get their features
7query = '"name" LIKE \'Z%\''
8features = layer.getFeatures(QgsFeatureRequest().setFilterExpression(query))
9
10for f in features:
11 geom = f.geometry()
12 name = f.attribute('NAME')
13 print(name)
14 print("Perimeter (m):", d.measurePerimeter(geom))
15 print("Area (m2):", d.measureArea(geom))
16
17 # let's calculate and print the area again, but this time in square kilometers
18 print("Area (km2):", d.convertAreaMeasurement(d.measureArea(geom), QgsUnitTypes.AreaSquareKilometers))
1Zambia
2Perimeter (m): 5539361.250294601
3Area (m2): 751989035032.9031
4Area (km2): 751989.0350329031
5Zimbabwe
6Perimeter (m): 2865021.3325076113
7Area (m2): 389267821381.6008
8Area (km2): 389267.8213816008
Alternativt kanske du vill veta avståndet mellan två punkter.
1d = QgsDistanceArea()
2d.setEllipsoid('WGS84')
3
4# Let's create two points.
5# Santa claus is a workaholic and needs a summer break,
6# lets see how far is Tenerife from his home
7santa = QgsPointXY(25.847899, 66.543456)
8tenerife = QgsPointXY(-16.5735, 28.0443)
9
10print("Distance in meters: ", d.measureLine(santa, tenerife))
Du kan hitta många exempel på algoritmer som ingår i QGIS och använda dessa metoder för att analysera och omvandla vektordata. Här är några länkar till koden för några av dem.
Avstånd och area med hjälp av
QgsDistanceArea
class: Distance matrix algorithm