Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ file(
PATTERN "*.cmake" EXCLUDE
PATTERN "vcpkg*" EXCLUDE
)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/app/assets/us_nga_egm96_15.tif
DESTINATION ${ASSETS_DIR_PATH}/app/android/assets/qgis-data/proj
)
# ########################################################################################
# SUBDIRECTORIES
# ########################################################################################
Expand Down
Binary file added app/assets/us_nga_egm96_15.tif
Binary file not shown.
25 changes: 11 additions & 14 deletions app/inpututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ QString InputUtils::geometryLengthAsString( const QgsGeometry &geometry )
{
QgsDistanceArea distanceArea;
distanceArea.setEllipsoid( QStringLiteral( "WGS84" ) );
distanceArea.setSourceCrs( QgsCoordinateReferenceSystem::fromEpsgId( 4326 ), QgsCoordinateTransformContext() );
distanceArea.setSourceCrs( PositionKit::positionCrs2D(), QgsCoordinateTransformContext() );

qreal length = distanceArea.measureLength( geometry );

Expand Down Expand Up @@ -879,32 +879,30 @@ QgsPoint InputUtils::transformPoint( const QgsCoordinateReferenceSystem &srcCrs,
// QGIS would convert them to a valid (0, 0) points
if ( srcPoint.isEmpty() )
{
return QgsPoint();
return {};
}

try
{
QgsCoordinateTransform ct( srcCrs, destCrs, context );
const QgsCoordinateTransform ct( srcCrs, destCrs, context );
if ( ct.isValid() )
{
if ( !ct.isShortCircuited() )
{
const QgsPointXY transformed = ct.transform( srcPoint.x(), srcPoint.y() );
const QgsPoint pt( transformed.x(), transformed.y(), srcPoint.z(), srcPoint.m() );
const QgsVector3D transformed = ct.transform( QgsVector3D( srcPoint.x(), srcPoint.y(), srcPoint.z() ) );
const QgsPoint pt( transformed.x(), transformed.y(), transformed.z(), srcPoint.m() );
return pt;
}
else
{
return srcPoint;
}

return srcPoint;
}
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse )
}

return QgsPoint();
return {};
}

QPointF InputUtils::transformPointToScreenCoordinates( const QgsCoordinateReferenceSystem &srcCrs, InputMapSettings *mapSettings, const QgsPoint &srcPoint )
Expand Down Expand Up @@ -953,11 +951,10 @@ QgsPoint InputUtils::mapPointToGps( QPointF mapPosition, InputMapSettings *mapSe
return QgsPoint();

QgsPoint positionMapCrs = mapSettings->screenToCoordinate( mapPosition );
QgsCoordinateReferenceSystem crsGPS = coordinateReferenceSystemFromEpsgId( 4326 );

const QgsPointXY transformedXY = transformPoint(
mapSettings->destinationCrs(),
crsGPS,
PositionKit::positionCrs2D(),
QgsCoordinateTransformContext(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not directly relevant to this PR, but we should not use empty QgsCoordinateTransformContext() - we should use coordinate transform context from the active project everywhere, to avoid some subtle transformation errors (e.g. when project admin picks a non-default transform). Worth checking elsewhere too!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is worth to do as a separate PR and go through the whole code base. I'll create a new issue for this and try to tackle it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #4221

positionMapCrs
);
Expand Down Expand Up @@ -1715,7 +1712,7 @@ qreal InputUtils::distanceBetweenGpsAndFeature( QgsPoint gpsPosition, const Feat

// Transform gps position to map CRS
QgsPointXY transformedPosition = transformPoint(
coordinateReferenceSystemFromEpsgId( 4326 ),
PositionKit::positionCrs3D(),
mapSettings->destinationCrs(),
mapSettings->transformContext(),
gpsPosition
Expand Down Expand Up @@ -1763,7 +1760,7 @@ qreal InputUtils::angleBetweenGpsAndFeature( QgsPoint gpsPoint, const FeatureLay

// Transform gps position to map CRS
QgsPointXY transformedPosition = transformPoint(
coordinateReferenceSystemFromEpsgId( 4326 ),
PositionKit::positionCrs3D(),
mapSettings->destinationCrs(),
mapSettings->transformContext(),
gpsPoint
Expand Down
13 changes: 6 additions & 7 deletions app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,13 @@ int main( int argc, char *argv[] )
LayerDetailLegendImageProvider *layerDetailLegendImageProvider( new LayerDetailLegendImageProvider );

// build position kit, save active provider to QSettings and load previously active provider
PositionKit pk;
QObject::connect( &pk, &PositionKit::positionProviderChanged, as, [as]( AbstractPositionProvider * provider )
PositionKit *pk = engine.singletonInstance<PositionKit *>( "MMInput", "PositionKit" );
QObject::connect( pk, &PositionKit::positionProviderChanged, as, [as]( AbstractPositionProvider * provider )
{
as->setActivePositionProviderId( provider ? provider->id() : QLatin1String() );
} );
pk.setPositionProvider( pk.constructActiveProvider( as ) );
pk.setAppSettings( as );
pk->setPositionProvider( PositionKit::constructActiveProvider( as ) );
pk->setAppSettings( as );

// Lambda context object can be used in all lambda functions defined here,
// it secures lambdas, so that they are destroyed when this object is destroyed to avoid crashes.
Expand Down Expand Up @@ -648,7 +648,7 @@ int main( int argc, char *argv[] )
notificationModel.addError( message );
} );
// Direct connections
QObject::connect( &app, &QGuiApplication::applicationStateChanged, &pk, &PositionKit::appStateChanged );
QObject::connect( &app, &QGuiApplication::applicationStateChanged, pk, &PositionKit::appStateChanged );
QObject::connect( &pw, &ProjectWizard::projectCreated, &localProjectsManager, &LocalProjectsManager::addLocalProject );
QObject::connect( &activeProject, &ActiveProject::projectReloaded, vm.get(), &VariablesManager::merginProjectChanged );
QObject::connect( &activeProject, &ActiveProject::projectWillBeReloaded, &inputProjUtils, &InputProjUtils::resetHandlers );
Expand Down Expand Up @@ -679,7 +679,7 @@ int main( int argc, char *argv[] )
if ( tests.testingRequested() )
{
tests.initTestDeclarative();
tests.init( ma.get(), &iu, vm.get(), &pk, as );
tests.init( ma.get(), &iu, vm.get(), pk, as );
return tests.runTest();
}
#endif
Expand Down Expand Up @@ -722,7 +722,6 @@ int main( int argc, char *argv[] )
engine.rootContext()->setContextProperty( "__projectWizard", &pw );
engine.rootContext()->setContextProperty( "__localProjectsManager", &localProjectsManager );
engine.rootContext()->setContextProperty( "__variablesManager", vm.get() );
engine.rootContext()->setContextProperty( "__positionKit", &pk );

// add image provider to pass QIcons/QImages from C++ to QML
engine.rootContext()->setContextProperty( "__layerTreeModelPixmapProvider", layerTreeModelPixmapProvider );
Expand Down
4 changes: 3 additions & 1 deletion app/map/inputcoordinatetransformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
*/

#include "inputcoordinatetransformer.h"

#include "positionkit.h"
#include "qgslogger.h"

InputCoordinateTransformer::InputCoordinateTransformer( QObject *parent )
: QObject( parent )
{
mCoordinateTransform.setSourceCrs( QgsCoordinateReferenceSystem::fromEpsgId( 4326 ) );
mCoordinateTransform.setSourceCrs( PositionKit::positionCrs3D() );
}

QgsPoint InputCoordinateTransformer::projectedPosition() const
Expand Down
4 changes: 2 additions & 2 deletions app/maptools/recordingmaptool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void RecordingMapTool::addPoint( const QgsPoint &point )
pointToAdd = mPositionKit->positionCoordinate();

QgsPoint transformed = InputUtils::transformPoint(
PositionKit::positionCRS(),
PositionKit::positionCrs3D(),
mActiveLayer->crs(),
mActiveLayer->transformContext(),
pointToAdd
Expand Down Expand Up @@ -594,7 +594,7 @@ void RecordingMapTool::onPositionChanged()
QgsPoint position = mPositionKit->positionCoordinate();

QgsPointXY transformed = InputUtils::transformPoint(
PositionKit::positionCRS(),
PositionKit::positionCrs3D(),
mActiveLayer->sourceCrs(),
mActiveLayer->transformContext(),
position
Expand Down
2 changes: 1 addition & 1 deletion app/position/mapposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void MapPosition::recalculateMapPosition()
{
QgsPointXY srcPoint = QgsPointXY( geoposition.x(), geoposition.y() );
QgsPointXY mapPositionXY = InputUtils::transformPointXY(
mPositionKit->positionCRS(),
mPositionKit->positionCrs3D(),
mMapSettings->destinationCrs(),
mMapSettings->transformContext(),
srcPoint
Expand Down
12 changes: 11 additions & 1 deletion app/position/positionkit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,21 @@ PositionKit::PositionKit( QObject *parent )
{
}

QgsCoordinateReferenceSystem PositionKit::positionCRS()
QgsCoordinateReferenceSystem PositionKit::positionCrs3D()
{
return QgsCoordinateReferenceSystem::fromEpsgId( 9707 );
}

QgsCoordinateReferenceSystem PositionKit::positionCrs2D()
{
return QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
}

QgsCoordinateReferenceSystem PositionKit::positionCrs3DEllipsoidHeight()
{
return QgsCoordinateReferenceSystem::fromEpsgId( 4979 );
}

void PositionKit::startUpdates()
{
if ( mPositionProvider )
Expand Down
11 changes: 9 additions & 2 deletions app/position/positionkit.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "qgspoint.h"
#include "qgscoordinatereferencesystem.h"
#include <QObject>
#include <QtQml/qqmlregistration.h>

class AppSettings;

Expand All @@ -27,6 +28,8 @@ class AppSettings;
class PositionKit : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON

Q_PROPERTY( double latitude READ latitude NOTIFY latitudeChanged )
Q_PROPERTY( double longitude READ longitude NOTIFY longitudeChanged )
Expand Down Expand Up @@ -112,8 +115,12 @@ class PositionKit : public QObject
double vdop() const;
double pdop() const;

// Coordinate reference system of position - WGS84 (constant)
Q_INVOKABLE static QgsCoordinateReferenceSystem positionCRS();
// Coordinate reference system - WGS84 (EPSG:4326)
static QgsCoordinateReferenceSystem positionCrs2D();
// Coordinate reference system - WGS84 + ellipsoid height (EPSG:4979)
static QgsCoordinateReferenceSystem positionCrs3DEllipsoidHeight();
// Coordinate reference system of position - WGS84 + geoid height - egm96_15 (EPSG:9707)
static QgsCoordinateReferenceSystem positionCrs3D();

Q_INVOKABLE static AbstractPositionProvider *constructProvider( const QString &type, const QString &id, const QString &name = QString() );
Q_INVOKABLE static AbstractPositionProvider *constructActiveProvider( AppSettings *appsettings );
Expand Down
17 changes: 11 additions & 6 deletions app/position/providers/androidpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include <QTimeZone>

#include "inpututils.h"


int AndroidPositionProvider::sLastInstanceId = 0;
QMap<int, AndroidPositionProvider *> AndroidPositionProvider::sInstances;
Expand Down Expand Up @@ -53,14 +55,17 @@ void jniOnPositionUpdated( JNIEnv *env, jclass clazz, jint instanceId, jobject l
{
const jdouble value = location.callMethod<jdouble>( "getAltitude" );
if ( !qFuzzyIsNull( value ) )
pos.elevation = value;
{
// transform the altitude from EPSG:4979 (WGS84 (EPSG:4326) + ellipsoidal height) to specified geoid model
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsCoordinateTransformContext(),
{longitude, latitude, value} );
pos.elevation = geoidPosition.z();
}
}

// TODO: we are getting ellipsoid elevation here. From API level 34 (Android 14),
// there is AltitudeConverter() class in Java that can be used to add MSL altitude
// to Location object. How to deal with this correctly? (we could also convert
// to MSL (orthometric) altitude ourselves if we add geoid model to our APK

// horizontal accuracy
if ( location.callMethod<jboolean>( "hasAccuracy" ) )
{
Expand Down
11 changes: 9 additions & 2 deletions app/position/providers/internalpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "internalpositionprovider.h"
#include "coreutils.h"
#include "inpututils.h"

#include "qgis.h"

Expand Down Expand Up @@ -140,9 +141,15 @@ void InternalPositionProvider::parsePositionUpdate( const QGeoPositionInfo &posi
positionDataHasChanged = true;
}

if ( !qgsDoubleNear( position.coordinate().altitude(), mLastPosition.elevation ) )
// transform the altitude from EPSG:4979 (WGS84 (EPSG:4326) + ellipsoidal height) to specified geoid model
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsProject::instance()->transformContext(),
{position.coordinate().longitude(), position.coordinate().latitude(), position.coordinate().altitude()} );
if ( !qgsDoubleNear( geoidPosition.z(), mLastPosition.elevation ) )
{
mLastPosition.elevation = position.coordinate().altitude();
mLastPosition.elevation = geoidPosition.z();
positionDataHasChanged = true;
}

Expand Down
4 changes: 2 additions & 2 deletions app/position/tracking/positiontrackingmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void PositionTrackingManager::commitTrackedPath()
}

// convert captured geometry to the destination layer's CRS
QgsGeometry geometryInLayerCRS = InputUtils::transformGeometry( mTrackedGeometry, QgsCoordinateReferenceSystem::fromEpsgId( 4326 ), trackingLayer );
QgsGeometry geometryInLayerCRS = InputUtils::transformGeometry( mTrackedGeometry, PositionKit::positionCrs3D(), trackingLayer );

// create feature - add tracking variables to scope
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QStringLiteral( "MM_Tracking" ) );
Expand Down Expand Up @@ -332,7 +332,7 @@ void PositionTrackingManager::setVariablesManager( VariablesManager *newVariable

QgsCoordinateReferenceSystem PositionTrackingManager::crs() const
{
return QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
return PositionKit::positionCrs3D();
}

void PositionTrackingManager::tryAgain()
Expand Down
5 changes: 3 additions & 2 deletions app/qml/gps/MMBluetoothConnectionDrawer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import QtQuick.Controls
import QtQuick.Layouts

import mm 1.0 as MM
import MMInput

import "../components" as MMComponents

MMComponents.MMDrawer {
id: root

property var positionProvider: __positionKit.positionProvider
property var positionProvider: PositionKit.positionProvider
property string howToConnectGPSLink: __inputHelp.howToConnectGPSLink

property string titleText: {
Expand Down Expand Up @@ -52,7 +53,7 @@ MMComponents.MMDrawer {
}
else if ( rootstate.state === "waitingToReconnect" )
{
return __positionKit.positionProvider.stateMessage + "<br><br>" +
return PositionKit.positionProvider.stateMessage + "<br><br>" +
qsTr( "You can close this message, we will try to repeatedly connect to your device." )
}

Expand Down
Loading
Loading