Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
More generic closest point on line interpolation
  • Loading branch information
m-kuhn committed Jun 26, 2017
1 parent 75e5726 commit 13775c2
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 30 deletions.
8 changes: 5 additions & 3 deletions python/core/geometry/qgsgeometryutils.sip
Expand Up @@ -37,10 +37,12 @@ class QgsGeometryUtils
:rtype: QgsPoint
%End

static double closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt );
static QgsPoint closestPoint( const QgsAbstractGeometry &geometry, const QgsPoint &point );
%Docstring
Returns measure of nearest point on a geometry for a specified point or NaN if geometry does not have measures
:rtype: float
Returns the nearest point on a segment of a ``geometry``
for the specified ``point``. The z and m values will be linearly interpolated between
the two neighbouring vertices.
:rtype: QgsPoint
%End

static double distanceToVertex( const QgsAbstractGeometry &geom, QgsVertexId id );
Expand Down
44 changes: 21 additions & 23 deletions src/core/geometry/qgsgeometryutils.cpp
Expand Up @@ -93,33 +93,31 @@ QgsPoint QgsGeometryUtils::closestVertex( const QgsAbstractGeometry &geom, const
return minDistPoint;
}

double QgsGeometryUtils::closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt )
QgsPoint QgsGeometryUtils::closestPoint( const QgsAbstractGeometry &geometry, const QgsPoint &point )
{
if ( QgsWkbTypes::hasM( geom.wkbType() ) )
{
QgsPoint closestPoint;
QgsVertexId vertexAfter;
bool leftOf;
geom.closestSegment( pt, closestPoint, vertexAfter, &leftOf, DEFAULT_SEGMENT_EPSILON );
if ( vertexAfter.isValid() )
QgsPoint closestPoint;
QgsVertexId vertexAfter;
bool leftOf;
geometry.closestSegment( point, closestPoint, vertexAfter, &leftOf, DEFAULT_SEGMENT_EPSILON );
if ( vertexAfter.isValid() )
{
QgsPoint pointAfter = geometry.vertexAt( vertexAfter );
if ( vertexAfter.vertex > 0 )
{
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();
}
QgsVertexId vertexBefore = vertexAfter;
vertexBefore.vertex--;
QgsPoint pointBefore = geometry.vertexAt( vertexBefore );
double length = pointBefore.distance( pointAfter );
double distance = pointBefore.distance( closestPoint );

if ( QgsWkbTypes::hasZ( geometry.wkbType() ) )
closestPoint.addZValue( pointBefore.z() + ( pointAfter.z() - pointBefore.z() ) * distance / length );
if ( QgsWkbTypes::hasM( geometry.wkbType() ) )
closestPoint.addMValue( pointBefore.m() + ( pointAfter.m() - pointBefore.m() ) * distance / length );
}
}
return std::numeric_limits<double>::quiet_NaN();

return closestPoint;
}

double QgsGeometryUtils::distanceToVertex( const QgsAbstractGeometry &geom, QgsVertexId id )
Expand Down
7 changes: 5 additions & 2 deletions src/core/geometry/qgsgeometryutils.h
Expand Up @@ -44,9 +44,12 @@ 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
/**
* Returns the nearest point on a segment of a \a geometry
* for the specified \a point. The z and m values will be linearly interpolated between
* the two neighbouring vertices.
*/
static double closestPointMeasure( const QgsAbstractGeometry &geom, const QgsPoint &pt );
static QgsPoint closestPoint( const QgsAbstractGeometry &geometry, const QgsPoint &point );

/** Returns the distance along a geometry from its first vertex to the specified vertex.
* \param geom geometry
Expand Down
4 changes: 2 additions & 2 deletions src/gui/qgsmaptoolidentify.cpp
Expand Up @@ -332,8 +332,8 @@ void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geom
// measure
if ( QgsWkbTypes::hasM( geometry.wkbType() ) )
{
double measure = QgsGeometryUtils::closestPointMeasure( geometry, QgsPoint( layerPoint.x(), layerPoint.y() ) );
QString str = QLocale::system().toString( measure, 'g', 10 );
QgsPoint closestPoint = QgsGeometryUtils::closestPoint( geometry, QgsPoint( layerPoint.x(), layerPoint.y() ) );
QString str = QLocale::system().toString( closestPoint.m(), 'g', 10 );
derivedAttributes.insert( QStringLiteral( "Closest point M" ), str );
}
}
Expand Down

0 comments on commit 13775c2

Please sign in to comment.