From 5c6e794b2d57e1ac38fa86e5adf13ebce59e07a5 Mon Sep 17 00:00:00 2001 From: Radim Blazek Date: Thu, 22 Jun 2017 15:31:21 +0200 Subject: [PATCH] nearest point measure in identify tool --- python/core/geometry/qgsgeometryutils.sip | 6 +++++ src/core/geometry/qgsgeometryutils.cpp | 29 +++++++++++++++++++++++ src/core/geometry/qgsgeometryutils.h | 4 ++++ src/gui/qgsmaptoolidentify.cpp | 13 ++++++++++ src/gui/qgsmaptoolidentify.h | 4 ++++ 5 files changed, 56 insertions(+) diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index c496cb930ca..2871a86ce84 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -37,6 +37,12 @@ class QgsGeometryUtils :rtype: QgsPoint %End + static double closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt ); +%Docstring + Returns measure of nearest point on a geometry for a specified point or NaN if geometry does not have measures + :rtype: float +%End + static double distanceToVertex( const QgsAbstractGeometry &geom, QgsVertexId id ); %Docstring Returns the distance along a geometry from its first vertex to the specified vertex. diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index e8c52e32f9d..da5e167ddd3 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -93,6 +93,35 @@ QgsPoint QgsGeometryUtils::closestVertex( const QgsAbstractGeometry &geom, const return minDistPoint; } +double QgsGeometryUtils::closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt ) +{ + if ( QgsWkbTypes::hasM( geom.wkbType() ) ) + { + QgsPoint closestPoint; + QgsVertexId vertexAfter; + bool leftOf; + geom.closestSegment( pt, closestPoint, vertexAfter, &leftOf, DEFAULT_SEGMENT_EPSILON ); + if ( vertexAfter.isValid() ) + { + QgsPoint pointAfter = geom.vertexAt( vertexAfter ); + if ( vertexAfter.vertex > 0 ) + { + QgsVertexId vertexBefore = vertexAfter; + vertexBefore.vertex--; + QgsPoint pointBefore = geom.vertexAt( vertexBefore ); + double length = pointBefore.distance( pointAfter ); + double distance = pointBefore.distance( closestPoint ); + return pointBefore.m() + ( pointAfter.m() - pointBefore.m() ) * distance / length; + } + else + { + return pointAfter.m(); + } + } + } + return std::numeric_limits::quiet_NaN(); +} + double QgsGeometryUtils::distanceToVertex( const QgsAbstractGeometry &geom, QgsVertexId id ) { double currentDist = 0; diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index b4b28376afe..c85a08a3712 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -44,6 +44,10 @@ class CORE_EXPORT QgsGeometryUtils */ static QgsPoint closestVertex( const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id SIP_OUT ); + /** Returns measure of nearest point on a geometry for a specified point or NaN if geometry does not have measures + */ + static double closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt ); + /** Returns the distance along a geometry from its first vertex to the specified vertex. * \param geom geometry * \param id vertex id to find distance to diff --git a/src/gui/qgsmaptoolidentify.cpp b/src/gui/qgsmaptoolidentify.cpp index 17d652f58eb..abb3d33cca4 100644 --- a/src/gui/qgsmaptoolidentify.cpp +++ b/src/gui/qgsmaptoolidentify.cpp @@ -326,6 +326,18 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo } } +void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geometry, QgsMapLayer *layer, const QgsPointXY &layerPoint, QMap< QString, QString > &derivedAttributes ) +{ + Q_UNUSED( layer ); + // measure + if ( QgsWkbTypes::hasM( geometry.wkbType() ) ) + { + double measure = QgsGeometryUtils::closestPointMeasure( geometry, QgsPoint( layerPoint.x(), layerPoint.y() ) ); + QString str = QLocale::system().toString( measure, 'g', 10 ); + derivedAttributes.insert( QStringLiteral( "Closest point M" ), str ); + } +} + QString QgsMapToolIdentify::formatCoordinate( const QgsPointXY &canvasPoint ) const { return QgsCoordinateUtils::formatCoordinateForProject( canvasPoint, mCanvas->mapSettings().destinationCrs(), @@ -392,6 +404,7 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur //add details of closest vertex to identify point closestVertexAttributes( *curve, vId, layer, derivedAttributes ); + closestPointAttributes( *curve, layer, layerPoint, derivedAttributes ); // Add the start and end points in as derived attributes QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) ); diff --git a/src/gui/qgsmaptoolidentify.h b/src/gui/qgsmaptoolidentify.h index 3cd27b69936..620d56cd149 100644 --- a/src/gui/qgsmaptoolidentify.h +++ b/src/gui/qgsmaptoolidentify.h @@ -183,6 +183,10 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool */ void closestVertexAttributes( const QgsAbstractGeometry &geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString > &derivedAttributes ); + /** Adds details of the closest point to derived attributes + */ + void closestPointAttributes( const QgsAbstractGeometry &geometry, QgsMapLayer *layer, const QgsPointXY &layerPoint, QMap< QString, QString > &derivedAttributes ); + QString formatCoordinate( const QgsPointXY &canvasPoint ) const; QString formatXCoordinate( const QgsPointXY &canvasPoint ) const; QString formatYCoordinate( const QgsPointXY &canvasPoint ) const;