@@ -474,12 +474,9 @@ void QgsVertexTool::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
474
474
475
475
// for each editable layer, select vertices
476
476
const auto layers = canvas ()->layers ();
477
- for ( QgsMapLayer *layer : layers )
477
+ const auto editableLayers = editableVectorLayers ();
478
+ for ( QgsVectorLayer *vlayer : editableLayers )
478
479
{
479
- QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
480
- if ( !vlayer || !vlayer->isEditable () || !vlayer->isSpatial () )
481
- continue ;
482
-
483
480
if ( mMode == ActiveLayer && vlayer != currentVectorLayer () )
484
481
continue ;
485
482
@@ -1165,6 +1162,65 @@ void QgsVertexTool::startDragging( QgsMapMouseEvent *e )
1165
1162
}
1166
1163
}
1167
1164
1165
+ QList<QgsVectorLayer *> QgsVertexTool::editableVectorLayers ()
1166
+ {
1167
+ QList<QgsVectorLayer *> editableLayers;
1168
+ const auto layers = canvas ()->layers ();
1169
+ for ( QgsMapLayer *layer : layers )
1170
+ {
1171
+ QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
1172
+ if ( vlayer && vlayer->isEditable () && vlayer->isSpatial () )
1173
+ editableLayers << vlayer;
1174
+ }
1175
+ return editableLayers;
1176
+ }
1177
+
1178
+ QSet<Vertex> QgsVertexTool::findCoincidentVertices ( const QSet<Vertex> &vertices )
1179
+ {
1180
+ QSet<Vertex> topoVertices;
1181
+ const auto editableLayers = editableVectorLayers ();
1182
+
1183
+ for ( const Vertex &v : qgis::as_const ( vertices ) )
1184
+ {
1185
+ QgsPointXY origPointV = cachedGeometryForVertex ( v ).vertexAt ( v.vertexId );
1186
+ QgsPointXY mapPointV = toMapCoordinates ( v.layer , origPointV );
1187
+ for ( QgsVectorLayer *vlayer : editableLayers )
1188
+ {
1189
+ const auto snappedVertices = layerVerticesSnappedToPoint ( vlayer, mapPointV );
1190
+ for ( const QgsPointLocator::Match &otherMatch : snappedVertices )
1191
+ {
1192
+ Vertex otherVertex ( otherMatch.layer (), otherMatch.featureId (), otherMatch.vertexIndex () );
1193
+ if ( !vertices.contains ( otherVertex ) )
1194
+ topoVertices << otherVertex;
1195
+ }
1196
+ }
1197
+ }
1198
+ return topoVertices;
1199
+ }
1200
+
1201
+ void QgsVertexTool::buildExtraVertices ( const QSet<Vertex> &vertices, const QgsPointXY &anchorPoint, QgsVectorLayer *anchorLayer )
1202
+ {
1203
+ for ( const Vertex &v : qgis::as_const ( vertices ) )
1204
+ {
1205
+ if ( mDraggingVertex && v == *mDraggingVertex )
1206
+ continue ;
1207
+
1208
+ QgsPointXY pointV = cachedGeometryForVertex ( v ).vertexAt ( v.vertexId );
1209
+
1210
+ // Calculate position of the anchor point in the coordinates of our vertex v
1211
+ // Try to avoid reprojection so we do not loose precision when map CRS does not match layer CRS
1212
+ QgsPointXY anchorPointLayer;
1213
+ if ( v.layer ->crs () == anchorLayer->crs () )
1214
+ anchorPointLayer = anchorPoint;
1215
+ else // reprojection is necessary: ANCHOR -> MAP -> V
1216
+ anchorPointLayer = toLayerCoordinates ( v.layer , toMapCoordinates ( anchorLayer, anchorPoint ) );
1217
+ QgsVector offset = pointV - anchorPointLayer;
1218
+
1219
+ mDraggingExtraVertices << v;
1220
+ mDraggingExtraVerticesOffset << offset;
1221
+ }
1222
+ }
1223
+
1168
1224
void QgsVertexTool::startDraggingMoveVertex ( const QgsPointLocator::Match &m )
1169
1225
{
1170
1226
Q_ASSERT ( m.hasVertex () );
@@ -1179,59 +1235,22 @@ void QgsVertexTool::startDraggingMoveVertex( const QgsPointLocator::Match &m )
1179
1235
1180
1236
setHighlightedVerticesVisible ( false ); // hide any extra highlight of vertices until we are done with moving
1181
1237
1182
- QgsPointXY origDraggingVertexPoint = geom.vertexAt ( mDraggingVertex ->vertexId );
1183
-
1184
- // if there are other highlighted vertices, they should be dragged as well with their offset
1238
+ QSet<Vertex> movingVertices;
1239
+ movingVertices << *mDraggingVertex ;
1185
1240
for ( const Vertex &v : qgis::as_const ( mSelectedVertices ) )
1186
- {
1187
- if ( v != *mDraggingVertex )
1188
- {
1189
- QgsPointXY origPointV = cachedGeometryForVertex ( v ).vertexAt ( v.vertexId );
1190
- QgsPointXY origPointLayer = origDraggingVertexPoint;
1191
- if ( v.layer ->crs () != mDraggingVertex ->layer ->crs () ) // reproject if necessary
1192
- origPointLayer = toLayerCoordinates ( v.layer , toMapCoordinates ( m.layer (), origDraggingVertexPoint ) );
1193
- QgsVector offset = origPointV - origPointLayer;
1194
-
1195
- mDraggingExtraVertices << v;
1196
- mDraggingExtraVerticesOffset << offset;
1197
- }
1198
- }
1199
-
1200
- cadDockWidget ()->setPoints ( QList<QgsPointXY>() << m.point () << m.point () );
1241
+ movingVertices << v;
1201
1242
1202
1243
if ( QgsProject::instance ()->topologicalEditing () )
1203
1244
{
1204
- // support for topo editing - find extra features
1205
- // that have coincident point with the vertex being dragged
1206
- const auto layers = canvas ()->layers ();
1207
- for ( QgsMapLayer *layer : layers )
1208
- {
1209
- QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
1210
- if ( !vlayer || !vlayer->isEditable () )
1211
- continue ;
1245
+ movingVertices.unite ( findCoincidentVertices ( movingVertices ) );
1246
+ }
1212
1247
1213
- const auto snappedVertices = layerVerticesSnappedToPoint ( vlayer, m.point () );
1214
- for ( const QgsPointLocator::Match &otherMatch : snappedVertices )
1215
- {
1216
- if ( otherMatch.layer () == m.layer () &&
1217
- otherMatch.featureId () == m.featureId () &&
1218
- otherMatch.vertexIndex () == m.vertexIndex () )
1219
- continue ;
1248
+ buildExtraVertices ( movingVertices, geom.vertexAt ( m.vertexIndex () ), m.layer () );
1220
1249
1221
- // start dragging of snapped point of current layer
1222
- mDraggingExtraVertices << Vertex ( otherMatch.layer (), otherMatch.featureId (), otherMatch.vertexIndex () );
1223
- mDraggingExtraVerticesOffset << QgsVector (); // topo vertices have the same position
1224
- }
1225
- }
1226
- }
1250
+ cadDockWidget ()->setPoints ( QList<QgsPointXY>() << m.point () << m.point () );
1227
1251
1228
1252
// now build drag rubber bands for extra vertices
1229
1253
1230
- QSet<Vertex> movingVertices;
1231
- movingVertices << *mDraggingVertex ;
1232
- for ( const Vertex &v : qgis::as_const ( mDraggingExtraVertices ) )
1233
- movingVertices << v;
1234
-
1235
1254
QgsPointXY dragVertexMapPoint = m.point ();
1236
1255
1237
1256
buildDragBandsForVertices ( movingVertices, dragVertexMapPoint );
@@ -1423,13 +1442,9 @@ void QgsVertexTool::startDraggingAddVertex( const QgsPointLocator::Match &m )
1423
1442
{
1424
1443
// find other segments coincident with the one user just picked and store them in a list
1425
1444
// so we can add a new vertex also in those to keep topology correct
1426
- const auto layers = canvas ()-> layers ();
1427
- for ( QgsMapLayer *layer : layers )
1445
+ const auto editableLayers = editableVectorLayers ();
1446
+ for ( QgsVectorLayer *vlayer : editableLayers )
1428
1447
{
1429
- QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
1430
- if ( !vlayer || !vlayer->isEditable () )
1431
- continue ;
1432
-
1433
1448
if ( vlayer->geometryType () != QgsWkbTypes::LineGeometry && vlayer->geometryType () != QgsWkbTypes::PolygonGeometry )
1434
1449
continue ;
1435
1450
@@ -1506,14 +1521,14 @@ void QgsVertexTool::startDraggingEdge( const QgsPointLocator::Match &m, const Qg
1506
1521
1507
1522
buildDragBandsForVertices ( movingVertices, mapPoint );
1508
1523
1509
- QgsPointXY layerPoint = toLayerCoordinates ( m.layer (), mapPoint );
1510
-
1511
- for ( const Vertex &v : qgis::as_const ( movingVertices ) )
1524
+ if ( QgsProject::instance ()->topologicalEditing () )
1512
1525
{
1513
- mDraggingExtraVertices << v;
1514
- mDraggingExtraVerticesOffset << ( geom.vertexAt ( v.vertexId ) - QgsPoint ( layerPoint ) );
1526
+ movingVertices.unite ( findCoincidentVertices ( movingVertices ) );
1515
1527
}
1516
1528
1529
+ QgsPointXY layerPoint = toLayerCoordinates ( m.layer (), mapPoint );
1530
+ buildExtraVertices ( movingVertices, layerPoint, m.layer () );
1531
+
1517
1532
cadDockWidget ()->setPoints ( QList<QgsPointXY>() << m.point () << m.point () );
1518
1533
}
1519
1534
0 commit comments