Skip to content

Commit 4626aa2

Browse files
committedSep 8, 2020
[refFunctions] refactor
1 parent 6c0eab7 commit 4626aa2

File tree

1 file changed

+39
-72
lines changed

1 file changed

+39
-72
lines changed
 

‎src/core/expression/qgsexpressionfunction.cpp

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5680,9 +5680,9 @@ static QVariant fcnFromBase64( const QVariantList &values, const QgsExpressionCo
56805680
return QVariant( decoded );
56815681
}
56825682

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;
56845684

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 )
56865686
{
56875687

56885688
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
57285728
if ( ! isNearestFunc )
57295729
{
57305730
// 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
57325732
// but taking distance into account)
57335733
request.setLimit( limit );
57345734
}
@@ -5812,6 +5812,7 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
58125812
QList<QgsFeatureId> fidsList;
58135813
if ( isNearestFunc )
58145814
{
5815+
// TODO : add 1 to limit if target and source layers are the same and ignore this feature
58155816
fidsList = spatialIndex.nearestNeighbor( geometry, limit, max_distance );
58165817
}
58175818
else
@@ -5822,12 +5823,10 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
58225823
QListIterator<QgsFeatureId> i(fidsList);
58235824
while ( i.hasNext() )
58245825
{
5826+
// TODO : ignore feature if same as this (and remove logic below)
58255827
features.append( cachedTarget->getFeature( i.next() ) );
58265828
}
58275829

5828-
// We use the cached layer as target layer !!
5829-
targetLayer = cachedTarget;
5830-
58315830
}
58325831
else
58335832
{
@@ -5838,6 +5837,7 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
58385837
QgsFeature feat;
58395838
while ( fit.nextFeature( feat ) )
58405839
{
5840+
// TODO : ignore feature if same as this (and remove logic below)
58415841
features.append( feat );
58425842
}
58435843
}
@@ -5851,16 +5851,6 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
58515851
subExpression.prepare( &subContext );
58525852
}
58535853

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-
{
58645854

58655855
bool found = false;
58665856
QVariantList results;
@@ -5870,127 +5860,104 @@ static QVariant indexedFilteredOverlay( QgsExpression &subExp, QgsExpressionCont
58705860
{
58715861
QgsFeature feat = i.next();
58725862

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
58735866
if ( !currentFeatId.isNull() && currentFeatId.toLongLong() == feat.id() )
58745867
{
5875-
continue; //if sourceLayer and targetLayer are the same, current feature have to be excluded from spatial check
5868+
continue;
58765869
}
58775870

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)
58795872
{
58805873
found = true;
58815874

58825875
// We just want a single boolean result if there is any intersect: finish and return true
58835876
if ( testOnly )
58845877
break;
58855878

5886-
// We want a list of attributes / geometries / other expression values, evaluate now
58875879
if ( !invert )
58885880
{
5881+
// We want a list of attributes / geometries / other expression values, evaluate now
58895882
subContext.setFeature( feat );
5890-
results.append( subExp.evaluate( &subContext ) );
5883+
results.append( subExpression.evaluate( &subContext ) );
58915884
}
58925885
else
58935886
{
5887+
// If not, results is a list of found ids, which we'll inverse and evaluate below
58945888
results.append( feat.id() );
58955889
}
58965890
}
58975891
}
5892+
58985893
if ( testOnly )
58995894
{
59005895
if ( invert )
59015896
found = !found;//for disjoint condition
59025897
return found;
59035898
}
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 ) )
59055908
{
5906-
if ( !invert )
5907-
return results;
5908-
else
5909+
if ( !results.contains( feat2.id() ) )
59095910
{
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 ) );
59235913
}
59245914
}
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;
59365916

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+
}
59455918

5946-
if ( testOnly )
5947-
{
5948-
if ( invert )
5949-
found = !found;//for disjoint condition
5950-
return found;
5951-
}
5919+
// Intersect functions:
59525920

5953-
return results;
5954-
}
5921+
typedef bool ( QgsGeometry::*t_relationFunction )( const QgsGeometry &geometry ) const;
59555922

59565923
static QVariant fcnGeomOverlayIntersects( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59575924
{
5958-
return executeGeomOverlay( values, context, parent, indexedFilteredOverlay<&QgsGeometry::intersects> );
5925+
return executeGeomOverlay( values, context, parent, &QgsGeometry::intersects );
59595926
}
59605927

59615928
static QVariant fcnGeomOverlayContains( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59625929
{
5963-
return executeGeomOverlay( values, context, parent, indexedFilteredOverlay<&QgsGeometry::contains> );
5930+
return executeGeomOverlay( values, context, parent, &QgsGeometry::contains );
59645931
}
59655932

59665933
static QVariant fcnGeomOverlayCrosses( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59675934
{
5968-
return executeGeomOverlay( values, context, parent, indexedFilteredOverlay<&QgsGeometry::crosses> );
5935+
return executeGeomOverlay( values, context, parent, &QgsGeometry::crosses );
59695936
}
59705937

59715938
static QVariant fcnGeomOverlayEquals( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59725939
{
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
59745941
}
59755942

59765943
static QVariant fcnGeomOverlayTouches( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59775944
{
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
59795946
}
59805947

59815948
static QVariant fcnGeomOverlayWithin( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59825949
{
5983-
return executeGeomOverlay( values, context, parent, indexedFilteredOverlay<&QgsGeometry::within> );
5950+
return executeGeomOverlay( values, context, parent, &QgsGeometry::within );
59845951
}
59855952

59865953
static QVariant fcnGeomOverlayDisjoint( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59875954
{
5988-
return executeGeomOverlay( values, context, parent, indexedFilteredOverlay<&QgsGeometry::intersects>, true );
5955+
return executeGeomOverlay( values, context, parent, &QgsGeometry::intersects, true );
59895956
}
59905957

59915958
static QVariant fcnGeomOverlayNearest( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
59925959
{
5993-
return executeGeomOverlay( values, context, parent, indexedFilteredNearest, false, 0, true );
5960+
return executeGeomOverlay( values, context, parent, nullptr, false, 0, true );
59945961
}
59955962

59965963
const QList<QgsExpressionFunction *> &QgsExpression::Functions()

0 commit comments

Comments
 (0)
Please sign in to comment.