Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #4868 from nyalldawson/nn
Port Remove Null Geometries algorithm to c++/new API
  • Loading branch information
nyalldawson committed Jul 16, 2017
2 parents 261391d + 1342f4d commit 23a4d60
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 97 deletions.
Expand Up @@ -293,7 +293,7 @@ class QgsProcessingModelAlgorithm : QgsProcessingAlgorithm
%End

QList< QgsProcessingModelChildParameterSource > availableSourcesForChild( const QString &childId, const QStringList &parameterTypes = QStringList(),
const QStringList &outputTypes = QStringList(), const QList< int > dataTypes = QList< int >() ) const;
const QStringList &outputTypes = QStringList(), const QList< int > &dataTypes = QList< int >() ) const;
%Docstring
Returns a list of possible sources which can be used for the parameters for a child
algorithm in the model. Returned sources are those which match either one of the
Expand Down
15 changes: 15 additions & 0 deletions python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -1636,6 +1636,21 @@ class QgsProcessingDestinationParameter : QgsProcessingParameterDefinition
:rtype: str
%End

bool createByDefault() const;
%Docstring
Returns true if the destination should be created by default. For optional parameters,
a return value of false indicates that the destination should not be created by default.
.. seealso:: setCreateByDefault()
:rtype: bool
%End

void setCreateByDefault( bool createByDefault );
%Docstring
Sets whether the destination should be created by default. For optional parameters,
a value of false indicates that the destination should not be created by default.
.. seealso:: createByDefault()
%End

};


Expand Down
2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Expand Up @@ -152,7 +152,6 @@
# from .Relief import Relief
# from .IdwInterpolation import IdwInterpolation
# from .TinInterpolation import TinInterpolation
# from .RemoveNullGeometry import RemoveNullGeometry
# from .ExtendLines import ExtendLines
# from .ExtractSpecificNodes import ExtractSpecificNodes
# from .GeometryByExpression import GeometryByExpression
Expand Down Expand Up @@ -220,7 +219,6 @@ def getAlgs(self):
# Slope(), Ruggedness(), Hillshade(),
# Relief(),
# IdwInterpolation(), TinInterpolation(),
# RemoveNullGeometry(),
# ExtendLines(), ExtractSpecificNodes(),
# GeometryByExpression(),
# PoleOfInaccessibility(),
Expand Down
76 changes: 0 additions & 76 deletions python/plugins/processing/algs/qgis/RemoveNullGeometry.py

This file was deleted.

2 changes: 1 addition & 1 deletion python/plugins/processing/gui/DestinationSelectionPanel.py
Expand Up @@ -72,7 +72,7 @@ def __init__(self, parameter, alg):
self.use_temporary = True

if hasattr(self.leText, 'setPlaceholderText'):
if parameter.flags() & QgsProcessingParameterDefinition.FlagOptional and parameter.defaultValue() is None:
if parameter.flags() & QgsProcessingParameterDefinition.FlagOptional and not parameter.createByDefault():
self.leText.setPlaceholderText(self.SKIP_OUTPUT)
self.use_temporary = False
elif isinstance(self.parameter, QgsProcessingParameterFeatureSink) \
Expand Down
22 changes: 11 additions & 11 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -1258,17 +1258,17 @@ tests:
# #TRIANULATION_FILE:
# # name: expected/triangulation.gml
# # type: vector
#
# - algorithm: qgis:removenullgeometries
# name: Remove null geometries
# params:
# INPUT_LAYER:
# name: polys.gml
# type: vector
# results:
# OUTPUT_LAYER:
# name: expected/remove_null_polys.gml
# type: vector

- algorithm: native:removenullgeometries
name: Remove null geometries
params:
INPUT:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/remove_null_polys.gml
type: vector
#
- algorithm: native:extractbyexpression
name: Extract by Expression
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/models/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -566,7 +566,7 @@ QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextS
return scope.release();
}

QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( const QString &childId, const QStringList &parameterTypes, const QStringList &outputTypes, const QList<int> dataTypes ) const
QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( const QString &childId, const QStringList &parameterTypes, const QStringList &outputTypes, const QList<int> &dataTypes ) const
{
QgsProcessingModelChildParameterSources sources;

Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/models/qgsprocessingmodelalgorithm.h
Expand Up @@ -296,7 +296,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
* sources to those with compatible data types for the parameter/outputs.
*/
QList< QgsProcessingModelChildParameterSource > availableSourcesForChild( const QString &childId, const QStringList &parameterTypes = QStringList(),
const QStringList &outputTypes = QStringList(), const QList< int > dataTypes = QList< int >() ) const;
const QStringList &outputTypes = QStringList(), const QList< int > &dataTypes = QList< int >() ) const;

/**
* Definition of a expression context variable available during model execution.
Expand Down
89 changes: 85 additions & 4 deletions src/core/processing/qgsnativealgorithms.cpp
Expand Up @@ -67,6 +67,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsMultipartToSinglepartAlgorithm() );
addAlgorithm( new QgsSubdivideAlgorithm() );
addAlgorithm( new QgsTransformAlgorithm() );
addAlgorithm( new QgsRemoveNullGeometryAlgorithm() );
}

void QgsCentroidAlgorithm::initAlgorithm( const QVariantMap & )
Expand Down Expand Up @@ -787,8 +788,10 @@ void QgsExtractByExpressionAlgorithm::initAlgorithm( const QVariantMap & )
addParameter( new QgsProcessingParameterExpression( QStringLiteral( "EXPRESSION" ), QObject::tr( "Expression" ), QVariant(), QStringLiteral( "INPUT" ) ) );

addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Matching features" ) ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Non-matching" ),
QgsProcessing::TypeVectorAny, QVariant(), true ) );
QgsProcessingParameterFeatureSink *failOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Non-matching" ),
QgsProcessing::TypeVectorAny, QVariant(), true );
failOutput->setCreateByDefault( false );
addParameter( failOutput );
}

QString QgsExtractByExpressionAlgorithm::shortHelpString() const
Expand Down Expand Up @@ -916,8 +919,10 @@ void QgsExtractByAttributeAlgorithm::initAlgorithm( const QVariantMap & )
addParameter( new QgsProcessingParameterString( QStringLiteral( "VALUE" ), QObject::tr( "Value" ), QVariant(), false, true ) );

addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extracted (attribute)" ) ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Extracted (non-matching)" ),
QgsProcessing::TypeVectorAny, QVariant(), true ) );
QgsProcessingParameterFeatureSink *failOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Extracted (non-matching)" ),
QgsProcessing::TypeVectorAny, QVariant(), true );
failOutput->setCreateByDefault( false );
addParameter( failOutput );
}

QString QgsExtractByAttributeAlgorithm::shortHelpString() const
Expand Down Expand Up @@ -1093,4 +1098,80 @@ QVariantMap QgsExtractByAttributeAlgorithm::processAlgorithm( const QVariantMap
return outputs;
}


void QgsRemoveNullGeometryAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );

addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Non null geometries" ),
QgsProcessing::TypeVectorAny, QVariant(), true ) );
QgsProcessingParameterFeatureSink *nullOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "NULL_OUTPUT" ), QObject::tr( "Null geometries" ),
QgsProcessing::TypeTable, QVariant(), true );
nullOutput->setCreateByDefault( false );
addParameter( nullOutput );
}

QString QgsRemoveNullGeometryAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm removes any features which do not have a geometry from a vector layer. "
"All other features will be copied unchanged.\n\n"
"Optionally, the features with null geometries can be saved to a separate output." );
}

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

QVariantMap QgsRemoveNullGeometryAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
if ( !source )
return QVariantMap();

QString nonNullSinkId;
std::unique_ptr< QgsFeatureSink > nonNullSink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, nonNullSinkId, source->fields(),
source->wkbType(), source->sourceCrs() ) );

QString nullSinkId;
std::unique_ptr< QgsFeatureSink > nullSink( parameterAsSink( parameters, QStringLiteral( "NULL_OUTPUT" ), context, nullSinkId, source->fields() ) );

long count = source->featureCount();
if ( count <= 0 )
return QVariantMap();

double step = 100.0 / count;
int current = 0;

QgsFeature f;
QgsFeatureIterator it = source->getFeatures();
while ( it.nextFeature( f ) )
{
if ( feedback->isCanceled() )
{
break;
}

if ( f.hasGeometry() && nonNullSink )
{
nonNullSink->addFeature( f, QgsFeatureSink::FastInsert );
}
else if ( !f.hasGeometry() && nullSink )
{
nullSink->addFeature( f, QgsFeatureSink::FastInsert );
}

feedback->setProgress( current * step );
current++;
}

QVariantMap outputs;
if ( nonNullSink )
outputs.insert( QStringLiteral( "OUTPUT" ), nonNullSinkId );
if ( nullSink )
outputs.insert( QStringLiteral( "NULL_OUTPUT" ), nullSinkId );
return outputs;
}


///@endcond
25 changes: 25 additions & 0 deletions src/core/processing/qgsnativealgorithms.h
Expand Up @@ -278,6 +278,31 @@ class QgsMultipartToSinglepartAlgorithm : public QgsProcessingAlgorithm

};


/**
* Remove null geometry algorithm.
*/
class QgsRemoveNullGeometryAlgorithm : public QgsProcessingAlgorithm
{

public:

QgsRemoveNullGeometryAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override { return QStringLiteral( "removenullgeometries" ); }
QString displayName() const override { return QObject::tr( "Remove null geometries" ); }
virtual QStringList tags() const override { return QObject::tr( "remove,drop,delete,empty,geometry" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector selection tools" ); }
QString shortHelpString() const override;
QgsRemoveNullGeometryAlgorithm *createInstance() const override SIP_FACTORY;

protected:

virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

};

///@endcond PRIVATE

#endif // QGSNATIVEALGORITHMS_H
Expand Down
12 changes: 12 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -2917,13 +2917,15 @@ QVariantMap QgsProcessingDestinationParameter::toVariantMap() const
{
QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
map.insert( QStringLiteral( "supports_non_file_outputs" ), mSupportsNonFileBasedOutputs );
map.insert( QStringLiteral( "create_by_default" ), mCreateByDefault );
return map;
}

bool QgsProcessingDestinationParameter::fromVariantMap( const QVariantMap &map )
{
QgsProcessingParameterDefinition::fromVariantMap( map );
mSupportsNonFileBasedOutputs = map.value( QStringLiteral( "supports_non_file_outputs" ) ).toBool();
mCreateByDefault = map.value( QStringLiteral( "create_by_default" ), QStringLiteral( "1" ) ).toBool();
return true;
}

Expand All @@ -2932,6 +2934,16 @@ QString QgsProcessingDestinationParameter::generateTemporaryDestination() const
return QgsProcessingUtils::generateTempFilename( name() + '.' + defaultFileExtension() );
}

bool QgsProcessingDestinationParameter::createByDefault() const
{
return mCreateByDefault;
}

void QgsProcessingDestinationParameter::setCreateByDefault( bool createByDefault )
{
mCreateByDefault = createByDefault;
}

QgsProcessingParameterVectorDestination::QgsProcessingParameterVectorDestination( const QString &name, const QString &description, QgsProcessing::LayerType type, const QVariant &defaultValue, bool optional )
: QgsProcessingDestinationParameter( name, description, defaultValue, optional )
, mDataType( type )
Expand Down
15 changes: 15 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -1555,9 +1555,24 @@ class CORE_EXPORT QgsProcessingDestinationParameter : public QgsProcessingParame
*/
virtual QString generateTemporaryDestination() const;

/**
* Returns true if the destination should be created by default. For optional parameters,
* a return value of false indicates that the destination should not be created by default.
* \see setCreateByDefault()
*/
bool createByDefault() const;

/**
* Sets whether the destination should be created by default. For optional parameters,
* a value of false indicates that the destination should not be created by default.
* \see createByDefault()
*/
void setCreateByDefault( bool createByDefault );

private:

bool mSupportsNonFileBasedOutputs = true;
bool mCreateByDefault = true;

};

Expand Down

0 comments on commit 23a4d60

Please sign in to comment.