Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #33368 from alexbruy/processing-updates
Processing updates
  • Loading branch information
alexbruy committed Dec 13, 2019
2 parents cf95f14 + ddb9360 commit fba3ab9
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 237 deletions.
Expand Up @@ -638,7 +638,7 @@ tests:
floatval: skip

- algorithm: qgis:rectanglesovalsdiamondsfixed
name: Create fixed distance rectange buffers around points
name: Create fixed distance rectangle buffers around points
params:
HEIGHT: 0.25
INPUT:
Expand Down Expand Up @@ -1386,7 +1386,7 @@ tests:
name: expected/single_sided_buffer_multiline_bevel.gml
type: vector

- algorithm: qgis:extractvertices
- algorithm: native:extractvertices
name: Extract vertices from multipolygons
params:
INPUT:
Expand All @@ -1403,7 +1403,7 @@ tests:
angle:
precision: 7

- algorithm: qgis:extractvertices
- algorithm: native:extractvertices
name: Extract vertices from polygons
params:
INPUT:
Expand All @@ -1420,7 +1420,7 @@ tests:
angle:
precision: 7

- algorithm: qgis:extractvertices
- algorithm: native:extractvertices
name: Extract vertices from multilines
params:
INPUT:
Expand All @@ -1437,7 +1437,7 @@ tests:
angle:
precision: 7

- algorithm: qgis:extractvertices
- algorithm: native:extractvertices
name: Extract vertices from lines
params:
INPUT:
Expand Down
176 changes: 101 additions & 75 deletions src/analysis/processing/qgsalgorithmextractspecificvertices.cpp
Expand Up @@ -64,134 +64,160 @@ QString QgsExtractSpecificVerticesAlgorithm::shortHelpString() const
"polygons), distance along the original geometry and bisector angle of vertex for the original geometry." );
}

QString QgsExtractSpecificVerticesAlgorithm::outputName() const
{
return QObject::tr( "Vertices" );
}

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

void QgsExtractSpecificVerticesAlgorithm::initAlgorithm( const QVariantMap & )
QgsProcessing::SourceType QgsExtractSpecificVerticesAlgorithm::outputLayerType() const
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
addParameter( new QgsProcessingParameterString( QStringLiteral( "VERTICES" ), QObject::tr( "Vertex indices" ), QStringLiteral( "0" ) ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Vertices" ), QgsProcessing::TypeVectorPoint ) );
return QgsProcessing::TypeVectorPoint;
}

QVariantMap QgsExtractSpecificVerticesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
QgsFields QgsExtractSpecificVerticesAlgorithm::outputFields( const QgsFields &inputFields ) const
{
std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
if ( !source )
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );

QgsFields outputFields = source->fields();
QgsFields outputFields = inputFields;
outputFields.append( QgsField( QStringLiteral( "vertex_pos" ), QVariant::Int ) );
outputFields.append( QgsField( QStringLiteral( "vertex_index" ), QVariant::Int ) );
outputFields.append( QgsField( QStringLiteral( "vertex_part" ), QVariant::Int ) );
if ( QgsWkbTypes::geometryType( source->wkbType() ) == QgsWkbTypes::PolygonGeometry )
if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
{
outputFields.append( QgsField( QStringLiteral( "vertex_part_ring" ), QVariant::Int ) );
}
outputFields.append( QgsField( QStringLiteral( "vertex_part_index" ), QVariant::Int ) );
outputFields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double ) );
outputFields.append( QgsField( QStringLiteral( "angle" ), QVariant::Double ) );

return outputFields;
}

QgsWkbTypes::Type QgsExtractSpecificVerticesAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
{
QgsWkbTypes::Type outputWkbType = QgsWkbTypes::Point;
if ( QgsWkbTypes::hasM( source->wkbType() ) )
if ( QgsWkbTypes::hasM( inputWkbType ) )
{
outputWkbType = QgsWkbTypes::addM( outputWkbType );
}
if ( QgsWkbTypes::hasZ( source->wkbType() ) )
if ( QgsWkbTypes::hasZ( inputWkbType ) )
{
outputWkbType = QgsWkbTypes::addZ( outputWkbType );
}

QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields, outputWkbType, source->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
return outputWkbType;
}

QgsProcessingFeatureSource::Flag QgsExtractSpecificVerticesAlgorithm::sourceFlags() const
{
return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks;
}

QgsFeatureSink::SinkFlags QgsExtractSpecificVerticesAlgorithm::sinkFlags() const
{
return QgsFeatureSink::RegeneratePrimaryKey;
}

void QgsExtractSpecificVerticesAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterString( QStringLiteral( "VERTICES" ), QObject::tr( "Vertex indices" ), QStringLiteral( "0" ) ) );
}

bool QgsExtractSpecificVerticesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
mGeometryType = QgsWkbTypes::geometryType( source->wkbType() );

QString verticesString = parameterAsString( parameters, QStringLiteral( "VERTICES" ), context );
const QStringList verticesList = verticesString.split( ',', QString::SkipEmptyParts );
QList< int > indices;
for ( const QString &vertex : verticesList )
{
bool ok = false;
int i = vertex.toInt( &ok );
if ( ok )
{
indices << i;
mIndices << i;
}
else
{
throw QgsProcessingException( QObject::tr( "'%1' is not a valid vertex index" ).arg( vertex ) );
}
}

double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
QgsFeatureIterator fi = source->getFeatures( QgsFeatureRequest(), QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
QgsFeature f;
int i = 0;
while ( fi.nextFeature( f ) )
return true;
}

QgsFeatureList QgsExtractSpecificVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
{
QgsFeatureList outputFeatures;

QgsFeature f = feature;
QgsGeometry inputGeom = f.geometry();
if ( inputGeom.isNull() )
{
if ( feedback->isCanceled() )
QgsAttributes attrs = f.attributes();
attrs << QVariant()
<< QVariant()
<< QVariant();
if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
{
break;
attrs << QVariant();
}
attrs << QVariant()
<< QVariant()
<< QVariant();

QgsGeometry inputGeom = f.geometry();
if ( inputGeom.isNull() )
{
sink->addFeature( f, QgsFeatureSink::FastInsert );
}
else
f.setAttributes( attrs );
outputFeatures << f;
}
else
{
int vertexIndex;
int totalVertices = inputGeom.constGet()->nCoordinates();
for ( int vertex : mIndices )
{
int vertexIndex;
int totalVertices = inputGeom.constGet()->nCoordinates();
for ( int vertex : indices )
if ( vertex < 0 )
{
vertexIndex = totalVertices + vertex;
}
else
{
vertexIndex = vertex;
}

if ( vertexIndex < 0 || vertexIndex >= totalVertices )
continue;

QgsVertexId vertexId;
inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );

double distance = inputGeom.distanceToVertex( vertexIndex );
double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;

QgsFeature outFeature = QgsFeature();
QgsAttributes attrs = f.attributes();
attrs << vertex
<< vertexIndex
<< vertexId.part;
if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
{
if ( vertex < 0 )
{
vertexIndex = totalVertices + vertex;
}
else
{
vertexIndex = vertex;
}

if ( vertexIndex < 0 || vertexIndex >= totalVertices )
continue;

QgsVertexId vertexId;
inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );

double distance = inputGeom.distanceToVertex( vertexIndex );
double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;

QgsFeature outputFeature = QgsFeature();
QgsAttributes attrs = f.attributes();
attrs << vertex
<< vertexIndex
<< vertexId.part;
if ( QgsWkbTypes::geometryType( source->wkbType() ) == QgsWkbTypes::PolygonGeometry )
{
attrs << vertexId.ring;
}
attrs << vertexId.vertex
<< distance
<< angle;

outputFeature.setAttributes( attrs );
QgsPoint point = inputGeom.vertexAt( vertexIndex );
outputFeature.setGeometry( QgsGeometry( point.clone() ) );
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
attrs << vertexId.ring;
}
attrs << vertexId.vertex
<< distance
<< angle;

outFeature.setAttributes( attrs );
QgsPoint point = inputGeom.vertexAt( vertexIndex );
outFeature.setGeometry( QgsGeometry( point.clone() ) );
outputFeatures << outFeature;
}
feedback->setProgress( i * step );
i++;
}

QVariantMap outputs;
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
return outputs;
return outputFeatures;
}

///@endcond
18 changes: 14 additions & 4 deletions src/analysis/processing/qgsalgorithmextractspecificvertices.h
Expand Up @@ -29,7 +29,7 @@
/**
* Native extract specific vertices algorithm.
*/
class QgsExtractSpecificVerticesAlgorithm : public QgsProcessingAlgorithm
class QgsExtractSpecificVerticesAlgorithm : public QgsProcessingFeatureBasedAlgorithm
{

public:
Expand All @@ -41,14 +41,24 @@ class QgsExtractSpecificVerticesAlgorithm : public QgsProcessingAlgorithm
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
QgsExtractSpecificVerticesAlgorithm *createInstance() const override SIP_FACTORY;

protected:

QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QString outputName() const override;
QgsFields outputFields( const QgsFields &inputFields ) const override;
QgsProcessing::SourceType outputLayerType() const override;
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override;
QgsProcessingFeatureSource::Flag sourceFlags() const override;
QgsFeatureSink::SinkFlags sinkFlags() const override;

bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

private:
QgsWkbTypes::GeometryType mGeometryType;
QList< int > mIndices;
};

///@endcond PRIVATE
Expand Down

0 comments on commit fba3ab9

Please sign in to comment.