Skip to content

Commit

Permalink
Enable the vertex tool to edit Z or M value if the layer supports it
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Dec 22, 2022
1 parent 73be65f commit 88dd070
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 8 deletions.
21 changes: 17 additions & 4 deletions src/core/vector/qgsvectorlayereditutils.cpp
Expand Up @@ -87,12 +87,25 @@ bool QgsVectorLayerEditUtils::moveVertex( const QgsPoint &p, QgsFeatureId atFeat

QgsGeometry geometry = f.geometry();

geometry.moveVertex( p, atVertex );
// If original point is not 3D but destination yes, check if it can be promoted
if ( p.is3D() && !geometry.vertexAt( atVertex ).is3D() && QgsWkbTypes::hasZ( mLayer->wkbType() ) )
{
if ( !geometry.get()->addZValue( std::numeric_limits<double>::quiet_NaN() ) )
return false;
}

mLayer->changeGeometry( atFeatureId, geometry );
return true;
}
// If original point has not M-value but destination yes, check if it can be promoted
if ( p.isMeasure() && !geometry.vertexAt( atVertex ).isMeasure() && QgsWkbTypes::hasM( mLayer->wkbType() ) )
{
if ( !geometry.get()->addMValue( std::numeric_limits<double>::quiet_NaN() ) )
return false;
}

if ( !geometry.moveVertex( p, atVertex ) )
return false;

return mLayer->changeGeometry( atFeatureId, geometry );
}

Qgis::VectorEditResult QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId featureId, int vertex )
{
Expand Down
156 changes: 152 additions & 4 deletions tests/src/python/test_qgsvectorlayereditutils.py
Expand Up @@ -16,8 +16,6 @@
import qgis # NOQA

from qgis.PyQt.QtCore import (
QDate,
QDateTime,
QVariant,
Qt,
QDateTime,
Expand All @@ -31,11 +29,9 @@
QgsFeature,
QgsGeometry,
QgsLineString,
QgsPolygon,
QgsPoint,
QgsPointXY,
QgsVectorLayer,
QgsVectorLayerTools,
QgsVectorLayerEditUtils)


Expand Down Expand Up @@ -272,6 +268,158 @@ def testAddRingV2SelectedFeatures(self):
"Polygon ((2 2, 6 2, 6 6, 2 6, 2 2))"
)

def testMoveVertex(self):
layer = QgsVectorLayer("Point", "point", "memory")
self.assertTrue(layer.startEditing())
self.assertTrue(layer.isValid())

pr = layer.dataProvider()
f1 = QgsFeature(layer.fields(), 1)
f1.setGeometry(QgsGeometry.fromWkt('Point(0 0)'))
self.assertTrue(pr.addFeatures([f1]))
self.assertEqual(layer.featureCount(), 1)

vle = QgsVectorLayerEditUtils(layer)

self.assertTrue(vle.moveVertex(1, 2, f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 1)
self.assertEqual(f1.geometry().constGet().y(), 2)

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 3)
self.assertEqual(f1.geometry().constGet().y(), 4)
self.assertFalse(f1.geometry().constGet().is3D())
self.assertFalse(f1.geometry().constGet().isMeasure())

def testMoveVertexPointZ(self):
layer = QgsVectorLayer("PointZ", "pointZ", "memory")
self.assertTrue(layer.startEditing())
self.assertTrue(layer.isValid())

pr = layer.dataProvider()
f1 = QgsFeature(layer.fields(), 1)
f1.setGeometry(QgsGeometry.fromWkt('PointZ(0 0 0)'))
self.assertTrue(pr.addFeatures([f1]))
self.assertEqual(layer.featureCount(), 1)

vle = QgsVectorLayerEditUtils(layer)

self.assertTrue(vle.moveVertex(1, 2, f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 1)
self.assertEqual(f1.geometry().constGet().y(), 2)
self.assertEqual(f1.geometry().constGet().z(), 0)

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 3)
self.assertEqual(f1.geometry().constGet().y(), 4)
self.assertEqual(f1.geometry().constGet().z(), 5)
self.assertTrue(f1.geometry().constGet().is3D())
self.assertFalse(f1.geometry().constGet().isMeasure())

# Add a non-Z point and check that Z get added on move
f2 = QgsFeature(layer.fields(), 2)
f2.setGeometry(QgsGeometry.fromWkt('Point(0 0)'))
self.assertTrue(pr.addFeatures([f2]))
self.assertEqual(layer.featureCount(), 2)

self.assertFalse(f2.geometry().constGet().is3D())
self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f2.id(), 0))
f2 = layer.getFeature(2)
self.assertEqual(f2.geometry().constGet().x(), 3)
self.assertEqual(f2.geometry().constGet().y(), 4)
self.assertEqual(f2.geometry().constGet().z(), 5)
self.assertTrue(f2.geometry().constGet().is3D())
self.assertFalse(f2.geometry().constGet().isMeasure())

def testMoveVertexPointM(self):
layer = QgsVectorLayer("PointM", "pointM", "memory")
self.assertTrue(layer.startEditing())
self.assertTrue(layer.isValid())

pr = layer.dataProvider()
f1 = QgsFeature(layer.fields(), 1)
f1.setGeometry(QgsGeometry.fromWkt('PointM(0 0 0)'))
self.assertTrue(pr.addFeatures([f1]))
self.assertEqual(layer.featureCount(), 1)

vle = QgsVectorLayerEditUtils(layer)

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 3)
self.assertEqual(f1.geometry().constGet().y(), 4)
self.assertEqual(f1.geometry().constGet().m(), 6)
self.assertFalse(f1.geometry().constGet().is3D())
self.assertTrue(f1.geometry().constGet().isMeasure())

# Add a non-M point and check that M get added on move
f2 = QgsFeature(layer.fields(), 2)
f2.setGeometry(QgsGeometry.fromWkt('Point(0 0)'))
self.assertTrue(pr.addFeatures([f2]))
self.assertEqual(layer.featureCount(), 2)

self.assertFalse(f2.geometry().constGet().isMeasure())

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f2.id(), 0))
f2 = layer.getFeature(2)

self.assertTrue(f2.geometry().constGet().isMeasure())
self.assertFalse(f2.geometry().constGet().is3D())
self.assertEqual(f2.geometry().constGet().x(), 3)
self.assertEqual(f2.geometry().constGet().y(), 4)
self.assertEqual(f2.geometry().constGet().m(), 6)

def testMoveVertexPointZM(self):
layer = QgsVectorLayer("PointZM", "pointZM", "memory")
self.assertTrue(layer.startEditing())
self.assertTrue(layer.isValid())

pr = layer.dataProvider()
f1 = QgsFeature(layer.fields(), 1)
f1.setGeometry(QgsGeometry.fromWkt('PointZM(0 0 0 0)'))
self.assertTrue(pr.addFeatures([f1]))
self.assertEqual(layer.featureCount(), 1)

vle = QgsVectorLayerEditUtils(layer)

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f1.id(), 0))
f1 = layer.getFeature(1)

self.assertEqual(f1.geometry().constGet().x(), 3)
self.assertEqual(f1.geometry().constGet().y(), 4)
self.assertEqual(f1.geometry().constGet().z(), 5)
self.assertEqual(f1.geometry().constGet().m(), 6)
self.assertTrue(f1.geometry().constGet().is3D())
self.assertTrue(f1.geometry().constGet().isMeasure())

# Add a non-ZM point and check that Z and M get added on move
f2 = QgsFeature(layer.fields(), 2)
f2.setGeometry(QgsGeometry.fromWkt('Point(0 0)'))
self.assertTrue(pr.addFeatures([f2]))
self.assertEqual(layer.featureCount(), 2)

self.assertFalse(f2.geometry().constGet().isMeasure())
self.assertFalse(f2.geometry().constGet().is3D())

self.assertTrue(vle.moveVertexV2(QgsPoint(3, 4, 5, 6), f2.id(), 0))
f2 = layer.getFeature(2)
self.assertTrue(f2.geometry().constGet().isMeasure())
self.assertTrue(f2.geometry().constGet().is3D())

self.assertEqual(f2.geometry().constGet().x(), 3)
self.assertEqual(f2.geometry().constGet().y(), 4)
self.assertEqual(f2.geometry().constGet().z(), 5)
self.assertEqual(f2.geometry().constGet().m(), 6)


if __name__ == '__main__':
unittest.main()

0 comments on commit 88dd070

Please sign in to comment.