Skip to content

Commit

Permalink
[processing] port geometry by expression to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Dec 9, 2019
1 parent c2d1649 commit eec0ac0
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 139 deletions.
5 changes: 0 additions & 5 deletions python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -160,11 +160,6 @@ qgis:fixeddistancebuffer: >
qgis:frequencyanalysis: >
This algorithm generates a table with frequency analysis of the values of a selected attribute from an input vector layer

qgis:geometrybyexpression: >
This algorithm updates existing geometries (or creates new geometries) for input features by use of a QGIS expression. This allows complex geometry modifications which can utilize all the flexibility of the QGIS expression engine to manipulate and create geometries for output features.

For help with QGIS expression functions, see the inbuilt help for specific functions which is available in the expression builder.

qgis:generatepointspixelcentroidsalongline: >
This algorithm generates a point vector layer from an input raster and line layer.
The points correspond to the pixel centroids that intersect the line layer.
Expand Down
129 changes: 0 additions & 129 deletions python/plugins/processing/algs/qgis/GeometryByExpression.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -48,7 +48,6 @@
from .FieldsMapper import FieldsMapper
from .FindProjection import FindProjection
from .GeometryConvert import GeometryConvert
from .GeometryByExpression import GeometryByExpression
from .Heatmap import Heatmap
from .HubDistanceLines import HubDistanceLines
from .HubDistancePoints import HubDistancePoints
Expand Down Expand Up @@ -139,7 +138,6 @@ def getAlgs(self):
FieldsMapper(),
FieldsPyculator(),
FindProjection(),
GeometryByExpression(),
GeometryConvert(),
Heatmap(),
HubDistanceLines(),
Expand Down
Expand Up @@ -378,7 +378,7 @@ tests:
hash: 71aecb383a686d78ea0e677901a8a93f822b9897d7a9e23ba4ebf24d
type: rasterhash

- algorithm: qgis:geometrybyexpression
- algorithm: native:geometrybyexpression
name: Geometry by expression (point)
params:
EXPRESSION: 'translate( $geometry,1,1)'
Expand All @@ -393,7 +393,7 @@ tests:
name: expected/geometry_by_expression_point.gml
type: vector

- algorithm: qgis:geometrybyexpression
- algorithm: native:geometrybyexpression
name: Geometry by expression (polygon)
params:
EXPRESSION: ' translate( centroid($geometry),1,1)'
Expand All @@ -411,7 +411,7 @@ tests:
geometry:
precision: 7

- algorithm: qgis:geometrybyexpression
- algorithm: native:geometrybyexpression
name: Geometry by expression (line)
params:
EXPRESSION: ' translate( $geometry,1,1)'
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -65,6 +65,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmfixgeometries.cpp
processing/qgsalgorithmforcerhr.cpp
processing/qgsalgorithmfuzzifyraster.cpp
processing/qgsalgorithmgeometrybyexpression.cpp
processing/qgsalgorithmgrid.cpp
processing/qgsalgorithmhillshade.cpp
processing/qgsalgorithmimportphotos.cpp
Expand Down
162 changes: 162 additions & 0 deletions src/analysis/processing/qgsalgorithmgeometrybyexpression.cpp
@@ -0,0 +1,162 @@
/***************************************************************************
qgsalgorithmgeometrybyexpression.cpp
------------------------
begin : November 2019
copyright : (C) 2019 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 "qgsalgorithmgeometrybyexpression.h"
#include "qgsgeometrycollection.h"

///@cond PRIVATE

QString QgsGeometryByExpressionAlgorithm::name() const
{
return QStringLiteral( "geometrybyexpression" );
}

QString QgsGeometryByExpressionAlgorithm::displayName() const
{
return QObject::tr( "Geometry by expression" );
}

QStringList QgsGeometryByExpressionAlgorithm::tags() const
{
return QObject::tr( "geometry,expression,create,modify" ).split( ',' );
}

QString QgsGeometryByExpressionAlgorithm::group() const
{
return QObject::tr( "Vector geometry" );
}

QString QgsGeometryByExpressionAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeometry" );
}

QString QgsGeometryByExpressionAlgorithm::outputName() const
{
return QObject::tr( "Modified geometry" );
}

QString QgsGeometryByExpressionAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm updates existing geometries (or creates new geometries) for input "
"features by use of a QGIS expression. This allows complex geometry modifications "
"which can utilize all the flexibility of the QGIS expression engine to manipulate "
"and create geometries for output features.\n\n"
"For help with QGIS expression functions, see the inbuilt help for specific functions "
"which is available in the expression builder." );
}

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

QList<int> QgsGeometryByExpressionAlgorithm::inputLayerTypes() const
{
return QList< int >() << QgsProcessing::TypeVector;
}

QgsWkbTypes::Type QgsGeometryByExpressionAlgorithm::outputWkbType( QgsWkbTypes::Type ) const
{
return mWkbType;
}

QgsProcessingFeatureSource::Flag QgsGeometryByExpressionAlgorithm::sourceFlags() const
{
return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks;
}

void QgsGeometryByExpressionAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterEnum( QStringLiteral( "OUTPUT_GEOMETRY" ), QObject::tr( "Output geometry type" ),
QStringList() << QObject::tr( "Polygon" ) << QObject::tr( "Line" ) << QObject::tr( "Point" ), false, 0 ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "WITH_Z" ), QObject::tr( "Output geometry has z dimension" ), false ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "WITH_M" ), QObject::tr( "Output geometry has m values" ), false ) );
addParameter( new QgsProcessingParameterExpression( QStringLiteral( "EXPRESSION" ), QObject::tr( "Geometry expression" ),
QStringLiteral( "$geometry" ), QStringLiteral( "INPUT" ) ) );
}

bool QgsGeometryByExpressionAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
int geometryType = parameterAsInt( parameters, QStringLiteral( "OUTPUT_GEOMETRY" ), context );
switch ( geometryType )
{
case 0:
mWkbType = QgsWkbTypes::Type::Polygon;
break;
case 1:
mWkbType = QgsWkbTypes::Type::LineString;
break;
case 2:
mWkbType = QgsWkbTypes::Type::Point;
break;
}

if ( parameterAsBoolean( parameters, QStringLiteral( "WITH_Z" ), context ) )
{
mWkbType = QgsWkbTypes::addZ( mWkbType );
}
if ( parameterAsBoolean( parameters, QStringLiteral( "WITH_M" ), context ) )
{
mWkbType = QgsWkbTypes::addM( mWkbType );
}

mExpression = QgsExpression( parameterAsString( parameters, QStringLiteral( "EXPRESSION" ), context ) );
if ( mExpression.hasParserError() )
{
feedback->reportError( mExpression.parserErrorString() );
return false;
}

mExpressionContext = createExpressionContext( parameters, context );
mExpression.prepare( &mExpressionContext );

return true;
}

QgsFeatureList QgsGeometryByExpressionAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback * )
{
QgsFeature feature = f;
mExpressionContext.setFeature( feature );
QVariant value = mExpression.evaluate( &mExpressionContext );

if ( mExpression.hasEvalError() )
{
throw QgsProcessingException( QObject::tr( "Evaluation error: %1" ).arg( mExpression.evalErrorString() ) );
}

if ( value.isNull() )
{
feature.setGeometry( QgsGeometry() );
}
else
{
if ( value.canConvert< QgsGeometry >() )
{
QgsGeometry geom = value.value<QgsGeometry>();
feature.setGeometry( geom );
}
else
{
throw QgsProcessingException( QObject::tr( "%1 is not a geometry" ).arg( value.toString() ) );
}
}

return QgsFeatureList() << feature;
}

///@endcond

0 comments on commit eec0ac0

Please sign in to comment.