Skip to content

Commit

Permalink
Add multipart option for processing geometry parameter
Browse files Browse the repository at this point in the history
(cherry picked from commit 9eb172a)
  • Loading branch information
dmarteau authored and nyalldawson committed Apr 17, 2021
1 parent a339465 commit 7a74d7f
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 8 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1650,12 +1650,13 @@ A geometry parameter for processing algorithms.
%End %End
public: public:


QgsProcessingParameterGeometry( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(), bool optional = false, const QList< int > &geometryTypes = QList< int >() ); QgsProcessingParameterGeometry( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(), bool optional = false, const QList< int > &geometryTypes = QList< int >(), bool allowMultipart = true );
%Docstring %Docstring
Constructor for QgsProcessingParameterGeometry. Constructor for QgsProcessingParameterGeometry.


The ``geometryTypes`` argument allows for specifying a list of geometry types (see QgsWkbTypes.GeometryType) acceptable for this The ``geometryTypes`` argument allows for specifying a list of geometry types (see QgsWkbTypes.GeometryType) acceptable for this
parameter. Passing a empty list will allow for any type of geometry. parameter. Passing a empty list will allow for any type of geometry.
The ``allowMultiPart`` argument allows specifying a multi part geometry
%End %End


static QString typeName(); static QString typeName();
Expand Down Expand Up @@ -1692,6 +1693,22 @@ Sets the allowed ``geometryTypes``, as a list of QgsWkbTypes.GeometryType value
.. seealso:: :py:func:`geometryTypes` .. seealso:: :py:func:`geometryTypes`
%End %End


bool allowMultipart() const;
%Docstring
Returns the parameter allow multipart geometries.

.. seealso:: :py:func:`setAllowMultipart`
%End

void setAllowMultipart( bool allowMultipart );
%Docstring
Sets the allow multipart geometries

.. seealso:: :py:func:`allowMultipart`
%End



static QgsProcessingParameterGeometry *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/; static QgsProcessingParameterGeometry *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring %Docstring
Creates a new parameter using the definition from a script code. Creates a new parameter using the definition from a script code.
Expand Down
2 changes: 2 additions & 0 deletions python/plugins/processing/core/parameters.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ def getParameterFromString(s, context=''):
params[4] = [int(p) for p in params[4].split(';')] params[4] = [int(p) for p in params[4].split(';')]
except: except:
params[4] = [getattr(QgsWkbTypes, p.split(".")[1]) for p in params[4].split(';')] params[4] = [getattr(QgsWkbTypes, p.split(".")[1]) for p in params[4].split(';')]
if len(params) > 5:
params[5] = True if params[5].lower() == 'true' else False
elif clazz == QgsProcessingParameterCrs: elif clazz == QgsProcessingParameterCrs:
if len(params) > 3: if len(params) > 3:
params[3] = True if params[3].lower() == 'true' else False params[3] = True if params[3].lower() == 'true' else False
Expand Down
22 changes: 16 additions & 6 deletions src/core/processing/qgsprocessingparameters.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2959,9 +2959,10 @@ QgsProcessingParameterPoint *QgsProcessingParameterPoint::fromScriptCode( const
} }


QgsProcessingParameterGeometry::QgsProcessingParameterGeometry( const QString &name, const QString &description, QgsProcessingParameterGeometry::QgsProcessingParameterGeometry( const QString &name, const QString &description,
const QVariant &defaultValue, bool optional, const QList<int> &geometryTypes ) const QVariant &defaultValue, bool optional, const QList<int> &geometryTypes, bool allowMultipart )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional ), : QgsProcessingParameterDefinition( name, description, defaultValue, optional ),
mGeomTypes( geometryTypes ) mGeomTypes( geometryTypes ),
mAllowMultipart( allowMultipart )
{ {


} }
Expand All @@ -2985,12 +2986,14 @@ bool QgsProcessingParameterGeometry::checkValueIsAcceptable( const QVariant &inp


if ( input.canConvert< QgsGeometry >() ) if ( input.canConvert< QgsGeometry >() )
{ {
return anyTypeAllowed || mGeomTypes.contains( input.value<QgsGeometry>().type() ); return ( anyTypeAllowed || mGeomTypes.contains( input.value<QgsGeometry>().type() ) ) &&
( mAllowMultipart || !input.value<QgsGeometry>().isMultipart() );
} }


if ( input.canConvert< QgsReferencedGeometry >() ) if ( input.canConvert< QgsReferencedGeometry >() )
{ {
return anyTypeAllowed || mGeomTypes.contains( input.value<QgsReferencedGeometry>().type() ); return ( anyTypeAllowed || mGeomTypes.contains( input.value<QgsReferencedGeometry>().type() ) ) &&
( mAllowMultipart || !input.value<QgsReferencedGeometry>().isMultipart() );
} }


if ( input.canConvert< QgsPointXY >() ) if ( input.canConvert< QgsPointXY >() )
Expand Down Expand Up @@ -3028,7 +3031,7 @@ bool QgsProcessingParameterGeometry::checkValueIsAcceptable( const QVariant &inp
QgsGeometry g = QgsGeometry::fromWkt( match.captured( 2 ) ); QgsGeometry g = QgsGeometry::fromWkt( match.captured( 2 ) );
if ( ! g.isNull() ) if ( ! g.isNull() )
{ {
return anyTypeAllowed || mGeomTypes.contains( g.type() ); return ( anyTypeAllowed || mGeomTypes.contains( g.type() ) ) && ( mAllowMultipart || !g.isMultipart() );
} }
else else
{ {
Expand Down Expand Up @@ -3123,7 +3126,7 @@ QString QgsProcessingParameterGeometry::asScriptCode() const
break; break;


default: default:
code += QLatin1String( "unknown" ); code += QLatin1String( "unknown " );
break; break;
} }
} }
Expand Down Expand Up @@ -3175,6 +3178,11 @@ QString QgsProcessingParameterGeometry::asPythonString( const QgsProcessing::Pyt
code += QStringLiteral( ", geometryTypes=[%1 ]" ).arg( options.join( ',' ) ); code += QStringLiteral( ", geometryTypes=[%1 ]" ).arg( options.join( ',' ) );
} }


if ( ! mAllowMultipart )
{
code += QStringLiteral( ", allowMultipart=False" );
}

QgsProcessingContext c; QgsProcessingContext c;
code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) ); code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
return code; return code;
Expand All @@ -3192,6 +3200,7 @@ QVariantMap QgsProcessingParameterGeometry::toVariantMap() const
types << type; types << type;
} }
map.insert( QStringLiteral( "geometrytypes" ), types ); map.insert( QStringLiteral( "geometrytypes" ), types );
map.insert( QStringLiteral( "multipart" ), mAllowMultipart );
return map; return map;
} }


Expand All @@ -3204,6 +3213,7 @@ bool QgsProcessingParameterGeometry::fromVariantMap( const QVariantMap &map )
{ {
mGeomTypes << val.toInt(); mGeomTypes << val.toInt();
} }
mAllowMultipart = map.value( QStringLiteral( "multipart" ) ).toBool();
return true; return true;
} }


Expand Down
18 changes: 17 additions & 1 deletion src/core/processing/qgsprocessingparameters.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1687,8 +1687,9 @@ class CORE_EXPORT QgsProcessingParameterGeometry : public QgsProcessingParameter
* *
* The \a geometryTypes argument allows for specifying a list of geometry types (see QgsWkbTypes::GeometryType) acceptable for this * The \a geometryTypes argument allows for specifying a list of geometry types (see QgsWkbTypes::GeometryType) acceptable for this
* parameter. Passing a empty list will allow for any type of geometry. * parameter. Passing a empty list will allow for any type of geometry.
* The \a allowMultiPart argument allows specifying a multi part geometry
*/ */
QgsProcessingParameterGeometry( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(), bool optional = false, const QList< int > &geometryTypes = QList< int >() ); QgsProcessingParameterGeometry( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(), bool optional = false, const QList< int > &geometryTypes = QList< int >(), bool allowMultipart = true );


/** /**
* Returns the type name for the parameter class. * Returns the type name for the parameter class.
Expand All @@ -1715,6 +1716,20 @@ class CORE_EXPORT QgsProcessingParameterGeometry : public QgsProcessingParameter
*/ */
void setGeometryTypes( const QList<int> &geometryTypes ) { mGeomTypes = geometryTypes; } void setGeometryTypes( const QList<int> &geometryTypes ) { mGeomTypes = geometryTypes; }


/**
* Returns the parameter allow multipart geometries.
* \see setAllowMultipart()
*/
bool allowMultipart() const { return mAllowMultipart; }

/**
* Sets the allow multipart geometries
* \see allowMultipart()
*/
void setAllowMultipart( bool allowMultipart ) { mAllowMultipart = allowMultipart; }



/** /**
* Creates a new parameter using the definition from a script code. * Creates a new parameter using the definition from a script code.
*/ */
Expand All @@ -1723,6 +1738,7 @@ class CORE_EXPORT QgsProcessingParameterGeometry : public QgsProcessingParameter
private: private:


QList<int> mGeomTypes; QList<int> mGeomTypes;
bool mAllowMultipart;


}; };


Expand Down
24 changes: 24 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3434,6 +3434,7 @@ void TestQgsProcessing::parameterGeometry()
QVERIFY( def->checkValueIsAcceptable( QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) ); QVERIFY( def->checkValueIsAcceptable( QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsRectangle( 10, 10, 20, 20 ) ) ); QVERIFY( def->checkValueIsAcceptable( QgsRectangle( 10, 10, 20, 20 ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle( 10, 10, 20, 20 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) ); QVERIFY( def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle( 10, 10, 20, 20 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
QVERIFY( def->checkValueIsAcceptable( QString( "MultiPoint((10 10), (20 20))" ) ) );


// string representing a geometry // string representing a geometry
QVariantMap params; QVariantMap params;
Expand Down Expand Up @@ -3601,9 +3602,32 @@ void TestQgsProcessing::parameterGeometry()
QCOMPARE( fromMap2.flags(), def->flags() ); QCOMPARE( fromMap2.flags(), def->flags() );
QCOMPARE( fromMap2.defaultValue(), def->defaultValue() ); QCOMPARE( fromMap2.defaultValue(), def->defaultValue() );
QCOMPARE( fromMap2.geometryTypes(), def->geometryTypes() ); QCOMPARE( fromMap2.geometryTypes(), def->geometryTypes() );
QCOMPARE( fromMap2.allowMultipart(), def->allowMultipart() );
def.reset( dynamic_cast< QgsProcessingParameterGeometry *>( QgsProcessingParameters::parameterFromVariantMap( map2 ) ) ); def.reset( dynamic_cast< QgsProcessingParameterGeometry *>( QgsProcessingParameters::parameterFromVariantMap( map2 ) ) );
QVERIFY( dynamic_cast< QgsProcessingParameterGeometry *>( def.get() ) ); QVERIFY( dynamic_cast< QgsProcessingParameterGeometry *>( def.get() ) );


// not multipart
def.reset( new QgsProcessingParameterGeometry( "not_multipart", QString(), QString( "Point(-1 3)" ), false, {}, false ) );
QVERIFY( !def->allowMultipart() );
QVERIFY( !def->checkValueIsAcceptable( QString( "MultiPoint((10 10), (20 20))" ) ) );
QVERIFY( !def->checkValueIsAcceptable( QgsGeometry::fromWkt( QStringLiteral( "MultiPoint((10 10), (20 20))" ) ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsGeometry::fromPointXY( QgsPointXY( 1, 2 ) ) ) );

pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterGeometry('not_multipart', '', allowMultipart=False, defaultValue='Point(-1 3)')" ) );

QVariantMap map3 = def->toVariantMap();
QgsProcessingParameterGeometry fromMap3( "x" );
QVERIFY( fromMap3.fromVariantMap( map3 ) );
QCOMPARE( fromMap3.allowMultipart(), false );

std::unique_ptr< QgsProcessingParameterGeometry > cloned( dynamic_cast< QgsProcessingParameterGeometry *>( def->clone() ) );
QCOMPARE( cloned->name(), def->name() );
QCOMPARE( cloned->description(), def->description() );
QCOMPARE( cloned->flags(), def->flags() );
QCOMPARE( cloned->defaultValue(), def->defaultValue() );
QCOMPARE( cloned->geometryTypes(), def->geometryTypes() );
QCOMPARE( cloned->allowMultipart(), def->allowMultipart() );


} }


Expand Down

0 comments on commit 7a74d7f

Please sign in to comment.