diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml index 858729302c9..333746b81cc 100644 --- a/python/plugins/processing/algs/help/qgis.yaml +++ b/python/plugins/processing/algs/help/qgis.yaml @@ -447,11 +447,6 @@ qgis:selectbyexpression: > For more information about expressions see the user manual -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. diff --git a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py index 2a4ee9f8bab..67730fa3c3a 100644 --- a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py @@ -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(), diff --git a/python/plugins/processing/algs/qgis/SetMValue.py b/python/plugins/processing/algs/qgis/SetMValue.py deleted file mode 100644 index c932194a6f0..00000000000 --- a/python/plugins/processing/algs/qgis/SetMValue.py +++ /dev/null @@ -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()) diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index aa335c8e5fc..1e0585ffae4 100644 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -865,7 +865,7 @@ tests: name: expected/multiline_boundary.gml type: vector - - algorithm: qgis:setmvalue + - algorithm: native:setmvalue name: Set M Value params: INPUT: diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt index 29fe9404066..7214bd6fd67 100644 --- a/src/analysis/CMakeLists.txt +++ b/src/analysis/CMakeLists.txt @@ -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 diff --git a/src/analysis/processing/qgsalgorithmsetmvalue.cpp b/src/analysis/processing/qgsalgorithmsetmvalue.cpp new file mode 100644 index 00000000000..212396b0660 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmsetmvalue.cpp @@ -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 ¶meters, 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 diff --git a/src/analysis/processing/qgsalgorithmsetmvalue.h b/src/analysis/processing/qgsalgorithmsetmvalue.h new file mode 100644 index 00000000000..931e220d851 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmsetmvalue.h @@ -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 ¶meters, 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 diff --git a/src/analysis/processing/qgsnativealgorithms.cpp b/src/analysis/processing/qgsnativealgorithms.cpp index c0c20f3de41..37d971ac95c 100644 --- a/src/analysis/processing/qgsnativealgorithms.cpp +++ b/src/analysis/processing/qgsnativealgorithms.cpp @@ -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() );