Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #52590 from alexbruy/processing-pointcloud-attribute
New parameter type for point cloud attribute
  • Loading branch information
alexbruy committed Apr 11, 2023
2 parents f1fd152 + c5947e4 commit c6eec2a
Show file tree
Hide file tree
Showing 31 changed files with 1,685 additions and 84 deletions.
Expand Up @@ -939,9 +939,19 @@ Evaluates the parameter with matching ``name`` to a list of files (for :py:class
Evaluates the parameter with matching ``name`` to a range of values.
%End

QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const /Deprecated/;
%Docstring
Evaluates the parameter with matching ``name`` to a list of fields.

.. deprecated::
use :py:func:`~QgsProcessingAlgorithm.parameterAsStrings` instead.
%End

QStringList parameterAsStrings( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a list of strings (e.g. field names or point cloud attributes).

.. versionadded:: 3.32
%End

QgsPrintLayout *parameterAsLayout( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
Expand Down
126 changes: 124 additions & 2 deletions python/core/auto_generated/processing/qgsprocessingparameters.sip.in
Expand Up @@ -335,6 +335,8 @@ their acceptable ranges, defaults, etc.
sipType = sipType_QgsProcessingParameterPointCloudLayer;
else if ( sipCpp->type() == QgsProcessingParameterAnnotationLayer::typeName() )
sipType = sipType_QgsProcessingParameterAnnotationLayer;
else if ( sipCpp->type() == QgsProcessingParameterPointCloudAttribute::typeName() )
sipType = sipType_QgsProcessingParameterPointCloudAttribute;
else
sipType = nullptr;
%End
Expand Down Expand Up @@ -1474,16 +1476,36 @@ Evaluates the parameter with matching ``definition`` and ``value`` to a range of
.. versionadded:: 3.4
%End

static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context ) /Deprecated/;
%Docstring
Evaluates the parameter with matching ``definition`` to a list of fields.

.. deprecated::
use :py:func:`~QgsProcessingParameters.parameterAsStrings` instead.
%End

static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context ) /Deprecated/;
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a list of fields.

.. versionadded:: 3.4

.. deprecated::
use :py:func:`~QgsProcessingParameters.parameterAsStrings` instead.
%End

static QStringList parameterAsStrings( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a list of strings (e.g. field names or point cloud attributes).

.. versionadded:: 3.32.
%End

static QStringList parameterAsStrings( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a list of strings (e.g. field names or point cloud attributes).

.. versionadded:: 3.32
%End

static QgsPrintLayout *parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
Expand Down Expand Up @@ -4762,6 +4784,106 @@ Creates a new parameter using the definition from a script code.
%End
};

class QgsProcessingParameterPointCloudAttribute : QgsProcessingParameterDefinition
{
%Docstring(signature="appended")
A point cloud layer attribute parameter for Processing algorithms.

.. versionadded:: 3.32
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterPointCloudAttribute( const QString &name, const QString &description = QString(), const QVariant &defaultValue = QVariant(),
const QString &parentLayerParameterName = QString(),
bool allowMultiple = false,
bool optional = false,
bool defaultToAllAttributes = false );
%Docstring
Constructor for :py:class:`QgsProcessingParameterField`.
%End

static QString typeName();
%Docstring
Returns the type name for the parameter class.
%End
virtual QgsProcessingParameterDefinition *clone() const /Factory/;

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;

virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;

virtual QString asScriptCode() const;

virtual QString asPythonString( QgsProcessing::PythonOutputType outputType = QgsProcessing::PythonQgsProcessingAlgorithmSubclass ) const;

virtual QStringList dependsOnOtherParameters() const;


QString parentLayerParameterName() const;
%Docstring
Returns the name of the parent layer parameter, or an empty string if this is not set.

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

void setParentLayerParameterName( const QString &parentLayerParameterName );
%Docstring
Sets the name of the parent layer parameter. Use an empty string if this is not required.

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

bool allowMultiple() const;
%Docstring
Returns whether multiple field selections are permitted.

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

void setAllowMultiple( bool allowMultiple );
%Docstring
Sets whether multiple field selections are permitted.

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

bool defaultToAllAttributes() const;
%Docstring
Returns whether a parameter which allows multiple selections (see :py:func:`~QgsProcessingParameterPointCloudAttribute.allowMultiple`) should automatically
select all attributes as the default value.

If ``True``, this will override any existing :py:func:`~QgsProcessingParameterPointCloudAttribute.defaultValue` set on the parameter.

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

void setDefaultToAllAttributes( bool enabled );
%Docstring
Sets whether a parameter which allows multiple selections (see :py:func:`~QgsProcessingParameterPointCloudAttribute.allowMultiple`) should automatically
select all attributes as the default value.

If ``True``, this will override any existing :py:func:`~QgsProcessingParameterPointCloudAttribute.defaultValue` set on the parameter.

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

virtual QVariantMap toVariantMap() const;

virtual bool fromVariantMap( const QVariantMap &map );


static QgsProcessingParameterPointCloudAttribute *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Creates a new parameter using the definition from a script code.
%End

};




Expand Down
19 changes: 2 additions & 17 deletions src/analysis/processing/pdal/qgsalgorithmpdalexportraster.cpp
Expand Up @@ -59,23 +59,8 @@ QgsPdalExportRasterAlgorithm *QgsPdalExportRasterAlgorithm::createInstance() con

void QgsPdalExportRasterAlgorithm::initAlgorithm( const QVariantMap & )
{
// for now we use hardcoded list of attributes, as currently there is
// no way to retrieve them from the point cloud layer without indexing
// it first. Later we will add a corresponding parameter type for it.
QStringList attributes =
{
QStringLiteral( "X" ),
QStringLiteral( "Y" ),
QStringLiteral( "Z" ),
QStringLiteral( "Intensity" ),
QStringLiteral( "ReturnNumber" ),
QStringLiteral( "NumberOfReturns" ),
QStringLiteral( "Classification" ),
QStringLiteral( "GpsTime" )
};

addParameter( new QgsProcessingParameterPointCloudLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
addParameter( new QgsProcessingParameterEnum( QStringLiteral( "ATTRIBUTE" ), QObject::tr( "Attribute" ), attributes, false, QStringLiteral( "Z" ), false, true ) );
addParameter( new QgsProcessingParameterPointCloudAttribute( QStringLiteral( "ATTRIBUTE" ), QObject::tr( "Attribute" ), QStringLiteral( "Z" ), QStringLiteral( "INPUT" ) ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "RESOLUTION" ), QObject::tr( "Resolution of the density raster" ), QgsProcessingParameterNumber::Integer, 1, false, 1 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "TILE_SIZE" ), QObject::tr( "Tile size for parallel runs" ), QgsProcessingParameterNumber::Integer, 1000, false, 1 ) );

Expand Down Expand Up @@ -108,7 +93,7 @@ QStringList QgsPdalExportRasterAlgorithm::createArgumentLists( const QVariantMap
const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context );
setOutputValue( QStringLiteral( "OUTPUT" ), outputFile );

const QString attribute = parameterAsEnumString( parameters, QStringLiteral( "ATTRIBUTE" ), context );
const QString attribute = parameterAsString( parameters, QStringLiteral( "ATTRIBUTE" ), context );
const int resolution = parameterAsInt( parameters, QStringLiteral( "RESOLUTION" ), context );
const int tileSize = parameterAsInt( parameters, QStringLiteral( "TILE_SIZE" ), context );

Expand Down
24 changes: 6 additions & 18 deletions src/analysis/processing/pdal/qgsalgorithmpdalexportvector.cpp
Expand Up @@ -59,23 +59,8 @@ QgsPdalExportVectorAlgorithm *QgsPdalExportVectorAlgorithm::createInstance() con

void QgsPdalExportVectorAlgorithm::initAlgorithm( const QVariantMap & )
{
// for now we use hardcoded list of attributes, as currently there is
// no way to retrieve them from the point cloud layer without indexing
// it first. Later we will add a corresponding parameter type for it.
QStringList attributes =
{
QStringLiteral( "X" ),
QStringLiteral( "Y" ),
QStringLiteral( "Z" ),
QStringLiteral( "Intensity" ),
QStringLiteral( "ReturnNumber" ),
QStringLiteral( "NumberOfReturns" ),
QStringLiteral( "Classification" ),
QStringLiteral( "GpsTime" )
};

addParameter( new QgsProcessingParameterPointCloudLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
addParameter( new QgsProcessingParameterEnum( QStringLiteral( "ATTRIBUTE" ), QObject::tr( "Attribute" ), attributes, false, QVariant(), true, true ) );
addParameter( new QgsProcessingParameterPointCloudAttribute( QStringLiteral( "ATTRIBUTE" ), QObject::tr( "Attribute" ), QVariant(), QStringLiteral( "INPUT" ), true, true ) );
addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Output vector" ), QgsProcessing::TypeVectorPoint ) );
}

Expand All @@ -97,8 +82,11 @@ QStringList QgsPdalExportVectorAlgorithm::createArgumentLists( const QVariantMap

if ( parameters.value( QStringLiteral( "ATTRIBUTE" ) ).isValid() )
{
const QString attribute = parameterAsEnumString( parameters, QStringLiteral( "ATTRIBUTE" ), context );
args << QStringLiteral( "--attribute=%1" ).arg( attribute );
const QStringList attributes = parameterAsStrings( parameters, QStringLiteral( "ATTRIBUTE" ), context );
for ( const QString &attr : attributes )
{
args << QStringLiteral( "--attribute=%1" ).arg( attr );
}
}

addThreadsParameter( args );
Expand Down
Expand Up @@ -114,7 +114,7 @@ bool QgsAddIncrementalFieldAlgorithm::prepareAlgorithm( const QVariantMap &param
mValue = mStartValue;
mModulusValue = parameterAsInt( parameters, QStringLiteral( "MODULUS" ), context );
mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context );
mGroupedFieldNames = parameterAsFields( parameters, QStringLiteral( "GROUP_FIELDS" ), context );
mGroupedFieldNames = parameterAsStrings( parameters, QStringLiteral( "GROUP_FIELDS" ), context );

mSortExpressionString = parameterAsExpression( parameters, QStringLiteral( "SORT_EXPRESSION" ), context );
mSortAscending = parameterAsBoolean( parameters, QStringLiteral( "SORT_ASCENDING" ), context );
Expand Down
Expand Up @@ -137,7 +137,7 @@ bool QgsDetectVectorChangesAlgorithm::prepareAlgorithm( const QVariantMap &param
feedback->reportError( QObject::tr( "CRS for revised layer (%1) does not match the original layer (%2) - reprojection accuracy may affect geometry matching" ).arg( mOriginal->sourceCrs().userFriendlyIdentifier(),
mRevised->sourceCrs().userFriendlyIdentifier() ), false );

mFieldsToCompare = parameterAsFields( parameters, QStringLiteral( "COMPARE_ATTRIBUTES" ), context );
mFieldsToCompare = parameterAsStrings( parameters, QStringLiteral( "COMPARE_ATTRIBUTES" ), context );
mOriginalFieldsToCompareIndices.reserve( mFieldsToCompare.size() );
mRevisedFieldsToCompareIndices.reserve( mFieldsToCompare.size() );
QStringList missingOriginalFields;
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmdissolve.cpp
Expand Up @@ -36,7 +36,7 @@ QVariantMap QgsCollectorAlgorithm::processCollection( const QVariantMap &paramet
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

const QStringList fields = parameterAsFields( parameters, QStringLiteral( "FIELD" ), context );
const QStringList fields = parameterAsStrings( parameters, QStringLiteral( "FIELD" ), context );

const long count = source->featureCount();

Expand Down
4 changes: 2 additions & 2 deletions src/analysis/processing/qgsalgorithmdropfields.cpp
Expand Up @@ -108,7 +108,7 @@ QgsFields QgsDropTableFieldsAlgorithm::outputFields( const QgsFields &inputField

bool QgsDropTableFieldsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
mFieldsToDelete = parameterAsFields( parameters, QStringLiteral( "COLUMN" ), context );
mFieldsToDelete = parameterAsStrings( parameters, QStringLiteral( "COLUMN" ), context );

if ( feedback )
{
Expand Down Expand Up @@ -241,7 +241,7 @@ QgsFields QgsRetainTableFieldsAlgorithm::outputFields( const QgsFields &inputFie

bool QgsRetainTableFieldsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
mFieldsToRetain = parameterAsFields( parameters, QStringLiteral( "FIELDS" ), context );
mFieldsToRetain = parameterAsStrings( parameters, QStringLiteral( "FIELDS" ), context );

if ( feedback )
{
Expand Down
4 changes: 2 additions & 2 deletions src/analysis/processing/qgsalgorithmintersection.cpp
Expand Up @@ -93,8 +93,8 @@ QVariantMap QgsIntersectionAlgorithm::processAlgorithm( const QVariantMap &param

const Qgis::WkbType geomType = QgsWkbTypes::multiType( sourceA->wkbType() );

const QStringList fieldsA = parameterAsFields( parameters, QStringLiteral( "INPUT_FIELDS" ), context );
const QStringList fieldsB = parameterAsFields( parameters, QStringLiteral( "OVERLAY_FIELDS" ), context );
const QStringList fieldsA = parameterAsStrings( parameters, QStringLiteral( "INPUT_FIELDS" ), context );
const QStringList fieldsB = parameterAsStrings( parameters, QStringLiteral( "OVERLAY_FIELDS" ), context );

const QList<int> fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( fieldsA, sourceA->fields() );
const QList<int> fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( fieldsB, sourceB->fields() );
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmjoinbyattribute.cpp
Expand Up @@ -118,7 +118,7 @@ QVariantMap QgsJoinByAttributeAlgorithm::processAlgorithm( const QVariantMap &pa

const QString field1Name = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
const QString field2Name = parameterAsString( parameters, QStringLiteral( "FIELD_2" ), context );
const QStringList fieldsToCopy = parameterAsFields( parameters, QStringLiteral( "FIELDS_TO_COPY" ), context );
const QStringList fieldsToCopy = parameterAsStrings( parameters, QStringLiteral( "FIELDS_TO_COPY" ), context );

const int joinField1Index = input->fields().lookupField( field1Name );
const int joinField2Index = input2->fields().lookupField( field2Name );
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmjoinbylocation.cpp
Expand Up @@ -128,7 +128,7 @@ QVariantMap QgsJoinByLocationAlgorithm::processAlgorithm( const QVariantMap &par

mJoinMethod = static_cast< JoinMethod >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );

const QStringList joinedFieldNames = parameterAsFields( parameters, QStringLiteral( "JOIN_FIELDS" ), context );
const QStringList joinedFieldNames = parameterAsStrings( parameters, QStringLiteral( "JOIN_FIELDS" ), context );

mPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context );
sortPredicates( mPredicates );
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmjoinbynearest.cpp
Expand Up @@ -131,7 +131,7 @@ QVariantMap QgsJoinByNearestAlgorithm::processAlgorithm( const QVariantMap &para
const bool sameSourceAndTarget = parameters.value( QStringLiteral( "INPUT" ) ) == parameters.value( QStringLiteral( "INPUT_2" ) );

const QString prefix = parameterAsString( parameters, QStringLiteral( "PREFIX" ), context );
const QStringList fieldsToCopy = parameterAsFields( parameters, QStringLiteral( "FIELDS_TO_COPY" ), context );
const QStringList fieldsToCopy = parameterAsStrings( parameters, QStringLiteral( "FIELDS_TO_COPY" ), context );

QgsFields outFields2;
QgsAttributeList fields2Indices;
Expand Down
4 changes: 2 additions & 2 deletions src/analysis/processing/qgsalgorithmjoinwithlines.cpp
Expand Up @@ -122,11 +122,11 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap &para

const QString fieldHubName = parameterAsString( parameters, QStringLiteral( "HUB_FIELD" ), context );
const int fieldHubIndex = hubSource->fields().lookupField( fieldHubName );
const QStringList hubFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "HUB_FIELDS" ), context );
const QStringList hubFieldsToCopy = parameterAsStrings( parameters, QStringLiteral( "HUB_FIELDS" ), context );

const QString fieldSpokeName = parameterAsString( parameters, QStringLiteral( "SPOKE_FIELD" ), context );
const int fieldSpokeIndex = spokeSource->fields().lookupField( fieldSpokeName );
const QStringList spokeFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "SPOKE_FIELDS" ), context );
const QStringList spokeFieldsToCopy = parameterAsStrings( parameters, QStringLiteral( "SPOKE_FIELDS" ), context );

if ( fieldHubIndex < 0 || fieldSpokeIndex < 0 )
throw QgsProcessingException( QObject::tr( "Invalid ID field" ) );
Expand Down
4 changes: 2 additions & 2 deletions src/analysis/processing/qgsalgorithmlineintersection.cpp
Expand Up @@ -91,8 +91,8 @@ QVariantMap QgsLineIntersectionAlgorithm::processAlgorithm( const QVariantMap &p
if ( !sourceB )
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );

const QStringList fieldsA = parameterAsFields( parameters, QStringLiteral( "INPUT_FIELDS" ), context );
const QStringList fieldsB = parameterAsFields( parameters, QStringLiteral( "INTERSECT_FIELDS" ), context );
const QStringList fieldsA = parameterAsStrings( parameters, QStringLiteral( "INPUT_FIELDS" ), context );
const QStringList fieldsB = parameterAsStrings( parameters, QStringLiteral( "INTERSECT_FIELDS" ), context );

QgsAttributeList fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( fieldsA, sourceA->fields() );
QgsAttributeList fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( fieldsB, sourceB->fields() );
Expand Down
Expand Up @@ -82,7 +82,7 @@ QVariantMap QgsRemoveDuplicatesByAttributeAlgorithm::processAlgorithm( const QVa
if ( !source )
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );

const QStringList fieldNames = parameterAsFields( parameters, QStringLiteral( "FIELDS" ), context );
const QStringList fieldNames = parameterAsStrings( parameters, QStringLiteral( "FIELDS" ), context );

QgsAttributeList attributes;
for ( const QString &field : fieldNames )
Expand Down
3 changes: 3 additions & 0 deletions src/core/pointcloud/qgspointcloudattributemodel.cpp
Expand Up @@ -35,7 +35,10 @@ void QgsPointCloudAttributeModel::setLayer( QgsPointCloudLayer *layer )
setAttributes( layer->attributes() );
}
else
{
mLayer = nullptr;
setAttributes( QgsPointCloudAttributeCollection() );
}
}

QgsPointCloudLayer *QgsPointCloudAttributeModel::layer()
Expand Down

0 comments on commit c6eec2a

Please sign in to comment.