@@ -133,6 +133,7 @@ QVariantMap QgsJoinByLocationAlgorithm::processAlgorithm( const QVariantMap &par
133
133
const QStringList joinedFieldNames = parameterAsFields ( parameters, QStringLiteral ( " JOIN_FIELDS" ), context );
134
134
135
135
mPredicates = parameterAsEnums ( parameters, QStringLiteral ( " PREDICATE" ), context );
136
+ sortPredicates ( mPredicates );
136
137
137
138
QString prefix = parameterAsString ( parameters, QStringLiteral ( " PREFIX" ), context );
138
139
@@ -303,6 +304,32 @@ bool QgsJoinByLocationAlgorithm::featureFilter( const QgsFeature &feature, QgsGe
303
304
return ok;
304
305
}
305
306
307
+ void QgsJoinByLocationAlgorithm::sortPredicates ( QList<int > &predicates )
308
+ {
309
+ // Sort predicate list so that faster predicates are earlier in the list
310
+ // Some predicates in GEOS do not have prepared geometry implementations, and are slow to calculate. So if users
311
+ // are testing multiple predicates, make sure the optimised ones are always tested first just in case we can shortcut
312
+ // these slower ones
313
+
314
+ std::sort ( predicates.begin (), predicates.end (), []( int a, int b ) -> bool
315
+ {
316
+ // return true if predicate a is faster than b
317
+
318
+ if ( a == 0 ) // intersects is fastest
319
+ return true ;
320
+ else if ( b == 0 )
321
+ return false ;
322
+
323
+ else if ( a == 5 ) // contains is fast for polygons
324
+ return true ;
325
+ else if ( b == 5 )
326
+ return false ;
327
+
328
+ // that's it, the rest don't have optimised prepared methods (as of GEOS 3.8)
329
+ return a < b;
330
+ } );
331
+ }
332
+
306
333
bool QgsJoinByLocationAlgorithm::processFeatures ( QgsFeature &joinFeature, QgsProcessingFeedback *feedback )
307
334
{
308
335
if ( !joinFeature.hasGeometry () )
0 commit comments