8

So I have one layerA with CRS:4326 and I can change CRS saving it:

# This layer has crs:4346
layerA = QgsVectorLayer("layerA.sqlite", "layerA", "ogr")

#New crs
crs = QgsCoordinateReferenceSystem("epsg:32629")

#saving layerA to layerB with new crs:32629
error = QgsVectorFileWriter.writeAsVectorFormat(layerA, "layerB.sqlite", "UTF-8", crs, "SpatiaLite")

With this code I can get a new LayerB with another CRS

I have read this: http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/crs

But I think this solution need to iterate over every feature to reproject it.

Is there any solution to reproject a layer with only one instruction (like when saving it) but without need to create a new layer?

Something like layerA.reproject(newCRS) ?

2

3 Answers 3

10

I don't think you can reproject a layer and overwrite its data at the same time it is being accessed. One option is to:

  1. Create a memory layer
  2. Transfer all data from the original layer to the memory layer
  3. Remove any dependencies on the original layer
  4. Overwrite original layer with the new CRS

# Get original shapefile and its features
layer = QgsVectorLayer("path/to/shapefile", "polygon", "ogr")
feats = [feat for feat in layer.getFeatures()]

# Create memory layer and copy over all attributes and geometries
mem_layer = QgsVectorLayer("Polygon?crs=epsg:4326", "memory_layer", "memory")
mem_layer_data = mem_layer.dataProvider()
attr = layer.dataProvider().fields().toList()
mem_layer_data.addAttributes(attr)
mem_layer.updateFields()
mem_layer_data.addFeatures(feats)
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

# Get original shapefile path
layer_source = layer.source()
# Remove dependence on shapefile
del layer
#New crs
crs = QgsCoordinateReferenceSystem("EPSG:32629")
# Overwrite original shapefile
error = QgsVectorFileWriter.writeAsVectorFormat(mem_layer, layer_source, "utf-8", crs, "ESRI Shapefile")
# Add result to canvas
QgsMapLayerRegistry.instance().addMapLayer(QgsVectorLayer(layer_source, "Result", "ogr"))
2
  • Thanks, Joseph. There is not a clean solution, maybe only save it to with another crs and reload (that is the more clean, I think), because calling to algorhtim docs.qgis.org/2.6/en/docs/user_manual/processing_algs/qgis/… need create a progress bar object before call it from standalone script. Commented Dec 15, 2016 at 11:15
  • 1
    @JuanmaFont - I agree that saving it to another shapefile is cleaner (especially easier using the Reproject algorithm) but in response to your question, the above code is what I have used :)
    – Joseph
    Commented Dec 15, 2016 at 11:19
4

Yes, you can reproject a layer in use without having to create a new one.

Unfortunately, no there is (still) no such short and simple method. It would shorten up things, but basically if there would be such a method, it would also have to iterate over the geometries to reproject them. Since the code can be really short I dont see much of an issue in doing it like:

layer = iface.activeLayer()
source_crs = QgsCoordinateReferenceSystem(layer.crs().authid())
target_crs = QgsCoordinateReferenceSystem("EPSG:25832")
with edit(layer):
    for feat in layer.getFeatures():
        # you need to store the geometry in a variable to reproject it; you can not reproject without doing so
        geom = feat.geometry() 
        # transform the geometry
        geom.transform(QgsCoordinateTransform(source_crs, target_crs, QgsProject.instance()))
        # now update the features geometry
        feat.setGeometry(geom)
        # dont forget to update the feature, otherwise the changes will have no effect
        layer.updateFeature(feat)
    # finally simply set the layers crs to the new one
    layer.setCrs(target_crs)

Also see:

3

Since QgsMapLayerRegistry has been removed, the QgsMapLayerRegistry in the @Joseph answer must be replaced by QgsProject.

Now, answering the question:

from qgis.core import *

iface.mainWindow().blockSignals(True)
vlayer = QgsVectorLayer(dfx_file, 'layer_test', 'ogr') 
crs = vlayer.crs()
crs.createFromId(5347) # Replace '5347' with whatever CRS id you want
vlayer.setCrs(crs)
QgsProject.instance().addMapLayer(vlayer)
iface.mainWindow().blockSignals(False)
3
  • Doesnt this just SET the crs?
    – MrXsquared
    Commented Dec 19, 2022 at 11:53
  • QGIS supports “on the fly” CRS transformation for both raster and vector data. This means that regardless of the underlying CRS of particular map layers in your project, they will always be automatically transformed into the common CRS defined for your project. Behind the scenes, QGIS transparently reprojects all layers contained within your project into the project’s CRS (From @MrXsquared comment). Commented Dec 28, 2022 at 6:44
  • But if you just set the crs to a different one without reprojecting the layer, the on-the-fly-reprojection will be incrorrect.
    – MrXsquared
    Commented Dec 28, 2022 at 9:31

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.