Skip to content
Permalink
Browse files

Merge pull request #6486 from nyalldawson/dynamic

[processing] Support dynamic properties for all native c++ algorithms
  • Loading branch information
nyalldawson committed Feb 28, 2018
2 parents 71d1074 + 5986444 commit b17a5560b87b44a72e9421e5f8132e18fba98916
@@ -112,7 +112,7 @@ def executeAlgorithm(self):
if isinstance(item, TreeLogEntryItem):
if item.isAlg:
script = 'import processing\n'
script += 'from qgis.core import QgsProcessingOutputLayerDefinition, QgsProcessingFeatureSourceDefinition\n'
script += 'from qgis.core import QgsProcessingOutputLayerDefinition, QgsProcessingFeatureSourceDefinition, QgsProperty\n'
script += item.entry.text.replace('processing.run(', 'processing.execAlgorithmDialog(')
self.close()
exec(script)
@@ -70,27 +70,52 @@ QgsAlgorithmRemoveDuplicateVertices *QgsAlgorithmRemoveDuplicateVertices::create

void QgsAlgorithmRemoveDuplicateVertices::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "TOLERANCE" ),
QObject::tr( "Tolerance" ), QgsProcessingParameterNumber::Double,
0.000001, false, 0, 10000000.0 ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "USE_Z_VALUE" ),
QObject::tr( "Use Z Value" ), false ) );
std::unique_ptr< QgsProcessingParameterNumber> tolerance = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "TOLERANCE" ),
QObject::tr( "Tolerance" ), QgsProcessingParameterNumber::Double,
0.000001, false, 0, 10000000.0 );
tolerance->setIsDynamic( true );
tolerance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Tolerance" ), QObject::tr( "Tolerance distance" ), QgsPropertyDefinition::DoublePositive ) );
tolerance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( tolerance.release() );

std::unique_ptr< QgsProcessingParameterBoolean > useZ = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "USE_Z_VALUE" ),
QObject::tr( "Use Z Value" ), false );
useZ->setIsDynamic( true );
useZ->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "UseZ" ), QObject::tr( "Use Z Value" ), QgsPropertyDefinition::Boolean ) );
useZ->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( useZ.release() );
}

bool QgsAlgorithmRemoveDuplicateVertices::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mTolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context );
mDynamicTolerance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "TOLERANCE" ) );
if ( mDynamicTolerance )
mToleranceProperty = parameters.value( QStringLiteral( "TOLERANCE" ) ).value< QgsProperty >();

mUseZValues = parameterAsBool( parameters, QStringLiteral( "USE_Z_VALUE" ), context );
mDynamicUseZ = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "USE_Z_VALUE" ) );
if ( mDynamicUseZ )
mUseZProperty = parameters.value( QStringLiteral( "USE_Z_VALUE" ) ).value< QgsProperty >();

return true;
}

QgsFeatureList QgsAlgorithmRemoveDuplicateVertices::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
QgsFeatureList QgsAlgorithmRemoveDuplicateVertices::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
QgsGeometry geometry = f.geometry();
geometry.removeDuplicateNodes( mTolerance, mUseZValues );
double tolerance = mTolerance;
if ( mDynamicTolerance )
tolerance = mToleranceProperty.valueAsDouble( context.expressionContext(), tolerance );

bool useZValue = mUseZValues;
if ( mDynamicUseZ )
useZValue = mUseZProperty.valueAsBool( context.expressionContext(), useZValue );

geometry.removeDuplicateNodes( tolerance, useZValue );
f.setGeometry( geometry );
}
return QgsFeatureList() << f;
@@ -51,8 +51,12 @@ class QgsAlgorithmRemoveDuplicateVertices : public QgsProcessingFeatureBasedAlgo
private:

double mTolerance = 1.0;
bool mUseZValues = false;
bool mDynamicTolerance = false;
QgsProperty mToleranceProperty;

bool mUseZValues = false;
bool mDynamicUseZ = false;
QgsProperty mUseZProperty;
};


@@ -78,22 +78,30 @@ void QgsSimplifyAlgorithm::initParameters( const QVariantMap & )
QStringLiteral( "METHOD" ),
QObject::tr( "Simplification method" ),
methods, false, 0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "TOLERANCE" ),
QObject::tr( "Tolerance" ), QgsProcessingParameterNumber::Double,
1.0, false, 0, 10000000.0 ) );
std::unique_ptr< QgsProcessingParameterNumber > tolerance = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "TOLERANCE" ),
QObject::tr( "Tolerance" ), QgsProcessingParameterNumber::Double,
1.0, false, 0, 10000000.0 );
tolerance->setIsDynamic( true );
tolerance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Tolerance" ), QObject::tr( "Tolerance distance" ), QgsPropertyDefinition::DoublePositive ) );
tolerance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( tolerance.release() );
}

bool QgsSimplifyAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mTolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context );
mDynamicTolerance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "TOLERANCE" ) );
if ( mDynamicTolerance )
mToleranceProperty = parameters.value( QStringLiteral( "TOLERANCE" ) ).value< QgsProperty >();

mMethod = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );
if ( mMethod != QgsMapToPixelSimplifier::Distance )
mSimplifier.reset( new QgsMapToPixelSimplifier( QgsMapToPixelSimplifier::SimplifyGeometry, mTolerance, mMethod ) );

return true;
}

QgsFeatureList QgsSimplifyAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
QgsFeatureList QgsSimplifyAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
@@ -102,11 +110,23 @@ QgsFeatureList QgsSimplifyAlgorithm::processFeature( const QgsFeature &feature,
QgsGeometry outputGeometry;
if ( mMethod == QgsMapToPixelSimplifier::Distance )
{
outputGeometry = inputGeometry.simplify( mTolerance );
double tolerance = mTolerance;
if ( mDynamicTolerance )
tolerance = mToleranceProperty.valueAsDouble( context.expressionContext(), tolerance );
outputGeometry = inputGeometry.simplify( tolerance );
}
else
{
outputGeometry = mSimplifier->simplify( inputGeometry );
if ( !mDynamicTolerance )
{
outputGeometry = mSimplifier->simplify( inputGeometry );
}
else
{
double tolerance = mToleranceProperty.valueAsDouble( context.expressionContext(), mTolerance );
QgsMapToPixelSimplifier simplifier( QgsMapToPixelSimplifier::SimplifyGeometry, tolerance, mMethod );
outputGeometry = simplifier.simplify( inputGeometry );
}
}
f.setGeometry( outputGeometry );
}
@@ -53,6 +53,8 @@ class QgsSimplifyAlgorithm : public QgsProcessingFeatureBasedAlgorithm
private:

double mTolerance = 1.0;
bool mDynamicTolerance = false;
QgsProperty mToleranceProperty;
QgsMapToPixelSimplifier::SimplifyAlgorithm mMethod = QgsMapToPixelSimplifier::Distance;
std::unique_ptr< QgsMapToPixelSimplifier > mSimplifier;

@@ -82,31 +82,69 @@ QList<int> QgsSmoothAlgorithm::inputLayerTypes() const

void QgsSmoothAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "ITERATIONS" ),
QObject::tr( "Iterations" ), QgsProcessingParameterNumber::Integer,
1, false, 1, 10 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "OFFSET" ),
QObject::tr( "Offset" ), QgsProcessingParameterNumber::Double,
0.25, false, 0.0, 0.5 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MAX_ANGLE" ),
QObject::tr( "Maximum node angle to smooth" ), QgsProcessingParameterNumber::Double,
180.0, false, 0.0, 180.0 ) );
std::unique_ptr< QgsProcessingParameterNumber > iterations = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "ITERATIONS" ),
QObject::tr( "Iterations" ), QgsProcessingParameterNumber::Integer,
1, false, 1, 10 );
iterations->setIsDynamic( true );
iterations->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "ITERATIONS" ), QObject::tr( "Iterations" ), QgsPropertyDefinition::IntegerPositiveGreaterZero ) );
iterations->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( iterations.release() );

std::unique_ptr< QgsProcessingParameterNumber > offset = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "OFFSET" ),
QObject::tr( "Offset" ), QgsProcessingParameterNumber::Double,
0.25, false, 0.0, 0.5 );
offset->setIsDynamic( true );
offset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "OFFSET" ), QObject::tr( "Offset" ), QgsPropertyDefinition::Double0To1 ) );
offset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( offset.release() );

std::unique_ptr< QgsProcessingParameterNumber > maxAngle = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MAX_ANGLE" ),
QObject::tr( "Maximum node angle to smooth" ), QgsProcessingParameterNumber::Double,
180.0, false, 0.0, 180.0 );
maxAngle->setIsDynamic( true );
maxAngle->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "MAX_ANGLE" ), QObject::tr( "Maximum node angle to smooth" ), QgsPropertyDefinition::Rotation ) );
maxAngle->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( maxAngle.release() );
}

bool QgsSmoothAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mIterations = parameterAsInt( parameters, QStringLiteral( "ITERATIONS" ), context );
mDynamicIterations = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ITERATIONS" ) );
if ( mDynamicIterations )
mIterationsProperty = parameters.value( QStringLiteral( "ITERATIONS" ) ).value< QgsProperty >();

mOffset = parameterAsDouble( parameters, QStringLiteral( "OFFSET" ), context );
mDynamicOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "OFFSET" ) );
if ( mDynamicOffset )
mOffsetProperty = parameters.value( QStringLiteral( "OFFSET" ) ).value< QgsProperty >();

mMaxAngle = parameterAsDouble( parameters, QStringLiteral( "MAX_ANGLE" ), context );
mDynamicMaxAngle = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "MAX_ANGLE" ) );
if ( mDynamicMaxAngle )
mMaxAngleProperty = parameters.value( QStringLiteral( "MAX_ANGLE" ) ).value< QgsProperty >();

return true;
}

QgsFeatureList QgsSmoothAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
QgsFeatureList QgsSmoothAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
QgsGeometry outputGeometry = f.geometry().smooth( mIterations, mOffset, -1, mMaxAngle );
int iterations = mIterations;
if ( mDynamicIterations )
iterations = mIterationsProperty.valueAsInt( context.expressionContext(), iterations );

double offset = mOffset;
if ( mDynamicOffset )
offset = mOffsetProperty.valueAsDouble( context.expressionContext(), offset );

double maxAngle = mMaxAngle;
if ( mDynamicMaxAngle )
maxAngle = mMaxAngleProperty.valueAsDouble( context.expressionContext(), maxAngle );

QgsGeometry outputGeometry = f.geometry().smooth( iterations, offset, -1, maxAngle );
if ( !outputGeometry )
{
feedback->reportError( QObject::tr( "Error smoothing geometry %1" ).arg( feature.id() ) );
@@ -52,8 +52,16 @@ class QgsSmoothAlgorithm : public QgsProcessingFeatureBasedAlgorithm

private:
int mIterations = 1;
bool mDynamicIterations = false;
QgsProperty mIterationsProperty;

double mOffset = 0.25;
bool mDynamicOffset = false;
QgsProperty mOffsetProperty;

double mMaxAngle = 0;
bool mDynamicMaxAngle = false;
QgsProperty mMaxAngleProperty;
};

///@endcond PRIVATE
@@ -67,35 +67,86 @@ QgsSnapToGridAlgorithm *QgsSnapToGridAlgorithm::createInstance() const

void QgsSnapToGridAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "HSPACING" ),
QObject::tr( "X Grid Spacing" ), QgsProcessingParameterNumber::Double,
1, false, 0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "VSPACING" ),
QObject::tr( "Y Grid Spacing" ), QgsProcessingParameterNumber::Double,
1, false, 0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "ZSPACING" ),
QObject::tr( "Z Grid Spacing" ), QgsProcessingParameterNumber::Double,
0, false, 0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MSPACING" ),
QObject::tr( "M Grid Spacing" ), QgsProcessingParameterNumber::Double,
0, false, 0 ) );
std::unique_ptr< QgsProcessingParameterNumber> hSpacing = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "HSPACING" ),
QObject::tr( "X Grid Spacing" ), QgsProcessingParameterNumber::Double,
1, false, 0 );
hSpacing->setIsDynamic( true );
hSpacing->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "HSPACING" ), QObject::tr( "X Grid Spacing" ), QgsPropertyDefinition::DoublePositive ) );
hSpacing->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( hSpacing.release() );

std::unique_ptr< QgsProcessingParameterNumber> vSpacing = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "VSPACING" ),
QObject::tr( "Y Grid Spacing" ), QgsProcessingParameterNumber::Double,
1, false, 0 );
vSpacing->setIsDynamic( true );
vSpacing->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "VSPACING" ), QObject::tr( "Y Grid Spacing" ), QgsPropertyDefinition::DoublePositive ) );
vSpacing->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( vSpacing.release() );

std::unique_ptr< QgsProcessingParameterNumber > zSpacing = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "ZSPACING" ),
QObject::tr( "Z Grid Spacing" ), QgsProcessingParameterNumber::Double,
0, false, 0 );
zSpacing->setIsDynamic( true );
zSpacing->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "ZSPACING" ), QObject::tr( "Z Grid Spacing" ), QgsPropertyDefinition::DoublePositive ) );
zSpacing->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( zSpacing.release() );

std::unique_ptr< QgsProcessingParameterNumber > mSpacing = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MSPACING" ),
QObject::tr( "M Grid Spacing" ), QgsProcessingParameterNumber::Double,
0, false, 0 );
mSpacing->setIsDynamic( true );
mSpacing->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "MSPACING" ), QObject::tr( "M Grid Spacing" ), QgsPropertyDefinition::DoublePositive ) );
mSpacing->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( mSpacing.release() );
}

bool QgsSnapToGridAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mIntervalX = parameterAsDouble( parameters, QStringLiteral( "HSPACING" ), context );
mDynamicIntervalX = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "HSPACING" ) );
if ( mDynamicIntervalX )
mIntervalXProperty = parameters.value( QStringLiteral( "HSPACING" ) ).value< QgsProperty >();

mIntervalY = parameterAsDouble( parameters, QStringLiteral( "VSPACING" ), context );
mDynamicIntervalY = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "VSPACING" ) );
if ( mDynamicIntervalY )
mIntervalYProperty = parameters.value( QStringLiteral( "VSPACING" ) ).value< QgsProperty >();

mIntervalZ = parameterAsDouble( parameters, QStringLiteral( "ZSPACING" ), context );
mDynamicIntervalZ = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ZSPACING" ) );
if ( mDynamicIntervalZ )
mIntervalZProperty = parameters.value( QStringLiteral( "ZSPACING" ) ).value< QgsProperty >();

mIntervalM = parameterAsDouble( parameters, QStringLiteral( "MSPACING" ), context );
mDynamicIntervalM = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "MSPACING" ) );
if ( mDynamicIntervalM )
mIntervalMProperty = parameters.value( QStringLiteral( "MSPACING" ) ).value< QgsProperty >();

return true;
}

QgsFeatureList QgsSnapToGridAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
QgsFeatureList QgsSnapToGridAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
QgsGeometry outputGeometry = f.geometry().snappedToGrid( mIntervalX, mIntervalY, mIntervalZ, mIntervalM );
double intervalX = mIntervalX;
if ( mDynamicIntervalX )
intervalX = mIntervalXProperty.valueAsDouble( context.expressionContext(), intervalX );

double intervalY = mIntervalY;
if ( mDynamicIntervalY )
intervalY = mIntervalYProperty.valueAsDouble( context.expressionContext(), intervalY );

double intervalZ = mIntervalZ;
if ( mDynamicIntervalZ )
intervalZ = mIntervalZProperty.valueAsDouble( context.expressionContext(), intervalZ );

double intervalM = mIntervalM;
if ( mDynamicIntervalM )
intervalM = mIntervalMProperty.valueAsDouble( context.expressionContext(), intervalM );

QgsGeometry outputGeometry = f.geometry().snappedToGrid( intervalX, intervalY, intervalZ, intervalM );
if ( !outputGeometry )
{
feedback->reportError( QObject::tr( "Error snapping geometry %1" ).arg( feature.id() ) );
@@ -50,9 +50,21 @@ class QgsSnapToGridAlgorithm : public QgsProcessingFeatureBasedAlgorithm

private:
double mIntervalX = 0.0;
bool mDynamicIntervalX = false;
QgsProperty mIntervalXProperty;

double mIntervalY = 0.0;
bool mDynamicIntervalY = false;
QgsProperty mIntervalYProperty;

double mIntervalZ = 0.0;
bool mDynamicIntervalZ = false;
QgsProperty mIntervalZProperty;

double mIntervalM = 0.0;
bool mDynamicIntervalM = false;
QgsProperty mIntervalMProperty;

};

///@endcond PRIVATE

0 comments on commit b17a556

Please sign in to comment.
You can’t perform that action at this time.