Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port Define Projection algorithm to C++ #60881

Merged
merged 2 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions python/plugins/processing/algs/help/qgis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ qgis:convertgeometrytype: >

See the "Polygonize" or "Lines to polygons" algorithm for alternative options.

qgis:definecurrentprojection: >
This algorithm sets an existing Shapefile's projection to the provided CRS. Contrary to the "Assign projection" algorithm, it will not output a new layer.

The .prj and .qpj files associated with the Shapefile will be overwritten - or created if missing - to match the provided CRS.

qgis:distancematrix: >
This algorithm creates a table containing a distance matrix, with distances between all the points in a points layer.

Expand Down
110 changes: 0 additions & 110 deletions python/plugins/processing/algs/qgis/DefineProjection.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from .BoxPlot import BoxPlot
from .CheckValidity import CheckValidity
from .Climb import Climb
from .DefineProjection import DefineProjection
from .EliminateSelection import EliminateSelection
from .ExecuteSQL import ExecuteSQL
from .ExportGeometryInfo import ExportGeometryInfo
Expand Down Expand Up @@ -94,7 +93,6 @@ def getAlgs(self):
BoxPlot(),
CheckValidity(),
Climb(),
DefineProjection(),
EliminateSelection(),
ExecuteSQL(),
ExportGeometryInfo(),
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ set(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmcoveragevalidate.cpp
processing/qgsalgorithmcreatedirectory.cpp
processing/qgsalgorithmdbscanclustering.cpp
processing/qgsalgorithmdefineprojection.cpp
processing/qgsalgorithmdelaunaytriangulation.cpp
processing/qgsalgorithmdeleteduplicategeometries.cpp
processing/qgsalgorithmdensifygeometriesbycount.cpp
Expand Down
137 changes: 137 additions & 0 deletions src/analysis/processing/qgsalgorithmdefineprojection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/***************************************************************************
qgsalgorithmdefineprojection.cpp
---------------------
begin : February 2025
copyright : (C) 2025 by Alexander Bruy
email : alexander dot bruy at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmdefineprojection.h"
#include "qgsvectorlayer.h"
#include "qgsproviderregistry.h"

///@cond PRIVATE

QString QgsDefineProjectionAlgorithm::name() const
{
return QStringLiteral( "definecurrentprojection" );
}

QString QgsDefineProjectionAlgorithm::displayName() const
{
return QObject::tr( "Define projection" );
}

QStringList QgsDefineProjectionAlgorithm::tags() const
{
return QObject::tr( "layer,shp,prj,qpj,change,alter" ).split( ',' );
}

QString QgsDefineProjectionAlgorithm::group() const
{
return QObject::tr( "Vector general" );
}

QString QgsDefineProjectionAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeneral" );
}

QString QgsDefineProjectionAlgorithm::shortHelpString() const
{
return QObject::tr( "Sets an existing layer's projection to the provided CRS without reprojecting features. "
"Contrary to the \"Assign projection\" algorithm, it will not output a new layer.\n\n"
"If the input layer is a shapefile, the .prj file will be overwritten — or created if "
"missing — to match the provided CRS." );
}

QgsDefineProjectionAlgorithm *QgsDefineProjectionAlgorithm::createInstance() const
{
return new QgsDefineProjectionAlgorithm();
}

void QgsDefineProjectionAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input shapefile" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS" ), QObject::tr( "CRS" ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
addOutput( new QgsProcessingOutputVectorLayer( QStringLiteral( "OUTPUT" ), QObject::tr( "Layer with projection" ) ) );
}

bool QgsDefineProjectionAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsVectorLayer *layer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context );
const QgsCoordinateReferenceSystem crs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );

if ( !layer )
throw QgsProcessingException( QObject::tr( "Invalid input layer" ) );

mLayerId = layer->id();

if ( layer->providerType().compare( QStringLiteral( "ogr" ), Qt::CaseSensitivity::CaseInsensitive ) == 0 )
{
const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->dataProvider()->dataSourceUri() );
QString layerPath;
if ( parts.size() > 0 )
{
layerPath = parts.value( QStringLiteral( "path" ) ).toString();
}

if ( !layerPath.isEmpty() && layerPath.endsWith( QStringLiteral( ".shp" ), Qt::CaseSensitivity::CaseInsensitive ) )
{
const QString filePath = layerPath.chopped( 4 );
const QString wkt = crs.toWkt( Qgis::CrsWktVariant::Wkt1Esri );

QFile prjFile( filePath + QLatin1String( ".prj" ) );
if ( prjFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
{
QTextStream stream( &prjFile );
stream << wkt << Qt::endl;
}
else
{
feedback->pushWarning( QObject::tr( "Failed to open .prj file for writing." ) );
}

QFile qpjFile( filePath + QLatin1String( ".qpj" ) );
if ( qpjFile.exists() )
{
qpjFile.remove();
}
}
else
{
feedback->pushWarning( QObject::tr( "Data source isn't a shapefile, skipping .prj creation" ) );
}
}
else
{
feedback->pushInfo( QObject::tr( "Data source isn't a shapefile, skipping .prj creation" ) );
}

layer->setCrs( crs );
layer->triggerRepaint();

return true;
}

QVariantMap QgsDefineProjectionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
Q_UNUSED( parameters );
Q_UNUSED( context );
Q_UNUSED( feedback );

QVariantMap results;
results.insert( QStringLiteral( "OUTPUT" ), mLayerId );
return results;
}

///@endcond
54 changes: 54 additions & 0 deletions src/analysis/processing/qgsalgorithmdefineprojection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/***************************************************************************
qgsalgorithmdefineprojection.h
---------------------
begin : February 2025
copyright : (C) 2025 by Alexander Bruy
email : alexander dot bruy at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMDEFINEPROJECTION_H
#define QGSALGORITHMDEFINEPROJECTION_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgsprocessingalgorithm.h"

///@cond PRIVATE

/**
* Native define layer projection algorithm.
*/
class QgsDefineProjectionAlgorithm : public QgsProcessingAlgorithm
{
public:
QgsDefineProjectionAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QgsDefineProjectionAlgorithm *createInstance() const override SIP_FACTORY;

protected:
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QVariantMap processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

private:
QString mLayerId;
};

///@endcond PRIVATE

#endif // QGSALGORITHMDEFINEPROJECTION_H
2 changes: 2 additions & 0 deletions src/analysis/processing/qgsnativealgorithms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "qgsalgorithmcoveragevalidate.h"
#include "qgsalgorithmcreatedirectory.h"
#include "qgsalgorithmdbscanclustering.h"
#include "qgsalgorithmdefineprojection.h"
#include "qgsalgorithmdelaunaytriangulation.h"
#include "qgsalgorithmdeleteduplicategeometries.h"
#include "qgsalgorithmdensifygeometriesbycount.h"
Expand Down Expand Up @@ -350,6 +351,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsCoverageValidateAlgorithm() );
addAlgorithm( new QgsCreateDirectoryAlgorithm() );
addAlgorithm( new QgsDbscanClusteringAlgorithm() );
addAlgorithm( new QgsDefineProjectionAlgorithm() );
addAlgorithm( new QgsDelaunayTriangulationAlgorithm() );
addAlgorithm( new QgsDeleteDuplicateGeometriesAlgorithm() );
addAlgorithm( new QgsDetectVectorChangesAlgorithm() );
Expand Down
Loading
Loading