Skip to content

Commit 3769faa

Browse files
committedJan 30, 2019
[vertex tool] Fix vertex addition to polygon's first segment (fixes #20774)
With topo editing mode enabled, addition of extra points to keep the topology correct wasn't working correctly because for the first segment we were getting two matches due to duplicated first and last vertex in the ring. The fix ensures that only one match will be returned for the first duplicated vertex.
1 parent 6063591 commit 3769faa

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed
 

‎src/app/vertextool/qgsvertextool.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,18 +172,35 @@ class MatchCollectingFilter : public QgsPointLocator::MatchFilter
172172
{
173173
if ( match.distance() > 0 )
174174
return false;
175-
matches.append( match );
176175

177176
// there may be multiple points at the same location, but we get only one
178177
// result... the locator API needs a new method verticesInRect()
179178
QgsGeometry matchGeom = vertextool->cachedGeometry( match.layer(), match.featureId() );
179+
bool isPolygon = matchGeom.type() == QgsWkbTypes::PolygonGeometry;
180+
QgsVertexId polygonRingVid;
180181
QgsVertexId vid;
181182
QgsPoint pt;
182183
while ( matchGeom.constGet()->nextVertex( vid, pt ) )
183184
{
184185
int vindex = matchGeom.vertexNrFromVertexId( vid );
185-
if ( pt.x() == match.point().x() && pt.y() == match.point().y() && vindex != match.vertexIndex() )
186+
if ( pt.x() == match.point().x() && pt.y() == match.point().y() )
186187
{
188+
if ( isPolygon )
189+
{
190+
// for polygons we need to handle the case where the first vertex is matching because the
191+
// last point will have the same coordinates and we would have a duplicate match which
192+
// would make subsequent code behave incorrectly (topology editing mode would add a single
193+
// vertex twice)
194+
if ( vid.vertex == 0 )
195+
{
196+
polygonRingVid = vid;
197+
}
198+
else if ( vid.ringEqual( polygonRingVid ) && vid.vertex == matchGeom.constGet()->vertexCount( vid.part, vid.ring ) - 1 )
199+
{
200+
continue;
201+
}
202+
}
203+
187204
QgsPointLocator::Match extra_match( match.type(), match.layer(), match.featureId(),
188205
0, match.point(), vindex );
189206
matches.append( extra_match );

‎tests/src/app/testqgsvertextool.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class TestQgsVertexTool : public QObject
6767
void testDeleteVertexTopo();
6868
void testAddVertexTopo();
6969
void testMoveEdgeTopo();
70+
void testAddVertexTopoFirstSegment();
7071
void testActiveLayerPriority();
7172
void testSelectedFeaturesPriority();
7273

@@ -642,6 +643,27 @@ void TestQgsVertexTool::testMoveEdgeTopo()
642643
QgsProject::instance()->setTopologicalEditing( false );
643644
}
644645

646+
void TestQgsVertexTool::testAddVertexTopoFirstSegment()
647+
{
648+
// check that when adding a vertex to the first segment of a polygon's ring with topo editing
649+
// enabled, the geometry does not get corrupted (#20774)
650+
651+
QgsProject::instance()->setTopologicalEditing( true );
652+
653+
mouseClick( 5.5, 1, Qt::LeftButton );
654+
mouseClick( 5, 2, Qt::LeftButton );
655+
656+
QCOMPARE( mLayerPolygon->undoStack()->index(), 2 );
657+
658+
QCOMPARE( mLayerPolygon->getFeature( mFidPolygonF1 ).geometry(), QgsGeometry::fromWkt( "POLYGON((4 1, 5 2, 7 1, 7 4, 4 4, 4 1))" ) );
659+
660+
mLayerPolygon->undoStack()->undo();
661+
662+
QCOMPARE( mLayerPolygon->getFeature( mFidPolygonF1 ).geometry(), QgsGeometry::fromWkt( "POLYGON((4 1, 7 1, 7 4, 4 4, 4 1))" ) );
663+
664+
QgsProject::instance()->setTopologicalEditing( false );
665+
}
666+
645667
void TestQgsVertexTool::testActiveLayerPriority()
646668
{
647669
// check that features from current layer get priority when picking points

0 commit comments

Comments
 (0)