mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-04 00:06:46 -05:00
Merge pull request #60130 from Joonalai/fix-topological-slowness
Fix topological slowness with spatial filtering
This commit is contained in:
commit
d2aaa9c6e0
@ -332,6 +332,7 @@ Merge features into a single one.
|
||||
.. versionadded:: 3.30
|
||||
%End
|
||||
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
||||
@ -332,6 +332,7 @@ Merge features into a single one.
|
||||
.. versionadded:: 3.30
|
||||
%End
|
||||
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "qgisapp.h"
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayereditutils.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
@ -143,11 +144,16 @@ void QgsMapToolAddFeature::featureDigitized( const QgsFeature &feature )
|
||||
}
|
||||
if ( topologicalEditing )
|
||||
{
|
||||
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;
|
||||
@ -155,6 +161,23 @@ 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 );
|
||||
|
||||
// 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;
|
||||
|
||||
vectorLayer->beginEditCommand( tr( "Topological points added by 'Add Feature'" ) );
|
||||
|
||||
int res = 2;
|
||||
@ -164,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 )
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
#include "qgsmessagebar.h"
|
||||
#include "qgssettingsentryimpl.h"
|
||||
#include "qgsvectorlayereditutils.h"
|
||||
|
||||
|
||||
#include <QMenu>
|
||||
@ -2204,6 +2205,10 @@ 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().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
|
||||
const QgsRectangle bbox = layerPoint.boundingBox();
|
||||
|
||||
|
||||
const QList<QgsMapLayer *> targetLayers = canvas()->layers( true );
|
||||
|
||||
for ( auto itLayerEdits = edits.begin(); itLayerEdits != edits.end(); ++itLayerEdits )
|
||||
@ -2211,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;
|
||||
@ -2222,6 +2229,14 @@ 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;
|
||||
|
||||
vectorLayer->beginEditCommand( tr( "Topological points added by 'Vertex Tool'" ) );
|
||||
|
||||
bool topoPointsAdded = false;
|
||||
|
||||
@ -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;
|
||||
@ -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 );
|
||||
|
||||
@ -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:
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user