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 16, 2025
1 parent da156b7 commit 5cc1d16
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 22 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
26 changes: 21 additions & 5 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,22 +144,37 @@ 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() );
QgsFeature f;

QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
const QgsRectangle bbox = feature.geometry().boundingBox();
const QList<QgsMapLayer *> layers = canvas()->layers( true );

for ( QgsMapLayer *layer : layers )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
QgsRectangle searchRect;
QgsFeature f;
QgsCoordinateTransform transform;

if ( !vectorLayer || !vectorLayer->isEditable() )
continue;

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

// We check that there is actually at least one feature intersecting our geometry in the layer to avoid creating an empty edit command and calling costly addTopologicalPoint
if ( !vectorLayer->getFeatures( request ).nextFeature( f ) )
continue;

Expand All @@ -171,7 +187,7 @@ void QgsMapToolAddFeature::featureDigitized( const QgsFeature &feature )
try
{
// transform digitized geometry from vlayer crs to vectorLayer crs and add topological points
transformedGeom.transform( QgsCoordinateTransform( vlayer->crs(), vectorLayer->crs(), vectorLayer->transformContext() ) );
transformedGeom.transform( transform );
res = vectorLayer->addTopologicalPoints( transformedGeom );
}
catch ( QgsCsException &cse )
Expand Down
13 changes: 11 additions & 2 deletions 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,8 +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 );
QgsFeature f;
QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
const QgsRectangle bbox = layerPoint.boundingBox();


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

Expand All @@ -2214,6 +2216,8 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
for ( QgsMapLayer *targetLayer : targetLayers )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( targetLayer );
QgsRectangle searchRect;
QgsFeature f;

if ( !vectorLayer || !vectorLayer->isEditable() )
continue;
Expand All @@ -2225,6 +2229,11 @@ 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 );

// We check that there is actually at least one feature intersecting our geometry in the layer to avoid creating an empty edit command and calling costly addTopologicalPoint
if ( !vectorLayer->getFeatures( request ).nextFeature( f ) )
continue;

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

///@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 +823,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 5cc1d16

Please sign in to comment.