Skip to content

Commit

Permalink
Implement distance within for spatialite feature iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 5, 2021
1 parent 5f94fbd commit 394a4ce
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
48 changes: 39 additions & 9 deletions src/providers/spatialite/qgsspatialitefeatureiterator.cpp
Expand Up @@ -25,6 +25,7 @@
#include "qgsjsonutils.h"
#include "qgssettings.h"
#include "qgsexception.h"
#include "qgsgeometryengine.h"

QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource *source, bool ownSource, const QgsFeatureRequest &request )
: QgsAbstractFeatureIteratorFromSource<QgsSpatiaLiteFeatureSource>( source, ownSource, request )
Expand Down Expand Up @@ -64,9 +65,27 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
return;
}

// prepare spatial filter geometries for optimal speed
switch ( mRequest.spatialFilterType() )
{
case Qgis::SpatialFilterType::NoFilter:
case Qgis::SpatialFilterType::BoundingBox:
break;

case Qgis::SpatialFilterType::DistanceWithin:
if ( !mRequest.referenceGeometry().isEmpty() )
{
mDistanceWithinGeom = mRequest.referenceGeometry();
mDistanceWithinEngine.reset( QgsGeometry::createGeometryEngine( mDistanceWithinGeom.constGet() ) );
mDistanceWithinEngine->prepareGeometry();
mFetchGeometry = true;
}
break;
}

//beware - limitAtProvider needs to be set to false if the request cannot be completely handled
//by the provider (e.g., utilising QGIS expression filters)
bool limitAtProvider = ( mRequest.limit() >= 0 );
bool limitAtProvider = ( mRequest.limit() >= 0 ) && mRequest.spatialFilterType() != Qgis::SpatialFilterType::DistanceWithin;

if ( !mFilterRect.isNull() && !mSource->mGeometryColumn.isNull() )
{
Expand Down Expand Up @@ -238,16 +257,27 @@ bool QgsSpatiaLiteFeatureIterator::fetchFeature( QgsFeature &feature )
return false;
}

if ( !getFeature( sqliteStatement, feature ) )
bool foundMatchingFeature = false;
while ( !foundMatchingFeature )
{
sqlite3_finalize( sqliteStatement );
sqliteStatement = nullptr;
close();
return false;
}
if ( !getFeature( sqliteStatement, feature ) )
{
sqlite3_finalize( sqliteStatement );
sqliteStatement = nullptr;
close();
return false;
}

foundMatchingFeature = true;
feature.setValid( true );
geometryToDestinationCrs( feature, mTransform );

feature.setValid( true );
geometryToDestinationCrs( feature, mTransform );
if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( feature.geometry().constGet() ) > mRequest.distanceWithin() )
{
foundMatchingFeature = false;
feature.setValid( false );
}
}
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions src/providers/spatialite/qgsspatialitefeatureiterator.h
Expand Up @@ -110,6 +110,8 @@ class QgsSpatiaLiteFeatureIterator final: public QgsAbstractFeatureIteratorFromS

QgsRectangle mFilterRect;
QgsCoordinateTransform mTransform;
QgsGeometry mDistanceWithinGeom;
std::unique_ptr< QgsGeometryEngine > mDistanceWithinEngine;
};

#endif // QGSSPATIALITEFEATUREITERATOR_H

0 comments on commit 394a4ce

Please sign in to comment.