mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-15 00:02:52 -04:00
do not create spatial index if preserving attributes is not needed
This commit is contained in:
parent
514e8b5b24
commit
ea6a706c01
@ -66,46 +66,58 @@ void QgsVoronoiPolygonsAlgorithm::initAlgorithm( const QVariantMap & )
|
|||||||
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Voronoi polygons" ), QgsProcessing::TypeVectorPolygon ) );
|
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Voronoi polygons" ), QgsProcessing::TypeVectorPolygon ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap QgsVoronoiPolygonsAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
bool QgsVoronoiPolygonsAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||||
{
|
{
|
||||||
std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
Q_UNUSED( feedback );
|
||||||
if ( !source )
|
|
||||||
|
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||||
|
if ( !mSource )
|
||||||
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
|
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
|
||||||
|
|
||||||
if ( source->featureCount() < 3 )
|
if ( mSource->featureCount() < 3 )
|
||||||
throw QgsProcessingException( QObject::tr( "Input layer should contain at least 3 points." ) );
|
throw QgsProcessingException( QObject::tr( "Input layer should contain at least 3 points." ) );
|
||||||
|
|
||||||
const double buffer = parameterAsDouble( parameters, QStringLiteral( "BUFFER" ), context );
|
mBuffer = parameterAsDouble( parameters, QStringLiteral( "BUFFER" ), context );
|
||||||
const double tolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context );
|
mTolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context );
|
||||||
const bool copyAttributes = parameterAsBool( parameters, QStringLiteral( "COPY_ATTRIBUTES" ), context );
|
mCopyAttributes = parameterAsBool( parameters, QStringLiteral( "COPY_ATTRIBUTES" ), context );
|
||||||
|
|
||||||
QgsFields fields;
|
return true;
|
||||||
if ( copyAttributes )
|
}
|
||||||
|
|
||||||
|
QVariantMap QgsVoronoiPolygonsAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||||
|
{
|
||||||
|
QString dest;
|
||||||
|
if ( mCopyAttributes )
|
||||||
{
|
{
|
||||||
fields = source->fields();
|
dest = voronoiWithAttributes( parameters, context, feedback );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fields.append( QgsField( QStringLiteral( "id" ), QVariant::LongLong ) );
|
dest = voronoiWithoutAttributes( parameters, context, feedback );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap outputs;
|
||||||
|
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||||
|
return outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsVoronoiPolygonsAlgorithm::voronoiWithAttributes( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||||
|
{
|
||||||
|
QgsFields fields = mSource->fields();
|
||||||
|
|
||||||
QString dest;
|
QString dest;
|
||||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, Qgis::WkbType::Polygon, source->sourceCrs() ) );
|
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, Qgis::WkbType::Polygon, mSource->sourceCrs() ) );
|
||||||
if ( !sink )
|
if ( !sink )
|
||||||
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
|
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||||
|
|
||||||
QgsFeatureRequest request;
|
QgsFeatureRequest request;
|
||||||
if ( !copyAttributes )
|
QgsFeatureIterator it = mSource->getFeatures( request, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
|
||||||
{
|
|
||||||
request.setSubsetOfAttributes( QList< int >() );
|
|
||||||
}
|
|
||||||
QgsFeatureIterator it = source->getFeatures( request, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
|
|
||||||
|
|
||||||
QgsGeometry allPoints;
|
QgsGeometry allPoints;
|
||||||
QHash< QgsFeatureId, QgsAttributes > attributeCache;
|
QHash< QgsFeatureId, QgsAttributes > attributeCache;
|
||||||
|
|
||||||
long i = 0;
|
long i = 0;
|
||||||
double step = source->featureCount() > 0 ? 50.0 / source->featureCount() : 1;
|
double step = mSource->featureCount() > 0 ? 50.0 / mSource->featureCount() : 1;
|
||||||
|
|
||||||
const QgsSpatialIndex index( it, [&]( const QgsFeature & f )->bool
|
const QgsSpatialIndex index( it, [&]( const QgsFeature & f )->bool
|
||||||
{
|
{
|
||||||
@ -137,16 +149,16 @@ QVariantMap QgsVoronoiPolygonsAlgorithm::processAlgorithm( const QVariantMap &pa
|
|||||||
return true;
|
return true;
|
||||||
}, QgsSpatialIndex::FlagStoreFeatureGeometries );
|
}, QgsSpatialIndex::FlagStoreFeatureGeometries );
|
||||||
|
|
||||||
QgsRectangle extent = source->sourceExtent();
|
QgsRectangle extent = mSource->sourceExtent();
|
||||||
double delta = extent.width() * buffer / 100.0;
|
double delta = extent.width() * mBuffer / 100.0;
|
||||||
extent.setXMinimum( extent.xMinimum() - delta );
|
extent.setXMinimum( extent.xMinimum() - delta );
|
||||||
extent.setXMaximum( extent.xMaximum() + delta );
|
extent.setXMaximum( extent.xMaximum() + delta );
|
||||||
delta = extent.height() * buffer / 100.0;
|
delta = extent.height() * mBuffer / 100.0;
|
||||||
extent.setYMinimum( extent.yMinimum() - delta );
|
extent.setYMinimum( extent.yMinimum() - delta );
|
||||||
extent.setYMaximum( extent.yMaximum() + delta );
|
extent.setYMaximum( extent.yMaximum() + delta );
|
||||||
QgsGeometry clippingGeom = QgsGeometry::fromRect( extent );
|
QgsGeometry clippingGeom = QgsGeometry::fromRect( extent );
|
||||||
|
|
||||||
QgsGeometry voronoiDiagram = allPoints.voronoiDiagram( clippingGeom, tolerance );
|
QgsGeometry voronoiDiagram = allPoints.voronoiDiagram( clippingGeom, mTolerance );
|
||||||
|
|
||||||
if ( !voronoiDiagram.isEmpty() )
|
if ( !voronoiDiagram.isEmpty() )
|
||||||
{
|
{
|
||||||
@ -162,33 +174,78 @@ QVariantMap QgsVoronoiPolygonsAlgorithm::processAlgorithm( const QVariantMap &pa
|
|||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
f.setFields( fields );
|
f.setFields( fields );
|
||||||
f.setGeometry( QgsGeometry( extentEngine->intersection( collection[i].constGet() ) ) );
|
f.setGeometry( QgsGeometry( extentEngine->intersection( collection[i].constGet() ) ) );
|
||||||
if ( copyAttributes )
|
const QList< QgsFeatureId > intersected = index.intersects( collection[i].boundingBox() );
|
||||||
|
engine.reset( QgsGeometry::createGeometryEngine( collection[i].constGet() ) );
|
||||||
|
engine->prepareGeometry();
|
||||||
|
for ( const QgsFeatureId id : intersected )
|
||||||
{
|
{
|
||||||
const QList< QgsFeatureId > intersected = index.intersects( collection[i].boundingBox() );
|
if ( engine->intersects( index.geometry( id ).constGet() ) )
|
||||||
engine.reset( QgsGeometry::createGeometryEngine( collection[i].constGet() ) );
|
|
||||||
engine->prepareGeometry();
|
|
||||||
for ( const QgsFeatureId id : intersected )
|
|
||||||
{
|
{
|
||||||
if ( engine->intersects( index.geometry( id ).constGet() ) )
|
f.setAttributes( attributeCache.value( id ) );
|
||||||
{
|
break;
|
||||||
f.setAttributes( attributeCache.value( id ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
f.setAttributes( QgsAttributes() << i );
|
|
||||||
}
|
|
||||||
if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
|
if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
|
||||||
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
|
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||||
feedback->setProgress( 50 + i * step );
|
feedback->setProgress( 50 + i * step );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap outputs;
|
return dest;
|
||||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
}
|
||||||
return outputs;
|
|
||||||
|
QString QgsVoronoiPolygonsAlgorithm::voronoiWithoutAttributes( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||||
|
{
|
||||||
|
QgsFields fields;
|
||||||
|
fields.append( QgsField( QStringLiteral( "id" ), QVariant::LongLong ) );
|
||||||
|
|
||||||
|
QString dest;
|
||||||
|
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, Qgis::WkbType::Polygon, mSource->sourceCrs() ) );
|
||||||
|
if ( !sink )
|
||||||
|
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||||
|
|
||||||
|
QgsFeatureRequest request;
|
||||||
|
request.setSubsetOfAttributes( QList< int >() );
|
||||||
|
QgsFeatureIterator it = mSource->getFeatures( request, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
|
||||||
|
|
||||||
|
QgsGeometry allPoints;
|
||||||
|
QHash< QgsFeatureId, QgsAttributes > attributeCache;
|
||||||
|
|
||||||
|
double step = mSource->featureCount() > 0 ? 100.0 / mSource->featureCount() : 1;
|
||||||
|
|
||||||
|
QgsRectangle extent = mSource->sourceExtent();
|
||||||
|
double delta = extent.width() * mBuffer / 100.0;
|
||||||
|
extent.setXMinimum( extent.xMinimum() - delta );
|
||||||
|
extent.setXMaximum( extent.xMaximum() + delta );
|
||||||
|
delta = extent.height() * mBuffer / 100.0;
|
||||||
|
extent.setYMinimum( extent.yMinimum() - delta );
|
||||||
|
extent.setYMaximum( extent.yMaximum() + delta );
|
||||||
|
QgsGeometry clippingGeom = QgsGeometry::fromRect( extent );
|
||||||
|
|
||||||
|
QgsGeometry voronoiDiagram = allPoints.voronoiDiagram( clippingGeom, mTolerance );
|
||||||
|
|
||||||
|
if ( !voronoiDiagram.isEmpty() )
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsGeometryEngine > engine;
|
||||||
|
std::unique_ptr< QgsGeometryEngine > extentEngine( QgsGeometry::createGeometryEngine( clippingGeom.constGet() ) );
|
||||||
|
QVector< QgsGeometry > collection = voronoiDiagram.asGeometryCollection();
|
||||||
|
for ( int i = 0; i < collection.length(); i++ )
|
||||||
|
{
|
||||||
|
if ( feedback->isCanceled() )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QgsFeature f;
|
||||||
|
f.setFields( fields );
|
||||||
|
f.setGeometry( QgsGeometry( extentEngine->intersection( collection[i].constGet() ) ) );
|
||||||
|
f.setAttributes( QgsAttributes() << i );
|
||||||
|
if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
|
||||||
|
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||||
|
feedback->setProgress( i * step );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
///@endcond
|
///@endcond
|
||||||
|
@ -47,8 +47,18 @@ class QgsVoronoiPolygonsAlgorithm : public QgsProcessingAlgorithm
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||||
QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString voronoiWithAttributes( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||||
|
QString voronoiWithoutAttributes( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||||
|
|
||||||
|
std::unique_ptr< QgsProcessingFeatureSource > mSource;
|
||||||
|
double mBuffer;
|
||||||
|
double mTolerance;
|
||||||
|
bool mCopyAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
///@endcond PRIVATE
|
///@endcond PRIVATE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user