Skip to content

Commit

Permalink
Grow search rect based on layer precision
Browse files Browse the repository at this point in the history
  • Loading branch information
Joonalai committed Jan 15, 2025
1 parent da156b7 commit 1848553
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ Merge features into a single one.
.. versionadded:: 3.30
%End


};

/************************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ Merge features into a single one.
.. versionadded:: 3.30
%End


};

/************************************************************************
Expand Down
20 changes: 18 additions & 2 deletions src/app/qgsmaptooladdfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "qgisapp.h"
#include "qgsexpressioncontextutils.h"
#include "qgsrubberband.h"
#include "qgsvectorlayereditutils.h"

#include <QSettings>

Expand Down Expand Up @@ -143,9 +144,11 @@ void QgsMapToolAddFeature::featureDigitized( const QgsFeature &feature )
}
if ( topologicalEditing )
{
QgsFeatureRequest request = QgsFeatureRequest().setFilterRect( feature.geometry().boundingBox() ).setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
request.setDestinationCrs( vlayer->crs(), vlayer->transformContext() );
QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
QgsRectangle bbox = feature.geometry().boundingBox();
QgsRectangle searchRect;
QgsFeature f;
QgsCoordinateTransform transform;

const QList<QgsMapLayer *> layers = canvas()->layers( true );

Expand All @@ -159,6 +162,19 @@ void QgsMapToolAddFeature::featureDigitized( const QgsFeature &feature )
if ( !( vectorLayer->geometryType() == Qgis::GeometryType::Polygon || vectorLayer->geometryType() == Qgis::GeometryType::Line ) )
continue;

if ( vectorLayer->crs() == vlayer->crs() )
{
searchRect = QgsRectangle( bbox );
}
else
{
transform = QgsCoordinateTransform( vlayer->crs(), vectorLayer->crs(), vectorLayer->transformContext() );
searchRect = transform.transformBoundingBox( bbox );
}

searchRect.grow( QgsVectorLayerEditUtils::getTopologicalSearchRadius( vectorLayer ) );
request.setFilterRect( searchRect );

if ( !vectorLayer->getFeatures( request ).nextFeature( f ) )
continue;

Expand Down
9 changes: 8 additions & 1 deletion src/app/vertextool/qgsvertextool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "qgsexpressioncontextutils.h"
#include "qgsmessagebar.h"
#include "qgssettingsentryimpl.h"
#include "qgsvectorlayereditutils.h"


#include <QMenu>
Expand Down Expand Up @@ -2204,7 +2205,9 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
{
// topo editing: add vertex to existing segments when moving/adding a vertex to such segment.

QgsFeatureRequest request = QgsFeatureRequest().setFilterRect( layerPoint.boundingBox() ).setDestinationCrs( dragLayer->crs(), mCanvas->mapSettings().transformContext() ).setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
QgsRectangle bbox = layerPoint.boundingBox();
QgsRectangle searchRect;
QgsFeature f;

const QList<QgsMapLayer *> targetLayers = canvas()->layers( true );
Expand All @@ -2225,6 +2228,10 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
if ( vectorLayer->crs() != itLayerEdits.key()->crs() )
continue;

searchRect = QgsRectangle( bbox );
searchRect.grow( QgsVectorLayerEditUtils::getTopologicalSearchRadius( vectorLayer ) );
request.setFilterRect( searchRect );

if ( !vectorLayer->getFeatures( request ).nextFeature( f ) )
continue;

Expand Down
39 changes: 24 additions & 15 deletions src/core/vector/qgsvectorlayereditutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,29 @@ Qgis::GeometryOperationResult staticAddRing( QgsVectorLayer *layer, std::unique_
return success ? Qgis::GeometryOperationResult::Success : addRingReturnCode;
}

// this method might be inlined later on
///@cond PRIVATE
double QgsVectorLayerEditUtils::getTopologicalSearchRadius( const QgsVectorLayer *layer )
{
double threshold = layer->geometryOptions()->geometryPrecision();

if ( qgsDoubleNear( threshold, 0.0 ) )
{
threshold = 1e-8;

if ( layer->crs().mapUnits() == Qgis::DistanceUnit::Meters )
{
threshold = 0.001;
}
else if ( layer->crs().mapUnits() == Qgis::DistanceUnit::Feet )
{
threshold = 0.0001;
}
}
return threshold;
}
///@endcond

Qgis::GeometryOperationResult QgsVectorLayerEditUtils::addRing( const QVector<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
{
QgsPointSequence l;
Expand Down Expand Up @@ -801,21 +824,7 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPoint &p )
double segmentSearchEpsilon = mLayer->crs().isGeographic() ? 1e-12 : 1e-8;

//work with a tolerance because coordinate projection may introduce some rounding
double threshold = mLayer->geometryOptions()->geometryPrecision();

if ( qgsDoubleNear( threshold, 0.0 ) )
{
threshold = 1e-8;

if ( mLayer->crs().mapUnits() == Qgis::DistanceUnit::Meters )
{
threshold = 0.001;
}
else if ( mLayer->crs().mapUnits() == Qgis::DistanceUnit::Feet )
{
threshold = 0.0001;
}
}
double threshold = getTopologicalSearchRadius( mLayer );

QgsRectangle searchRect( p, p, false );
searchRect.grow( threshold );
Expand Down
4 changes: 4 additions & 0 deletions src/core/vector/qgsvectorlayereditutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ class CORE_EXPORT QgsVectorLayerEditUtils
*/
bool mergeFeatures( const QgsFeatureId &targetFeatureId, const QgsFeatureIds &mergeFeatureIds, const QgsAttributes &mergeAttributes, const QgsGeometry &unionGeometry, QString &errorMessage SIP_OUT );

///@cond PRIVATE
static double getTopologicalSearchRadius( const QgsVectorLayer *layer ) SIP_SKIP;
///@endcond

private:

/**
Expand Down

0 comments on commit 1848553

Please sign in to comment.