Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vertex tool: add topological points to all editable layers (fixes #58855) #58913

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions src/app/vertextool/qgsvertextool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2258,29 +2258,46 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
{
// topo editing: add vertex to existing segments when moving/adding a vertex to such segment.

// compute layers we have to add topological point on (modified ones + snapped one)
QSet<QgsVectorLayer *> targetLayers( edits.keyBegin(), edits.keyEnd() );
if ( mapPointMatch->layer() )
targetLayers << mapPointMatch->layer();
const QList<QgsMapLayer *> targetLayers = canvas()->layers( true );

for ( auto itLayerEdits = edits.begin(); itLayerEdits != edits.end(); ++itLayerEdits )
{
for ( QgsVectorLayer *targetLayer : targetLayers )
for ( QgsMapLayer *targetLayer : targetLayers )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( targetLayer );

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

if ( !( vectorLayer->geometryType() == Qgis::GeometryType::Polygon || vectorLayer->geometryType() == Qgis::GeometryType::Line ) )
continue;

// layer's CRS need to be the the same (otherwise we would need to reproject the point and it will not be coincident)
if ( targetLayer->crs() != itLayerEdits.key()->crs() )
if ( vectorLayer->crs() != itLayerEdits.key()->crs() )
continue;

vectorLayer->beginEditCommand( tr( "Topological points added by 'Vertex Tool'" ) );

bool topoPointsAdded = false;

for ( auto itFeatEdit = itLayerEdits->begin(); itFeatEdit != itLayerEdits->end(); ++itFeatEdit )
{
for ( QgsPoint point : itFeatEdit->newPoints )
{
if ( !point.is3D() )
point.addZValue( defaultZValue() );

targetLayer->addTopologicalPoints( point );
int res = vectorLayer->addTopologicalPoints( point );

if ( res == 0 )
topoPointsAdded = true;
}
}

if ( topoPointsAdded )
vectorLayer->endEditCommand();
else
vectorLayer->destroyEditCommand();
}
}
}
Expand Down
58 changes: 58 additions & 0 deletions tests/src/app/testqgsvertextool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class TestQgsVertexTool : public QObject
void testAddVertexTopo();
void testMoveEdgeTopo();
void testAddVertexTopoFirstSegment();
void testAddVertexTopoMultipleLayers();
void testAvoidIntersectionsWithMultiPolygons();
void testActiveLayerPriority();
void testSelectedFeaturesPriority();
Expand Down Expand Up @@ -1182,6 +1183,63 @@ void TestQgsVertexTool::testAddVertexTopoFirstSegment()
QgsProject::instance()->setTopologicalEditing( false );
}

void TestQgsVertexTool::testAddVertexTopoMultipleLayers()
{
// check that when adding a vertex to a segment which is shared by more than one layer
// a topological point is added to all editable layers

QgsFeature fTmp;
fTmp.setGeometry( QgsGeometry::fromWkt( "POLYGON((1 8, 0 8, 0 5, 1 5, 1 8))" ) );
const bool resAdd = mLayerPolygon->addFeature( fTmp );
QVERIFY( resAdd );
const QgsFeatureId fTmpId = fTmp.id();

const bool topologicalEditing = QgsProject::instance()->topologicalEditing();
QgsProject::instance()->setTopologicalEditing( true );
QgsSnappingConfig cfg = mCanvas->snappingUtils()->config();
cfg.setMode( Qgis::SnappingMode::AllLayers );
cfg.setTolerance( 10 );
cfg.setTypeFlag( static_cast<Qgis::SnappingTypes>( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ) );
cfg.setEnabled( true );
mCanvas->snappingUtils()->setConfig( cfg );

QCOMPARE( mLayerPolygon->undoStack()->index(), 2 );
QCOMPARE( mLayerLine->undoStack()->index(), 1 );
QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 1 );

mouseClick( 1, 3, Qt::LeftButton, Qt::KeyboardModifiers(), true );
mouseClick( 1, 6, Qt::LeftButton, Qt::KeyboardModifiers(), true );

QCOMPARE( mLayerPolygon->undoStack()->index(), 3 );
QCOMPARE( mLayerLine->undoStack()->index(), 2 );
QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 2 );

QCOMPARE( mLayerPolygon->getFeature( fTmpId ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1 8, 0 8, 0 5, 1 5, 1 6, 1 8))" ) );
QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry().asWkt( 2 ), QStringLiteral( "LineString (2 1, 1 1, 1 6)" ) );
QCOMPARE( mLayerMultiPolygon->getFeature( mFidMultiPolygonF1 ).geometry().asWkt( 2 ), QStringLiteral( "MultiPolygon (((1 5, 2 5, 2 6.5, 2 8, 1 8, 1 6.5, 1 6, 1 5),(1.25 5.5, 1.25 6, 1.75 6, 1.75 5.5, 1.25 5.5),(1.25 7, 1.75 7, 1.75 7.5, 1.25 7.5, 1.25 7)),((3 5, 3 6.5, 3 8, 4 8, 4 6.5, 4 5, 3 5),(3.25 5.5, 3.75 5.5, 3.75 6, 3.25 6, 3.25 5.5),(3.25 7, 3.75 7, 3.75 7.5, 3.25 7.5, 3.25 7)))" ) );

mLayerPolygon->undoStack()->undo();
mLayerLine->undoStack()->undo();
mLayerMultiPolygon->undoStack()->undo();

QCOMPARE( mLayerPolygon->undoStack()->index(), 2 );
QCOMPARE( mLayerLine->undoStack()->index(), 1 );
QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 1 );

QCOMPARE( mLayerPolygon->getFeature( fTmpId ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1 8, 0 8, 0 5, 1 5, 1 8))" ) );
QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry().asWkt( 2 ), QStringLiteral( "LineString (2 1, 1 1, 1 3)" ) );
QCOMPARE( mLayerMultiPolygon->getFeature( mFidMultiPolygonF1 ).geometry().asWkt( 2 ), QStringLiteral( "MultiPolygon (((1 5, 2 5, 2 6.5, 2 8, 1 8, 1 6.5, 1 5),(1.25 5.5, 1.25 6, 1.75 6, 1.75 5.5, 1.25 5.5),(1.25 7, 1.75 7, 1.75 7.5, 1.25 7.5, 1.25 7)),((3 5, 3 6.5, 3 8, 4 8, 4 6.5, 4 5, 3 5),(3.25 5.5, 3.75 5.5, 3.75 6, 3.25 6, 3.25 5.5),(3.25 7, 3.75 7, 3.75 7.5, 3.25 7.5, 3.25 7)))" ) );

// undo to remove temp feature
mLayerPolygon->undoStack()->undo();

QCOMPARE( mLayerPolygon->undoStack()->index(), 1 );

QgsProject::instance()->setTopologicalEditing( topologicalEditing );
cfg.setEnabled( false );
mCanvas->snappingUtils()->setConfig( cfg );
}

void TestQgsVertexTool::testAvoidIntersections()
{
// There is one feature in the layer
Expand Down
Loading