Skip to content

Commit

Permalink
Add QgsAbstractFeatureIterator::updateRequestToSourceCrs method
Browse files Browse the repository at this point in the history
The method superceeds filterRectToSourceCrs, deprecating it for
shortage of functionality now that we support multiple spatial
filters.

This commit makes use of the new method from
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator
so to not drop the WithinDistance spatial filter from the
user Request.

References #45352

(cherry picked from commit 3004fde)
  • Loading branch information
strk authored and nyalldawson committed Jan 31, 2022
1 parent 6c08116 commit b46420b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 14 deletions.
11 changes: 11 additions & 0 deletions python/core/auto_generated/qgsfeatureiterator.sip.in
Expand Up @@ -138,6 +138,17 @@ Will throw a :py:class:`QgsCsException` if the rect cannot be transformed from t
.. versionadded:: 3.0
%End

void updateRequestToSourceCrs( QgsFeatureRequest &request, const QgsCoordinateTransform &transform ) const throw( QgsCsException );
%Docstring
Update a :py:class:`QgsFeatureRequest` so that spatial filters are
transformed to the source's coordinate reference system.
Iterators should call this method against the request used for filtering
features to ensure that any :py:func:`QgsFeatureRequest.destinationCrs()` set on the request is respected.
Will throw a :py:class:`QgsCsException` if the rect cannot be transformed from the destination CRS.

.. versionadded:: 3.22
%End




Expand Down
32 changes: 32 additions & 0 deletions src/core/qgsfeatureiterator.cpp
Expand Up @@ -17,6 +17,7 @@

#include "qgssimplifymethod.h"
#include "qgsexception.h"
#include "qgslinestring.h"
#include "qgsexpressionsorter.h"
#include "qgsfeedback.h"
#include "qgscoordinatetransform.h"
Expand Down Expand Up @@ -120,6 +121,37 @@ void QgsAbstractFeatureIterator::geometryToDestinationCrs( QgsFeature &feature,
}
}

void QgsAbstractFeatureIterator::updateRequestToSourceCrs( QgsFeatureRequest &request, const QgsCoordinateTransform &transform ) const
{
switch ( request.spatialFilterType() )
{
case Qgis::SpatialFilterType::NoFilter:
break;
case Qgis::SpatialFilterType::BoundingBox:
{
QgsRectangle newRect = transform.transformBoundingBox( request.filterRect(), Qgis::TransformDirection::Reverse );
request.setFilterRect( newRect );
break;
}
case Qgis::SpatialFilterType::DistanceWithin:
{
QgsGeometry geom = request.referenceGeometry();
QgsRectangle bbox = geom.boundingBox();
double x0 = bbox.xMaximum();
double y0 = bbox.yMaximum();
double dist = request.distanceWithin();
QgsPoint p0( x0, y0 );
QgsPoint p1( x0 + dist, y0 );
QgsLineString newDistLine( p0, p1 );
newDistLine.transform( transform, Qgis::TransformDirection::Reverse );
dist = newDistLine.length();
geom.transform( transform, Qgis::TransformDirection::Reverse );
request.setDistanceWithin( geom, dist );
break;
}
}
}

QgsRectangle QgsAbstractFeatureIterator::filterRectToSourceCrs( const QgsCoordinateTransform &transform ) const
{
if ( mRequest.filterRect().isNull() )
Expand Down
10 changes: 10 additions & 0 deletions src/core/qgsfeatureiterator.h
Expand Up @@ -149,6 +149,16 @@ class CORE_EXPORT QgsAbstractFeatureIterator
*/
QgsRectangle filterRectToSourceCrs( const QgsCoordinateTransform &transform ) const SIP_THROW( QgsCsException );

/**
* Update a QgsFeatureRequest so that spatial filters are
* transformed to the source's coordinate reference system.
* Iterators should call this method against the request used for filtering
* features to ensure that any QgsFeatureRequest::destinationCrs() set on the request is respected.
* Will throw a QgsCsException if the rect cannot be transformed from the destination CRS.
* \since QGIS 3.22
*/
void updateRequestToSourceCrs( QgsFeatureRequest &request, const QgsCoordinateTransform &transform ) const SIP_THROW( QgsCsException );

//! A copy of the feature request.
QgsFeatureRequest mRequest;

Expand Down
24 changes: 10 additions & 14 deletions src/core/vector/qgsvectorlayerfeatureiterator.cpp
Expand Up @@ -128,17 +128,6 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
{
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{
mFilterRect = filterRectToSourceCrs( mTransform );
}
catch ( QgsCsException & )
{
// can't reproject mFilterRect
close();
return;
}


// prepare spatial filter geometries for optimal speed
switch ( mRequest.spatialFilterType() )
Expand All @@ -158,12 +147,19 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
break;
}

if ( !mFilterRect.isNull() )
try
{
updateRequestToSourceCrs( mRequest, mTransform );
mFilterRect = mRequest.filterRect();
}
catch ( QgsCsException & )
{
// update request to be the unprojected filter rect
mRequest.setFilterRect( mFilterRect );
// can't reproject request filters
close();
return;
}


// check whether the order by clause(s) can be delegated to the provider
mDelegatedOrderByToProvider = !mSource->mHasEditBuffer;
if ( !mRequest.orderBy().isEmpty() )
Expand Down

0 comments on commit b46420b

Please sign in to comment.