Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsalgorithmdpolygonize.cpp 3 : : --------------------- 4 : : begin : May 2020 5 : : copyright : (C) 2020 by Alexander Bruy 6 : : email : alexander dot bruy at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #include "qgsalgorithmpolygonize.h" 19 : : #include "qgsgeometrycollection.h" 20 : : 21 : : ///@cond PRIVATE 22 : : 23 : 0 : QString QgsPolygonizeAlgorithm::name() const 24 : : { 25 : 0 : return QStringLiteral( "polygonize" ); 26 : : } 27 : : 28 : 0 : QString QgsPolygonizeAlgorithm::displayName() const 29 : : { 30 : 0 : return QObject::tr( "Polygonize" ); 31 : : } 32 : : 33 : 0 : QString QgsPolygonizeAlgorithm::shortHelpString() const 34 : : { 35 : 0 : return QObject::tr( "Creates a polygon layer from the input lines layer." ); 36 : : } 37 : : 38 : 0 : QStringList QgsPolygonizeAlgorithm::tags() const 39 : : { 40 : 0 : return QObject::tr( "create,lines,polygons,convert" ).split( ',' ); 41 : 0 : } 42 : : 43 : 0 : QString QgsPolygonizeAlgorithm::group() const 44 : : { 45 : 0 : return QObject::tr( "Vector geometry" ); 46 : : } 47 : : 48 : 0 : QString QgsPolygonizeAlgorithm::groupId() const 49 : : { 50 : 0 : return QStringLiteral( "vectorgeometry" ); 51 : : } 52 : : 53 : 0 : void QgsPolygonizeAlgorithm::initAlgorithm( const QVariantMap & ) 54 : : { 55 : 0 : addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), 56 : 0 : QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine ) ); 57 : 0 : addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "KEEP_FIELDS" ), 58 : 0 : QObject::tr( "Keep fields from the input layer" ), false, true ) ); 59 : 0 : addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), 60 : 0 : QObject::tr( "Polygons" ), QgsProcessing::TypeVectorPolygon ) ); 61 : 0 : addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NUM_POLYGONS" ), QObject::tr( "Number of polygons" ) ) ); 62 : 0 : } 63 : : 64 : 0 : QgsPolygonizeAlgorithm *QgsPolygonizeAlgorithm::createInstance() const 65 : : { 66 : 0 : return new QgsPolygonizeAlgorithm(); 67 : : } 68 : : 69 : 0 : QVariantMap QgsPolygonizeAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) 70 : : { 71 : 0 : std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); 72 : 0 : if ( !source ) 73 : 0 : throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); 74 : : 75 : 0 : QgsFields fields = QgsFields(); 76 : 0 : if ( parameterAsBoolean( parameters, QStringLiteral( "KEEP_FIELDS" ), context ) ) 77 : 0 : fields = source->fields(); 78 : : 79 : 0 : QString dest; 80 : 0 : std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, source->sourceCrs() ) ); 81 : 0 : if ( !sink ) 82 : 0 : throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); 83 : : 84 : 0 : int polygonCount = 0; 85 : : 86 : 0 : feedback->pushInfo( QObject::tr( "Collecting lines…" ) ); 87 : 0 : int i = 0; 88 : 0 : double step = source->featureCount() > 0 ? 40.0 / source->featureCount() : 1; 89 : 0 : QgsFeature f; 90 : 0 : QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setNoAttributes() ); 91 : 0 : QVector<QgsGeometry> linesList; 92 : 0 : linesList.reserve( source->featureCount() ); 93 : 0 : while ( features.nextFeature( f ) ) 94 : : { 95 : 0 : if ( feedback->isCanceled() ) 96 : 0 : break; 97 : : 98 : 0 : if ( f.hasGeometry() ) 99 : 0 : linesList << f.geometry(); 100 : : 101 : 0 : feedback->setProgress( i * step ); 102 : : } 103 : 0 : feedback->setProgress( 40 ); 104 : : 105 : 0 : feedback->pushInfo( QObject::tr( "Noding lines…" ) ); 106 : 0 : QgsGeometry lines = QgsGeometry::unaryUnion( linesList ); 107 : 0 : if ( feedback->isCanceled() ) 108 : 0 : return QVariantMap(); 109 : 0 : feedback->setProgress( 45 ); 110 : : 111 : 0 : feedback->pushInfo( QObject::tr( "Polygonizing…" ) ); 112 : 0 : QgsGeometry polygons = QgsGeometry::polygonize( QVector< QgsGeometry >() << lines ); 113 : 0 : if ( polygons.isEmpty() ) 114 : 0 : feedback->reportError( QObject::tr( "No polygons were created." ) ); 115 : : 116 : 0 : feedback->setProgress( 50 ); 117 : : 118 : 0 : if ( !polygons.isEmpty() ) 119 : : { 120 : 0 : const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( polygons.constGet() ); 121 : 0 : step = collection->numGeometries() > 0 ? 50.0 / collection->numGeometries() : 1; 122 : 0 : for ( int part = 0; part < collection->numGeometries(); ++part ) 123 : : { 124 : 0 : if ( feedback->isCanceled() ) 125 : 0 : break; 126 : : 127 : 0 : QgsFeature outFeat; 128 : 0 : outFeat.setGeometry( QgsGeometry( collection->geometryN( part )->clone() ) ); 129 : 0 : sink->addFeature( outFeat, QgsFeatureSink::FastInsert ); 130 : 0 : feedback->setProgress( 50 + i * step ); 131 : 0 : polygonCount += 1; 132 : 0 : } 133 : 0 : } 134 : : 135 : 0 : QVariantMap outputs; 136 : 0 : outputs.insert( QStringLiteral( "OUTPUT" ), dest ); 137 : 0 : outputs.insert( QStringLiteral( "NUM_POLYGONS" ), polygonCount ); 138 : 0 : return outputs; 139 : 0 : } 140 : : 141 : : ///@endcond