Refactor topological point addition into a static method

This commit is contained in:
uclaros 2025-06-18 14:38:15 +03:00
parent d0d74da7a1
commit a8a98e9ee8
6 changed files with 74 additions and 122 deletions

View File

@ -343,6 +343,7 @@ Merge features into a single one.
%End
};
/************************************************************************

View File

@ -343,6 +343,7 @@ Merge features into a single one.
%End
};
/************************************************************************

View File

@ -144,68 +144,8 @@ 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;
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;
if ( vectorLayer->crs() != vlayer->crs() )
{
QgsGeometry transformedGeom = feature.geometry();
try
{
// transform digitized geometry from vlayer crs to vectorLayer crs and add topological points
transformedGeom.transform( transform );
res = vectorLayer->addTopologicalPoints( transformedGeom );
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse )
QgsDebugError( QStringLiteral( "transformation to vectorLayer coordinate failed" ) );
}
}
else
{
res = vectorLayer->addTopologicalPoints( feature.geometry() );
}
if ( res == 0 ) // i.e. if any points were added
vectorLayer->endEditCommand();
else
vectorLayer->destroyEditCommand();
}
QgsVectorLayerEditUtils::addTopologicalPointsToLayers( feature.geometry(), vlayer, layers, mToolName );
}
}
}

View File

@ -218,68 +218,8 @@ void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer )
{
//check if we need to add topological points to other layers
const QList<QgsMapLayer *> layers = canvas()->layers( true );
QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
QgsGeometry pointsAsGeom( new QgsMultiPoint( pts ) );
QgsRectangle bbox = pointsAsGeom.boundingBox();
for ( QgsMapLayer *layer : layers )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vectorLayer && vectorLayer->isEditable() && vectorLayer->isSpatial() && ( vectorLayer->geometryType() == Qgis::GeometryType::Line || vectorLayer->geometryType() == Qgis::GeometryType::Polygon ) )
{
QgsCoordinateTransform ct;
if ( vectorLayer->crs() != vlayer->crs() )
{
ct = QgsCoordinateTransform( vlayer->crs(), vectorLayer->crs(), vectorLayer->transformContext() );
try
{
bbox = ct.transformBoundingBox( bbox );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Bounding box transformation failed, skipping topological points for layer %1" ).arg( vlayer->id() ) );
continue;
}
}
bbox.grow( QgsVectorLayerEditUtils::getTopologicalSearchRadius( vectorLayer ) );
request.setFilterRect( bbox );
// 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 Reshape" ) );
int returnValue = 2;
if ( vectorLayer->crs() != vlayer->crs() )
{
try
{
// transform digitized geometry from vlayer crs to vectorLayer crs and add topological points
pointsAsGeom.transform( ct );
returnValue = vectorLayer->addTopologicalPoints( pointsAsGeom );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "transformation to vectorLayer coordinate failed" ) );
}
}
else
{
returnValue = vectorLayer->addTopologicalPoints( pts );
}
if ( returnValue == 0 )
{
vectorLayer->endEditCommand();
}
else
{
// the layer was not modified, leave the undo buffer intact
vectorLayer->destroyEditCommand();
}
}
}
QgsVectorLayerEditUtils::addTopologicalPointsToLayers( pointsAsGeom, vlayer, layers, mToolName );
}
vlayer->endEditCommand();

View File

@ -231,6 +231,74 @@ double QgsVectorLayerEditUtils::getTopologicalSearchRadius( const QgsVectorLayer
}
return threshold;
}
void QgsVectorLayerEditUtils::addTopologicalPointsToLayers( const QgsGeometry &geom, QgsVectorLayer *vlayer, const QList<QgsMapLayer *> &layers, const QString &toolName )
{
QgsFeatureRequest request = QgsFeatureRequest().setNoAttributes().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 1 );
QgsFeature f;
for ( QgsMapLayer *layer : layers )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vectorLayer && vectorLayer->isEditable() && vectorLayer->isSpatial() && ( vectorLayer->geometryType() == Qgis::GeometryType::Line || vectorLayer->geometryType() == Qgis::GeometryType::Polygon ) )
{
// boundingBox() is cached, it doesn't matter calling it in the loop
QgsRectangle bbox = geom.boundingBox();
QgsCoordinateTransform ct;
if ( vectorLayer->crs() != vlayer->crs() )
{
ct = QgsCoordinateTransform( vlayer->crs(), vectorLayer->crs(), vectorLayer->transformContext() );
try
{
bbox = ct.transformBoundingBox( bbox );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Bounding box transformation failed, skipping topological points for layer %1" ).arg( vlayer->id() ) );
continue;
}
}
bbox.grow( getTopologicalSearchRadius( vectorLayer ) );
request.setFilterRect( bbox );
// 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( QObject::tr( "Topological points added by '%1'" ).arg( toolName ) );
int returnValue = 2;
if ( vectorLayer->crs() != vlayer->crs() )
{
try
{
// transform digitized geometry from vlayer crs to vectorLayer crs and add topological points
QgsGeometry transformedGeom( geom );
transformedGeom.transform( ct );
returnValue = vectorLayer->addTopologicalPoints( transformedGeom );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "transformation to vectorLayer coordinate failed" ) );
}
}
else
{
returnValue = vectorLayer->addTopologicalPoints( geom );
}
if ( returnValue == 0 )
{
vectorLayer->endEditCommand();
}
else
{
// the layer was not modified, leave the undo buffer intact
vectorLayer->destroyEditCommand();
}
}
}
}
///@endcond
Qgis::GeometryOperationResult QgsVectorLayerEditUtils::addRing( const QVector<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )

View File

@ -284,6 +284,8 @@ class CORE_EXPORT QgsVectorLayerEditUtils
///@cond PRIVATE
static double getTopologicalSearchRadius( const QgsVectorLayer *layer ) SIP_SKIP;
static void addTopologicalPointsToLayers( const QgsGeometry &geom, QgsVectorLayer *vlayer, const QList<QgsMapLayer *> &layers, const QString &toolName ) SIP_SKIP;
///@endcond
private: