Skip to content

Commit

Permalink
[processing] port Split vector layer algorithm to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed May 11, 2020
1 parent b2890f0 commit 072d27d
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 134 deletions.
2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -95,7 +95,6 @@
from .VectorLayerHistogram import VectorLayerHistogram
from .VectorLayerScatterplot import VectorLayerScatterplot
from .VectorLayerScatterplot3D import VectorLayerScatterplot3D
from .VectorSplit import VectorSplit
from .VoronoiPolygons import VoronoiPolygons


Expand Down Expand Up @@ -177,7 +176,6 @@ def getAlgs(self):
VectorLayerHistogram(),
VectorLayerScatterplot(),
VectorLayerScatterplot3D(),
VectorSplit(),
VoronoiPolygons(),
]

Expand Down
131 changes: 0 additions & 131 deletions python/plugins/processing/algs/qgis/VectorSplit.py

This file was deleted.

1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -155,6 +155,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmsplitfeaturesbyattributecharacter.cpp
processing/qgsalgorithmsplitlineantimeridian.cpp
processing/qgsalgorithmsplitlinesbylength.cpp
processing/qgsalgorithmsplitvectorlayer.cpp
processing/qgsalgorithmsplitwithlines.cpp
processing/qgsalgorithmstringconcatenation.cpp
processing/qgsalgorithmswapxy.cpp
Expand Down
130 changes: 130 additions & 0 deletions src/analysis/processing/qgsalgorithmsplitvectorlayer.cpp
@@ -0,0 +1,130 @@
/***************************************************************************
qgsalgorithmsplitvectorlayer.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 "qgsalgorithmsplitvectorlayer.h"
#include "qgsvectorfilewriter.h"

///@cond PRIVATE

QString QgsSplitVectorLayerAlgorithm::name() const
{
return QStringLiteral( "splitvectorlayer" );
}

QString QgsSplitVectorLayerAlgorithm::displayName() const
{
return QObject::tr( "Split vector layer" );
}

QStringList QgsSplitVectorLayerAlgorithm::tags() const
{
return QObject::tr( "vector,split,field,unique" ).split( ',' );
}

QString QgsSplitVectorLayerAlgorithm::group() const
{
return QObject::tr( "Vector general" );
}

QString QgsSplitVectorLayerAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeneral" );
}

QString QgsSplitVectorLayerAlgorithm::shortHelpString() const
{
return QObject::tr( "Splits input vector layer into multiple layers by specified unique ID field." );
}

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

void QgsSplitVectorLayerAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Unique ID field" ),
QVariant(), QStringLiteral( "INPUT" ) ) );
addParameter( new QgsProcessingParameterFolderDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Output directory" ) ) );
addOutput( new QgsProcessingOutputMultipleLayers( QStringLiteral( "OUTPUT_LAYERS" ), QObject::tr( "Output layers" ) ) );
}

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

QString fieldName = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
QString outputDir = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );

if ( !QDir().mkpath( outputDir ) )
throw QgsProcessingException( QStringLiteral( "Failed to create output directory." ) );

QgsFields fields = source->fields();
QgsCoordinateReferenceSystem crs = source->sourceCrs();
QgsWkbTypes::Type geometryType = source->wkbType();
int fieldIndex = fields.lookupField( fieldName );
QSet< QVariant > uniqueValues = source->uniqueValues( fieldIndex );
QString baseName = outputDir + QDir::separator() + fieldName;
QString outputFormat = context.preferredVectorFormat();
if ( !QgsVectorFileWriter::supportedFormatExtensions().contains( outputFormat, Qt::CaseInsensitive ) )
outputFormat = QStringLiteral( "gpkg" );

int current = 0;
double step = uniqueValues.size() > 0 ? 100.0 / uniqueValues.size() : 1;

int count = 0;
QgsFeature feat;
QStringList outputLayers;
std::unique_ptr< QgsFeatureSink > sink;

for ( auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
{
if ( feedback->isCanceled() )
break;

QString fileName = QStringLiteral( "%1_%2.%3" ).arg( baseName ).arg( current ).arg( outputFormat );
feedback->pushInfo( QObject::tr( "Creating layer: %1" ).arg( fileName ) );

sink.reset( QgsProcessingUtils::createFeatureSink( fileName, context, fields, geometryType, crs ) );
QString expr = QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( fieldName ), QgsExpression::quotedValue( *it ) );
QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setFilterExpression( expr ) );
while ( features.nextFeature( feat ) )
{
if ( feedback->isCanceled() )
break;

sink->addFeature( feat, QgsFeatureSink::FastInsert );
count += 1;
}

feedback->pushInfo( QObject::tr( "Added %1 features to layer" ).arg( count ) );
outputLayers << fileName;

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

QVariantMap outputs;
outputs.insert( QStringLiteral( "OUTPUT" ), outputDir );
outputs.insert( QStringLiteral( "OUTPUT_LAYERS" ), outputLayers );
return outputs;
}

///@endcond
57 changes: 57 additions & 0 deletions src/analysis/processing/qgsalgorithmsplitvectorlayer.h
@@ -0,0 +1,57 @@
/***************************************************************************
qgsalgorithmsplitvectorlayer.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 QGSALGORITHMSPLITVECTORLAYER_H
#define QGSALGORITHMSPLITVECTORLAYER_H

#define SIP_NO_FILE

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

///@cond PRIVATE

/**
* Native split vector layer algorithm.
*/
class QgsSplitVectorLayerAlgorithm : public QgsProcessingAlgorithm
{

public:

QgsSplitVectorLayerAlgorithm() = 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;
QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmSplitLayer.svg" ) ); }
QString svgIconPath() const override { return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmSplitLayer.svg" ) ); }
QgsSplitVectorLayerAlgorithm *createInstance() const override SIP_FACTORY;

protected:

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

///@endcond PRIVATE

#endif // QGSALGORITHMSPLITVECTORLAYER_H
4 changes: 3 additions & 1 deletion src/analysis/processing/qgsnativealgorithms.cpp
Expand Up @@ -146,10 +146,11 @@
#include "qgsalgorithmsmooth.h"
#include "qgsalgorithmsnaptogrid.h"
#include "qgsalgorithmspatialindex.h"
#include "qgsalgorithmsplitfeaturesbyattributecharacter.h"
#include "qgsalgorithmsplitlineantimeridian.h"
#include "qgsalgorithmsplitlinesbylength.h"
#include "qgsalgorithmsplitvectorlayer.h"
#include "qgsalgorithmsplitwithlines.h"
#include "qgsalgorithmsplitfeaturesbyattributecharacter.h"
#include "qgsalgorithmstringconcatenation.h"
#include "qgsalgorithmsubdivide.h"
#include "qgsalgorithmsumlinelength.h"
Expand Down Expand Up @@ -369,6 +370,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsSplitFeaturesByAttributeCharacterAlgorithm() );
addAlgorithm( new QgsSplitGeometryAtAntimeridianAlgorithm() );
addAlgorithm( new QgsSplitLinesByLengthAlgorithm() );
addAlgorithm( new QgsSplitVectorLayerAlgorithm() );
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
addAlgorithm( new QgsStringConcatenationAlgorithm() );
addAlgorithm( new QgsStyleFromProjectAlgorithm() );
Expand Down

0 comments on commit 072d27d

Please sign in to comment.