Skip to content

Commit 384da56

Browse files
committed
Fix floating point inaccuracies when digitizing (to fix bug #13745)
1 parent c8161aa commit 384da56

10 files changed

+95
-8
lines changed

python/gui/qgsmapmouseevent.sip

+7
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ class QgsMapMouseEvent : QMouseEvent
7878
*/
7979
QgsPoint mapPoint() const;
8080

81+
/**
82+
* Returns the matching data from the most recently snapped point.
83+
* @return the snapping data structure
84+
* @note added in 2.14
85+
*/
86+
QgsPointLocator::Match mapPointMatch() const;
87+
8188
/**
8289
* Set the (snapped) point this event points to in map coordinates.
8390
* The point in pixel coordinates will be calculated accordingly.

python/gui/qgsmaptoolcapture.sip

+12
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,22 @@ class QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
112112
*/
113113
int nextPoint( QPoint p, QgsPointV2 &layerPoint, QgsPointV2 &mapPoint );
114114

115+
/** Fetches the original point from the source layer if it has the same
116+
* CRS as the current layer.
117+
* @return 0 in case of success, 1 if not applicable (CRS mismatch), 2 in case of failure
118+
* @note added in 2.14 */
119+
int fetchLayerPoint( QgsPointLocator::Match match, QgsPointV2& layerPoint );
120+
115121
/** Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
116122
@return 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed*/
117123
int addVertex( const QgsPoint& point );
118124

125+
/** Variant to supply more information in the case of snapping
126+
@param mapPoint The vertex to add in map coordinates
127+
@param match Data about the snapping match. Can be an invalid match, if point not snapped.
128+
@note added in 2.14 */
129+
int addVertex( const QgsPoint& mapPoint, QgsPointLocator::Match match );
130+
119131
/** Removes the last vertex from mRubberBand and mCaptureList*/
120132
void undo();
121133

src/app/qgsmaptooladdfeature.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,17 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e )
113113
QgsPoint savePoint; //point in layer coordinates
114114
try
115115
{
116-
savePoint = toLayerCoordinates( vlayer, e->mapPoint() );
116+
QgsPointV2 fetchPoint;
117+
int res;
118+
res = fetchLayerPoint( e->mapPointMatch(), fetchPoint );
119+
if ( res == 0 )
120+
{
121+
savePoint = QgsPoint( fetchPoint.x(), fetchPoint.y() );
122+
}
123+
else
124+
{
125+
savePoint = toLayerCoordinates( vlayer, e->mapPoint() );
126+
}
117127
QgsDebugMsg( "savePoint = " + savePoint.toString() );
118128
}
119129
catch ( QgsCsException &cse )
@@ -184,7 +194,7 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e )
184194
//add point to list and to rubber band
185195
if ( e->button() == Qt::LeftButton )
186196
{
187-
int error = addVertex( e->mapPoint() );
197+
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
188198
if ( error == 1 )
189199
{
190200
//current layer is not a vector layer

src/app/qgsmaptooladdpart.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
9595
//add point to list and to rubber band
9696
if ( e->button() == Qt::LeftButton )
9797
{
98-
int error = addVertex( e->mapPoint() );
98+
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
9999
if ( error == 1 )
100100
{
101101
QgsDebugMsg( "current layer is not a vector layer" );

src/app/qgsmaptooladdring.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void QgsMapToolAddRing::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
5858
//add point to list and to rubber band
5959
if ( e->button() == Qt::LeftButton )
6060
{
61-
int error = addVertex( e->mapPoint() );
61+
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
6262
if ( error == 1 )
6363
{
6464
//current layer is not a vector layer

src/app/qgsmaptoolreshape.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
5050
//add point to list and to rubber band
5151
if ( e->button() == Qt::LeftButton )
5252
{
53-
int error = addVertex( e->mapPoint() );
53+
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
5454
if ( error == 1 )
5555
{
5656
//current layer is not a vector layer

src/app/qgsmaptoolsplitfeatures.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void QgsMapToolSplitFeatures::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
6767
}
6868
}
6969

70-
int error = addVertex( e->mapPoint() );
70+
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
7171
if ( error == 1 )
7272
{
7373
//current layer is not a vector layer

src/gui/qgsmapmouseevent.h

+7
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ class GUI_EXPORT QgsMapMouseEvent : public QMouseEvent
9393
*/
9494
inline QgsPoint mapPoint() const { return mMapPoint; }
9595

96+
/**
97+
* Returns the matching data from the most recently snapped point.
98+
* @return the snapping data structure
99+
* @note added in 2.14
100+
*/
101+
QgsPointLocator::Match mapPointMatch() const { return mSnapMatch; }
102+
96103
/**
97104
* Set the (snapped) point this event points to in map coordinates.
98105
* The point in pixel coordinates will be calculated accordingly.

src/gui/qgsmaptoolcapture.cpp

+40-2
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,41 @@ int QgsMapToolCapture::nextPoint( QPoint p, QgsPoint &layerPoint, QgsPoint &mapP
367367
Q_NOWARN_DEPRECATED_POP
368368
}
369369

370+
int QgsMapToolCapture::fetchLayerPoint( QgsPointLocator::Match match , QgsPointV2 &layerPoint )
371+
{
372+
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
373+
QgsVectorLayer* sourceLayer = match.layer();
374+
if ( match.isValid() && match.hasVertex() && sourceLayer &&
375+
( sourceLayer->crs() == vlayer->crs() ) )
376+
{
377+
QgsFeature f;
378+
QgsFeatureRequest request;
379+
QgsPoint foundPoint;
380+
request.setFilterFid( match.featureId() );
381+
bool fetched = match.layer()->getFeatures( request ).nextFeature( f );
382+
if ( fetched )
383+
{
384+
foundPoint = f.geometry()->vertexAt( match.vertexIndex() );
385+
layerPoint = QgsPointV2( foundPoint.x(), foundPoint.y() );
386+
return 0;
387+
}
388+
else
389+
{
390+
return 2;
391+
}
392+
}
393+
else
394+
{
395+
return 1;
396+
}
397+
}
398+
370399
int QgsMapToolCapture::addVertex( const QgsPoint& point )
400+
{
401+
return addVertex( point, QgsPointLocator::Match() );
402+
}
403+
404+
int QgsMapToolCapture::addVertex( const QgsPoint& point, QgsPointLocator::Match match )
371405
{
372406
if ( mode() == CaptureNone )
373407
{
@@ -377,10 +411,14 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )
377411

378412
int res;
379413
QgsPointV2 layerPoint;
380-
res = nextPoint( QgsPointV2( point ), layerPoint );
414+
res = fetchLayerPoint( match, layerPoint );
381415
if ( res != 0 )
382416
{
383-
return res;
417+
res = nextPoint( QgsPointV2( point ), layerPoint );
418+
if ( res != 0 )
419+
{
420+
return res;
421+
}
384422
}
385423

386424
if ( !mRubberBand )

src/gui/qgsmaptoolcapture.h

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgspoint.h"
2323
#include "qgsgeometry.h"
2424
#include "qgslayertreeview.h"
25+
#include "qgspointlocator.h"
2526

2627
#include <QPoint>
2728
#include <QList>
@@ -132,10 +133,22 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
132133
*/
133134
int nextPoint( QPoint p, QgsPointV2 &layerPoint, QgsPointV2 &mapPoint );
134135

136+
/** Fetches the original point from the source layer if it has the same
137+
* CRS as the current layer.
138+
* @return 0 in case of success, 1 if not applicable (CRS mismatch), 2 in case of failure
139+
* @note added in 2.14 */
140+
int fetchLayerPoint( QgsPointLocator::Match match, QgsPointV2& layerPoint );
141+
135142
/** Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
136143
@return 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed*/
137144
int addVertex( const QgsPoint& point );
138145

146+
/** Variant to supply more information in the case of snapping
147+
@param mapPoint The vertex to add in map coordinates
148+
@param match Data about the snapping match. Can be an invalid match, if point not snapped.
149+
@note added in 2.14 */
150+
int addVertex( const QgsPoint& mapPoint, QgsPointLocator::Match match );
151+
139152
/** Removes the last vertex from mRubberBand and mCaptureList*/
140153
void undo();
141154

0 commit comments

Comments
 (0)