Skip to content

Commit

Permalink
Resurrect display of interpolated z/m in identify results, and
Browse files Browse the repository at this point in the history
add closest point x/y (closest point on geometry)

Add tests

Fixes #19403

(cherry-picked from 3f9ea77)
  • Loading branch information
nyalldawson committed Aug 16, 2018
1 parent cef3b16 commit b58849f
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/gui/qgsmaptoolidentify.cpp
Expand Up @@ -374,6 +374,25 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo
}
}

void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geometry, const QgsPointXY &layerPoint, QMap<QString, QString> &derivedAttributes )
{
QgsPoint closestPoint = QgsGeometryUtils::closestPoint( geometry, QgsPoint( layerPoint.x(), layerPoint.y() ) );

derivedAttributes.insert( tr( "Closest X" ), formatXCoordinate( closestPoint ) );
derivedAttributes.insert( tr( "Closest Y" ), formatYCoordinate( closestPoint ) );

if ( closestPoint.is3D() )
{
const QString str = QLocale().toString( closestPoint.z(), 'g', 10 );
derivedAttributes.insert( tr( "Interpolated Z" ), str );
}
if ( closestPoint.isMeasure() )
{
const QString str = QLocale().toString( closestPoint.m(), 'g', 10 );
derivedAttributes.insert( tr( "Interpolated M" ), str );
}
}

QString QgsMapToolIdentify::formatCoordinate( const QgsPointXY &canvasPoint ) const
{
return QgsCoordinateUtils::formatCoordinateForProject( QgsProject::instance(), canvasPoint, mCanvas->mapSettings().destinationCrs(),
Expand Down Expand Up @@ -451,6 +470,7 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs
derivedAttributes.insert( tr( "Vertices" ), str );
//add details of closest vertex to identify point
closestVertexAttributes( *geom, vId, layer, derivedAttributes );
closestPointAttributes( *geom, layerPoint, derivedAttributes );

if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
{
Expand Down Expand Up @@ -498,6 +518,7 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs

//add details of closest vertex to identify point
closestVertexAttributes( *feature.geometry().constGet(), vId, layer, derivedAttributes );
closestPointAttributes( *feature.geometry().constGet(), layerPoint, derivedAttributes );
}
else if ( geometryType == QgsWkbTypes::PointGeometry )
{
Expand Down
5 changes: 5 additions & 0 deletions src/gui/qgsmaptoolidentify.h
Expand Up @@ -218,6 +218,11 @@ 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, 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;
Expand Down
59 changes: 59 additions & 0 deletions tests/src/app/testqgsmaptoolidentifyaction.cpp
Expand Up @@ -55,6 +55,7 @@ class TestQgsMapToolIdentifyAction : public QObject
void identifyRasterFloat64(); // test pixel identification and decimal precision
void identifyInvalidPolygons(); // test selecting invalid polygons
void clickxy(); // test if clicked_x and clicked_y variables are propagated
void closestPoint();

private:
void doAction();
Expand Down Expand Up @@ -209,6 +210,64 @@ void TestQgsMapToolIdentifyAction::clickxy()
mIdentifyAction->canvasReleaseEvent( &mapReleases );
}

void TestQgsMapToolIdentifyAction::closestPoint()
{
QgsSettings s;
s.setValue( QStringLiteral( "/qgis/measure/keepbaseunit" ), true );

//create a temporary layer
std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "LineStringZM?crs=epsg:3111&field=pk:int&field=col1:double" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
QVERIFY( tempLayer->isValid() );
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
f1.setAttribute( QStringLiteral( "pk" ), 1 );
f1.setAttribute( QStringLiteral( "col1" ), 0.0 );
QgsPolylineXY line3111;
line3111 << QgsPointXY( 2484588, 2425722 ) << QgsPointXY( 2482767, 2398853 );
QgsGeometry line3111G = QgsGeometry::fromWkt( QStringLiteral( "LineStringZM( 2484588 2425722 11 31, 2484588 2398853 15 37)" ) ) ;
f1.setGeometry( line3111G );
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );

// set project CRS and ellipsoid
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
canvas->setDestinationCrs( srs );
canvas->setExtent( f1.geometry().boundingBox() );
QgsProject::instance()->setCrs( srs );
QgsProject::instance()->setEllipsoid( QStringLiteral( "WGS84" ) );
QgsProject::instance()->setDistanceUnits( QgsUnitTypes::DistanceMeters );

QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 2484587, 2399800 );

std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) );

//check that closest point attributes are present
QList<QgsMapToolIdentify::IdentifyResult> result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer *>() << tempLayer.get() );
QCOMPARE( result.length(), 1 );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Closest X" )], QStringLiteral( "2484588" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Closest Y" )], QStringLiteral( "2399800" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Interpolated M" )].left( 4 ), QStringLiteral( "36.7" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Interpolated Z" )].left( 4 ), QStringLiteral( "14.8" ) );

// polygons
//create a temporary layer
std::unique_ptr< QgsVectorLayer> tempLayer2( new QgsVectorLayer( QStringLiteral( "PolygonZM?crs=epsg:3111&field=pk:int&field=col1:double" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
QVERIFY( tempLayer2->isValid() );
f1 = QgsFeature( tempLayer2->dataProvider()->fields(), 1 );
f1.setAttribute( QStringLiteral( "pk" ), 1 );
f1.setAttribute( QStringLiteral( "col1" ), 0.0 );

f1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PolygonZM((2484588 2425722 1 11, 2484588 2398853 2 12, 2520109 2397715 3 13, 2520792 2425494 4 14, 2484588 2425722 1 11))" ) ) );
QVERIFY( f1.hasGeometry() );
tempLayer2->dataProvider()->addFeatures( QgsFeatureList() << f1 );

mapPoint = canvas->getCoordinateTransform()->transform( 2484589, 2399800 );
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer *>() << tempLayer2.get() );
QCOMPARE( result.length(), 1 );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Closest X" )], QStringLiteral( "2484588" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Closest Y" )], QStringLiteral( "2399800" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Interpolated M" )].left( 4 ), QStringLiteral( "11.9" ) );
QCOMPARE( result.at( 0 ).mDerivedAttributes[tr( "Interpolated Z" )].left( 4 ), QStringLiteral( "1.96" ) );
}

void TestQgsMapToolIdentifyAction::lengthCalculation()
{
QgsSettings s;
Expand Down

0 comments on commit b58849f

Please sign in to comment.