Skip to content

Commit

Permalink
Port Join Attributes by Location (summary) to c++
Browse files Browse the repository at this point in the history
Refs #53806

The crash here is coming from sip internals -- somewhere it is
triggering a Python SystemError. I can't solve this one, so just
port the algorithm to c++ and deal with the much improved performance
instead.
  • Loading branch information
nyalldawson committed Sep 29, 2023
1 parent 3d2bded commit 25fc015
Show file tree
Hide file tree
Showing 9 changed files with 665 additions and 398 deletions.
7 changes: 0 additions & 7 deletions python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -104,13 +104,6 @@ qgis:idwinterpolation: >
qgis:importintospatialite: >
This algorithm imports a vector layer into a SpatiaLite database, creating a new table.

qgis:joinbylocationsummary: >
This algorithm takes an input vector layer and creates a new vector layer that is an extended version of the input one, with additional attributes in its attribute table.

The additional attributes and their values are taken from a second vector layer. A spatial criteria is applied to select the values from the second layer that are added to each feature from the first layer in the resulting one.

The algorithm calculates a statistical summary for the values from matching features in the second layer (e.g. maximum value, mean value, etc).

qgis:knearestconcavehull: >
This algorithm generates a concave hull polygon from a set of points. If the input layer is a line or polygon layer, it will use the nodes.

Expand Down
2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -71,7 +71,6 @@
from .SelectByExpression import SelectByExpression
from .SetRasterStyle import SetRasterStyle
from .SetVectorStyle import SetVectorStyle
from .SpatialJoinSummary import SpatialJoinSummary
from .StatisticsByCategories import StatisticsByCategories
from .TextToFloat import TextToFloat
from .TinInterpolation import TinInterpolation
Expand Down Expand Up @@ -136,7 +135,6 @@ def getAlgs(self):
SelectByExpression(),
SetRasterStyle(),
SetVectorStyle(),
SpatialJoinSummary(),
StatisticsByCategories(),
TextToFloat(),
TinInterpolation(),
Expand Down
373 changes: 0 additions & 373 deletions python/plugins/processing/algs/qgis/SpatialJoinSummary.py

This file was deleted.

1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -122,6 +122,7 @@ set(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmintersection.cpp
processing/qgsalgorithmjoinbyattribute.cpp
processing/qgsalgorithmjoinbylocation.cpp
processing/qgsalgorithmjoinbylocationsummary.cpp
processing/qgsalgorithmjoinbynearest.cpp
processing/qgsalgorithmjoinwithlines.cpp
processing/qgsalgorithmkeepnbiggestparts.cpp
Expand Down
29 changes: 15 additions & 14 deletions src/analysis/processing/qgsalgorithmjoinbylocation.cpp
Expand Up @@ -31,16 +31,7 @@ void QgsJoinByLocationAlgorithm::initAlgorithm( const QVariantMap & )
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
QObject::tr( "Join to features in" ), QList< int > () << QgsProcessing::QgsProcessing::TypeVectorAnyGeometry ) );

QStringList predicates;
predicates << QObject::tr( "intersect" )
<< QObject::tr( "contain" )
<< QObject::tr( "equal" )
<< QObject::tr( "touch" )
<< QObject::tr( "overlap" )
<< QObject::tr( "are within" )
<< QObject::tr( "cross" );

std::unique_ptr< QgsProcessingParameterEnum > predicateParam = std::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "PREDICATE" ), QObject::tr( "Features they (geometric predicate)" ), predicates, true, 0 );
std::unique_ptr< QgsProcessingParameterEnum > predicateParam = std::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "PREDICATE" ), QObject::tr( "Features they (geometric predicate)" ), translatedPredicates(), true, 0 );
QVariantMap predicateMetadata;
QVariantMap widgetMetadata;
widgetMetadata.insert( QStringLiteral( "useCheckBoxes" ), true );
Expand Down Expand Up @@ -115,6 +106,16 @@ QgsJoinByLocationAlgorithm *QgsJoinByLocationAlgorithm::createInstance() const
return new QgsJoinByLocationAlgorithm();
}

QStringList QgsJoinByLocationAlgorithm::translatedPredicates()
{
return { QObject::tr( "intersect" ),
QObject::tr( "contain" ),
QObject::tr( "equal" ),
QObject::tr( "touch" ),
QObject::tr( "overlap" ),
QObject::tr( "are within" ),
QObject::tr( "cross" ) };
}

QVariantMap QgsJoinByLocationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
Expand Down Expand Up @@ -226,11 +227,11 @@ QVariantMap QgsJoinByLocationAlgorithm::processAlgorithm( const QVariantMap &par
return outputs;
}

bool QgsJoinByLocationAlgorithm::featureFilter( const QgsFeature &feature, QgsGeometryEngine *engine, bool comparingToJoinedFeature ) const
bool QgsJoinByLocationAlgorithm::featureFilter( const QgsFeature &feature, QgsGeometryEngine *engine, bool comparingToJoinedFeature, const QList<int> &predicates )
{
const QgsAbstractGeometry *geom = feature.geometry().constGet();
bool ok = false;
for ( const int predicate : mPredicates )
for ( const int predicate : predicates )
{
switch ( predicate )
{
Expand Down Expand Up @@ -462,7 +463,7 @@ bool QgsJoinByLocationAlgorithm::processFeatureFromJoinSource( QgsFeature &joinF
joinAttributes.append( joinFeature.attribute( ix ) );
}
}
if ( featureFilter( baseFeature, engine.get(), false ) )
if ( featureFilter( baseFeature, engine.get(), false, mPredicates ) )
{
if ( mJoinedFeatures )
{
Expand Down Expand Up @@ -532,7 +533,7 @@ bool QgsJoinByLocationAlgorithm::processFeatureFromInputSource( QgsFeature &base
engine->prepareGeometry();
}

if ( featureFilter( joinFeature, engine.get(), true ) )
if ( featureFilter( joinFeature, engine.get(), true, mPredicates ) )
{
switch ( mJoinMethod )
{
Expand Down
17 changes: 15 additions & 2 deletions src/analysis/processing/qgsalgorithmjoinbylocation.h
Expand Up @@ -48,11 +48,25 @@ class QgsJoinByLocationAlgorithm : public QgsProcessingAlgorithm
QString shortDescription() const override;
QgsJoinByLocationAlgorithm *createInstance() const override SIP_FACTORY;

/**
* Returns a translated list of predicate names, in the order expected by the algorithm's enum parameter.
*/
static QStringList translatedPredicates();

/**
* Sorts a list of predicates so that faster ones are tested first
*/
static void sortPredicates( QList<int > &predicates );

/**
* Returns TRUE if \a feature satisfies any of the predicates.
*/
static bool featureFilter( const QgsFeature &feature, QgsGeometryEngine *engine, bool comparingToJoinedFeature, const QList<int> &predicates );

protected:
QVariantMap processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
bool processFeatureFromJoinSource( QgsFeature &joinFeature, QgsProcessingFeedback *feedback );
bool processFeatureFromInputSource( QgsFeature &inputFeature, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
bool featureFilter( const QgsFeature &feature, QgsGeometryEngine *engine, bool comparingToJoinedFeature ) const;

private:

Expand All @@ -76,7 +90,6 @@ class QgsJoinByLocationAlgorithm : public QgsProcessingAlgorithm
JoinMethod mJoinMethod = OneToMany;
QList<int> mPredicates;

static void sortPredicates( QList<int > &predicates );
};

///@endcond PRIVATE
Expand Down

0 comments on commit 25fc015

Please sign in to comment.