[processing] port set M value algorithm to C++

This commit is contained in:
Alexander Bruy 2019-11-24 11:42:13 +02:00 committed by Nyall Dawson
parent 5324d7f98d
commit 9411d96f60
8 changed files with 197 additions and 114 deletions

View File

@ -447,11 +447,6 @@ qgis:selectbyexpression: >
For more information about expressions see the <a href ="{qgisdocs}/user_manual/working_with_vector/expression.html">user manual</a>
qgis:setmvalue: >
This algorithm sets the M value for geometries in a layer.
If M values already exist in the layer, they will be overwritten with the new value. If no M values exist, the geometry will be upgraded to include M values and the specified value used as the initial M value for all geometries.
qgis:setstyleforrasterlayer: >
This algorithm sets the style of a raster layer. The style must be defined in a QML file.

View File

@ -94,7 +94,6 @@ from .RegularPoints import RegularPoints
from .Relief import Relief
from .SelectByAttribute import SelectByAttribute
from .SelectByExpression import SelectByExpression
from .SetMValue import SetMValue
from .SetRasterStyle import SetRasterStyle
from .SetVectorStyle import SetVectorStyle
from .SetZValue import SetZValue
@ -195,7 +194,6 @@ class QgisAlgorithmProvider(QgsProcessingProvider):
Relief(),
SelectByAttribute(),
SelectByExpression(),
SetMValue(),
SetRasterStyle(),
SetVectorStyle(),
SetZValue(),

View File

@ -1,106 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
SetMValue.py
--------------
Date : July 2017
Copyright : (C) 2017 by Nyall Dawson
Email : nyall dot dawson 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. *
* *
***************************************************************************
"""
__author__ = 'Nyall Dawson'
__date__ = 'July 2017'
__copyright__ = '(C) 2017, Nyall Dawson'
import os
from qgis.core import (QgsGeometry,
QgsWkbTypes,
QgsPropertyDefinition,
QgsProcessingParameters,
QgsProcessingParameterNumber,
QgsProcessingFeatureSource)
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
class SetMValue(QgisFeatureBasedAlgorithm):
M_VALUE = 'M_VALUE'
def group(self):
return self.tr('Vector geometry')
def groupId(self):
return 'vectorgeometry'
def __init__(self):
super().__init__()
self.m_value = 0
self.dynamic_m = False
self.m_property = None
def name(self):
return 'setmvalue'
def displayName(self):
return self.tr('Set M value')
def outputName(self):
return self.tr('M Added')
def tags(self):
return self.tr('set,add,m,measure,values').split(',')
def initParameters(self, config=None):
m_param = QgsProcessingParameterNumber(self.M_VALUE,
self.tr('M Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0)
m_param.setIsDynamic(True)
m_param.setDynamicLayerParameterName('INPUT')
m_param.setDynamicPropertyDefinition(QgsPropertyDefinition(self.M_VALUE, self.tr("M Value"), QgsPropertyDefinition.Double))
self.addParameter(m_param)
def outputWkbType(self, inputWkb):
return QgsWkbTypes.addM(inputWkb)
def prepareAlgorithm(self, parameters, context, feedback):
self.m_value = self.parameterAsDouble(parameters, self.M_VALUE, context)
self.dynamic_m = QgsProcessingParameters.isDynamic(parameters, self.M_VALUE)
if self.dynamic_m:
self.m_property = parameters[self.M_VALUE]
return True
def sourceFlags(self):
return QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks
def processFeature(self, feature, context, feedback):
input_geometry = feature.geometry()
if input_geometry:
new_geom = input_geometry.constGet().clone()
if QgsWkbTypes.hasM(new_geom.wkbType()):
# addMValue won't alter existing M values, so drop them first
new_geom.dropMValue()
m = self.m_value
if self.dynamic_m:
m, ok = self.m_property.valueAsDouble(context.expressionContext(), m)
new_geom.addMValue(m)
feature.setGeometry(QgsGeometry(new_geom))
return [feature]
def supportInPlaceEdit(self, layer):
return super().supportInPlaceEdit(layer) and QgsWkbTypes.hasM(layer.wkbType())

View File

@ -865,7 +865,7 @@ tests:
name: expected/multiline_boundary.gml
type: vector
- algorithm: qgis:setmvalue
- algorithm: native:setmvalue
name: Set M Value
params:
INPUT:

View File

@ -111,6 +111,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmsegmentize.cpp
processing/qgsalgorithmserviceareafromlayer.cpp
processing/qgsalgorithmserviceareafrompoint.cpp
processing/qgsalgorithmsetmvalue.cpp
processing/qgsalgorithmshortestpathlayertopoint.cpp
processing/qgsalgorithmshortestpathpointtolayer.cpp
processing/qgsalgorithmshortestpathpointtopoint.cpp

View File

@ -0,0 +1,128 @@
/***************************************************************************
qgsalgorithmsetmvalue.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 "qgsalgorithmsetmvalue.h"
#include "qgsvectorlayer.h"
///@cond PRIVATE
QString QgsSetMValueAlgorithm::name() const
{
return QStringLiteral( "setmvalue" );
}
QString QgsSetMValueAlgorithm::displayName() const
{
return QObject::tr( "Set M value" );
}
QStringList QgsSetMValueAlgorithm::tags() const
{
return QObject::tr( "set,add,m,measure,values" ).split( ',' );
}
QString QgsSetMValueAlgorithm::group() const
{
return QObject::tr( "Vector geometry" );
}
QString QgsSetMValueAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeometry" );
}
QString QgsSetMValueAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm sets the M value for geometries in a layer.\n\n"
"If M values already exist in the layer, they will be overwritten "
"with the new value. If no M values exist, the geometry will be "
"upgraded to include M values and the specified value used as "
"the initial M value for all geometries." );
}
QString QgsSetMValueAlgorithm::outputName() const
{
return QObject::tr( "M Added" );
}
QgsSetMValueAlgorithm *QgsSetMValueAlgorithm::createInstance() const
{
return new QgsSetMValueAlgorithm();
}
bool QgsSetMValueAlgorithm::supportInPlaceEdit( const QgsMapLayer *l ) const
{
const QgsVectorLayer *layer = qobject_cast< const QgsVectorLayer * >( l );
if ( !layer )
return false;
return QgsProcessingFeatureBasedAlgorithm::supportInPlaceEdit( l ) && QgsWkbTypes::hasM( layer->wkbType() );
}
QgsProcessingFeatureSource::Flag QgsSetMValueAlgorithm::sourceFlags() const
{
return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks;
}
QgsWkbTypes::Type QgsSetMValueAlgorithm::outputWkbType( QgsWkbTypes::Type type ) const
{
return QgsWkbTypes::addM( type );
}
void QgsSetMValueAlgorithm::initParameters( const QVariantMap & )
{
auto mValueParam = qgis::make_unique < QgsProcessingParameterNumber >( QStringLiteral( "M_VALUE" ), QObject::tr( "M Value" ), QgsProcessingParameterNumber::Double, 0.0 );
mValueParam->setIsDynamic( true );
mValueParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "M_VALUE" ), QObject::tr( "M Value" ), QgsPropertyDefinition::Double ) );
mValueParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( mValueParam.release() );
}
bool QgsSetMValueAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mMValue = parameterAsDouble( parameters, QStringLiteral( "M_VALUE" ), context );
mDynamicMValue = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "M_VALUE" ) );
if ( mDynamicMValue )
mMValueProperty = parameters.value( QStringLiteral( "M_VALUE" ) ).value< QgsProperty >();
return true;
}
QgsFeatureList QgsSetMValueAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
std::unique_ptr< QgsAbstractGeometry > newGeometry( f.geometry().constGet()->clone() );
// addMValue won't alter existing M values, so drop them first
if ( QgsWkbTypes::hasM( newGeometry->wkbType() ) )
newGeometry->dropMValue();
double m = mMValue;
if ( mDynamicMValue )
m = mMValueProperty.valueAsDouble( context.expressionContext(), m );
newGeometry->addMValue( m );
f.setGeometry( QgsGeometry( std::move( newGeometry ) ) );
}
return QgsFeatureList() << f;
}
///@endcond

View File

@ -0,0 +1,65 @@
/***************************************************************************
qgsalgorithmsetmvalue.h
---------------------
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. *
* *
***************************************************************************/
#ifndef QGSALGORITHMSETMVALUE_H
#define QGSALGORITHMSETMVALUE_H
#define SIP_NO_FILE
#include "qgis_sip.h"
#include "qgsprocessingalgorithm.h"
///@cond PRIVATE
/**
* Native set M value algorithm.
*/
class QgsSetMValueAlgorithm : public QgsProcessingFeatureBasedAlgorithm
{
public:
QgsSetMValueAlgorithm() = default;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QgsSetMValueAlgorithm *createInstance() const override SIP_FACTORY;
protected:
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
QString outputName() const override;
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override;
QgsProcessingFeatureSource::Flag sourceFlags() const override;
bool supportInPlaceEdit( const QgsMapLayer *l ) const override;
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
private:
double mMValue = 0.0;
bool mDynamicMValue = false;
QgsProperty mMValueProperty;
};
///@endcond PRIVATE
#endif // QGSALGORITHMSETMVALUE_H

View File

@ -105,6 +105,7 @@
#include "qgsalgorithmsegmentize.h"
#include "qgsalgorithmserviceareafromlayer.h"
#include "qgsalgorithmserviceareafrompoint.h"
#include "qgsalgorithmsetmvalue.h"
#include "qgsalgorithmshortestpathlayertopoint.h"
#include "qgsalgorithmshortestpathpointtolayer.h"
#include "qgsalgorithmshortestpathpointtopoint.h"
@ -279,6 +280,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsSelectByLocationAlgorithm() );
addAlgorithm( new QgsServiceAreaFromLayerAlgorithm() );
addAlgorithm( new QgsServiceAreaFromPointAlgorithm() );
addAlgorithm( new QgsSetMValueAlgorithm() );
addAlgorithm( new QgsShortestPathLayerToPointAlgorithm() );
addAlgorithm( new QgsShortestPathPointToLayerAlgorithm() );
addAlgorithm( new QgsShortestPathPointToPointAlgorithm() );