10

I have a polyline layer with roads in WGS84 that covers several UTM zones. For every road I need to place a set of points at different distances (in metres). To do so I want to reproject each road to respective UTM zone, create points in this UTM zone, reproject points to WGS84 and add them to respectful layer.

There is a QgsCoordinateTransform() class that allows to perform transformation for individual points, but it doesn't accept polylines. I guess I could manually disassemble polylines into the set of points, transform each of them and recreate a polyline, but I hope that there is a build-in method or class that I overlooked, that allows to transform individual polylines.

1
  • One option would be to convert your polyline to a polygon, then transformPolygon() that, then just take the outer ring again. Its pretty much just QVector operations all the way down...
    – BradHards
    Commented Sep 21, 2015 at 10:11

2 Answers 2

18

Use QgsGeometry.transform(QgsCoordinateTransform). For example after created your instance of QgsCoordinateTransform with source and dest crs, for each geometry instance do:

sourceCrs = QgsCoordinateReferenceSystem(4326)
destCrs = QgsCoordinateReferenceSystem(2154)
tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
myGeometryInstance.transform(tr)

Documentation of the QgsCoordinateTransform class: https://qgis.org/api/classQgsCoordinateTransform.html#aa5ad428819ac020f8f5716e835ab754f

Beware that the transformation (applying QgsCoordinateTransform) will change the QgsGeometry instance.

6
  • 3
    Thank you for this answer. The operation gives me back a 0 number and my geometry doesn't seems to be reprojected.
    – SIGIS
    Commented Sep 14, 2017 at 8:42
  • can you give more details abut what you did? e.g. wkt of the geom, origin and dest epsg code and all that can be usefl to replicate. Obviously also qgis version and platform. tnx Commented Sep 14, 2017 at 10:54
  • Ok I missed a step to get a QgsCoordinateSystemReference class in the choosen coordinate eg 2154. It still gave back a 0 but the vertex has changed their coordinate.
    – SIGIS
    Commented Sep 14, 2017 at 12:23
  • This codesnippet does not work anymore in QGIS 3.4.4 : TypeError: QgsCoordinateTransform(): arguments did not match any overloaded call: overload 1: too many arguments overload 2: not enough arguments overload 3: not enough arguments overload 4: not enough arguments overload 5: argument 1 has unexpected type 'QgsCoordinateReferenceSystem'
    – Riccardo
    Commented Jan 25, 2019 at 15:11
  • 3
    @Riccardo The API has changed and you need to add a third parameter QgsCoordinateTransformContext. You can get it from QgsProject.instance(). So the call should be like QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) Commented Apr 4, 2019 at 11:19
14

Old Question, but duckduckgo brings you here for "pyqgis transform single geometry"

Just like Riccardo Pointed out, the accepted answer does not work for scripts in QGIS 3, the situation is explained in the api reference:

Python scripts should utilize the QgsProject.instance() project instance when creating QgsCoordinateTransform. This will ensure that any datum transforms defined in the project will be correctly respected during coordinate transforms. E.g.

transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:3111"),
                                   QgsCoordinateReferenceSystem("EPSG:4326"), QgsProject.instance())

Using QgsCoordinateTransform in QGIS 3 will transform the geometry instance inplace, and return 0:

geom = QgsGeometry(QgsPoint(5,20))
sourceCrs = QgsCoordinateReferenceSystem(4326)
destCrs = QgsCoordinateReferenceSystem(2154)
tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
geom.transform(tr)
#[out]: 0

geom
#[out]: <QgsGeometry: Point (930236.95432910311501473 3567516.9810206750407815)>

back_tr = QgsCoordinateTransform(destCrs, sourceCrs, QgsProject.instance())
geom.transform(back_tr)
#[out]: 0

geom
#[out]: <QgsGeometry: Point (5 19.99999999999911182)>

If you want to copy an already existing QgsGeometry Instance, the QgsGeometry class constructor will make the trick. From the docs:

Class: QgsGeometry class qgis.core.QgsGeometry Bases: sip.wrapper

Constructor

QgsGeometry(QgsGeometry) Copy constructor will prompt a deep copy of the object

example:

geom2 = QgsGeometry(geom)
geom2
#[out]: <QgsGeometry: Point (5 19.99999999999911182)>
geom
#[out]: <QgsGeometry: Point (5 19.99999999999911182)>
geom2.transform(tr)
#[out]: 0
geom2
#[out]: <QgsGeometry: Point (930236.95432910579256713 3567516.98102056747302413)>
geom
#[out]: <QgsGeometry: Point (5 19.99999999999911182)>
3
  • 2
    OMG, using project as an argument for transformation looks like a terrible design to me... Commented Mar 8, 2019 at 20:50
  • 1
    I was just copying the docs there.
    – Javier JC
    Commented Mar 8, 2019 at 21:23
  • 1
    The reason for that is that the project might have defined specific transformation rules to be used for a specific transformation. Commented Nov 23, 2021 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.