4242 QgsProviderRegistry ,
4343 QgsProviderMetadata ,
4444 QgsGeometryEngine ,
45+ QgsSpatialIndex ,
4546)
4647
4748from qgis .PyQt .QtCore import QVariant
@@ -65,6 +66,9 @@ def __init__(self, source, request):
6566 else :
6667 self ._select_rect_engine = None
6768 self ._select_rect_geom = None
69+ self ._feature_id_list = None
70+ if self ._filter_rect is not None and self ._source ._provider ._spatialindex is not None :
71+ self ._feature_id_list = self ._source ._provider ._spatialindex .intersects (self ._filter_rect )
6872
6973 def fetchFeature (self , f ):
7074 """fetch next feature, return true on success"""
@@ -77,6 +81,21 @@ def fetchFeature(self, f):
7781 while not found :
7882 _f = self ._source ._features [list (self ._source ._features .keys ())[self ._index ]]
7983 self ._index += 1
84+
85+ if self ._feature_id_list is not None and f .id () not in self ._feature_id_list :
86+ continue
87+
88+ if not self ._filter_rect .isNull ():
89+ if not _f .hasGeometry ():
90+ continue
91+ if self ._request .flags () & QgsFeatureRequest .ExactIntersect :
92+ # do exact check in case we're doing intersection
93+ if not self ._select_rect_engine .intersects (_f .geometry ().constGet ()):
94+ continue
95+ else :
96+ if not _f .geometry ().boundingBox ().intersects (self ._filter_rect ):
97+ continue
98+
8099 self ._source ._expression_context .setFeature (_f )
81100 if self ._request .filterType () == QgsFeatureRequest .FilterExpression :
82101 if not self ._request .filterExpression ().evaluate (self ._source ._expression_context ):
@@ -90,16 +109,6 @@ def fetchFeature(self, f):
90109 elif self ._request .filterType () == QgsFeatureRequest .FilterFid :
91110 if _f .id () != self ._request .filterFid ():
92111 continue
93- if not self ._filter_rect .isNull ():
94- if not _f .hasGeometry ():
95- continue
96- if self ._request .flags () & QgsFeatureRequest .ExactIntersect :
97- # do exact check in case we're doing intersection
98- if not self ._select_rect_engine .intersects (_f .geometry ().constGet ()):
99- continue
100- else :
101- if not _f .geometry ().boundingBox ().intersects (self ._filter_rect ):
102- continue
103112 f .setGeometry (_f .geometry ())
104113 self .geometryToDestinationCrs (f , self ._transform )
105114 f .setFields (_f .fields ())
@@ -198,6 +207,9 @@ def __init__(self, uri=''):
198207 self ._extent .setMinimal ()
199208 self ._subset_string = ''
200209 self ._crs = mlayer .crs ()
210+ self ._spatialindex = None
211+ if 'index=yes' in self ._uri :
212+ self .createSpatialIndex ()
201213
202214 def featureSource (self ):
203215 return PyFeatureSource (self )
@@ -256,6 +268,9 @@ def addFeatures(self, flist, flags=None):
256268 added = True
257269 f_added .append (_f )
258270
271+ if self ._spatialindex is not None :
272+ self ._spatialindex .insertFeature (_f )
273+
259274 if len (f_added ):
260275 self .updateExtents ()
261276
@@ -267,6 +282,8 @@ def deleteFeatures(self, ids):
267282 removed = False
268283 for id in ids :
269284 if id in self ._features :
285+ if self ._spatialindex is not None :
286+ self ._spatialindex .deleteFeature (self ._features [id ])
270287 del self ._features [id ]
271288 removed = True
272289 if removed :
@@ -349,6 +366,10 @@ def supportsSubsetString(self):
349366 return True
350367
351368 def createSpatialIndex (self ):
369+ if self ._spatialindex is None :
370+ self ._spatialindex = QgsSpatialIndex ()
371+ for f in self ._features :
372+ self ._spatialindex .insertFeature (f )
352373 return True
353374
354375 def capabilities (self ):
0 commit comments