From 6b8f8c0c09646c688c01dccce493545517ea3876 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 7 Oct 2020 15:34:27 +1000 Subject: [PATCH] [gps] When calculating rotation to apply to map canvas, use ellipsoidal calculations so that rotation is stable for different canvas CRS settings --- src/app/gps/qgsgpsinformationwidget.cpp | 28 ++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/app/gps/qgsgpsinformationwidget.cpp b/src/app/gps/qgsgpsinformationwidget.cpp index b27fdbef628a..30ee14d9df62 100644 --- a/src/app/gps/qgsgpsinformationwidget.cpp +++ b/src/app/gps/qgsgpsinformationwidget.cpp @@ -1037,7 +1037,33 @@ void QgsGpsInformationWidget::displayGPSInformation( const QgsGpsInformation &in if ( mRotateMapCheckBox->isChecked() && ( !mLastRotateTimer.isValid() || mLastRotateTimer.hasExpired( mSpinMapRotateInterval->value() * 1000 ) ) ) { - mMapCanvas->setRotation( trueNorth - bearing - adjustment ); + QgsCoordinateTransform wgs84ToCanvas( mWgs84CRS, mMapCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() ); + + try + { + QLineF bearingLine; + bearingLine.setP1( wgs84ToCanvas.transform( myNewCenter ).toQPointF() ); + + // project out the bearing line by roughly the size of the canvas + QgsDistanceArea da1; + da1.setSourceCrs( mMapCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() ); + da1.setEllipsoid( QgsProject::instance()->ellipsoid() ); + const double totalLength = da1.measureLine( mMapCanvas->mapSettings().extent().center(), QgsPointXY( mMapCanvas->mapSettings().extent().xMaximum(), + mMapCanvas->mapSettings().extent().yMaximum() ) ); + + QgsDistanceArea da; + da.setSourceCrs( mWgs84CRS, QgsProject::instance()->transformContext() ); + da.setEllipsoid( QgsProject::instance()->ellipsoid() ); + const QgsPointXY res = da.computeSpheroidProject( myNewCenter, totalLength, ( bearing - trueNorth + adjustment ) * M_PI / 180.0 ); + bearingLine.setP2( wgs84ToCanvas.transform( res ).toQPointF() ); + + mMapCanvas->setRotation( 270 - bearingLine.angle() ); + } + catch ( QgsCsException & ) + { + QgsDebugMsg( QStringLiteral( "Coordinate exception encountered while calculating GPS bearing rotation" ) ); + mMapCanvas->setRotation( trueNorth - bearing - adjustment ); + } mLastRotateTimer.restart(); }