Skip to content

Commit 4dcf8d8

Browse files
committed
[FEATURE][processing] New algorithm for subdividing geometries
The returned geometry will be a collection containing subdivided parts from the original geometry, where no part has more then the specified maximum number of nodes. This is useful for dividing a complex geometry into less complex parts, which are better able to be spatially indexed and faster to perform further operations such as intersects on. The returned geometry parts may not be valid and may contain self-intersections.
1 parent e74395d commit 4dcf8d8

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

src/core/processing/qgsnativealgorithms.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
6363
addAlgorithm( new QgsDissolveAlgorithm() );
6464
addAlgorithm( new QgsClipAlgorithm() );
6565
addAlgorithm( new QgsTransformAlgorithm() );
66+
addAlgorithm( new QgsSubdivideAlgorithm() );
6667
}
6768

6869

@@ -594,5 +595,75 @@ QVariantMap QgsTransformAlgorithm::processAlgorithm( const QVariantMap &paramete
594595
}
595596

596597

598+
QgsSubdivideAlgorithm::QgsSubdivideAlgorithm()
599+
{
600+
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
601+
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MAX_NODES" ), QObject::tr( "Maximum nodes in parts" ), QgsProcessingParameterNumber::Integer,
602+
256, false, 8, 100000 ) );
603+
604+
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Subdivided" ) ) );
605+
addOutput( new QgsProcessingOutputVectorLayer( QStringLiteral( "OUTPUT" ), QObject::tr( "Subdivided" ) ) );
606+
}
607+
608+
QString QgsSubdivideAlgorithm::shortHelpString() const
609+
{
610+
return QObject::tr( "Subdivides the geometry. The returned geometry will be a collection containing subdivided parts "
611+
"from the original geometry, where no part has more then the specified maximum number of nodes.\n\n"
612+
"This is useful for dividing a complex geometry into less complex parts, which are better able to be spatially "
613+
"indexed and faster to perform further operations such as intersects on. The returned geometry parts may "
614+
"not be valid and may contain self-intersections.\n\n"
615+
"Curved geometries will be segmentized before subdivision." );
616+
}
617+
618+
QVariantMap QgsSubdivideAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
619+
{
620+
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
621+
if ( !source )
622+
return QVariantMap();
623+
624+
int maxNodes = parameterAsInt( parameters, QStringLiteral( "MAX_NODES" ), context );
625+
QString dest;
626+
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, source->fields(),
627+
QgsWkbTypes::multiType( source->wkbType() ), source->sourceCrs(), dest ) );
628+
if ( !sink )
629+
return QVariantMap();
630+
631+
long count = source->featureCount();
632+
if ( count <= 0 )
633+
return QVariantMap();
634+
635+
QgsFeature f;
636+
QgsFeatureIterator it = source->getFeatures();
637+
638+
double step = 100.0 / count;
639+
int current = 0;
640+
while ( it.nextFeature( f ) )
641+
{
642+
if ( feedback->isCanceled() )
643+
{
644+
break;
645+
}
646+
647+
QgsFeature out = f;
648+
if ( out.hasGeometry() )
649+
{
650+
out.setGeometry( f.geometry().subdivide( maxNodes ) );
651+
if ( !out.geometry() )
652+
{
653+
QgsMessageLog::logMessage( QObject::tr( "Error calculating subdivision for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
654+
}
655+
}
656+
sink->addFeature( out );
657+
658+
feedback->setProgress( current * step );
659+
current++;
660+
}
661+
662+
QVariantMap outputs;
663+
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
664+
return outputs;
665+
}
666+
597667
///@endcond
598668

669+

src/core/processing/qgsnativealgorithms.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,30 @@ class QgsClipAlgorithm : public QgsProcessingAlgorithm
158158

159159
};
160160

161+
162+
/**
163+
* Native subdivide algorithm.
164+
*/
165+
class QgsSubdivideAlgorithm : public QgsProcessingAlgorithm
166+
{
167+
168+
public:
169+
170+
QgsSubdivideAlgorithm();
171+
172+
QString name() const override { return QStringLiteral( "subdivide" ); }
173+
QString displayName() const override { return QObject::tr( "Subdivide" ); }
174+
virtual QStringList tags() const override { return QObject::tr( "subdivide,segmentize,split,tesselate" ).split( ',' ); }
175+
QString group() const override { return QObject::tr( "Vector geometry tools" ); }
176+
QString shortHelpString() const override;
177+
178+
protected:
179+
180+
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
181+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const override;
182+
183+
};
184+
161185
///@endcond PRIVATE
162186

163187
#endif // QGSNATIVEALGORITHMS_H

0 commit comments

Comments
 (0)