SuperAPI AI Directory

qgis-core-coordinate-systems

Data & analytics

View repository

Updated 10-15 22:18

About this skill

qgis-core-coordinate-systems

Quick Reference

Core CRS Classes

Class Purpose Key Methods
QgsCoordinateReferenceSystem Represents a spatial reference system isValid(), authid(), isGeographic(), mapUnits()
QgsCoordinateTransform Transforms coordinates between two CRS transform(), transformBoundingBox()
QgsCoordinateTransformContext Project-level datum transformation settings Used as parameter for transforms
QgsDistanceArea Measures distances and areas in any CRS measureLine(), measureArea(), setEllipsoid()

CRS Creation Methods

Input Format Constructor Syntax Example
EPSG code QgsCoordinateReferenceSystem("EPSG:<code>") "EPSG:4326"
PostGIS SRID QgsCoordinateReferenceSystem("POSTGIS:<srid>") "POSTGIS:4326"
Internal ID QgsCoordinateReferenceSystem("INTERNAL:<srsid>") "INTERNAL:3452"
Proj string QgsCoordinateReferenceSystem("PROJ:<proj>") "PROJ:+proj=longlat +datum=WGS84"
WKT string QgsCoordinateReferenceSystem("WKT:<wkt>") "WKT:GEOGCS[...]"

CRS Property Methods

Method Returns Description
authid() str Authority identifier, e.g., "EPSG:4326"
description() str Human-readable name, e.g., "WGS 84"
isValid() bool Whether the CRS was successfully created
isGeographic() bool True for geographic CRS (degrees), False for projected (meters)
mapUnits() Qgis.DistanceUnit Unit enumeration for the CRS
toProj() str Full Proj string representation
toWkt() str Full WKT string representation
postgisSrid() int PostGIS SRID value
srsid() int QGIS internal ID
projectionAcronym() str Projection type, e.g., "longlat"
ellipsoidAcronym() str Ellipsoid identifier, e.g., "EPSG:7030"

Common EPSG Codes

Code Name Type Units Use Case
4326 WGS 84 Geographic Degrees GPS coordinates, global data exchange
3857 Web Mercator Projected Meters Web maps (OpenStreetMap, Google Maps)
32631-32660 UTM Zones 31N-60N Projected Meters Accurate local measurements (Northern Hemisphere)
32701-32760 UTM Zones 1S-60S Projected Meters Accurate local measurements (Southern Hemisphere)
28992 Amersfoort / RD New Projected Meters Netherlands national grid
27700 OSGB 1936 Projected Meters UK Ordnance Survey
2154 RGF93 / Lambert-93 Projected Meters France national grid

Critical Warnings

NEVER create a QgsCoordinateTransform without a QgsCoordinateTransformContext. The bare constructor ignores datum transformation preferences and produces silently inaccurate results.

NEVER assign a CRS to a layer as a substitute for reprojection. layer.setCrs() changes the interpretation of existing coordinates -- it does NOT transform the data. Use QgsCoordinateTransform to actually reproject.

NEVER assume QgsPointXY takes latitude first for EPSG:4326. QgsPointXY ALWAYS takes (x, y) = (longitude, latitude), regardless of the EPSG axis order specification.

NEVER use deprecated creation methods (createFromSrid(), createFromEpsg()). ALWAYS use the string-prefix constructor: QgsCoordinateReferenceSystem("EPSG:4326").

NEVER skip isValid() checks after CRS creation. An invalid CRS silently produces wrong results in ALL downstream operations (transforms, measurements, spatial queries).

NEVER run standalone PyQGIS scripts without QgsApplication.setPrefixPath() set correctly. Without it, QGIS cannot find the srs.db database and ALL CRS operations fail silently.

ALWAYS use QgsProject.instance().transformContext() instead of a bare QgsCoordinateTransformContext(). The project context includes user-configured datum transformation preferences.

ALWAYS check datum transformation grid availability before transforming between datums that require grid files. Missing grids cause silent loss of precision.


Decision Tree

Which CRS to Use?

Need to handle coordinates?
├── Receiving GPS/WGS84 data?
│   └── Use EPSG:4326 (geographic, degrees)
├── Displaying on a web map?
│   └── Use EPSG:3857 (Web Mercator, meters)
├── Measuring distances/areas accurately?
│   ├── Local area (< 6 degrees longitude)?
│   │   └── Use UTM zone for the area (EPSG:326xx for N, EPSG:327xx for S)
│   └── Large area or global?
│       └── Use EPSG:4326 + QgsDistanceArea with ellipsoidal measurement
├── Working with national data?
│   └── Use the country's national CRS (e.g., EPSG:28992 for NL)
└── Storing data for exchange?
    └── Use EPSG:4326 (universal standard)

How to Transform Coordinates?

Need to transform coordinates?
├── Single point?
│   └── QgsCoordinateTransform.transform(QgsPointXY)
├── Bounding box?
│   └── QgsCoordinateTransform.transformBoundingBox(QgsRectangle)
├── Full geometry?
│   └── geometry.transform(QgsCoordinateTransform)
├── Entire layer?
│   └── Use processing: native:reprojectlayer
└── Just for display?
    └── Set project CRS — on-the-fly reprojection handles rendering

Ellipsoidal vs. Planimetric Measurement?

Need to measure distances or areas?
├── Source CRS is geographic (degrees)?
│   └── ALWAYS use QgsDistanceArea with ellipsoid set
├── Source CRS is projected (meters)?
│   ├── Need high precision over large areas?
│   │   └── Use QgsDistanceArea with ellipsoid set
│   └── Local area, moderate precision OK?
│       └── Planimetric (Cartesian) measurement is acceptable
└── Unsure?
    └── ALWAYS use QgsDistanceArea with ellipsoid — it handles both cases

Essential Patterns

Pattern 1: Create and Validate a CRS

from qgis.core import QgsCoordinateReferenceSystem

crs = QgsCoordinateReferenceSystem("EPSG:4326")
if not crs.isValid():
    raise RuntimeError("Failed to create CRS: EPSG:4326")

print(crs.authid())        # "EPSG:4326"
print(crs.description())   # "WGS 84"
print(crs.isGeographic())  # True

Pattern 2: Transform Coordinates Between CRS

from qgis.core import (
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsProject,
    QgsPointXY
)

crs_src = QgsCoordinateReferenceSystem("EPSG:4326")
crs_dest = QgsCoordinateReferenceSystem("EPSG:32633")
context = QgsProject.instance().transformContext()

xform = QgsCoordinateTransform(crs_src, crs_dest, context)

# Forward transform (source -> destination)
pt_utm = xform.transform(QgsPointXY(18.0, 5.0))

# Reverse transform (destination -> source)
pt_wgs = xform.transform(pt_utm, QgsCoordinateTransform.ReverseTransform)

Pattern 3: Transform a Geometry

from qgis.core import (
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsProject,
    QgsGeometry,
    QgsPointXY
)

geom = QgsGeometry.fromPointXY(QgsPointXY(5.0, 52.0))
xform = QgsCoordinateTransform(
    QgsCoordinateReferenceSystem("EPSG:4326"),
    QgsCoordinateReferenceSystem("EPSG:28992"),
    QgsProject.instance().transformContext()
)
geom.transform(xform)  # In-place transformation

Pattern 4: Measure Distance with QgsDistanceArea

from qgis.core import (
    QgsDistanceArea,
    QgsCoordinateReferenceSystem,
    QgsPointXY,
    QgsProject,
    Qgis
)

d = QgsDistanceArea()
d.setSourceCrs(
    QgsCoordinateReferenceSystem("EPSG:4326"),
    QgsProject.instance().transformContext()
)
d.setEllipsoid("WGS84")

point1 = QgsPointXY(5.0, 52.0)
point2 = QgsPointXY(5.1, 52.1)
distance_m = d.measureLine(point1, point2)

# Convert to kilometers
distance_km = d.convertLengthMeasurement(distance_m, Qgis.DistanceUnit.Kilometers)

Pattern 5: Set Project CRS

from qgis.core import QgsProject, QgsCoordinateReferenceSystem

# Set project CRS: all layers render in this CRS via on-the-fly reprojection
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3857"))

Common Operations

Get CRS from an Existing Layer

layer = QgsProject.instance().mapLayersByName("my_layer")[0]
crs = layer.crs()
print(crs.authid())  # e.g., "EPSG:4326"

Transform a Bounding Box

from qgis.core import QgsRectangle

bbox = QgsRectangle(4.0, 51.0, 6.0, 53.0)  # xmin, ymin, xmax, ymax
xform = QgsCoordinateTransform(
    QgsCoordinateReferenceSystem("EPSG:4326"),
    QgsCoordinateReferenceSystem("EPSG:3857"),
    QgsProject.instance().transformContext()
)
bbox_transformed = xform.transformBoundingBox(bbox)

Measure Area of a Polygon

from qgis.core import QgsDistanceArea, QgsCoordinateReferenceSystem, QgsProject, Qgis

d = QgsDistanceArea()
d.setSourceCrs(layer.crs(), QgsProject.instance().transformContext())
d.setEllipsoid("WGS84")

for feature in layer.getFeatures():
    area_sqm = d.measureArea(feature.geometry())
    area_ha = d.convertAreaMeasurement(area_sqm, Qgis.AreaUnit.Hectares)

Reproject a Layer via Processing

import processing

result = processing.run("native:reprojectlayer", {
    "INPUT": layer,
    "TARGET_CRS": QgsCoordinateReferenceSystem("EPSG:32632"),
    "OUTPUT": "memory:"
})
reprojected_layer = result["OUTPUT"]

Reference Links

Official Sources