/*************************************************************************** testqgsadvanceddigitizing.cpp ---------------------- Date : December 2021 Copyright : (C) 2021 Antoine Facchini Email : antoine dot facchini at oslandia dot com *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "qgstest.h" #include "qgsadvanceddigitizingdockwidget.h" #include "qgsapplication.h" #include "qgsmapcanvas.h" #include "qgsvectorlayer.h" #include "qgsmaptooladdfeature.h" #include "qgsmapcanvassnappingutils.h" #include "qgssettingsregistrycore.h" #include "testqgsmaptoolutils.h" class TestQgsAdvancedDigitizing : public QObject { Q_OBJECT private slots: void initTestCase(); // will be called before the first testfunction is executed. void cleanupTestCase(); // will be called after the last testfunction was executed. void init(); // will be called before each testfunction is executed. void cleanup(); // will be called after every testfunction. void distanceConstraint(); void distanceConstraintDiffCrs(); void distanceConstraintWhenSnapping(); void angleConstraint(); void angleConstraintWithGeographicCrs(); void distanceConstraintWithAngleConstraint(); void coordinateConstraint(); void coordinateConstraintWithZM(); void coordinateConstraintWhenSnapping(); void perpendicularConstraint(); void xyExtensionConstraint(); void lineExtensionConstraint(); void lineExtensionConstraintGeographicCrs(); void cadPointList(); void lockedSnapVertices(); void currentPointWhenSanpping(); void currentPointWhenSanppingWithDiffCanvasCRS(); void releaseLockAfterDisable(); void constructionGuides(); private: TestQgsMapToolAdvancedDigitizingUtils getMapToolDigitizingUtils( QgsVectorLayer *layer ); QString getWktFromLastAddedFeature( TestQgsMapToolAdvancedDigitizingUtils utils, QSet oldFeatures ); void setCanvasCrs( QString crsString ); QgisApp *mQgisApp = nullptr; QgsMapToolAddFeature *mCaptureTool = nullptr; QgsMapCanvas *mCanvas = nullptr; QgsVectorLayer *mLayer3950 = nullptr; QgsVectorLayer *mLayer3950ZM = nullptr; QgsVectorLayer *mLayer4326 = nullptr; QgsVectorLayer *mLayer4326ZM = nullptr; QgsAdvancedDigitizingDockWidget *mAdvancedDigitizingDockWidget = nullptr; const double WKT_PRECISION = 2; }; void TestQgsAdvancedDigitizing::initTestCase() { QgsApplication::init(); QgsApplication::initQgis(); mQgisApp = new QgisApp(); mCanvas = new QgsMapCanvas(); setCanvasCrs( QStringLiteral( "EPSG:3950" ) ); QgsSettingsRegistryCore::settingsDigitizingDefaultZValue->setValue( 33 ); QgsSettingsRegistryCore::settingsDigitizingDefaultMValue->setValue( 66 ); // make test layers QList layers; mLayer3950 = new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:3950" ), QStringLiteral( "line layer" ), QStringLiteral( "memory" ) ); QVERIFY( mLayer3950->isValid() ); layers << mLayer3950; mLayer3950ZM = new QgsVectorLayer( QStringLiteral( "LineStringZM?crs=EPSG:3950" ), QStringLiteral( "ZM line layer" ), QStringLiteral( "memory" ) ); QVERIFY( mLayer3950ZM->isValid() ); layers << mLayer3950ZM; mLayer4326 = new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:4326" ), QStringLiteral( "line layer diff crs" ), QStringLiteral( "memory" ) ); QVERIFY( mLayer4326->isValid() ); layers << mLayer4326; mLayer4326ZM = new QgsVectorLayer( QStringLiteral( "LineStringZM?crs=EPSG:4326" ), QStringLiteral( "ZM line layer diff crs" ), QStringLiteral( "memory" ) ); QVERIFY( mLayer4326ZM->isValid() ); layers << mLayer4326ZM; // set layers in canvas QgsProject::instance()->addMapLayers( layers ); mCanvas->setLayers( layers ); mCanvas->setCurrentLayer( mLayer3950 ); // create advanced digitizing dock widget mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mCanvas ); // create snapping config QgsSnappingConfig snapConfig; snapConfig.setEnabled( false ); snapConfig.setIntersectionSnapping( true ); snapConfig.setSelfSnapping( true ); snapConfig.setMode( Qgis::SnappingMode::AllLayers ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex ); snapConfig.setTolerance( 1.0 ); QgsMapSettings mapSettings; mapSettings.setExtent( QgsRectangle( 0, 0, 8, 8 ) ); mapSettings.setOutputSize( QSize( 512, 512 ) ); mapSettings.setLayers( layers ); QgsSnappingUtils *snappingUtils = new QgsMapCanvasSnappingUtils( mCanvas ); snappingUtils->setConfig( snapConfig ); snappingUtils->setMapSettings( mapSettings ); snappingUtils->locatorForLayer( mLayer3950 )->init(); snappingUtils->locatorForLayer( mLayer3950ZM )->init(); snappingUtils->locatorForLayer( mLayer4326 )->init(); snappingUtils->locatorForLayer( mLayer4326ZM )->init(); mCanvas->setSnappingUtils( snappingUtils ); // create base map tool mCaptureTool = new QgsMapToolAddFeature( mCanvas, mAdvancedDigitizingDockWidget, QgsMapToolCapture::CaptureLine ); mCanvas->setMapTool( mCaptureTool ); } void TestQgsAdvancedDigitizing::cleanupTestCase() { QgsSettingsRegistryCore::settingsDigitizingDefaultZValue->setValue( 0 ); QgsSettingsRegistryCore::settingsDigitizingDefaultMValue->setValue( 0 ); delete mAdvancedDigitizingDockWidget; delete mCaptureTool; delete mCanvas; QgsApplication::exitQgis(); } void TestQgsAdvancedDigitizing::init() { } void TestQgsAdvancedDigitizing::cleanup() { // reset the advanced digitizing dock mAdvancedDigitizingDockWidget->releaseLocks(); mAdvancedDigitizingDockWidget->enableAction()->trigger(); QVERIFY( !mAdvancedDigitizingDockWidget->cadEnabled() ); // disable the snapping QgsSnappingUtils *snappingUtils = mCanvas->snappingUtils(); QgsSnappingConfig snapConfig = snappingUtils->config(); snapConfig.setEnabled( false ); snapConfig.setIntersectionSnapping( true ); snapConfig.setSelfSnapping( true ); snapConfig.setMode( Qgis::SnappingMode::AllLayers ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex ); snappingUtils->setConfig( snapConfig ); // reset all layers mLayer3950->rollBack(); mLayer3950ZM->rollBack(); mLayer4326->rollBack(); mLayer4326ZM->rollBack(); } TestQgsMapToolAdvancedDigitizingUtils TestQgsAdvancedDigitizing::getMapToolDigitizingUtils( QgsVectorLayer *layer ) { mCanvas->setCurrentLayer( layer ); layer->startEditing(); mCaptureTool->setLayer( layer ); // enable the advanced digitizing dock mAdvancedDigitizingDockWidget->enableAction()->trigger(); return TestQgsMapToolAdvancedDigitizingUtils( mCaptureTool ); } QString TestQgsAdvancedDigitizing::getWktFromLastAddedFeature( TestQgsMapToolAdvancedDigitizingUtils utils, QSet oldFeatures ) { auto layer = qobject_cast( mCanvas->currentLayer() ); const QgsFeatureId newFid = utils.newFeatureId( oldFeatures ); QgsGeometry geom = layer->getFeature( newFid ).geometry(); // transform the coordinates when canvas CRS and layer CRS are different const QgsCoordinateTransform transform( layer->sourceCrs(), mCanvas->mapSettings().destinationCrs(), QgsProject::instance() ); geom.transform( transform, Qgis::TransformDirection::Forward ); return geom.asWkt( WKT_PRECISION ); } void TestQgsAdvancedDigitizing::setCanvasCrs( QString crsString ) { const QgsCoordinateReferenceSystem crs( crsString ); QVERIFY( crs.isValid() ); mCanvas->setDestinationCrs( crs ); mCanvas->setFrameStyle( QFrame::NoFrame ); mCanvas->resize( 512, 512 ); mCanvas->setExtent( QgsRectangle( 0, 0, 8, 8 ) ); mCanvas->show(); // to make the canvas resize mCanvas->hide(); } void TestQgsAdvancedDigitizing::distanceConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QSet oldFeatures = utils.existingFeatureIds(); // with no digitized vertex auto capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); QVERIFY( !mAdvancedDigitizingDockWidget->mAngleLineEdit->isEnabled() ); QVERIFY( !mAdvancedDigitizingDockWidget->mDistanceLineEdit->isEnabled() ); // activate constraint on the second point (one digitized vertex) utils.mouseClick( 1, 1, Qt::LeftButton ); capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "10" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 8.07 8.07)" ) ); // activate constraint on the third point oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 1, 1, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 3, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 2 2, 7 2)" ) ); capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); } void TestQgsAdvancedDigitizing::distanceConstraintDiffCrs() { auto utils = getMapToolDigitizingUtils( mLayer4326 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); utils.mouseClick( 1, 1, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "10" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 8.07 8.07)" ) ); // activate constraint on third point oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 1, 1, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 3, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 2 2, 7 2)" ) ); } void TestQgsAdvancedDigitizing::distanceConstraintWhenSnapping() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QSet oldFeatures = utils.existingFeatureIds(); // line for snapping utils.mouseClick( 1, 1, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 2 2)" ) ); oldFeatures = utils.existingFeatureIds(); // with no digitized vertex auto capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); QVERIFY( !mAdvancedDigitizingDockWidget->mAngleLineEdit->isEnabled() ); QVERIFY( !mAdvancedDigitizingDockWidget->mDistanceLineEdit->isEnabled() ); // activate constraint on the second point (one digitized vertex) utils.mouseClick( 1, 1, Qt::LeftButton ); capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "10" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 8.07 8.07)" ) ); // activate constraint on the third point oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 1, 1, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 3, 2, Qt::LeftButton ); utils.mouseClick( 1, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 2 2, 7 2)" ) ); capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::Distance ) ); } void TestQgsAdvancedDigitizing::angleConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); // with no digitized vertex auto capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::AbsoluteAngle ) ); // try angle hard lock in a side utils.mouseClick( 1, 1, Qt::LeftButton ); capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( capacities.testFlag( QgsAdvancedDigitizingDockWidget::AbsoluteAngle ) ); mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "90" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 1 2)" ) ); // and in the other side oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 1, 1, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "90" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2, -2, Qt::LeftButton ); utils.mouseClick( 2, -2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 1 -2)" ) ); // try with an angle of 45° oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "45" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 1 1)" ) ); } void TestQgsAdvancedDigitizing::angleConstraintWithGeographicCrs() { setCanvasCrs( QStringLiteral( "EPSG:4326" ) ); QVERIFY( mCanvas->mapSettings().destinationCrs().isGeographic() ); auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); utils.mouseClick( 1, 1, Qt::LeftButton ); auto capacities = mAdvancedDigitizingDockWidget->capacities(); QVERIFY( !capacities.testFlag( QgsAdvancedDigitizingDockWidget::AbsoluteAngle ) ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); utils.mouseClick( 0, 2, Qt::RightButton ); utils.mouseClick( 1, 1, Qt::LeftButton ); // constraint angle can be forced even with geographical // should be normal ? mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "90" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); QVERIFY( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 1 2)" ) ); setCanvasCrs( QStringLiteral( "EPSG:3950" ) ); } void TestQgsAdvancedDigitizing::distanceConstraintWithAngleConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); // with these 2 next locks, there are only 2 possibilities // first utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "10" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "45" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 7.07 7.07)" ) ); // second oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "10" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "45" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( -1000, 59, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, -7.07 -7.07)" ) ); } void TestQgsAdvancedDigitizing::coordinateConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setY( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 3, 9, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "6" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setY( QStringLiteral( "7" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (5 0, 3 5, 6 7)" ) ); // set Z/M constraints should have no effect oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setZ( QStringLiteral( "3" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setM( QStringLiteral( "3" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 0 2)" ) ); } void TestQgsAdvancedDigitizing::coordinateConstraintWithZM() { auto utils = getMapToolDigitizingUtils( mLayer3950ZM ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 0, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setY( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 3, 9, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setZ( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 4, 4, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setM( QStringLiteral( "5" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 6, 6, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "9" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setY( QStringLiteral( "9" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setZ( QStringLiteral( "9" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setM( QStringLiteral( "9" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString ZM (5 0 33 66, 3 5 33 66, 4 4 5 66, 6 6 33 5, 9 9 9 9)" ) ); } void TestQgsAdvancedDigitizing::coordinateConstraintWhenSnapping() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); // line for snapping utils.mouseClick( 1, 1, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (1 1, 2 2)" ) ); oldFeatures = utils.existingFeatureIds(); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); mCanvas->snappingUtils()->setConfig( snapConfig ); // move to trigger a re-indexing and wait for it to complete utils.mouseMove( 0, 0 ); if ( QgsPointLocator *loc = mCanvas->snappingUtils()->locatorForLayer( mLayer3950 ) ) { if ( loc->isIndexing() ) { loc->waitForIndexingFinished(); } } // simple snap test utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 2.02, 2, Qt::LeftButton ); utils.mouseClick( 2, 2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 2, 2 2)" ) ); oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, -2, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 2.02, 2, Qt::LeftButton ); // shouldn't snap to (2 2) utils.mouseClick( -2, -2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 -2, 0 2)" ) ); oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, -2, Qt::LeftButton ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "2.02" ), // shouldn't snap to (2 2) QgsAdvancedDigitizingDockWidget::ReturnPressed ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( -2, -2, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 -2, 2.02 2)" ) ); } void TestQgsAdvancedDigitizing::perpendicularConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); // line for the perpendicular test utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 0, 10, Qt::LeftButton ); utils.mouseClick( 1, 1, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 0 10)" ) ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ); mCanvas->snappingUtils()->setConfig( snapConfig ); // test snapping on segment utils.mouseMove( 0.1, 4 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 4 ) ); QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::NoConstraint ); // digitizing a first vertex utils.mouseClick( 5, 5, Qt::LeftButton ); mAdvancedDigitizingDockWidget->lockBetweenLineConstraint( Qgis::BetweenLineConstraint::Perpendicular ); QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::Perpendicular ); // select the previous digitized line utils.mouseClick( 0.1, 4, Qt::LeftButton ); // test the perpendicular constraint utils.mouseMove( 3, 2 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 3, 5 ) ); utils.mouseClick( 0, 0, Qt::RightButton ); } void TestQgsAdvancedDigitizing::xyExtensionConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); // line for the xy extension test utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 10, 10, Qt::LeftButton ); utils.mouseClick( 1, 1, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 10 10)" ) ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ); mCanvas->snappingUtils()->setConfig( snapConfig ); // test snapping on segment utils.mouseMove( 4.9, 5.1 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 5, 5 ) ); // activate xy extension constraint QCOMPARE( mAdvancedDigitizingDockWidget->mXyVertexConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::NoLock ); mAdvancedDigitizingDockWidget->mXyVertexAction->trigger(); QCOMPARE( mAdvancedDigitizingDockWidget->mXyVertexConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::SoftLock ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 0 ); // move to the segment, shouldn't activate constraint utils.mouseMove( 5, 5 ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 0 ); // move to a vertex to activate constraint utils.mouseMove( 10.1, 10 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 10 ) ); // check if the vertex is in the heap mLockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.first().point(), QgsPointXY( 10, 10 ) ); // test soft constraint on X utils.mouseMove( 10.1, 0 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 0 ) ); // test soft constraint on Y utils.mouseMove( 0, 10.1 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 10 ) ); utils.mouseClick( 0, 0, Qt::RightButton ); } void TestQgsAdvancedDigitizing::lineExtensionConstraint() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); // line for the xy extension test utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 10, 10, Qt::LeftButton ); utils.mouseClick( 1, 1, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 10 10)" ) ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ); mCanvas->snappingUtils()->setConfig( snapConfig ); // test snapping on segment utils.mouseMove( 4.9, 5.1 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 5, 5 ) ); // activate xy extension constraint QCOMPARE( mAdvancedDigitizingDockWidget->mLineExtensionConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::NoLock ); mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QCOMPARE( mAdvancedDigitizingDockWidget->mLineExtensionConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::SoftLock ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 0 ); // move to a vertex to activate constraint utils.mouseMove( 10.1, 10 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 10 ) ); // check if the vertex is in the heap mLockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.first().point(), QgsPointXY( 10, 10 ) ); // test the 2 configurations utils.mouseMove( 15.1, 14.9 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 15, 15 ) ); utils.mouseMove( -15.1, -14.9 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( -15, -15 ) ); utils.mouseClick( 0, 0, Qt::RightButton ); } void TestQgsAdvancedDigitizing::lineExtensionConstraintGeographicCrs() { auto utils = getMapToolDigitizingUtils( mLayer4326 ); QSet oldFeatures = utils.existingFeatureIds(); // line for the xy extension test utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 10, 10, Qt::LeftButton ); utils.mouseClick( 1, 1, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 10 10)" ) ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); snapConfig.setTypeFlag( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ); mCanvas->snappingUtils()->setConfig( snapConfig ); // Wait for indexing to complete if ( QgsPointLocator *loc = mCanvas->snappingUtils()->locatorForLayer( mLayer4326 ) ) { if ( loc->isIndexing() ) { loc->waitForIndexingFinished(); } } // test snapping on segment utils.mouseMove( 4.9, 5.1 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 5, 5 ) ); // activate xy extension constraint QCOMPARE( mAdvancedDigitizingDockWidget->mLineExtensionConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::NoLock ); mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QCOMPARE( mAdvancedDigitizingDockWidget->mLineExtensionConstraint->lockMode(), QgsAdvancedDigitizingDockWidget::CadConstraint::SoftLock ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 0 ); // move to a vertex to activate constraint utils.mouseMove( 10.1, 10 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 10 ) ); // check if the vertex is in the heap mLockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.size(), 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->mLockedSnapVertices.first().point(), QgsPointXY( 10, 10 ) ); // test the 2 configurations utils.mouseMove( 15.1, 14.9 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 15, 15 ) ); utils.mouseMove( -15.1, -14.9 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( -15, -15 ) ); utils.mouseClick( 0, 0, Qt::RightButton ); } void TestQgsAdvancedDigitizing::cadPointList() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); // start a digitized line utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 0, 1, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 0, 3, Qt::LeftButton ); utils.mouseClick( 0, 4, Qt::LeftButton ); utils.mouseMove( 0, 5 ); bool exist; QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2( &exist ), QgsPoint( 0, 5 ) ); QVERIFY( exist ); QCOMPARE( mAdvancedDigitizingDockWidget->previousPointV2( &exist ), QgsPoint( 0, 4 ) ); QVERIFY( exist ); QCOMPARE( mAdvancedDigitizingDockWidget->penultimatePointV2( &exist ), QgsPoint( 0, 3 ) ); QVERIFY( exist ); QCOMPARE( mAdvancedDigitizingDockWidget->pointsCount(), 6 ); utils.mouseClick( 1, 1, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 0 1, 0 2, 0 3, 0 4)" ) ); utils.mouseMove( 1, 1 ); // with no digitized points QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2( &exist ), QgsPoint( 1, 1 ) ); QVERIFY( exist ); QCOMPARE( mAdvancedDigitizingDockWidget->previousPointV2( &exist ), QgsPoint() ); QVERIFY( !exist ); QCOMPARE( mAdvancedDigitizingDockWidget->penultimatePointV2( &exist ), QgsPoint() ); QVERIFY( !exist ); QCOMPARE( mAdvancedDigitizingDockWidget->pointsCount(), 1 ); } void TestQgsAdvancedDigitizing::lockedSnapVertices() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QSet oldFeatures = utils.existingFeatureIds(); // digitizes a line utils.mouseClick( 0, 0, Qt::LeftButton ); utils.mouseClick( 0, 1, Qt::LeftButton ); utils.mouseClick( 0, 2, Qt::LeftButton ); utils.mouseClick( 0, 3, Qt::LeftButton ); utils.mouseClick( 0, 4, Qt::LeftButton ); utils.mouseClick( 0, 4, Qt::RightButton ); QCOMPARE( getWktFromLastAddedFeature( utils, oldFeatures ), QStringLiteral( "LineString (0 0, 0 1, 0 2, 0 3, 0 4)" ) ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); mCanvas->snappingUtils()->setConfig( snapConfig ); // no locked snap vertex while xy vertex constraint or line extension QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 0 ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); utils.mouseMove( 0, 0 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 0 ); // enable xy vertex constraint mAdvancedDigitizingDockWidget->mXyVertexAction->trigger(); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); utils.mouseMove( 0, 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 1 ) ); // enable also line extension constraint mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QVERIFY( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); utils.mouseMove( 0, 2 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 2 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 2 ) ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().first().point(), QgsPointXY( 0, 1 ) ); utils.mouseMove( 0, 3 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 3 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 3 ) ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().first().point(), QgsPointXY( 0, 1 ) ); // the max size of lockedSnapVertices is 3 utils.mouseMove( 0, 4 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 3 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 4 ) ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().first().point(), QgsPointXY( 0, 2 ) ); // start to digitizing a new line utils.mouseClick( 10, 0, Qt::LeftButton ); utils.mouseClick( 10, 1, Qt::LeftButton ); utils.mouseClick( 10, 2, Qt::LeftButton ); // this shouldn't reset lockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 3 ); // QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 4 ) ); // QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().first().point(), QgsPointXY( 0, 2 ) ); // disable line extension constraint mAdvancedDigitizingDockWidget->mXyVertexAction->trigger(); QVERIFY( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // this shouldn't reset lockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 3 ); // QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 4 ) ); // QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().first().point(), QgsPointXY( 0, 2 ) ); // stops digitizing utils.mouseClick( 10, 2, Qt::RightButton ); // this should reset lockedSnapVertices QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 0 ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // enable line extension constraint mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QVERIFY( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // add one locked snap vertex utils.mouseMove( 0, 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 1 ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().last().point(), QgsPointXY( 0, 1 ) ); // line extension constraint and xy vertex constraint are disable, this should reset lockedSnapVertices mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); QCOMPARE( mAdvancedDigitizingDockWidget->lockedSnapVertices().size(), 0 ); } void TestQgsAdvancedDigitizing::currentPointWhenSanpping() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); utils.mouseClick( 0, 10, Qt::LeftButton ); utils.mouseClick( 0, -10, Qt::LeftButton ); utils.mouseClick( 0, -10, Qt::RightButton ); utils.mouseClick( 10, 0, Qt::LeftButton ); utils.mouseClick( -10, 0, Qt::LeftButton ); utils.mouseClick( -10, 0, Qt::RightButton ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); mCanvas->snappingUtils()->setConfig( snapConfig ); QCOMPARE( mCanvas->snappingUtils()->currentLayer(), mLayer3950 ); utils.mouseClick( 25, 0, Qt::LeftButton ); utils.mouseClick( 30, 0, Qt::LeftButton ); // on an existing point utils.mouseMove( 0.1, 10 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 10 ) ); // on an intersection (see issue #46128) utils.mouseMove( 0.1, 0 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 0 ) ); // on a self point utils.mouseMove( 25, 0.1 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 25, 0 ) ); utils.mouseClick( 30, 0, Qt::RightButton ); } void TestQgsAdvancedDigitizing::currentPointWhenSanppingWithDiffCanvasCRS() { auto utils = getMapToolDigitizingUtils( mLayer4326 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QSet oldFeatures = utils.existingFeatureIds(); utils.mouseClick( 0, 10, Qt::LeftButton ); utils.mouseClick( 0, -10, Qt::LeftButton ); utils.mouseClick( 0, -10, Qt::RightButton ); utils.mouseClick( 10, 0, Qt::LeftButton ); utils.mouseClick( -10, 0, Qt::LeftButton ); utils.mouseClick( -10, 0, Qt::RightButton ); oldFeatures = utils.existingFeatureIds(); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); mCanvas->snappingUtils()->setConfig( snapConfig ); QCOMPARE( mCanvas->snappingUtils()->currentLayer(), mLayer4326 ); utils.mouseClick( 25, 0, Qt::LeftButton ); utils.mouseClick( 0.1, 10, Qt::LeftButton ); utils.mouseClick( 0.1, 10, Qt::RightButton ); // on an existing point (see issue #46352) utils.mouseMove( 0.1, 10 ); QGSCOMPARENEARPOINT( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 10 ), 0.000001 ); // on an intersection utils.mouseMove( 0.1, 0 ); QGSCOMPARENEARPOINT( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 0, 0 ), 0.000001 ); // on a self point utils.mouseMove( 25, 0.1 ); QGSCOMPARENEARPOINT( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 25, 0 ), 0.000001 ); } void TestQgsAdvancedDigitizing::releaseLockAfterDisable() { // activate advanced digitizing getMapToolDigitizingUtils( mLayer4326 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::NoConstraint ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintX()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintY()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintZ()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintM()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // enable some constraints mAdvancedDigitizingDockWidget->setAngle( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setDistance( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setX( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setY( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setZ( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); mAdvancedDigitizingDockWidget->setM( QStringLiteral( "0" ), QgsAdvancedDigitizingDockWidget::ReturnPressed ); QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::NoConstraint ); QVERIFY( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintX()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintY()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintZ()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintM()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // disable advanced digitizing mAdvancedDigitizingDockWidget->enableAction()->trigger(); QVERIFY( !mAdvancedDigitizingDockWidget->cadEnabled() ); // all constraints should be deactivated QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::NoConstraint ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintX()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintY()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintZ()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintM()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // activate advanced digitizing mAdvancedDigitizingDockWidget->enableAction()->trigger(); // enable another constraints mAdvancedDigitizingDockWidget->lockBetweenLineConstraint( Qgis::BetweenLineConstraint::Perpendicular ); mAdvancedDigitizingDockWidget->mXyVertexAction->trigger(); mAdvancedDigitizingDockWidget->mLineExtensionAction->trigger(); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::Perpendicular ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintX()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintY()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintZ()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintM()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // disable advanced digitizing mAdvancedDigitizingDockWidget->enableAction()->trigger(); QVERIFY( !mAdvancedDigitizingDockWidget->cadEnabled() ); // all constraints should be deactivated QCOMPARE( mAdvancedDigitizingDockWidget->betweenLineConstraint(), Qgis::BetweenLineConstraint::NoConstraint ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintX()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintY()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintZ()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintM()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintLineExtension()->isLocked() ); QVERIFY( !mAdvancedDigitizingDockWidget->constraintXyVertex()->isLocked() ); // to be compliant with the integration mAdvancedDigitizingDockWidget->enableAction()->trigger(); } void TestQgsAdvancedDigitizing::constructionGuides() { auto utils = getMapToolDigitizingUtils( mLayer3950 ); QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() ); QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 0 ); mAdvancedDigitizingDockWidget->mRecordConstructionGuides->setChecked( true ); mAdvancedDigitizingDockWidget->setConstructionMode( true ); // enter a few construction steps while guide recording is on utils.mouseClick( 10, 10, Qt::LeftButton ); utils.mouseClick( 10, 11, Qt::LeftButton ); utils.mouseClick( 10, 12, Qt::LeftButton ); utils.mouseClick( 10, 13, Qt::LeftButton ); utils.mouseClick( 10, 14, Qt::LeftButton ); utils.mouseClick( 20, 01, Qt::RightButton ); QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 1 ); mAdvancedDigitizingDockWidget->mRecordConstructionGuides->setChecked( false ); // enter a few construction steps while guide recording is off utils.mouseClick( 10, 10, Qt::LeftButton ); utils.mouseClick( 10, 11, Qt::LeftButton ); utils.mouseClick( 10, 12, Qt::LeftButton ); utils.mouseClick( 10, 13, Qt::LeftButton ); utils.mouseClick( 10, 14, Qt::LeftButton ); utils.mouseClick( 20, 01, Qt::RightButton ); QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 1 ); QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config(); snapConfig.setEnabled( true ); mCanvas->snappingUtils()->setConfig( snapConfig ); mAdvancedDigitizingDockWidget->mSnapToConstructionGuides->setChecked( true ); // snap on an existing constructio guide vertex utils.mouseMove( 10.1, 10 ); QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 10 ) ); mAdvancedDigitizingDockWidget->mSnapToConstructionGuides->setChecked( false ); // do not snap on an existing construction guide vertex utils.mouseMove( 10.5, 14.5 ); QGSCOMPARENEARPOINT( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10.5, 14.5 ), 0.1 ); } QGSTEST_MAIN( TestQgsAdvancedDigitizing ) #include "testqgsadvanceddigitizing.moc"