diff --git a/python/plugins/processing/tests/testdata/expected/assign_projection.gml b/python/plugins/processing/tests/testdata/expected/assign_projection.gml
new file mode 100644
index 00000000000..7c31c835278
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/assign_projection.gml
@@ -0,0 +1,77 @@
+
+
+
+
+ 0-5
+ 83
+
+
+
+
+
+ 1,1
+ 1
+ 2
+
+
+
+
+ 3,3
+ 2
+ 1
+
+
+
+
+ 2,2
+ 3
+ 0
+
+
+
+
+ 5,2
+ 4
+ 2
+
+
+
+
+ 4,1
+ 5
+ 1
+
+
+
+
+ 0,-5
+ 6
+ 0
+
+
+
+
+ 8,-1
+ 7
+ 0
+
+
+
+
+ 7,-1
+ 8
+ 0
+
+
+
+
+ 0,-1
+ 9
+ 0
+
+
+
diff --git a/python/plugins/processing/tests/testdata/expected/assign_projection.xsd b/python/plugins/processing/tests/testdata/expected/assign_projection.xsd
new file mode 100644
index 00000000000..469af490a3e
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/assign_projection.xsd
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
index 35b178ca445..e2fbd30aa5f 100755
--- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -4148,3 +4148,15 @@ tests:
OUTPUT:
name: expected/extract_by_extent_clip.gml
type: vector
+
+ - algorithm: native:assignprojection
+ name: Assign projection
+ params:
+ CRS: EPSG:4283
+ INPUT:
+ name: custom/points.shp
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/assign_projection.gml
+ type: vector
diff --git a/src/core/processing/qgsnativealgorithms.cpp b/src/core/processing/qgsnativealgorithms.cpp
index fb866b7bbe8..a479e67e26c 100644
--- a/src/core/processing/qgsnativealgorithms.cpp
+++ b/src/core/processing/qgsnativealgorithms.cpp
@@ -92,6 +92,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsRasterLayerUniqueValuesReportAlgorithm() );
addAlgorithm( new QgsJoinByAttributeAlgorithm() );
addAlgorithm( new QgsJoinWithLinesAlgorithm() );
+ addAlgorithm( new QgsAssignProjectionAlgorithm() );
}
void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & )
@@ -666,6 +667,37 @@ QgsFeature QgsTransformAlgorithm::processFeature( const QgsFeature &f, QgsProces
}
+QString QgsAssignProjectionAlgorithm::shortHelpString() const
+{
+ return QObject::tr( "This algorithm assigns a new projection to a vector layer. It creates a new layer with the exact same features "
+ "and geometries as the input one, but assigned to a new CRS. E.g. the geometries are not reprojected, they are just assigned "
+ "to a different CRS. This algorithm can be used to repair layers which have been assigned an incorrect projection.\n\n"
+ "Attributes are not modified by this algorithm." );
+}
+
+QgsAssignProjectionAlgorithm *QgsAssignProjectionAlgorithm::createInstance() const
+{
+ return new QgsAssignProjectionAlgorithm();
+}
+
+void QgsAssignProjectionAlgorithm::initParameters( const QVariantMap & )
+{
+ addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS" ), QObject::tr( "Assigned CRS" ), QStringLiteral( "EPSG:4326" ) ) );
+}
+
+bool QgsAssignProjectionAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
+{
+ mDestCrs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
+ return true;
+}
+
+QgsFeature QgsAssignProjectionAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * )
+{
+ return feature;
+}
+
+
+
void QgsSubdivideAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MAX_NODES" ), QObject::tr( "Maximum nodes in parts" ), QgsProcessingParameterNumber::Integer,
diff --git a/src/core/processing/qgsnativealgorithms.h b/src/core/processing/qgsnativealgorithms.h
index 4c2180c6d7a..49106824fca 100644
--- a/src/core/processing/qgsnativealgorithms.h
+++ b/src/core/processing/qgsnativealgorithms.h
@@ -131,6 +131,39 @@ class QgsTransformAlgorithm : public QgsProcessingFeatureBasedAlgorithm
};
+
+
+/**
+ * Native assign projection algorithm.
+ */
+class QgsAssignProjectionAlgorithm : public QgsProcessingFeatureBasedAlgorithm
+{
+
+ public:
+
+ QgsAssignProjectionAlgorithm() = default;
+ QString name() const override { return QStringLiteral( "assignprojection" ); }
+ QString displayName() const override { return QObject::tr( "Assign projection" ); }
+ virtual QStringList tags() const override { return QObject::tr( "assign,set,transform,reproject,crs,srs,warp" ).split( ',' ); }
+ QString group() const override { return QObject::tr( "Vector general" ); }
+ QString shortHelpString() const override;
+ QgsAssignProjectionAlgorithm *createInstance() const override SIP_FACTORY;
+
+ protected:
+
+ void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
+ QgsCoordinateReferenceSystem outputCrs( const QgsCoordinateReferenceSystem & ) const override { return mDestCrs; }
+ QString outputName() const override { return QObject::tr( "Assigned CRS" ); }
+
+ bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
+ QgsFeature processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) override;
+
+ private:
+
+ QgsCoordinateReferenceSystem mDestCrs;
+
+};
+
/**
* Native buffer algorithm.
*/