From 1bab9f72be535f7dca45cc54ba56f02d5c3de919 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 17 Jul 2024 16:07:25 +1000 Subject: [PATCH 1/3] Respect layer/project vert datum in identify results When a vector layer and the project have vertical datums present, and they differ, then include the transformed Z value for the identified features in the project's datum too. --- src/gui/qgsmaptoolidentify.cpp | 147 +++++++++++++++++++++++------- src/gui/qgsmaptoolidentify.h | 12 ++- tests/src/app/testqgsidentify.cpp | 102 +++++++++++++++++++++ 3 files changed, 224 insertions(+), 37 deletions(-) diff --git a/src/gui/qgsmaptoolidentify.cpp b/src/gui/qgsmaptoolidentify.cpp index f0a9b0c77cee..af4550bded32 100644 --- a/src/gui/qgsmaptoolidentify.cpp +++ b/src/gui/qgsmaptoolidentify.cpp @@ -54,6 +54,7 @@ #include "qgsrasterlayerelevationproperties.h" #include "qgssymbol.h" #include "qgsguiutils.h" +#include "qgsmessagelog.h" #include #include @@ -723,7 +724,11 @@ int QgsMapToolIdentify::identifyVectorLayer( QList *results, Qgs return featureCount; } -void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString > &derivedAttributes ) +void QgsMapToolIdentify::closestVertexAttributes( const QgsCoordinateTransform layerToMapTransform, + const QgsCoordinateReferenceSystem &layerVertCrs, + const QgsCoordinateReferenceSystem &mapVertCrs, + const QgsAbstractGeometry &geometry, QgsVertexId vId, + bool showTransformedZ, QMap< QString, QString > &derivedAttributes ) { if ( ! vId.isValid( ) ) { @@ -736,8 +741,18 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo derivedAttributes.insert( tr( "Closest vertex number" ), str ); QgsPoint closestPoint = geometry.vertexAt( vId ); - - QgsPoint closestPointMapCoords = mCanvas->mapSettings().layerToMapCoordinates( layer, closestPoint ); + QgsPoint closestPointMapCoords = closestPoint; + if ( layerToMapTransform.isValid() ) + { + try + { + closestPointMapCoords.transform( layerToMapTransform, Qgis::TransformDirection::Forward, layerToMapTransform.hasVerticalComponent() ); + } + catch ( QgsCsException &cse ) + { + QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) ); + } + } QString x; QString y; @@ -747,9 +762,16 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo if ( closestPoint.is3D() ) { - str = QLocale().toString( closestPointMapCoords.z(), 'g', 10 ); - derivedAttributes.insert( tr( "Closest vertex Z" ), str ); + str = QLocale().toString( closestPoint.z(), 'g', 10 ); + derivedAttributes.insert( showTransformedZ ? tr( "Closest vertex Z (%1)" ).arg( layerVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ) + : tr( "Closest vertex Z" ), str ); + } + if ( showTransformedZ && !std::isnan( closestPointMapCoords.z() ) && !qgsDoubleNear( closestPoint.z(), closestPointMapCoords.z() ) ) + { + const QString str = QLocale().toString( closestPointMapCoords.z(), 'g', 10 ); + derivedAttributes.insert( tr( "Closest vertex Z (%1)" ).arg( mapVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ), str ); } + if ( closestPoint.isMeasure() ) { str = QLocale().toString( closestPointMapCoords.m(), 'g', 10 ); @@ -769,9 +791,27 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo } } -void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geometry, const QgsPointXY &layerPoint, QMap &derivedAttributes ) +void QgsMapToolIdentify::closestPointAttributes( const QgsCoordinateTransform layerToMapTransform, + const QgsCoordinateReferenceSystem &layerVertCrs, + const QgsCoordinateReferenceSystem &mapVertCrs, + const QgsAbstractGeometry &geometry, + const QgsPointXY &layerPoint, + bool showTransformedZ, + QMap &derivedAttributes ) { QgsPoint closestPoint = QgsGeometryUtils::closestPoint( geometry, QgsPoint( layerPoint ) ); + QgsPoint closestPointMapCrs = closestPoint; + if ( layerToMapTransform.isValid() ) + { + try + { + closestPointMapCrs.transform( layerToMapTransform, Qgis::TransformDirection::Forward, layerToMapTransform.hasVerticalComponent() ); + } + catch ( QgsCsException &cse ) + { + QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) ); + } + } QString x; QString y; @@ -782,8 +822,15 @@ void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geom if ( closestPoint.is3D() ) { const QString str = QLocale().toString( closestPoint.z(), 'g', 10 ); - derivedAttributes.insert( tr( "Interpolated Z" ), str ); + derivedAttributes.insert( showTransformedZ ? tr( "Interpolated Z (%1)" ).arg( layerVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ) + : tr( "Interpolated Z" ), str ); + } + if ( showTransformedZ && !std::isnan( closestPointMapCrs.z() ) && !qgsDoubleNear( closestPoint.z(), closestPointMapCrs.z() ) ) + { + const QString str = QLocale().toString( closestPointMapCrs.z(), 'g', 10 ); + derivedAttributes.insert( tr( "Interpolated Z (%1)" ).arg( mapVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ), str ); } + if ( closestPoint.isMeasure() ) { const QString str = QLocale().toString( closestPoint.m(), 'g', 10 ); @@ -841,9 +888,30 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs Qgis::AreaUnit cartesianAreaUnits = QgsUnitTypes::unitType( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ) ) == QgsUnitTypes::unitType( displayAreaUnits() ) ? displayAreaUnits() : QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ); + const QgsCoordinateReferenceSystem mapVertCrs = QgsProject::instance()->crs3D().verticalCrs().isValid() ? QgsProject::instance()->crs3D().verticalCrs() + : QgsProject::instance()->crs3D(); + const QgsCoordinateReferenceSystem layerVertCrs = layer->crs3D().verticalCrs().isValid() ? layer->crs3D().verticalCrs() + : layer->crs3D(); + const bool showTransformedZ = QgsProject::instance()->crs3D() != layer->crs3D() && QgsProject::instance()->crs3D().hasVerticalAxis() && layer->crs3D().hasVerticalAxis(); + const QgsCoordinateTransform layerToMapTransform( layer->crs3D(), QgsProject::instance()->crs3D(), QgsProject::instance()->transformContext() ); + + const QgsGeometry layerCrsGeometry = feature.geometry(); + QgsGeometry mapCrsGeometry = layerCrsGeometry; + try + { + if ( layerToMapTransform.isValid() ) + { + mapCrsGeometry.transform( layerToMapTransform, Qgis::TransformDirection::Forward, layerToMapTransform.hasVerticalComponent() ); + } + } + catch ( QgsCsException &cse ) + { + QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) ); + } + if ( geometryType == Qgis::GeometryType::Line ) { - const QgsAbstractGeometry *geom = feature.geometry().constGet(); + const QgsAbstractGeometry *layerCrsGeom = layerCrsGeometry.constGet(); double dist = calc.measureLength( feature.geometry() ); dist = calc.convertLengthMeasurement( dist, displayDistanceUnits() ); @@ -854,15 +922,15 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs derivedAttributes.insert( tr( "Length (Ellipsoidal — %1)" ).arg( ellipsoid ), str ); } - str = formatDistance( geom->length() + str = formatDistance( layerCrsGeom->length() * QgsUnitTypes::fromUnitToUnitFactor( layer->crs().mapUnits(), cartesianDistanceUnits ), cartesianDistanceUnits ); - if ( QgsWkbTypes::hasZ( geom->wkbType() ) - && QgsWkbTypes::flatType( QgsWkbTypes::singleType( geom->wkbType() ) ) == Qgis::WkbType::LineString ) + if ( QgsWkbTypes::hasZ( layerCrsGeom->wkbType() ) + && QgsWkbTypes::flatType( QgsWkbTypes::singleType( layerCrsGeom->wkbType() ) ) == Qgis::WkbType::LineString ) { // 3d linestring (or multiline) derivedAttributes.insert( tr( "Length (Cartesian — 2D)" ), str ); - double totalLength3d = std::accumulate( geom->const_parts_begin(), geom->const_parts_end(), 0.0, []( double total, const QgsAbstractGeometry * part ) + double totalLength3d = std::accumulate( layerCrsGeom->const_parts_begin(), layerCrsGeom->const_parts_end(), 0.0, []( double total, const QgsAbstractGeometry * part ) { return total + qgsgeometry_cast< const QgsLineString * >( part )->length3D(); } ); @@ -875,16 +943,16 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs derivedAttributes.insert( tr( "Length (Cartesian)" ), str ); } - str = QLocale().toString( geom->nCoordinates() ); + str = QLocale().toString( layerCrsGeom->nCoordinates() ); derivedAttributes.insert( tr( "Vertices" ), str ); if ( !layerPoint.isEmpty() ) { //add details of closest vertex to identify point - closestVertexAttributes( *geom, vId, layer, derivedAttributes ); - closestPointAttributes( *geom, layerPoint, derivedAttributes ); + closestVertexAttributes( layerToMapTransform, layerVertCrs, mapVertCrs, *layerCrsGeom, vId, showTransformedZ, derivedAttributes ); + closestPointAttributes( layerToMapTransform, layerVertCrs, mapVertCrs, *layerCrsGeom, layerPoint, showTransformedZ, derivedAttributes ); } - if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) ) + if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( layerCrsGeom ) ) { // Add the start and end points in as derived attributes QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) ); @@ -901,7 +969,7 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs } else if ( geometryType == Qgis::GeometryType::Polygon ) { - double area = calc.measureArea( feature.geometry() ); + double area = calc.measureArea( layerCrsGeometry ); area = calc.convertAreaMeasurement( area, displayAreaUnits() ); QString str; if ( ellipsoid != geoNone() ) @@ -909,63 +977,72 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const Qgs str = formatArea( area ); derivedAttributes.insert( tr( "Area (Ellipsoidal — %1)" ).arg( ellipsoid ), str ); } - str = formatArea( feature.geometry().area() + str = formatArea( layerCrsGeometry.area() * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ), cartesianAreaUnits ), cartesianAreaUnits ); derivedAttributes.insert( tr( "Area (Cartesian)" ), str ); if ( ellipsoid != geoNone() ) { - double perimeter = calc.measurePerimeter( feature.geometry() ); + double perimeter = calc.measurePerimeter( layerCrsGeometry ); perimeter = calc.convertLengthMeasurement( perimeter, displayDistanceUnits() ); str = formatDistance( perimeter ); derivedAttributes.insert( tr( "Perimeter (Ellipsoidal — %1)" ).arg( ellipsoid ), str ); } - str = formatDistance( feature.geometry().constGet()->perimeter() + str = formatDistance( layerCrsGeometry.constGet()->perimeter() * QgsUnitTypes::fromUnitToUnitFactor( layer->crs().mapUnits(), cartesianDistanceUnits ), cartesianDistanceUnits ); derivedAttributes.insert( tr( "Perimeter (Cartesian)" ), str ); - str = QLocale().toString( feature.geometry().constGet()->nCoordinates() ); + str = QLocale().toString( layerCrsGeometry.constGet()->nCoordinates() ); derivedAttributes.insert( tr( "Vertices" ), str ); if ( !layerPoint.isEmpty() ) { //add details of closest vertex to identify point - closestVertexAttributes( *feature.geometry().constGet(), vId, layer, derivedAttributes ); - closestPointAttributes( *feature.geometry().constGet(), layerPoint, derivedAttributes ); + closestVertexAttributes( layerToMapTransform, layerVertCrs, mapVertCrs, *layerCrsGeometry.constGet(), vId, showTransformedZ, derivedAttributes ); + closestPointAttributes( layerToMapTransform, layerVertCrs, mapVertCrs, *layerCrsGeometry.constGet(), layerPoint, showTransformedZ, derivedAttributes ); } } else if ( geometryType == Qgis::GeometryType::Point ) { - if ( QgsWkbTypes::flatType( wkbType ) == Qgis::WkbType::Point ) + // Include the x, y, z coordinates of the point as a derived attribute + if ( const QgsPoint *mapCrsPoint = qgsgeometry_cast< const QgsPoint * >( mapCrsGeometry.constGet() ) ) { - // Include the x and y coordinates of the point as a derived attribute - QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature.geometry().asPoint() ); QString x; QString y; - formatCoordinate( pnt, x, y ); + formatCoordinate( QgsPointXY( mapCrsPoint->x(), mapCrsPoint->y() ), x, y ); derivedAttributes.insert( tr( "X" ), x ); derivedAttributes.insert( tr( "Y" ), y ); - if ( QgsWkbTypes::hasZ( wkbType ) ) + const double originalZ = QgsWkbTypes::hasZ( wkbType ) ? qgsgeometry_cast( layerCrsGeometry.constGet() )->z() + : std::numeric_limits< double >::quiet_NaN(); + const double mapCrsZ = mapCrsPoint->is3D() ? mapCrsPoint->z() : std::numeric_limits< double >::quiet_NaN(); + + if ( !std::isnan( originalZ ) ) { - const QString str = QLocale().toString( static_cast( feature.geometry().constGet() )->z(), 'g', 10 ); - derivedAttributes.insert( tr( "Z" ), str ); + const QString str = QLocale().toString( originalZ, 'g', 10 ); + derivedAttributes.insert( showTransformedZ ? tr( "Z (%1)" ).arg( layerVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ) + : tr( "Z" ), str ); } + if ( showTransformedZ && !std::isnan( mapCrsZ ) && !qgsDoubleNear( originalZ, mapCrsZ ) ) + { + const QString str = QLocale().toString( mapCrsZ, 'g', 10 ); + derivedAttributes.insert( tr( "Z (%1)" ).arg( mapVertCrs.userFriendlyIdentifier( Qgis::CrsIdentifierType::MediumString ) ), str ); + } + if ( QgsWkbTypes::hasM( wkbType ) ) { - const QString str = QLocale().toString( static_cast( feature.geometry().constGet() )->m(), 'g', 10 ); + const QString str = QLocale().toString( qgsgeometry_cast( layerCrsGeometry.constGet() )->m(), 'g', 10 ); derivedAttributes.insert( tr( "M" ), str ); } } else { - //multipart - + //multipoint if ( !layerPoint.isEmpty() ) { //add details of closest vertex to identify point - const QgsAbstractGeometry *geom = feature.geometry().constGet(); - closestVertexAttributes( *geom, vId, layer, derivedAttributes ); + const QgsAbstractGeometry *geom = layerCrsGeometry.constGet(); + closestVertexAttributes( layerToMapTransform, layerVertCrs, mapVertCrs, *geom, vId, showTransformedZ, derivedAttributes ); } } } diff --git a/src/gui/qgsmaptoolidentify.h b/src/gui/qgsmaptoolidentify.h index e785a5887164..c33a5035b84b 100644 --- a/src/gui/qgsmaptoolidentify.h +++ b/src/gui/qgsmaptoolidentify.h @@ -38,6 +38,7 @@ class QgsPointCloudLayer; class QgsPointCloudLayerElevationProperties; class QgsFeatureRenderer; class QgsExpressionContext; +class QgsCoordinateReferenceSystem; /** * \ingroup gui @@ -295,12 +296,19 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool /** * Adds details of the closest vertex to derived attributes */ - void closestVertexAttributes( const QgsAbstractGeometry &geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString > &derivedAttributes ); + void closestVertexAttributes( const QgsCoordinateTransform layerToMapTransform, + const QgsCoordinateReferenceSystem &layerVertCrs, + const QgsCoordinateReferenceSystem &mapVertCrs, + const QgsAbstractGeometry &geometry, QgsVertexId vId, + bool showTransformedZ, 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 ); + void closestPointAttributes( const QgsCoordinateTransform layerToMapTransform, + const QgsCoordinateReferenceSystem &layerVertCrs, + const QgsCoordinateReferenceSystem &mapVertCrs, + const QgsAbstractGeometry &geometry, const QgsPointXY &layerPoint, bool showTransformedZ, QMap< QString, QString > &derivedAttributes ); void formatCoordinate( const QgsPointXY &canvasPoint, QString &x, QString &y ) const; diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index 553add644800..59d39e0935b6 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -66,6 +66,9 @@ class TestQgsIdentify : public QObject void clickxy(); // test if click_x and click_y variables are propagated void closestPoint(); void testRelations(); + void testPointZ(); + void testLineStringZ(); + void testPolygonZ(); private: void doAction(); @@ -1167,6 +1170,105 @@ void TestQgsIdentify::testRelations() } } +void TestQgsIdentify::testPointZ() +{ + std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "PointZ?crs=epsg:4979" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) ); + QVERIFY( tempLayer->isValid() ); + QCOMPARE( tempLayer->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4979" ) ); + + QgsFeature f1( tempLayer->dataProvider()->fields(), 1 ); + f1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PointZ(134.445567853 -23.445567853 5543.325)" ) ) ); + tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 ); + + // set project CRS and ellipsoid + const QgsCoordinateReferenceSystem srs( QStringLiteral( "EPSG:4985" ) ); + QgsProject::instance()->setCrs( srs ); + canvas->setDestinationCrs( srs ); + QCOMPARE( QgsProject::instance()->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4985" ) ); + + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/Automatic" ), false ); + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DecimalPlaces" ), 3 ); + + const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 134.445567853, -23.445567853 ); + + std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); + QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QCOMPARE( result.length(), 1 ); + double z4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Z (EPSG:4979 - WGS 84)" )].toDouble(); + double z4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Z (EPSG:4985 - WGS 72)" )].toDouble(); + QGSCOMPARENEAR( z4979, 5543.325, 0.001 ); + QGSCOMPARENEAR( z4985, 5545.6857, 0.01 ); +} + +void TestQgsIdentify::testLineStringZ() +{ + std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=epsg:4979" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) ); + QVERIFY( tempLayer->isValid() ); + QCOMPARE( tempLayer->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4979" ) ); + + QgsFeature f1( tempLayer->dataProvider()->fields(), 1 ); + f1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineStringZ(134.445567853 -23.445567853 5543.325, 140.485567853 -23.445567853 5563.325)" ) ) ); + tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 ); + + // set project CRS and ellipsoid + const QgsCoordinateReferenceSystem srs( QStringLiteral( "EPSG:4985" ) ); + QgsProject::instance()->setCrs( srs ); + canvas->setDestinationCrs( srs ); + canvas->setExtent( tempLayer->extent() ); + QCOMPARE( QgsProject::instance()->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4985" ) ); + + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/Automatic" ), false ); + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DecimalPlaces" ), 3 ); + + const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 136.46, -23.445567853 ); + + std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); + QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QCOMPARE( result.length(), 1 ); + double interpolatedZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4979 - WGS 84)" )].toDouble(); + double interpolatedZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4985 - WGS 72)" )].toDouble(); + double closestZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4979 - WGS 84)" )].toDouble(); + double closestZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4985 - WGS 72)" )].toDouble(); + QGSCOMPARENEAR( interpolatedZ4979, 5548.472636, 0.001 ); + QGSCOMPARENEAR( interpolatedZ4985, 5550.8333350, 0.01 ); + QGSCOMPARENEAR( closestZ4979, 5543.325, 0.001 ); + QGSCOMPARENEAR( closestZ4985, 5545.6857, 0.01 ); +} + +void TestQgsIdentify::testPolygonZ() +{ + std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "PolygonZ?crs=epsg:4979" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) ); + QVERIFY( tempLayer->isValid() ); + QCOMPARE( tempLayer->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4979" ) ); + + QgsFeature f1( tempLayer->dataProvider()->fields(), 1 ); + f1.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PolygonZ((134.445567853 -23.445567853 5543.325, 140.485567853 -23.445567853 5563.325, 140.485567853 -20.445567853 5523.325, 134.445567853 -23.445567853 5543.325))" ) ) ); + tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 ); + + // set project CRS and ellipsoid + const QgsCoordinateReferenceSystem srs( QStringLiteral( "EPSG:4985" ) ); + QgsProject::instance()->setCrs( srs ); + canvas->setDestinationCrs( srs ); + canvas->setExtent( tempLayer->extent() ); + QCOMPARE( QgsProject::instance()->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:4985" ) ); + + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/Automatic" ), false ); + QgsProject::instance()->writeEntry( QStringLiteral( "PositionPrecision" ), QStringLiteral( "/DecimalPlaces" ), 3 ); + + const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 136.46, -23.445567853 ); + + std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); + QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QCOMPARE( result.length(), 1 ); + double interpolatedZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4979 - WGS 84)" )].toDouble(); + double interpolatedZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4985 - WGS 72)" )].toDouble(); + double closestZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4979 - WGS 84)" )].toDouble(); + double closestZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4985 - WGS 72)" )].toDouble(); + QGSCOMPARENEAR( interpolatedZ4979, 5549.9817600000, 0.001 ); + QGSCOMPARENEAR( interpolatedZ4985, 5552.3424580000, 0.01 ); + QGSCOMPARENEAR( closestZ4979, 5543.325, 0.001 ); + QGSCOMPARENEAR( closestZ4985, 5545.6857, 0.01 ); +} QGSTEST_MAIN( TestQgsIdentify ) #include "testqgsidentify.moc" From ca55c722afc0a9f0b9fe340af1f7b85a167eaa30 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 18 Jul 2024 11:20:43 +1000 Subject: [PATCH 2/3] Fix clang tidy warnings --- tests/src/app/testqgsidentify.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index 59d39e0935b6..11d7f7128e97 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -1192,7 +1192,7 @@ void TestQgsIdentify::testPointZ() const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 134.445567853, -23.445567853 ); std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); - QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QList result = action->identify( static_cast< int >( mapPoint.x() ), static_cast< int >( mapPoint.y() ), QList() << tempLayer.get() ); QCOMPARE( result.length(), 1 ); double z4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Z (EPSG:4979 - WGS 84)" )].toDouble(); double z4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Z (EPSG:4985 - WGS 72)" )].toDouble(); @@ -1223,7 +1223,7 @@ void TestQgsIdentify::testLineStringZ() const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 136.46, -23.445567853 ); std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); - QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QList result = action->identify( static_cast< int >( mapPoint.x() ), static_cast< int >( mapPoint.y() ), QList() << tempLayer.get() ); QCOMPARE( result.length(), 1 ); double interpolatedZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4979 - WGS 84)" )].toDouble(); double interpolatedZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4985 - WGS 72)" )].toDouble(); @@ -1258,7 +1258,7 @@ void TestQgsIdentify::testPolygonZ() const QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( 136.46, -23.445567853 ); std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) ); - QList result = action->identify( mapPoint.x(), mapPoint.y(), QList() << tempLayer.get() ); + QList result = action->identify( static_cast< int >( mapPoint.x() ), static_cast< int >( mapPoint.y() ), QList() << tempLayer.get() ); QCOMPARE( result.length(), 1 ); double interpolatedZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4979 - WGS 84)" )].toDouble(); double interpolatedZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4985 - WGS 72)" )].toDouble(); From 4522e7174ecc0d202899b14ee0799e977e40fbf9 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 18 Jul 2024 11:22:14 +1000 Subject: [PATCH 3/3] More test tolerance --- tests/src/app/testqgsidentify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index 11d7f7128e97..ffd748c9a112 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -1264,8 +1264,8 @@ void TestQgsIdentify::testPolygonZ() double interpolatedZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Interpolated Z (EPSG:4985 - WGS 72)" )].toDouble(); double closestZ4979 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4979 - WGS 84)" )].toDouble(); double closestZ4985 = result.at( 0 ).mDerivedAttributes[ QStringLiteral( "Closest vertex Z (EPSG:4985 - WGS 72)" )].toDouble(); - QGSCOMPARENEAR( interpolatedZ4979, 5549.9817600000, 0.001 ); - QGSCOMPARENEAR( interpolatedZ4985, 5552.3424580000, 0.01 ); + QGSCOMPARENEAR( interpolatedZ4979, 5549.9817600000, 0.02 ); + QGSCOMPARENEAR( interpolatedZ4985, 5552.3424580000, 0.02 ); QGSCOMPARENEAR( closestZ4979, 5543.325, 0.001 ); QGSCOMPARENEAR( closestZ4985, 5545.6857, 0.01 ); }