mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-18 00:03:05 -04:00
Allow bulk load of QgsSpatialIndex to be canceled via QgsFeedback
This commit is contained in:
parent
b441a4f2c9
commit
7baa623f6f
@ -28,19 +28,28 @@ class QgsSpatialIndex
|
|||||||
Constructor - creates R-tree
|
Constructor - creates R-tree
|
||||||
%End
|
%End
|
||||||
|
|
||||||
explicit QgsSpatialIndex( const QgsFeatureIterator &fi );
|
explicit QgsSpatialIndex( const QgsFeatureIterator &fi, QgsFeedback *feedback = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
Constructor - creates R-tree and bulk loads it with features from the iterator.
|
Constructor - creates R-tree and bulk loads it with features from the iterator.
|
||||||
This is much faster approach than creating an empty index and then inserting features one by one.
|
This is much faster approach than creating an empty index and then inserting features one by one.
|
||||||
|
|
||||||
|
The optional ``feedback`` object can be used to allow cancelation of bulk feature loading. Ownership
|
||||||
|
of ``feedback`` is not transferred, and callers must take care that the lifetime of feedback exceeds
|
||||||
|
that of the spatial index construction.
|
||||||
|
|
||||||
.. versionadded:: 2.8
|
.. versionadded:: 2.8
|
||||||
%End
|
%End
|
||||||
|
|
||||||
explicit QgsSpatialIndex( const QgsFeatureSource &source );
|
explicit QgsSpatialIndex( const QgsFeatureSource &source, QgsFeedback *feedback = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
Constructor - creates R-tree and bulk loads it with features from the source.
|
Constructor - creates R-tree and bulk loads it with features from the source.
|
||||||
This is much faster approach than creating an empty index and then inserting features one by one.
|
This is much faster approach than creating an empty index and then inserting features one by one.
|
||||||
|
|
||||||
|
The optional ``feedback`` object can be used to allow cancelation of bulk feature loading. Ownership
|
||||||
|
of ``feedback`` is not transferred, and callers must take care that the lifetime of feedback exceeds
|
||||||
|
that of the spatial index construction.
|
||||||
|
|
||||||
|
|
||||||
.. versionadded:: 3.0
|
.. versionadded:: 3.0
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class Difference(QgisAlgorithm):
|
|||||||
featB = QgsFeature()
|
featB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
|
|
||||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
|
||||||
|
|
||||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -95,7 +95,7 @@ class Intersection(QgisAlgorithm):
|
|||||||
fields, geomType, sourceA.sourceCrs())
|
fields, geomType, sourceA.sourceCrs())
|
||||||
|
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
|
||||||
|
|
||||||
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
|
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -94,7 +94,7 @@ class NearestNeighbourAnalysis(QgisAlgorithm):
|
|||||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||||
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
||||||
|
|
||||||
spatialIndex = QgsSpatialIndex(source)
|
spatialIndex = QgsSpatialIndex(source, feedback)
|
||||||
|
|
||||||
distance = QgsDistanceArea()
|
distance = QgsDistanceArea()
|
||||||
distance.setSourceCrs(source.sourceCrs())
|
distance.setSourceCrs(source.sourceCrs())
|
||||||
|
@ -111,7 +111,7 @@ class PointsInPolygon(QgisAlgorithm):
|
|||||||
fields, poly_source.wkbType(), poly_source.sourceCrs())
|
fields, poly_source.wkbType(), poly_source.sourceCrs())
|
||||||
|
|
||||||
spatialIndex = QgsSpatialIndex(point_source.getFeatures(
|
spatialIndex = QgsSpatialIndex(point_source.getFeatures(
|
||||||
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())))
|
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
|
||||||
|
|
||||||
point_attribute_indices = []
|
point_attribute_indices = []
|
||||||
if weight_field_index >= 0:
|
if weight_field_index >= 0:
|
||||||
|
@ -83,7 +83,7 @@ class SelectByAttributeSum(QgisAlgorithm):
|
|||||||
geom = ft.geometry()
|
geom = ft.geometry()
|
||||||
attrSum = ft[fieldName]
|
attrSum = ft[fieldName]
|
||||||
|
|
||||||
idx = QgsSpatialIndex(layer.getFeatures(QgsFeatureRequest.setSubsetOfAttributes([])))
|
idx = QgsSpatialIndex(layer.getFeatures(QgsFeatureRequest.setSubsetOfAttributes([])), feedback)
|
||||||
req = QgsFeatureRequest()
|
req = QgsFeatureRequest()
|
||||||
completed = False
|
completed = False
|
||||||
while not completed:
|
while not completed:
|
||||||
|
@ -101,7 +101,7 @@ class SumLines(QgisAlgorithm):
|
|||||||
fields, poly_source.wkbType(), poly_source.sourceCrs())
|
fields, poly_source.wkbType(), poly_source.sourceCrs())
|
||||||
|
|
||||||
spatialIndex = QgsSpatialIndex(line_source.getFeatures(
|
spatialIndex = QgsSpatialIndex(line_source.getFeatures(
|
||||||
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())))
|
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
|
||||||
|
|
||||||
distArea = QgsDistanceArea()
|
distArea = QgsDistanceArea()
|
||||||
distArea.setSourceCrs(poly_source.sourceCrs())
|
distArea.setSourceCrs(poly_source.sourceCrs())
|
||||||
|
@ -87,8 +87,8 @@ class SymmetricalDifference(QgisAlgorithm):
|
|||||||
featB = QgsFeature()
|
featB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
|
|
||||||
indexA = QgsSpatialIndex(sourceA)
|
indexA = QgsSpatialIndex(sourceA, feedback)
|
||||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
|
||||||
|
|
||||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -97,8 +97,8 @@ class Union(QgisAlgorithm):
|
|||||||
featB = QgsFeature()
|
featB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
|
|
||||||
indexA = QgsSpatialIndex(sourceA)
|
indexA = QgsSpatialIndex(sourceA, feedback)
|
||||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
|
||||||
|
|
||||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "qgsrectangle.h"
|
#include "qgsrectangle.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgsfeaturesource.h"
|
#include "qgsfeaturesource.h"
|
||||||
|
#include "qgsfeedback.h"
|
||||||
|
|
||||||
#include "SpatialIndex.h"
|
#include "SpatialIndex.h"
|
||||||
|
|
||||||
@ -92,9 +93,10 @@ class QgsFeatureIteratorDataStream : public IDataStream
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! constructor - needs to load all data to a vector for later access when bulk loading
|
//! constructor - needs to load all data to a vector for later access when bulk loading
|
||||||
explicit QgsFeatureIteratorDataStream( const QgsFeatureIterator &fi )
|
explicit QgsFeatureIteratorDataStream( const QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
|
||||||
: mFi( fi )
|
: mFi( fi )
|
||||||
, mNextData( nullptr )
|
, mNextData( nullptr )
|
||||||
|
, mFeedback( feedback )
|
||||||
{
|
{
|
||||||
readNextEntry();
|
readNextEntry();
|
||||||
}
|
}
|
||||||
@ -107,6 +109,9 @@ class QgsFeatureIteratorDataStream : public IDataStream
|
|||||||
//! returns a pointer to the next entry in the stream or 0 at the end of the stream.
|
//! returns a pointer to the next entry in the stream or 0 at the end of the stream.
|
||||||
IData *getNext() override
|
IData *getNext() override
|
||||||
{
|
{
|
||||||
|
if ( mFeedback && mFeedback->isCanceled() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
RTree::Data *ret = mNextData;
|
RTree::Data *ret = mNextData;
|
||||||
mNextData = nullptr;
|
mNextData = nullptr;
|
||||||
readNextEntry();
|
readNextEntry();
|
||||||
@ -141,6 +146,7 @@ class QgsFeatureIteratorDataStream : public IDataStream
|
|||||||
private:
|
private:
|
||||||
QgsFeatureIterator mFi;
|
QgsFeatureIterator mFi;
|
||||||
RTree::Data *mNextData = nullptr;
|
RTree::Data *mNextData = nullptr;
|
||||||
|
QgsFeedback *mFeedback = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -157,9 +163,9 @@ class QgsSpatialIndexData : public QSharedData
|
|||||||
initTree();
|
initTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit QgsSpatialIndexData( const QgsFeatureIterator &fi )
|
explicit QgsSpatialIndexData( const QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
|
||||||
{
|
{
|
||||||
QgsFeatureIteratorDataStream fids( fi );
|
QgsFeatureIteratorDataStream fids( fi, feedback );
|
||||||
initTree( &fids );
|
initTree( &fids );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,14 +230,14 @@ QgsSpatialIndex::QgsSpatialIndex()
|
|||||||
d = new QgsSpatialIndexData;
|
d = new QgsSpatialIndexData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureIterator &fi )
|
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureIterator &fi, QgsFeedback *feedback )
|
||||||
{
|
{
|
||||||
d = new QgsSpatialIndexData( fi );
|
d = new QgsSpatialIndexData( fi, feedback );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureSource &source )
|
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureSource &source, QgsFeedback *feedback )
|
||||||
{
|
{
|
||||||
d = new QgsSpatialIndexData( source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ) );
|
d = new QgsSpatialIndexData( source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ), feedback );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSpatialIndex::QgsSpatialIndex( const QgsSpatialIndex &other ) //NOLINT
|
QgsSpatialIndex::QgsSpatialIndex( const QgsSpatialIndex &other ) //NOLINT
|
||||||
|
@ -33,6 +33,7 @@ namespace SpatialIndex SIP_SKIP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QgsFeedback;
|
||||||
class QgsFeature;
|
class QgsFeature;
|
||||||
class QgsRectangle;
|
class QgsRectangle;
|
||||||
class QgsPointXY;
|
class QgsPointXY;
|
||||||
@ -64,17 +65,26 @@ class CORE_EXPORT QgsSpatialIndex
|
|||||||
/** Constructor - creates R-tree and bulk loads it with features from the iterator.
|
/** Constructor - creates R-tree and bulk loads it with features from the iterator.
|
||||||
* This is much faster approach than creating an empty index and then inserting features one by one.
|
* This is much faster approach than creating an empty index and then inserting features one by one.
|
||||||
*
|
*
|
||||||
|
* The optional \a feedback object can be used to allow cancelation of bulk feature loading. Ownership
|
||||||
|
* of \a feedback is not transferred, and callers must take care that the lifetime of feedback exceeds
|
||||||
|
* that of the spatial index construction.
|
||||||
|
*
|
||||||
* \since QGIS 2.8
|
* \since QGIS 2.8
|
||||||
*/
|
*/
|
||||||
explicit QgsSpatialIndex( const QgsFeatureIterator &fi );
|
explicit QgsSpatialIndex( const QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor - creates R-tree and bulk loads it with features from the source.
|
* Constructor - creates R-tree and bulk loads it with features from the source.
|
||||||
* This is much faster approach than creating an empty index and then inserting features one by one.
|
* This is much faster approach than creating an empty index and then inserting features one by one.
|
||||||
|
*
|
||||||
|
* The optional \a feedback object can be used to allow cancelation of bulk feature loading. Ownership
|
||||||
|
* of \a feedback is not transferred, and callers must take care that the lifetime of feedback exceeds
|
||||||
|
* that of the spatial index construction.
|
||||||
|
|
||||||
*
|
*
|
||||||
* \since QGIS 3.0
|
* \since QGIS 3.0
|
||||||
*/
|
*/
|
||||||
explicit QgsSpatialIndex( const QgsFeatureSource &source );
|
explicit QgsSpatialIndex( const QgsFeatureSource &source, QgsFeedback *feedback = nullptr );
|
||||||
|
|
||||||
//! Copy constructor
|
//! Copy constructor
|
||||||
QgsSpatialIndex( const QgsSpatialIndex &other );
|
QgsSpatialIndex( const QgsSpatialIndex &other );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user