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.

Taras
  • 32,823
  • 4
  • 66
  • 137
SS_Rebelious
  • 5,621
  • 3
  • 27
  • 62
  • 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 Sep 21 '15 at 10:11

2 Answers2

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.

Taras
  • 32,823
  • 4
  • 66
  • 137
Luigi Pirelli
  • 2,013
  • 14
  • 19
  • 3
    Thank you for this answer. The operation gives me back a 0 number and my geometry doesn't seems to be reprojected. – SIGIS Sep 14 '17 at 08: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 – Luigi Pirelli Sep 14 '17 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 Sep 14 '17 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 Jan 25 '19 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()) – spatialthoughts Apr 04 '19 at 11:19
  • tnx @spatialthoughts I've updated the post – Luigi Pirelli Apr 10 '19 at 08:40
12

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)>
Javier JC
  • 882
  • 6
  • 10