@@ -5680,9 +5680,9 @@ static QVariant fcnFromBase64( const QVariantList &values, const QgsExpressionCo
5680
5680
return QVariant ( decoded );
5681
5681
}
5682
5682
5683
- typedef std::function < QVariant( QgsExpression &subExp, QgsExpressionContext &subContext, QgsVectorLayer *cachedTarget, QList<QgsFeature> features, const QgsGeometry &geometry, bool testOnly, bool invert, QVariant currentFeatId, int neighbors, double max_distance, double bboxGrow ) > overlayFunc ;
5683
+ typedef bool ( QgsGeometry::*RelationFunction )( const QgsGeometry &geometry ) const ;
5684
5684
5685
- static QVariant executeGeomOverlay ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const overlayFunc &overlayFunction , bool invert = false , double bboxGrow = 0 , bool isNearestFunc = false )
5685
+ static QVariant executeGeomOverlay ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const RelationFunction &relationFunction , bool invert = false , double bboxGrow = 0 , bool isNearestFunc = false )
5686
5686
{
5687
5687
5688
5688
const QVariant sourceLayerRef = context->variable ( QStringLiteral ( " layer" ) ); // used to detect if sourceLayer and targetLayer are the same
@@ -5728,7 +5728,7 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
5728
5728
if ( ! isNearestFunc )
5729
5729
{
5730
5730
// for all functions but nearest_neighbour, the limit parameters limits queryset.
5731
- // (for nearest_neighbour, it will be passed to the overlayFunction , which will limit
5731
+ // (for nearest_neighbour, it will be used by the spatial index below , which will limit
5732
5732
// but taking distance into account)
5733
5733
request.setLimit ( limit );
5734
5734
}
@@ -5812,6 +5812,7 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
5812
5812
QList<QgsFeatureId> fidsList;
5813
5813
if ( isNearestFunc )
5814
5814
{
5815
+ // TODO : add 1 to limit if target and source layers are the same and ignore this feature
5815
5816
fidsList = spatialIndex.nearestNeighbor ( geometry, limit, max_distance );
5816
5817
}
5817
5818
else
@@ -5822,12 +5823,10 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
5822
5823
QListIterator<QgsFeatureId> i (fidsList);
5823
5824
while ( i.hasNext () )
5824
5825
{
5826
+ // TODO : ignore feature if same as this (and remove logic below)
5825
5827
features.append ( cachedTarget->getFeature ( i.next () ) );
5826
5828
}
5827
5829
5828
- // We use the cached layer as target layer !!
5829
- targetLayer = cachedTarget;
5830
-
5831
5830
}
5832
5831
else
5833
5832
{
@@ -5838,6 +5837,7 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
5838
5837
QgsFeature feat;
5839
5838
while ( fit.nextFeature ( feat ) )
5840
5839
{
5840
+ // TODO : ignore feature if same as this (and remove logic below)
5841
5841
features.append ( feat );
5842
5842
}
5843
5843
}
@@ -5851,16 +5851,6 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
5851
5851
subExpression.prepare ( &subContext );
5852
5852
}
5853
5853
5854
- return overlayFunction ( subExpression, subContext, targetLayer, features, geometry, testOnly, invert, currentFeatId, limit, max_distance, bboxGrow );
5855
- }
5856
-
5857
- // Intersect functions:
5858
-
5859
- typedef bool ( QgsGeometry::*t_relationFunction )( const QgsGeometry &geometry ) const ;
5860
-
5861
- template <t_relationFunction T>
5862
- static QVariant indexedFilteredOverlay ( QgsExpression &subExp, QgsExpressionContext &subContext, QgsVectorLayer *targetLayer, QList<QgsFeature> features, const QgsGeometry &geometry, bool testOnly, bool invert, QVariant currentFeatId, int neighbors, double max_distance, double bboxGrow = 0 )
5863
- {
5864
5854
5865
5855
bool found = false ;
5866
5856
QVariantList results;
@@ -5870,127 +5860,104 @@ static QVariant indexedFilteredOverlay( QgsExpression &subExp, QgsExpressionCont
5870
5860
{
5871
5861
QgsFeature feat = i.next ();
5872
5862
5863
+ // TODO : remove this, and implement above
5864
+ // currentFeatId is only set if sourceLayer and targetLayer are the same,
5865
+ // in which case current feature have to be excluded from spatial check
5873
5866
if ( !currentFeatId.isNull () && currentFeatId.toLongLong () == feat.id () )
5874
5867
{
5875
- continue ; // if sourceLayer and targetLayer are the same, current feature have to be excluded from spatial check
5868
+ continue ;
5876
5869
}
5877
5870
5878
- if ( ( feat.geometry ().*T )( geometry ) ) // Calls the method provided as template argument for the function (e.g. QgsGeometry::intersects)
5871
+ if ( ! relationFunction || ( feat.geometry ().*relationFunction )( geometry ) ) // Calls the method provided as template argument for the function (e.g. QgsGeometry::intersects)
5879
5872
{
5880
5873
found = true ;
5881
5874
5882
5875
// We just want a single boolean result if there is any intersect: finish and return true
5883
5876
if ( testOnly )
5884
5877
break ;
5885
5878
5886
- // We want a list of attributes / geometries / other expression values, evaluate now
5887
5879
if ( !invert )
5888
5880
{
5881
+ // We want a list of attributes / geometries / other expression values, evaluate now
5889
5882
subContext.setFeature ( feat );
5890
- results.append ( subExp .evaluate ( &subContext ) );
5883
+ results.append ( subExpression .evaluate ( &subContext ) );
5891
5884
}
5892
5885
else
5893
5886
{
5887
+ // If not, results is a list of found ids, which we'll inverse and evaluate below
5894
5888
results.append ( feat.id () );
5895
5889
}
5896
5890
}
5897
5891
}
5892
+
5898
5893
if ( testOnly )
5899
5894
{
5900
5895
if ( invert )
5901
5896
found = !found;// for disjoint condition
5902
5897
return found;
5903
5898
}
5904
- else
5899
+
5900
+ if ( !invert )
5901
+ return results;
5902
+
5903
+ // for disjoint condition returns the results for cached layers not intersected feats
5904
+ QVariantList disjoint_results;
5905
+ QgsFeature feat2;
5906
+ QgsFeatureIterator fi = targetLayer->getFeatures ();
5907
+ while ( fi.nextFeature ( feat2 ) )
5905
5908
{
5906
- if ( !invert )
5907
- return results;
5908
- else
5909
+ if ( !results.contains ( feat2.id () ) )
5909
5910
{
5910
- // for disjoint condition returns the results for cached layers not intersected feats
5911
- QVariantList disjoint_results;
5912
- QgsFeature feat;
5913
- QgsFeatureIterator fi = targetLayer->getFeatures ();
5914
- while ( fi.nextFeature ( feat ) )
5915
- {
5916
- if ( !results.contains ( feat.id () ) )
5917
- {
5918
- subContext.setFeature ( feat );
5919
- disjoint_results.append ( subExp.evaluate ( &subContext ) );
5920
- }
5921
- }
5922
- return disjoint_results;
5911
+ subContext.setFeature ( feat2 );
5912
+ disjoint_results.append ( subExpression.evaluate ( &subContext ) );
5923
5913
}
5924
5914
}
5925
- }
5926
-
5927
- static QVariant indexedFilteredNearest ( QgsExpression &subExp, QgsExpressionContext &subContext, QgsVectorLayer *targetLayer, QList<QgsFeature> features, const QgsGeometry &geometry, bool testOnly, bool invert, QVariant currentFeatId, int neighbors, double max_distance, double bboxGrow = 0 )
5928
- {
5929
-
5930
- bool found = false ;
5931
- QVariantList results;
5932
- QListIterator<QgsFeature> i (features);
5933
- while ( i.hasNext () )
5934
- {
5935
- QgsFeature feat = i.next ();
5915
+ return disjoint_results;
5936
5916
5937
- found = true ;
5938
- // We just want a single boolean result if there is any intersect: finish and return true
5939
- if ( testOnly )
5940
- break ;
5941
-
5942
- subContext.setFeature ( feat );
5943
- results.append ( subExp.evaluate ( &subContext ) );
5944
- }
5917
+ }
5945
5918
5946
- if ( testOnly )
5947
- {
5948
- if ( invert )
5949
- found = !found;// for disjoint condition
5950
- return found;
5951
- }
5919
+ // Intersect functions:
5952
5920
5953
- return results;
5954
- }
5921
+ typedef bool ( QgsGeometry::*t_relationFunction )( const QgsGeometry &geometry ) const ;
5955
5922
5956
5923
static QVariant fcnGeomOverlayIntersects ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5957
5924
{
5958
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::intersects> );
5925
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::intersects );
5959
5926
}
5960
5927
5961
5928
static QVariant fcnGeomOverlayContains ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5962
5929
{
5963
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::contains> );
5930
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::contains );
5964
5931
}
5965
5932
5966
5933
static QVariant fcnGeomOverlayCrosses ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5967
5934
{
5968
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::crosses> );
5935
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::crosses );
5969
5936
}
5970
5937
5971
5938
static QVariant fcnGeomOverlayEquals ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5972
5939
{
5973
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::equals> , false , 0.01 ); // grow amount should adapt to current units
5940
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::equals, false , 0.01 ); // grow amount should adapt to current units
5974
5941
}
5975
5942
5976
5943
static QVariant fcnGeomOverlayTouches ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5977
5944
{
5978
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::touches> , false , 0.01 ); // grow amount should adapt to current units
5945
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::touches, false , 0.01 ); // grow amount should adapt to current units
5979
5946
}
5980
5947
5981
5948
static QVariant fcnGeomOverlayWithin ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5982
5949
{
5983
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::within> );
5950
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::within );
5984
5951
}
5985
5952
5986
5953
static QVariant fcnGeomOverlayDisjoint ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5987
5954
{
5988
- return executeGeomOverlay ( values, context, parent, indexedFilteredOverlay< &QgsGeometry::intersects> , true );
5955
+ return executeGeomOverlay ( values, context, parent, &QgsGeometry::intersects, true );
5989
5956
}
5990
5957
5991
5958
static QVariant fcnGeomOverlayNearest ( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
5992
5959
{
5993
- return executeGeomOverlay ( values, context, parent, indexedFilteredNearest , false , 0 , true );
5960
+ return executeGeomOverlay ( values, context, parent, nullptr , false , 0 , true );
5994
5961
}
5995
5962
5996
5963
const QList<QgsExpressionFunction *> &QgsExpression::Functions ()
0 commit comments