Skip to content

Commit 0b1556d

Browse files
authored
Merge pull request #9618 from qgis/backport-9294-on-release-3_4
Backport #9294 on release-3_4: Fix Z snapping for point.
2 parents 3373838 + 1f4b81a commit 0b1556d

File tree

4 files changed

+202
-23
lines changed

4 files changed

+202
-23
lines changed

src/app/qgsmaptooldigitizefeature.cpp

+19-9
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,31 @@ void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
138138
return;
139139
}
140140

141-
QgsPointXY savePoint; //point in layer coordinates
141+
QgsPoint savePoint; //point in layer coordinates
142+
bool isMatchPointZ = false;
142143
try
143144
{
144145
QgsPoint fetchPoint;
145146
int res;
146147
res = fetchLayerPoint( e->mapPointMatch(), fetchPoint );
148+
if ( QgsWkbTypes::hasZ( fetchPoint.wkbType() ) )
149+
isMatchPointZ = true;
150+
147151
if ( res == 0 )
148152
{
149-
savePoint = QgsPointXY( fetchPoint.x(), fetchPoint.y() );
153+
if ( isMatchPointZ )
154+
savePoint = fetchPoint;
155+
else
156+
savePoint = QgsPoint( fetchPoint.x(), fetchPoint.y() );
150157
}
151158
else
152159
{
153-
savePoint = toLayerCoordinates( vlayer, e->mapPoint() );
160+
QgsPointXY layerPoint = toLayerCoordinates( vlayer, e->mapPoint() );
161+
if ( isMatchPointZ )
162+
savePoint = QgsPoint( QgsWkbTypes::PointZ, layerPoint.x(), layerPoint.y(), fetchPoint.z() );
163+
else
164+
savePoint = QgsPoint( layerPoint.x(), layerPoint.y() );
154165
}
155-
QgsDebugMsg( "savePoint = " + savePoint.toString() );
156166
}
157167
catch ( QgsCsException &cse )
158168
{
@@ -171,11 +181,11 @@ void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
171181
QgsGeometry g;
172182
if ( layerWKBType == QgsWkbTypes::Point )
173183
{
174-
g = QgsGeometry::fromPointXY( savePoint );
184+
g = QgsGeometry( qgis::make_unique<QgsPoint>( savePoint ) );
175185
}
176186
else if ( !QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) )
177187
{
178-
g = QgsGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) );
188+
g = QgsGeometry( qgis::make_unique<QgsPoint>( savePoint.x(), savePoint.y(), isMatchPointZ ? savePoint.z() : defaultZValue() ) );
179189
}
180190
else if ( QgsWkbTypes::isMultiType( layerWKBType ) && !QgsWkbTypes::hasZ( layerWKBType ) )
181191
{
@@ -184,13 +194,13 @@ void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
184194
else if ( QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) )
185195
{
186196
QgsMultiPoint *mp = new QgsMultiPoint();
187-
mp->addGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) );
188-
g = QgsGeometry( mp );
197+
mp->addGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), isMatchPointZ ? savePoint.z() : defaultZValue() ) );
198+
g.set( mp );
189199
}
190200
else
191201
{
192202
// if layer supports more types (mCheckGeometryType is false)
193-
g = QgsGeometry::fromPointXY( savePoint );
203+
g = QgsGeometry( qgis::make_unique<QgsPoint>( savePoint ) );
194204
}
195205

196206
if ( QgsWkbTypes::hasM( layerWKBType ) )

tests/src/app/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ ADD_QGIS_TEST(qgisappclipboard testqgisappclipboard.cpp)
9797
ADD_QGIS_TEST(attributetabletest testqgsattributetable.cpp)
9898
ADD_QGIS_TEST(applocatorfilters testqgsapplocatorfilters.cpp)
9999
ADD_QGIS_TEST(fieldcalculatortest testqgsfieldcalculator.cpp)
100-
ADD_QGIS_TEST(maptooladdfeature testqgsmaptooladdfeature.cpp)
100+
ADD_QGIS_TEST(maptooladdfeatureline testqgsmaptooladdfeatureline.cpp)
101+
ADD_QGIS_TEST(maptooladdfeaturepoint testqgsmaptooladdfeaturepoint.cpp)
101102
ADD_QGIS_TEST(maptoolidentifyaction testqgsmaptoolidentifyaction.cpp)
102103
ADD_QGIS_TEST(maptoolselect testqgsmaptoolselect.cpp)
103104
ADD_QGIS_TEST(maptoolreshape testqgsmaptoolreshape.cpp)

tests/src/app/testqgsmaptooladdfeature.cpp renamed to tests/src/app/testqgsmaptooladdfeatureline.cpp

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/***************************************************************************
2-
testqgsmaptooladdfeature.cpp
2+
testqgsmaptooladdfeatureline.cpp
33
----------------------
44
Date : October 2017
55
Copyright : (C) 2017 by Martin Dobias
@@ -53,11 +53,11 @@ namespace QTest
5353
* \ingroup UnitTests
5454
* This is a unit test for the vertex tool
5555
*/
56-
class TestQgsMapToolAddFeature : public QObject
56+
class TestQgsMapToolAddFeatureLine : public QObject
5757
{
5858
Q_OBJECT
5959
public:
60-
TestQgsMapToolAddFeature();
60+
TestQgsMapToolAddFeatureLine();
6161

6262
private slots:
6363
void initTestCase();// will be called before the first testfunction is executed.
@@ -81,11 +81,11 @@ class TestQgsMapToolAddFeature : public QObject
8181
QgsFeatureId mFidLineF1 = 0;
8282
};
8383

84-
TestQgsMapToolAddFeature::TestQgsMapToolAddFeature() = default;
84+
TestQgsMapToolAddFeatureLine::TestQgsMapToolAddFeatureLine() = default;
8585

8686

8787
//runs before all tests
88-
void TestQgsMapToolAddFeature::initTestCase()
88+
void TestQgsMapToolAddFeatureLine::initTestCase()
8989
{
9090
qDebug() << "TestMapToolCapture::initTestCase()";
9191
// init QGIS's paths - true means that all path will be inited from prefix
@@ -177,14 +177,14 @@ void TestQgsMapToolAddFeature::initTestCase()
177177
}
178178

179179
//runs after all tests
180-
void TestQgsMapToolAddFeature::cleanupTestCase()
180+
void TestQgsMapToolAddFeatureLine::cleanupTestCase()
181181
{
182182
delete mCaptureTool;
183183
delete mCanvas;
184184
QgsApplication::exitQgis();
185185
}
186186

187-
void TestQgsMapToolAddFeature::testNoTracing()
187+
void TestQgsMapToolAddFeatureLine::testNoTracing()
188188
{
189189
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
190190

@@ -205,7 +205,7 @@ void TestQgsMapToolAddFeature::testNoTracing()
205205
QCOMPARE( mLayerLine->undoStack()->index(), 1 );
206206
}
207207

208-
void TestQgsMapToolAddFeature::testTracing()
208+
void TestQgsMapToolAddFeatureLine::testTracing()
209209
{
210210
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
211211

@@ -250,7 +250,7 @@ void TestQgsMapToolAddFeature::testTracing()
250250
mEnableTracingAction->setChecked( false );
251251
}
252252

253-
void TestQgsMapToolAddFeature::testTracingWithOffset()
253+
void TestQgsMapToolAddFeatureLine::testTracingWithOffset()
254254
{
255255
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
256256

@@ -328,7 +328,7 @@ void TestQgsMapToolAddFeature::testTracingWithOffset()
328328
mEnableTracingAction->setChecked( false );
329329
}
330330

331-
void TestQgsMapToolAddFeature::testZ()
331+
void TestQgsMapToolAddFeatureLine::testZ()
332332
{
333333
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
334334

@@ -369,7 +369,7 @@ void TestQgsMapToolAddFeature::testZ()
369369
mCanvas->setCurrentLayer( mLayerLine );
370370
}
371371

372-
void TestQgsMapToolAddFeature::testZMSnapping()
372+
void TestQgsMapToolAddFeatureLine::testZMSnapping()
373373
{
374374
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
375375

@@ -397,5 +397,5 @@ void TestQgsMapToolAddFeature::testZMSnapping()
397397
mCanvas->snappingUtils()->setConfig( cfg );
398398
}
399399

400-
QGSTEST_MAIN( TestQgsMapToolAddFeature )
401-
#include "testqgsmaptooladdfeature.moc"
400+
QGSTEST_MAIN( TestQgsMapToolAddFeatureLine )
401+
#include "testqgsmaptooladdfeatureline.moc"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/***************************************************************************
2+
testqgsmaptooladdfeaturepoint.cpp
3+
----------------------
4+
Date : October 2017
5+
Copyright : (C) 2017 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgstest.h"
17+
18+
#include "qgisapp.h"
19+
#include "qgsadvanceddigitizingdockwidget.h"
20+
#include "qgsgeometry.h"
21+
#include "qgsmapcanvas.h"
22+
#include "qgsmapcanvassnappingutils.h"
23+
#include "qgssnappingconfig.h"
24+
#include "qgssnappingutils.h"
25+
#include "qgsmaptooladdfeature.h"
26+
#include "qgsmapcanvastracer.h"
27+
#include "qgsproject.h"
28+
#include "qgssettings.h"
29+
#include "qgsvectorlayer.h"
30+
#include "qgsmapmouseevent.h"
31+
#include "testqgsmaptoolutils.h"
32+
33+
34+
/**
35+
* \ingroup UnitTests
36+
* This is a unit test for the vertex tool
37+
*/
38+
class TestQgsMapToolAddFeaturePoint : public QObject
39+
{
40+
Q_OBJECT
41+
public:
42+
TestQgsMapToolAddFeaturePoint();
43+
44+
private slots:
45+
void initTestCase();// will be called before the first testfunction is executed.
46+
void cleanupTestCase();// will be called after the last testfunction was executed.
47+
48+
void testPointZ();
49+
50+
private:
51+
QgisApp *mQgisApp = nullptr;
52+
QgsMapCanvas *mCanvas = nullptr;
53+
QgsMapToolAddFeature *mCaptureTool = nullptr;
54+
QgsVectorLayer *mLayerPointZSnap = nullptr;
55+
QgsVectorLayer *mLayerPointZ = nullptr;
56+
};
57+
58+
TestQgsMapToolAddFeaturePoint::TestQgsMapToolAddFeaturePoint() = default;
59+
60+
61+
//runs before all tests
62+
void TestQgsMapToolAddFeaturePoint::initTestCase()
63+
{
64+
qDebug() << "TestMapToolCapture::initTestCase()";
65+
// init QGIS's paths - true means that all path will be inited from prefix
66+
QgsApplication::init();
67+
QgsApplication::initQgis();
68+
69+
// Set up the QSettings environment
70+
QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
71+
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
72+
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
73+
74+
mQgisApp = new QgisApp();
75+
76+
mCanvas = new QgsMapCanvas();
77+
78+
mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) );
79+
80+
mCanvas->setFrameStyle( QFrame::NoFrame );
81+
mCanvas->resize( 512, 512 );
82+
mCanvas->setExtent( QgsRectangle( 0, 0, 8, 8 ) );
83+
mCanvas->show(); // to make the canvas resize
84+
mCanvas->hide();
85+
86+
// make testing layers
87+
mLayerPointZ = new QgsVectorLayer( QStringLiteral( "PointZ?crs=EPSG:27700" ), QStringLiteral( "layer point Z" ), QStringLiteral( "memory" ) );
88+
QVERIFY( mLayerPointZ->isValid() );
89+
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerPointZ );
90+
91+
mLayerPointZ->startEditing();
92+
QgsFeature pointFZ;
93+
QString pointWktZ = "PointZ(7 7 4)";
94+
pointFZ.setGeometry( QgsGeometry::fromWkt( pointWktZ ) );
95+
96+
mLayerPointZ->addFeature( pointFZ );
97+
QCOMPARE( mLayerPointZ->featureCount(), ( long )1 );
98+
99+
// make layer for snapping
100+
mLayerPointZSnap = new QgsVectorLayer( QStringLiteral( "PointZ?crs=EPSG:27700" ), QStringLiteral( "Snap point" ), QStringLiteral( "memory" ) );
101+
QVERIFY( mLayerPointZSnap->isValid() );
102+
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerPointZSnap );
103+
104+
mLayerPointZSnap->startEditing();
105+
QgsFeature pointF;
106+
QString pointWktZSnap = "PointZ(6 6 3)";
107+
pointF.setGeometry( QgsGeometry::fromWkt( pointWktZSnap ) );
108+
109+
mLayerPointZSnap->addFeature( pointF );
110+
QCOMPARE( mLayerPointZSnap->featureCount(), ( long )1 );
111+
112+
QgsSnappingConfig cfg = mCanvas->snappingUtils()->config();
113+
cfg.setMode( QgsSnappingConfig::AllLayers );
114+
cfg.setTolerance( 100 );
115+
cfg.setType( QgsSnappingConfig::VertexAndSegment );
116+
cfg.setEnabled( true );
117+
mCanvas->snappingUtils()->setConfig( cfg );
118+
119+
mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerPointZ << mLayerPointZSnap );
120+
mCanvas->setCurrentLayer( mLayerPointZ );
121+
122+
// create the tool
123+
mCaptureTool = new QgsMapToolAddFeature( mCanvas, /*mAdvancedDigitizingDockWidget, */ QgsMapToolCapture::CapturePoint );
124+
mCanvas->setMapTool( mCaptureTool );
125+
126+
QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) );
127+
QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) );
128+
}
129+
130+
//runs after all tests
131+
void TestQgsMapToolAddFeaturePoint::cleanupTestCase()
132+
{
133+
delete mCaptureTool;
134+
delete mCanvas;
135+
QgsApplication::exitQgis();
136+
}
137+
138+
void TestQgsMapToolAddFeaturePoint::testPointZ()
139+
{
140+
TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool );
141+
142+
// test with default Z value = 333
143+
QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 );
144+
145+
QSet<QgsFeatureId> oldFids = utils.existingFeatureIds();
146+
147+
utils.mouseClick( 4, 0, Qt::LeftButton, Qt::KeyboardModifiers(), true );
148+
QgsFeatureId newFid = utils.newFeatureId( oldFids );
149+
150+
QCOMPARE( mLayerPointZ->featureCount(), ( long )2 );
151+
152+
QString wkt = "PointZ (4 0 333)";
153+
QCOMPARE( mLayerPointZ->getFeature( newFid ).geometry().asWkt(), wkt );
154+
155+
mLayerPointZ->undoStack()->undo();
156+
157+
oldFids = utils.existingFeatureIds();
158+
utils.mouseClick( 6, 6, Qt::LeftButton, Qt::KeyboardModifiers(), true );
159+
newFid = utils.newFeatureId( oldFids );
160+
161+
wkt = "PointZ (6 6 3)";
162+
QCOMPARE( mLayerPointZ->getFeature( newFid ).geometry().asWkt(), wkt );
163+
164+
mLayerPointZ->undoStack()->undo();
165+
}
166+
167+
QGSTEST_MAIN( TestQgsMapToolAddFeaturePoint )
168+
#include "testqgsmaptooladdfeaturepoint.moc"

0 commit comments

Comments
 (0)