Skip to content

Commit 7baa623

Browse files
committed
Allow bulk load of QgsSpatialIndex to be canceled via QgsFeedback
1 parent b441a4f commit 7baa623

File tree

11 files changed

+46
-21
lines changed

11 files changed

+46
-21
lines changed

python/core/qgsspatialindex.sip

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,28 @@ class QgsSpatialIndex
2828
Constructor - creates R-tree
2929
%End
3030

31-
explicit QgsSpatialIndex( const QgsFeatureIterator &fi );
31+
explicit QgsSpatialIndex( const QgsFeatureIterator &fi, QgsFeedback *feedback = 0 );
3232
%Docstring
3333
Constructor - creates R-tree and bulk loads it with features from the iterator.
3434
This is much faster approach than creating an empty index and then inserting features one by one.
3535

36+
The optional ``feedback`` object can be used to allow cancelation of bulk feature loading. Ownership
37+
of ``feedback`` is not transferred, and callers must take care that the lifetime of feedback exceeds
38+
that of the spatial index construction.
39+
3640
.. versionadded:: 2.8
3741
%End
3842

39-
explicit QgsSpatialIndex( const QgsFeatureSource &source );
43+
explicit QgsSpatialIndex( const QgsFeatureSource &source, QgsFeedback *feedback = 0 );
4044
%Docstring
4145
Constructor - creates R-tree and bulk loads it with features from the source.
4246
This is much faster approach than creating an empty index and then inserting features one by one.
4347

48+
The optional ``feedback`` object can be used to allow cancelation of bulk feature loading. Ownership
49+
of ``feedback`` is not transferred, and callers must take care that the lifetime of feedback exceeds
50+
that of the spatial index construction.
51+
52+
4453
.. versionadded:: 3.0
4554
%End
4655

python/plugins/processing/algs/qgis/Difference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def processAlgorithm(self, parameters, context, feedback):
8383
featB = QgsFeature()
8484
outFeat = QgsFeature()
8585

86-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
86+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
8787

8888
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
8989
count = 0

python/plugins/processing/algs/qgis/Intersection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def processAlgorithm(self, parameters, context, feedback):
9595
fields, geomType, sourceA.sourceCrs())
9696

9797
outFeat = QgsFeature()
98-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
98+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
9999

100100
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
101101
count = 0

python/plugins/processing/algs/qgis/NearestNeighbourAnalysis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def processAlgorithm(self, parameters, context, feedback):
9494
source = self.parameterAsSource(parameters, self.INPUT, context)
9595
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
9696

97-
spatialIndex = QgsSpatialIndex(source)
97+
spatialIndex = QgsSpatialIndex(source, feedback)
9898

9999
distance = QgsDistanceArea()
100100
distance.setSourceCrs(source.sourceCrs())

python/plugins/processing/algs/qgis/PointsInPolygon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def processAlgorithm(self, parameters, context, feedback):
111111
fields, poly_source.wkbType(), poly_source.sourceCrs())
112112

113113
spatialIndex = QgsSpatialIndex(point_source.getFeatures(
114-
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())))
114+
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
115115

116116
point_attribute_indices = []
117117
if weight_field_index >= 0:

python/plugins/processing/algs/qgis/SelectByAttributeSum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def processAlgorithm(self, parameters, context, feedback):
8383
geom = ft.geometry()
8484
attrSum = ft[fieldName]
8585

86-
idx = QgsSpatialIndex(layer.getFeatures(QgsFeatureRequest.setSubsetOfAttributes([])))
86+
idx = QgsSpatialIndex(layer.getFeatures(QgsFeatureRequest.setSubsetOfAttributes([])), feedback)
8787
req = QgsFeatureRequest()
8888
completed = False
8989
while not completed:

python/plugins/processing/algs/qgis/SumLines.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def processAlgorithm(self, parameters, context, feedback):
101101
fields, poly_source.wkbType(), poly_source.sourceCrs())
102102

103103
spatialIndex = QgsSpatialIndex(line_source.getFeatures(
104-
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())))
104+
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
105105

106106
distArea = QgsDistanceArea()
107107
distArea.setSourceCrs(poly_source.sourceCrs())

python/plugins/processing/algs/qgis/SymmetricalDifference.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def processAlgorithm(self, parameters, context, feedback):
8787
featB = QgsFeature()
8888
outFeat = QgsFeature()
8989

90-
indexA = QgsSpatialIndex(sourceA)
91-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
90+
indexA = QgsSpatialIndex(sourceA, feedback)
91+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
9292

9393
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
9494
count = 0

python/plugins/processing/algs/qgis/Union.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ def processAlgorithm(self, parameters, context, feedback):
9797
featB = QgsFeature()
9898
outFeat = QgsFeature()
9999

100-
indexA = QgsSpatialIndex(sourceA)
101-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
100+
indexA = QgsSpatialIndex(sourceA, feedback)
101+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
102102

103103
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
104104
count = 0

src/core/qgsspatialindex.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgsrectangle.h"
2222
#include "qgslogger.h"
2323
#include "qgsfeaturesource.h"
24+
#include "qgsfeedback.h"
2425

2526
#include "SpatialIndex.h"
2627

@@ -92,9 +93,10 @@ class QgsFeatureIteratorDataStream : public IDataStream
9293
{
9394
public:
9495
//! constructor - needs to load all data to a vector for later access when bulk loading
95-
explicit QgsFeatureIteratorDataStream( const QgsFeatureIterator &fi )
96+
explicit QgsFeatureIteratorDataStream( const QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
9697
: mFi( fi )
9798
, mNextData( nullptr )
99+
, mFeedback( feedback )
98100
{
99101
readNextEntry();
100102
}
@@ -107,6 +109,9 @@ class QgsFeatureIteratorDataStream : public IDataStream
107109
//! returns a pointer to the next entry in the stream or 0 at the end of the stream.
108110
IData *getNext() override
109111
{
112+
if ( mFeedback && mFeedback->isCanceled() )
113+
return nullptr;
114+
110115
RTree::Data *ret = mNextData;
111116
mNextData = nullptr;
112117
readNextEntry();
@@ -141,6 +146,7 @@ class QgsFeatureIteratorDataStream : public IDataStream
141146
private:
142147
QgsFeatureIterator mFi;
143148
RTree::Data *mNextData = nullptr;
149+
QgsFeedback *mFeedback = nullptr;
144150
};
145151

146152

@@ -157,9 +163,9 @@ class QgsSpatialIndexData : public QSharedData
157163
initTree();
158164
}
159165

160-
explicit QgsSpatialIndexData( const QgsFeatureIterator &fi )
166+
explicit QgsSpatialIndexData( const QgsFeatureIterator &fi, QgsFeedback *feedback = nullptr )
161167
{
162-
QgsFeatureIteratorDataStream fids( fi );
168+
QgsFeatureIteratorDataStream fids( fi, feedback );
163169
initTree( &fids );
164170
}
165171

@@ -224,14 +230,14 @@ QgsSpatialIndex::QgsSpatialIndex()
224230
d = new QgsSpatialIndexData;
225231
}
226232

227-
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureIterator &fi )
233+
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureIterator &fi, QgsFeedback *feedback )
228234
{
229-
d = new QgsSpatialIndexData( fi );
235+
d = new QgsSpatialIndexData( fi, feedback );
230236
}
231237

232-
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureSource &source )
238+
QgsSpatialIndex::QgsSpatialIndex( const QgsFeatureSource &source, QgsFeedback *feedback )
233239
{
234-
d = new QgsSpatialIndexData( source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ) );
240+
d = new QgsSpatialIndexData( source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ), feedback );
235241
}
236242

237243
QgsSpatialIndex::QgsSpatialIndex( const QgsSpatialIndex &other ) //NOLINT

0 commit comments

Comments
 (0)