Skip to content

Commit

Permalink
Add Z or M to vertex when snapping with vertex tool
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Jan 2, 2023
1 parent 88dd070 commit 8b4d907
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 12 deletions.
23 changes: 23 additions & 0 deletions src/app/vertextool/qgsvertextool.cpp
Expand Up @@ -2189,6 +2189,26 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato

QgsAbstractGeometry *geomTmp = geom.constGet()->clone();

// If moving point is not 3D but destination yes, check if it can be promoted
if ( layerPoint.is3D() && !geom.vertexAt( dragVertexId ).is3D() && QgsWkbTypes::hasZ( dragLayer->wkbType() ) )
{
if ( !geomTmp->addZValue( std::numeric_limits<double>::quiet_NaN() ) )
{
QgsDebugMsg( QStringLiteral( "add Z value to vertex failed!" ) );
return;
}
}

// If moving point has not M-value but destination yes, check if it can be promoted
if ( layerPoint.isMeasure() && !geom.vertexAt( dragVertexId ).isMeasure() && QgsWkbTypes::hasM( dragLayer->wkbType() ) )
{
if ( !geomTmp->addMValue( std::numeric_limits<double>::quiet_NaN() ) )
{
QgsDebugMsg( QStringLiteral( "add M value to vertex failed!" ) );
return;
}
}

// add/move vertex
if ( addingVertex )
{
Expand All @@ -2199,6 +2219,9 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
if ( QgsWkbTypes::hasZ( dragLayer->wkbType() ) && !pt.is3D() )
pt.addZValue( defaultZValue() );

if ( QgsWkbTypes::hasM( dragLayer->wkbType() ) && !pt.isMeasure() )
pt.addMValue( defaultMValue() );

if ( !geomTmp->insertVertex( vid, pt ) )
{
QgsDebugMsg( QStringLiteral( "append vertex failed!" ) );
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgisapppython.cpp
Expand Up @@ -65,7 +65,7 @@ void TestQgisAppPython::initTestCase()
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );

qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgisAppPython::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsattributetable.cpp
Expand Up @@ -77,7 +77,7 @@ TestQgsAttributeTable::TestQgsAttributeTable() = default;
//runs before all tests
void TestQgsAttributeTable::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsAttributeTable::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsdecorationscalebar.cpp
Expand Up @@ -40,7 +40,7 @@ TestQgsDecorationScalebar::TestQgsDecorationScalebar() = default;
//runs before all tests
void TestQgsDecorationScalebar::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsDecorationScalebar::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsfieldcalculator.cpp
Expand Up @@ -52,7 +52,7 @@ TestQgsFieldCalculator::TestQgsFieldCalculator() = default;
//runs before all tests
void TestQgsFieldCalculator::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsFieldCalculator::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsgeoreferencer.cpp
Expand Up @@ -64,7 +64,7 @@ TestQgsGeoreferencer::TestQgsGeoreferencer() = default;
//runs before all tests
void TestQgsGeoreferencer::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsGeoreferencer::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsmeasurebearingtool.cpp
Expand Up @@ -56,7 +56,7 @@ TestQgsMeasureBearingTool::TestQgsMeasureBearingTool() = default;
//runs before all tests
void TestQgsMeasureBearingTool::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsMeasureBearingTool::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsmeasuretool.cpp
Expand Up @@ -57,7 +57,7 @@ TestQgsMeasureTool::TestQgsMeasureTool() = default;
//runs before all tests
void TestQgsMeasureTool::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsMeasureTool::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/app/testqgsmeshcalculatordialog.cpp
Expand Up @@ -51,7 +51,7 @@ TestQgsMeshCalculatorDialog::TestQgsMeshCalculatorDialog() = default;
//runs before all tests
void TestQgsMeshCalculatorDialog::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsMeshCalculatorDialog::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down
60 changes: 57 additions & 3 deletions tests/src/app/testqgsvertextool.cpp
Expand Up @@ -70,6 +70,7 @@ class TestQgsVertexTool : public QObject
void testTopologicalEditingMoveVertexOnIntersectionZ();
void testMoveVertex();
void testMoveEdge();
void testMovePointAddingZ();
void testAddVertex();
void testAddVertexAtEndpoint();
void testAddVertexDoubleClick();
Expand Down Expand Up @@ -157,6 +158,7 @@ class TestQgsVertexTool : public QObject
QgsVectorLayer *mLayerPolygon = nullptr;
QgsVectorLayer *mLayerMultiPolygon = nullptr;
QgsVectorLayer *mLayerPoint = nullptr;
QgsVectorLayer *mLayerPointZ = nullptr;
QgsVectorLayer *mLayerLineZ = nullptr;
QgsVectorLayer *mLayerCompoundCurve = nullptr;
QgsVectorLayer *mLayerLineReprojected = nullptr;
Expand All @@ -169,6 +171,7 @@ class TestQgsVertexTool : public QObject
QgsFeatureId mFidPolygonF1 = 0;
QgsFeatureId mFidMultiPolygonF1 = 0;
QgsFeatureId mFidPointF1 = 0;
QgsFeatureId mFidPointZF1 = 0;
QgsFeatureId mFidCompoundCurveF1 = 0;
QgsFeatureId mFidCompoundCurveF2 = 0;
};
Expand All @@ -179,7 +182,7 @@ TestQgsVertexTool::TestQgsVertexTool() = default;
//runs before all tests
void TestQgsVertexTool::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsVertexTool::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down Expand Up @@ -209,11 +212,13 @@ void TestQgsVertexTool::initTestCase()
QVERIFY( mLayerMultiPolygon->isValid() );
mLayerPoint = new QgsVectorLayer( QStringLiteral( "Point?crs=EPSG:27700" ), QStringLiteral( "layer point" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerPoint->isValid() );
mLayerPointZ = new QgsVectorLayer( QStringLiteral( "PointZ?crs=EPSG:27700" ), QStringLiteral( "layer pointz" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerPointZ->isValid() );
mLayerLineZ = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerLineZ->isValid() );
mLayerCompoundCurve = new QgsVectorLayer( QStringLiteral( "CompoundCurve?crs=27700" ), QStringLiteral( "layer compound curve" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerCompoundCurve->isValid() );
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerLineZ << mLayerCompoundCurve );
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerCompoundCurve );

QgsFeature lineF1;
lineF1.setGeometry( QgsGeometry::fromWkt( "LineString (2 1, 1 1, 1 3)" ) );
Expand All @@ -236,6 +241,9 @@ void TestQgsVertexTool::initTestCase()
QgsFeature pointF1;
pointF1.setGeometry( QgsGeometry::fromWkt( "Point (2 3)" ) );

QgsFeature pointZF1;
pointZF1.setGeometry( QgsGeometry::fromWkt( "PointZ (20 25 4)" ) );

QgsFeature linez1, linez2, linez3;
linez1.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 5 1, 6 6 1, 7 5 1)" ) );
linez2.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 7 5, 7 7 10)" ) );
Expand Down Expand Up @@ -276,6 +284,11 @@ void TestQgsVertexTool::initTestCase()
mFidPointF1 = pointF1.id();
QCOMPARE( mLayerPoint->featureCount(), ( long )1 );

mLayerPointZ->startEditing();
mLayerPointZ->addFeature( pointZF1 );
mFidPointZF1 = pointZF1.id();
QCOMPARE( mLayerPointZ->featureCount(), ( long )1 );

mLayerLineZ->startEditing();
mLayerLineZ->addFeature( linez1 );
mLayerLineZ->addFeature( linez2 );
Expand All @@ -298,6 +311,7 @@ void TestQgsVertexTool::initTestCase()
QCOMPARE( mLayerPolygon->undoStack()->index(), 1 );
QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 1 );
QCOMPARE( mLayerPoint->undoStack()->index(), 1 );
QCOMPARE( mLayerPointZ->undoStack()->index(), 1 );
// except for layerLineZ
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerCompoundCurve->undoStack()->index(), 2 );
Expand All @@ -310,7 +324,7 @@ void TestQgsVertexTool::initTestCase()
QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) );
QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) );

mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerLineReprojected << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerLineZ << mLayerCompoundCurve );
mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerLineReprojected << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerCompoundCurve );

QgsMapCanvasSnappingUtils *snappingUtils = new QgsMapCanvasSnappingUtils( mCanvas, this );
mCanvas->setSnappingUtils( snappingUtils );
Expand All @@ -321,6 +335,7 @@ void TestQgsVertexTool::initTestCase()
snappingUtils->locatorForLayer( mLayerPolygon )->init();
snappingUtils->locatorForLayer( mLayerMultiPolygon )->init();
snappingUtils->locatorForLayer( mLayerPoint )->init();
snappingUtils->locatorForLayer( mLayerPointZ )->init();
snappingUtils->locatorForLayer( mLayerLineZ )->init();
snappingUtils->locatorForLayer( mLayerCompoundCurve )->init();

Expand Down Expand Up @@ -529,6 +544,45 @@ void TestQgsVertexTool::testMoveEdge()
QCOMPARE( mLayerPoint->undoStack()->index(), 1 );
}

void TestQgsVertexTool::testMovePointAddingZ()
{
mouseClick( 20, 25, Qt::LeftButton );
mouseClick( 25, 20, Qt::LeftButton );

QCOMPARE( mLayerPointZ->undoStack()->index(), 2 );
QCOMPARE( mLayerPointZ->getFeature( mFidPointZF1 ).geometry(), QgsGeometry::fromWkt( "POINTZ(25 20 4)" ) );

mLayerPointZ->undoStack()->undo();
QCOMPARE( mLayerPointZ->undoStack()->index(), 1 );
QCOMPARE( mLayerPointZ->getFeature( mFidPointZF1 ).geometry(), QgsGeometry::fromWkt( "POINTZ(20 25 4)" ) );

// Add a point whitout Z
QgsFeature pointZF2;
pointZF2.setGeometry( QgsGeometry::fromWkt( "Point (30 35)" ) );
mLayerPointZ->addFeature( pointZF2 );
QCOMPARE( mLayerPointZ->featureCount(), ( long )2 );
QCOMPARE( mLayerPointZ->undoStack()->index(), 2 );

// And snap on a point whith Z
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.setIntersectionSnapping( true );
cfg.setEnabled( true );
mCanvas->snappingUtils()->setConfig( cfg );

mouseClick( 30, 35, Qt::LeftButton );
mouseClick( 20, 25, Qt::LeftButton, Qt::KeyboardModifier(), true );

QCOMPARE( mLayerPointZ->undoStack()->index(), 3 );
QCOMPARE( mLayerPointZ->getFeature( pointZF2.id() ).geometry(), QgsGeometry::fromWkt( "POINTZ(20 25 4)" ) );

mLayerPointZ->undoStack()->undo();
mLayerPointZ->undoStack()->undo();
QCOMPARE( mLayerPointZ->undoStack()->index(), 1 );
}

void TestQgsVertexTool::testAddVertex()
{
// add vertex in linestring
Expand Down
2 changes: 1 addition & 1 deletion tests/src/gui/testqgsmeshlayerpropertiesdialog.cpp
Expand Up @@ -53,7 +53,7 @@ TestQgsMeshLayerPropertiesDialog::TestQgsMeshLayerPropertiesDialog() = default;
//runs before all tests
void TestQgsMeshLayerPropertiesDialog::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
qDebug() << "TestQgsMeshLayerPropertiesDialog::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Expand Down

0 comments on commit 8b4d907

Please sign in to comment.