@@ -67,17 +67,10 @@ void QgsSnappingUtils::clearAllLocators()
67
67
68
68
QgsPointLocator* QgsSnappingUtils::locatorForLayerUsingStrategy ( QgsVectorLayer* vl, const QgsPoint& pointMap, double tolerance )
69
69
{
70
- if ( mStrategy == IndexAlwaysFull )
70
+ if ( willUseIndex ( vl ) )
71
71
return locatorForLayer ( vl );
72
- else if ( mStrategy == IndexNeverFull )
72
+ else
73
73
return temporaryLocatorForLayer ( vl, pointMap, tolerance );
74
- else // Hybrid
75
- {
76
- if ( vl->pendingFeatureCount () > 1000000 )
77
- return temporaryLocatorForLayer ( vl, pointMap, tolerance );
78
- else
79
- return locatorForLayer ( vl );
80
- }
81
74
}
82
75
83
76
QgsPointLocator* QgsSnappingUtils::temporaryLocatorForLayer ( QgsVectorLayer* vl, const QgsPoint& pointMap, double tolerance )
@@ -92,6 +85,22 @@ QgsPointLocator* QgsSnappingUtils::temporaryLocatorForLayer( QgsVectorLayer* vl,
92
85
return mTemporaryLocators .value ( vl );
93
86
}
94
87
88
+ bool QgsSnappingUtils::willUseIndex ( QgsVectorLayer* vl ) const
89
+ {
90
+ if ( mStrategy == IndexAlwaysFull )
91
+ return true ;
92
+ else if ( mStrategy == IndexNeverFull )
93
+ return false ;
94
+ else
95
+ {
96
+ if ( mHybridNonindexableLayers .contains ( vl->id () ) )
97
+ return false ;
98
+
99
+ // if the layer is too big, the locator will later stop indexing it after reaching a threshold
100
+ return true ;
101
+ }
102
+ }
103
+
95
104
96
105
static QgsPointLocator::Match _findClosestSegmentIntersection ( const QgsPoint& pt, const QgsPointLocator::MatchList& segments )
97
106
{
@@ -204,6 +213,8 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg
204
213
if ( !mCurrentLayer )
205
214
return QgsPointLocator::Match ();
206
215
216
+ prepareIndex ( QList<QgsVectorLayer*>() << mCurrentLayer );
217
+
207
218
// data from project
208
219
double tolerance = QgsTolerance::toleranceInMapUnits ( mDefaultTolerance , mMapSettings , mDefaultUnit );
209
220
int type = mDefaultType ;
@@ -227,6 +238,11 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg
227
238
}
228
239
else if ( mSnapToMapMode == SnapAdvanced )
229
240
{
241
+ QList<QgsVectorLayer*> layers;
242
+ foreach ( const LayerConfig& layerConfig, mLayers )
243
+ layers << layerConfig.layer ;
244
+ prepareIndex ( layers );
245
+
230
246
QgsPointLocator::Match bestMatch;
231
247
QgsPointLocator::MatchList edges; // for snap on intersection
232
248
double maxSnapIntTolerance = 0 ;
@@ -257,15 +273,17 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg
257
273
double tolerance = QgsTolerance::toleranceInMapUnits ( mDefaultTolerance , mMapSettings , mDefaultUnit );
258
274
int type = mDefaultType ;
259
275
276
+ QList<QgsVectorLayer*> layers;
277
+ foreach ( const QString& layerID, mMapSettings .layers () )
278
+ if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance ()->mapLayer ( layerID ) ) )
279
+ layers << vl;
280
+ prepareIndex ( layers );
281
+
260
282
QgsPointLocator::MatchList edges; // for snap on intersection
261
283
QgsPointLocator::Match bestMatch;
262
284
263
- foreach ( const QString& layerID, mMapSettings . layers () )
285
+ foreach ( QgsVectorLayer* vl, layers )
264
286
{
265
- QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance ()->mapLayer ( layerID ) );
266
- if ( !vl )
267
- continue ;
268
-
269
287
if ( QgsPointLocator* loc = locatorForLayerUsingStrategy ( vl, pointMap, tolerance ) )
270
288
{
271
289
_updateBestMatch ( bestMatch, pointMap, loc, type, tolerance, filter );
@@ -285,6 +303,31 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg
285
303
}
286
304
287
305
306
+ void QgsSnappingUtils::prepareIndex ( const QList<QgsVectorLayer*>& layers )
307
+ {
308
+ // check if we need to build any index
309
+ QList<QgsVectorLayer*> layersToIndex;
310
+ foreach ( QgsVectorLayer* vl, layers )
311
+ {
312
+ if ( willUseIndex ( vl ) && !locatorForLayer ( vl )->hasIndex () )
313
+ layersToIndex << vl;
314
+ }
315
+ if ( layersToIndex.isEmpty () )
316
+ return ;
317
+
318
+ // build indexes
319
+ QTime t; t.start ();
320
+ foreach ( QgsVectorLayer* vl, layersToIndex )
321
+ {
322
+ QTime tt; tt.start ();
323
+ if ( !locatorForLayer ( vl )->init ( mStrategy == IndexHybrid ? 1000000 : -1 ) )
324
+ mHybridNonindexableLayers .insert ( vl->id () );
325
+ QgsDebugMsg ( QString ( " Index init: %1 ms (%2)" ).arg ( tt.elapsed () ).arg ( vl->id () ) );
326
+ }
327
+ QgsDebugMsg ( QString ( " Prepare index total: %1 ms" ).arg ( t.elapsed () ) );
328
+ }
329
+
330
+
288
331
QgsPointLocator::Match QgsSnappingUtils::snapToCurrentLayer ( const QPoint& point, int type, QgsPointLocator::MatchFilter* filter )
289
332
{
290
333
if ( !mCurrentLayer )
0 commit comments