Skip to content
Permalink
Browse files

Merge pull request #2729 from dgoedkoop/digitisecrs2

Fix floating point inaccuracies when digitizing (to fix bug #13745)
  • Loading branch information
wonder-sk committed Feb 12, 2016
2 parents a111889 + 384da56 commit 0c478d01488de546fcc3dd2d869a2b7081d49bda
@@ -78,6 +78,13 @@ class QgsMapMouseEvent : QMouseEvent
*/
QgsPoint mapPoint() const;

/**
* Returns the matching data from the most recently snapped point.
* @return the snapping data structure
* @note added in 2.14
*/
QgsPointLocator::Match mapPointMatch() const;

/**
* Set the (snapped) point this event points to in map coordinates.
* The point in pixel coordinates will be calculated accordingly.
@@ -112,10 +112,22 @@ class QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
*/
int nextPoint( QPoint p, QgsPointV2 &layerPoint, QgsPointV2 &mapPoint );

/** Fetches the original point from the source layer if it has the same
* CRS as the current layer.
* @return 0 in case of success, 1 if not applicable (CRS mismatch), 2 in case of failure
* @note added in 2.14 */
int fetchLayerPoint( QgsPointLocator::Match match, QgsPointV2& layerPoint );

/** Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
@return 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed*/
int addVertex( const QgsPoint& point );

/** Variant to supply more information in the case of snapping
@param mapPoint The vertex to add in map coordinates
@param match Data about the snapping match. Can be an invalid match, if point not snapped.
@note added in 2.14 */
int addVertex( const QgsPoint& mapPoint, QgsPointLocator::Match match );

/** Removes the last vertex from mRubberBand and mCaptureList*/
void undo();

@@ -113,7 +113,17 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e )
QgsPoint savePoint; //point in layer coordinates
try
{
savePoint = toLayerCoordinates( vlayer, e->mapPoint() );
QgsPointV2 fetchPoint;
int res;
res = fetchLayerPoint( e->mapPointMatch(), fetchPoint );
if ( res == 0 )
{
savePoint = QgsPoint( fetchPoint.x(), fetchPoint.y() );
}
else
{
savePoint = toLayerCoordinates( vlayer, e->mapPoint() );
}
QgsDebugMsg( "savePoint = " + savePoint.toString() );
}
catch ( QgsCsException &cse )
@@ -184,7 +194,7 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e )
//add point to list and to rubber band
if ( e->button() == Qt::LeftButton )
{
int error = addVertex( e->mapPoint() );
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
if ( error == 1 )
{
//current layer is not a vector layer
@@ -95,7 +95,7 @@ void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
//add point to list and to rubber band
if ( e->button() == Qt::LeftButton )
{
int error = addVertex( e->mapPoint() );
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
if ( error == 1 )
{
QgsDebugMsg( "current layer is not a vector layer" );
@@ -58,7 +58,7 @@ void QgsMapToolAddRing::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
//add point to list and to rubber band
if ( e->button() == Qt::LeftButton )
{
int error = addVertex( e->mapPoint() );
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
if ( error == 1 )
{
//current layer is not a vector layer
@@ -50,7 +50,7 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
//add point to list and to rubber band
if ( e->button() == Qt::LeftButton )
{
int error = addVertex( e->mapPoint() );
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
if ( error == 1 )
{
//current layer is not a vector layer
@@ -67,7 +67,7 @@ void QgsMapToolSplitFeatures::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
}
}

int error = addVertex( e->mapPoint() );
int error = addVertex( e->mapPoint(), e->mapPointMatch() );
if ( error == 1 )
{
//current layer is not a vector layer
@@ -93,6 +93,13 @@ class GUI_EXPORT QgsMapMouseEvent : public QMouseEvent
*/
inline QgsPoint mapPoint() const { return mMapPoint; }

/**
* Returns the matching data from the most recently snapped point.
* @return the snapping data structure
* @note added in 2.14
*/
QgsPointLocator::Match mapPointMatch() const { return mSnapMatch; }

/**
* Set the (snapped) point this event points to in map coordinates.
* The point in pixel coordinates will be calculated accordingly.
@@ -367,7 +367,41 @@ int QgsMapToolCapture::nextPoint( QPoint p, QgsPoint &layerPoint, QgsPoint &mapP
Q_NOWARN_DEPRECATED_POP
}

int QgsMapToolCapture::fetchLayerPoint( QgsPointLocator::Match match , QgsPointV2 &layerPoint )
{
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
QgsVectorLayer* sourceLayer = match.layer();
if ( match.isValid() && match.hasVertex() && sourceLayer &&
( sourceLayer->crs() == vlayer->crs() ) )
{
QgsFeature f;
QgsFeatureRequest request;
QgsPoint foundPoint;
request.setFilterFid( match.featureId() );
bool fetched = match.layer()->getFeatures( request ).nextFeature( f );
if ( fetched )
{
foundPoint = f.geometry()->vertexAt( match.vertexIndex() );
layerPoint = QgsPointV2( foundPoint.x(), foundPoint.y() );
return 0;
}
else
{
return 2;
}
}
else
{
return 1;
}
}

int QgsMapToolCapture::addVertex( const QgsPoint& point )
{
return addVertex( point, QgsPointLocator::Match() );
}

int QgsMapToolCapture::addVertex( const QgsPoint& point, QgsPointLocator::Match match )
{
if ( mode() == CaptureNone )
{
@@ -377,10 +411,14 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )

int res;
QgsPointV2 layerPoint;
res = nextPoint( QgsPointV2( point ), layerPoint );
res = fetchLayerPoint( match, layerPoint );
if ( res != 0 )
{
return res;
res = nextPoint( QgsPointV2( point ), layerPoint );
if ( res != 0 )
{
return res;
}
}

if ( !mRubberBand )
@@ -22,6 +22,7 @@
#include "qgspoint.h"
#include "qgsgeometry.h"
#include "qgslayertreeview.h"
#include "qgspointlocator.h"

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

/** Fetches the original point from the source layer if it has the same
* CRS as the current layer.
* @return 0 in case of success, 1 if not applicable (CRS mismatch), 2 in case of failure
* @note added in 2.14 */
int fetchLayerPoint( QgsPointLocator::Match match, QgsPointV2& layerPoint );

/** Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
@return 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed*/
int addVertex( const QgsPoint& point );

/** Variant to supply more information in the case of snapping
@param mapPoint The vertex to add in map coordinates
@param match Data about the snapping match. Can be an invalid match, if point not snapped.
@note added in 2.14 */
int addVertex( const QgsPoint& mapPoint, QgsPointLocator::Match match );

/** Removes the last vertex from mRubberBand and mCaptureList*/
void undo();

0 comments on commit 0c478d0

Please sign in to comment.
You can’t perform that action at this time.