Skip to content

Commit

Permalink
[processing] port Polygonize algorithm to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed May 11, 2020
1 parent c0e8178 commit b4a52d3
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 125 deletions.
123 changes: 0 additions & 123 deletions python/plugins/processing/algs/qgis/Polygonize.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -63,7 +63,6 @@
from .PointsFromLines import PointsFromLines
from .PointsToPaths import PointsToPaths
from .PolarPlot import PolarPlot
from .Polygonize import Polygonize
from .PostGISExecuteAndLoadSQL import PostGISExecuteAndLoadSQL
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
from .RandomPointsAlongLines import RandomPointsAlongLines
Expand Down Expand Up @@ -141,7 +140,6 @@ def getAlgs(self):
PointsFromLines(),
PointsToPaths(),
PolarPlot(),
Polygonize(),
PostGISExecuteAndLoadSQL(),
RandomExtractWithinSubsets(),
RandomPointsAlongLines(),
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -110,6 +110,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmpointsalonggeometry.cpp
processing/qgsalgorithmpointslayerfromtable.cpp
processing/qgsalgorithmpoleofinaccessibility.cpp
processing/qgsalgorithmpolygonize.cpp
processing/qgsalgorithmprojectpointcartesian.cpp
processing/qgsalgorithmpromotetomultipart.cpp
processing/qgsalgorithmraiseexception.cpp
Expand Down
141 changes: 141 additions & 0 deletions src/analysis/processing/qgsalgorithmpolygonize.cpp
@@ -0,0 +1,141 @@
/***************************************************************************
qgsalgorithmdpolygonize.cpp
---------------------
begin : May 2020
copyright : (C) 2020 by Alexander Bruy
email : alexander dot bruy at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmpolygonize.h"
#include "qgsgeometrycollection.h"

///@cond PRIVATE

QString QgsPolygonizeAlgorithm::name() const
{
return QStringLiteral( "polygonize" );
}

QString QgsPolygonizeAlgorithm::displayName() const
{
return QObject::tr( "Polygonize" );
}

QString QgsPolygonizeAlgorithm::shortHelpString() const
{
return QObject::tr( "Creates a polygon layer from the input lines layer." );
}

QStringList QgsPolygonizeAlgorithm::tags() const
{
return QObject::tr( "create,lines,polygons,convert" ).split( ',' );
}

QString QgsPolygonizeAlgorithm::group() const
{
return QObject::tr( "Vector geometry" );
}

QString QgsPolygonizeAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeometry" );
}

void QgsPolygonizeAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "KEEP_FIELDS" ),
QObject::tr( "Keep fields from the input layer" ), false, true ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ),
QObject::tr( "Polygons" ), QgsProcessing::TypeVectorPolygon ) );
addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NUM_POLYGONS" ), QObject::tr( "Number of polygons" ) ) );
}

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

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

QgsFields fields = QgsFields();
if ( parameterAsBoolean( parameters, QStringLiteral( "KEEP_FIELDS" ), context ) )
fields = source->fields();

QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, source->sourceCrs() ) );
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

int polygonCount = 0;

feedback->pushInfo( QObject::tr( "Collecting lines…" ) );
int i = 0;
double step = source->featureCount() > 0 ? 40.0 / source->featureCount() : 1;
QgsFeature f;
QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setNoAttributes() );
QVector<QgsGeometry> linesList;
linesList.reserve( source->featureCount() );
while ( features.nextFeature( f ) )
{
if ( feedback->isCanceled() )
break;

if ( f.hasGeometry() )
linesList << f.geometry();

feedback->setProgress( i * step );
}
feedback->setProgress( 40 );

feedback->pushInfo( QObject::tr( "Noding lines…" ) );
QgsGeometry lines = QgsGeometry::unaryUnion( linesList );
if ( feedback->isCanceled() )
return QVariantMap();
feedback->setProgress( 45 );

feedback->pushInfo( QObject::tr( "Polygonizing…" ) );
QgsGeometry polygons = QgsGeometry::polygonize( QVector< QgsGeometry >() << lines );
if ( polygons.isEmpty() )
feedback->reportError( QObject::tr( "No polygons were created." ) );

feedback->setProgress( 50 );

if ( !polygons.isEmpty() )
{
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( polygons.constGet() );
step = collection->numGeometries() > 0 ? 50.0 / collection->numGeometries() : 1;
for ( int part = 0; part < collection->numGeometries(); ++part )
{
if ( feedback->isCanceled() )
break;

QgsFeature outFeat;
outFeat.setGeometry( QgsGeometry( collection->geometryN( part )->clone() ) );
sink->addFeature( outFeat, QgsFeatureSink::FastInsert );
feedback->setProgress( 50 + i * step );
polygonCount += 1;
}
}

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

///@endcond
54 changes: 54 additions & 0 deletions src/analysis/processing/qgsalgorithmpolygonize.h
@@ -0,0 +1,54 @@
/***************************************************************************
qgsalgorithmpolygonize.h
---------------------
begin : May 2020
copyright : (C) 2020 by Alexander Bruy
email : alexander dot bruy at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMPOLYGONIZE_H
#define QGSALGORITHMPOLYGONIZE_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgsprocessingalgorithm.h"

///@cond PRIVATE

/**
* Native polygonize algorithm.
*/
class QgsPolygonizeAlgorithm : public QgsProcessingAlgorithm
{

public:

QgsPolygonizeAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QgsPolygonizeAlgorithm *createInstance() const override SIP_FACTORY;

protected:

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

///@endcond PRIVATE

#endif // QGSALGORITHMPOLYGONIZE_H
2 changes: 2 additions & 0 deletions src/analysis/processing/qgsnativealgorithms.cpp
Expand Up @@ -104,6 +104,7 @@
#include "qgsalgorithmpointsalonggeometry.h"
#include "qgsalgorithmpointslayerfromtable.h"
#include "qgsalgorithmpoleofinaccessibility.h"
#include "qgsalgorithmpolygonize.h"
#include "qgsalgorithmprojectpointcartesian.h"
#include "qgsalgorithmpromotetomultipart.h"
#include "qgsalgorithmraiseexception.h"
Expand Down Expand Up @@ -313,6 +314,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsPointsAlongGeometryAlgorithm() );
addAlgorithm( new QgsPointsLayerFromTableAlgorithm() );
addAlgorithm( new QgsPoleOfInaccessibilityAlgorithm() );
addAlgorithm( new QgsPolygonizeAlgorithm() );
addAlgorithm( new QgsProjectPointCartesianAlgorithm() );
addAlgorithm( new QgsPromoteToMultipartAlgorithm() );
addAlgorithm( new QgsRaiseExceptionAlgorithm() );
Expand Down

0 comments on commit b4a52d3

Please sign in to comment.