[feature ] Add PositionKit, PositionMarker and other related classes to QgsQuick.

For background information see the associated QEP (https://github.com/qgis/QGIS-Enhancement-Proposals/issues/109
This commit is contained in:
viktor.sklencar@lutraconsulting.co.uk 2018-05-16 11:01:00 +02:00 committed by Peter Petrik
parent 7acfe037c4
commit 5f07851a2d
21 changed files with 1343 additions and 9 deletions

View File

@ -13,7 +13,9 @@ QGIS Quick consists of a Qt plugin that provides the QML components and of a sha
\subsection qgsquick_overview_widgets QML Classes
\subsubsection qgsquick_overview_widgets_mapcanvas MapCanvas
Similarly to QgsMapCanvas, this component can be used for displaying GIS data on a canvas. See also QgsQuickMapCanvasMap.
\subsubsection qgsquick_overview_widgets_positionmarker PositionMarker
The element refers to current position according gps location device connected to it. It holds information about longitude, latitude, altitude,
direction of the movement and accuracy of the signal. See also QgsQuickPostionKit.
\subsubsection qgsquick_overview_widgets_scalebar ScaleBar
A QML component that shows the scale ratio between its length and distance on the MapCanvas. There are predefined rounded values
for several zooming levels with 'm' or 'km' postfixes. After any zoom in/out event on canvas recalculates its properties and updates

View File

@ -2,13 +2,16 @@
# sources
SET(QGIS_QUICK_GUI_MOC_HDRS
qgsquickfeaturelayerpair.h
qgsquickcoordinatetransformer.h
qgsquickfeaturehighlight.h
qgsquickidentifykit.h
qgsquickmapcanvasmap.h
qgsquickmapsettings.h
qgsquickmaptransform.h
qgsquickmessagelogmodel.h
qgsquickpositionkit.h
qgsquickscalebarkit.h
qgsquicksimulatedpositionsource.h
qgsquickutils.h
)
@ -18,6 +21,7 @@ SET(QGIS_QUICK_GUI_HDRS
SET(QGIS_QUICK_GUI_SRC
qgsquickfeaturelayerpair.cpp
qgsquickcoordinatetransformer.cpp
qgsquickfeaturehighlight.cpp
qgsquickhighlightsgnode.cpp
qgsquickidentifykit.cpp
@ -25,7 +29,9 @@ SET(QGIS_QUICK_GUI_SRC
qgsquickmapsettings.cpp
qgsquickmaptransform.cpp
qgsquickmessagelogmodel.cpp
qgsquickpositionkit.cpp
qgsquickscalebarkit.cpp
qgsquicksimulatedpositionsource.cpp
qgsquickutils.cpp
)
@ -69,6 +75,10 @@ INCLUDE_DIRECTORIES(SYSTEM
ADD_DEFINITIONS(-DCORE_EXPORT=)
SET(QGIS_QUICK_GUI_IMAGE_RCCS ./images/images.qrc)
QT5_ADD_RESOURCES(QGIS_QUICK_GUI_IMAGE_RCC_SRCS ${QGIS_QUICK_GUI_IMAGE_RCCS})
############################################################
# qgis_quick shared library
QT5_WRAP_CPP(QGIS_QUICK_GUI_MOC_SRCS ${QGIS_QUICK_GUI_MOC_HDRS})

View File

@ -0,0 +1,4 @@
<svg fill="#000000" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"/>
</svg>

After

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>ic_navigation_black.svg</file>
</qresource>
</RCC>

View File

@ -12,6 +12,7 @@ SET(QGIS_QUICK_PLUGIN_SRC
SET(QGIS_QUICK_PLUGIN_RESOURCES
qgsquickmapcanvas.qml
qgsquickmessagelog.qml
qgsquickpositionmarker.qml
qgsquickscalebar.qml
qmldir
)

View File

@ -30,6 +30,7 @@
#include "qgsvectorlayer.h"
#include "qgsquickfeaturehighlight.h"
#include "qgsquickcoordinatetransformer.h"
#include "qgsquickidentifykit.h"
#include "qgsquickfeaturelayerpair.h"
#include "qgsquickmapcanvasmap.h"
@ -37,6 +38,7 @@
#include "qgsquickmaptransform.h"
#include "qgsquickmessagelogmodel.h"
#include "qgsquickplugin.h"
#include "qgsquickpositionkit.h"
#include "qgsquickscalebarkit.h"
#include "qgsquickutils.h"
@ -61,11 +63,13 @@ void QgsQuickPlugin::registerTypes( const char *uri )
qmlRegisterType< QgsProject >( uri, 0, 1, "Project" );
qmlRegisterType< QgsQuickFeatureHighlight >( uri, 0, 1, "FeatureHighlight" );
qmlRegisterType< QgsQuickCoordinateTransformer >( uri, 0, 1, "CoordinateTransformer" );
qmlRegisterType< QgsQuickIdentifyKit >( uri, 0, 1, "IdentifyKit" );
qmlRegisterType< QgsQuickMapCanvasMap >( uri, 0, 1, "MapCanvasMap" );
qmlRegisterType< QgsQuickMapSettings >( uri, 0, 1, "MapSettings" );
qmlRegisterType< QgsQuickMapTransform >( uri, 0, 1, "MapTransform" );
qmlRegisterType< QgsQuickMessageLogModel >( uri, 0, 1, "MessageLogModel" );
qmlRegisterType< QgsQuickPositionKit >( uri, 0, 1, "PositionKit" );
qmlRegisterType< QgsQuickScaleBarKit >( uri, 0, 1, "ScaleBarKit" );
qmlRegisterType< QgsVectorLayer >( uri, 0, 1, "VectorLayer" );

View File

@ -0,0 +1,115 @@
/***************************************************************************
qgsquickpositionmarker.qml
--------------------------------------
Date : Dec 2017
Copyright : (C) 2017 by Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 2.2
import QtQml 2.2
import QtGraphicalEffects 1.0
import QgsQuick 0.1 as QgsQuick
/**
* \brief Graphical representation of physical location on the map.
*
* Source position and accuracy taken from PositionKit is drawn as a marker on the map.
* Marker is grayed out when position is not available. When PositionKit support reading of the accuracy,
* the circle is drawn around the marker. PositionKit must be connected, for example GPS position source from QgsQuickPositionKit.
*/
Item {
id: positionMarker
property int size: 48 * QgsQuick.Utils.dp
/**
* Utils for handling position.
*/
property QgsQuick.PositionKit positionKit
/**
* Color of the marker when position is known.
*/
property color baseColor: "darkblue"
/**
* Color of the marker when position is unknown (e.g. GPS signal lost).
*/
property color unavailableColor: "gray"
/**
* Whether circle representing accuracy of the position should be rendered.
*/
property var withAccuracy: true
/**
* Icon for position marker.
*/
property var markerIcon: QgsQuick.Utils.getThemeIcon("ic_navigation_black")
/**
* Source position accuracy circle-shaped indicator around positionMarker.
*/
Rectangle {
id: accuracyIndicator
visible: withAccuracy &&
positionKit.hasPosition &&
(positionKit.accuracy > 0) &&
(accuracyIndicator.width > positionMarker.size / 2.0)
x: positionKit.screenPosition.x - width/2
y: positionKit.screenPosition.y - height/2
width:positionKit.screenAccuracy
height: accuracyIndicator.width
color: baseColor
border.color: "black"
border.width: 3 * QgsQuick.Utils.dp
radius: width*0.5
opacity: 0.1
}
/**
* Position marker.
*/
Rectangle {
id: navigationMarker
property int borderWidth: 2 * QgsQuick.Utils.dp
width: positionMarker.size + 20 * QgsQuick.Utils.dp
height: width
color: "white"
border.color: baseColor
border.width: borderWidth
radius: width*0.5
antialiasing: true
x: positionKit.screenPosition.x - width/2
y: positionKit.screenPosition.y - height/2
Image {
id: navigation
source: positionMarker.markerIcon
fillMode: Image.PreserveAspectFit
rotation: positionKit.direction
anchors.centerIn: parent
width: positionMarker.size
height: width
}
/**
* Makes positionMarker (navigation) grey if position is unknown.
*/
ColorOverlay {
anchors.fill: navigation
source: navigation
color: positionKit.hasPosition ? baseColor : unavailableColor
rotation: positionKit.direction
visible: !(positionKit.hasPosition)
}
}
}

View File

@ -14,6 +14,7 @@ module QgsQuick
plugin qgis_quick_plugin
MapCanvas 0.1 qgsquickmapcanvas.qml
PositionMarker 0.1 qgsquickpositionmarker.qml
ScaleBar 0.1 qgsquickscalebar.qml
MessageLog 0.1 qgsquickmessagelog.qml

View File

@ -0,0 +1,102 @@
/***************************************************************************
qgsquickcoordinatetransformer.cpp
--------------------------------------
Date : 1.6.2017
Copyright : (C) 2017 by Matthias Kuhn
Email : matthias (at) opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QtDebug>
#include "qgsquickcoordinatetransformer.h"
QgsQuickCoordinateTransformer::QgsQuickCoordinateTransformer( QObject *parent )
: QObject( parent )
{
mCoordinateTransform.setSourceCrs( QgsCoordinateReferenceSystem::fromEpsgId( 4326 ) );
mCoordinateTransform.setContext( QgsCoordinateTransformContext() );
}
QgsPoint QgsQuickCoordinateTransformer::projectedPosition() const
{
return mProjectedPosition;
}
QgsPoint QgsQuickCoordinateTransformer::sourcePosition() const
{
return mSourcePosition;
}
void QgsQuickCoordinateTransformer::setSourcePosition( QgsPoint sourcePosition )
{
if ( mSourcePosition == sourcePosition )
return;
mSourcePosition = sourcePosition;
emit sourcePositionChanged();
updatePosition();
}
QgsCoordinateReferenceSystem QgsQuickCoordinateTransformer::destinationCrs() const
{
return mCoordinateTransform.destinationCrs();
}
void QgsQuickCoordinateTransformer::setDestinationCrs( const QgsCoordinateReferenceSystem &destinationCrs )
{
if ( destinationCrs == mCoordinateTransform.destinationCrs() )
return;
mCoordinateTransform.setDestinationCrs( destinationCrs );
emit destinationCrsChanged();
updatePosition();
}
QgsCoordinateReferenceSystem QgsQuickCoordinateTransformer::sourceCrs() const
{
return mCoordinateTransform.sourceCrs();
}
void QgsQuickCoordinateTransformer::setSourceCrs( const QgsCoordinateReferenceSystem &sourceCrs )
{
if ( sourceCrs == mCoordinateTransform.sourceCrs() )
return;
mCoordinateTransform.setSourceCrs( sourceCrs );
emit sourceCrsChanged();
updatePosition();
}
void QgsQuickCoordinateTransformer::updatePosition()
{
double x = mSourcePosition.x();
double y = mSourcePosition.y();
double z = mSourcePosition.z();
// If Z is NaN, coordinate transformation (proj4) will
// also set X and Y to NaN. But we also want to get projected
// coords if we do not have any Z coordinate.
if ( qIsNaN( z ) )
{
z = 0;
}
if ( mMapSettings )
mCoordinateTransform.setContext( mMapSettings->transformContext() );
mCoordinateTransform.transformInPlace( x, y, z );
mProjectedPosition = QgsPoint( x, y );
mProjectedPosition.addZValue( mSourcePosition.z() );
emit projectedPositionChanged();
}

View File

@ -0,0 +1,103 @@
/***************************************************************************
qgsquickcoordinatetransformer.h
--------------------------------------
Date : 1.6.2017
Copyright : (C) 2017 by Matthias Kuhn
Email : matthias (at) opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSQUICKCOORDINATETRANSFORMER_H
#define QGSQUICKCOORDINATETRANSFORMER_H
#include <QObject>
#include "qgspoint.h"
#include "qgis_quick.h"
#include "qgsquickmapsettings.h"
/**
* \ingroup quick
* Helper class for transform of coordinates (QgsPoint) to a different coordinate reference system.
*
* \note QML Type: CoordinateTransformer
*
* \since QGIS 3.2
*/
class QUICK_EXPORT QgsQuickCoordinateTransformer : public QObject
{
Q_OBJECT
//! Projected (destination) position (in destination CRS)
Q_PROPERTY( QgsPoint projectedPosition READ projectedPosition NOTIFY projectedPositionChanged )
//! Source position (in source CRS)
Q_PROPERTY( QgsPoint sourcePosition READ sourcePosition WRITE setSourcePosition NOTIFY sourcePositionChanged )
//! Destination CRS
Q_PROPERTY( QgsCoordinateReferenceSystem destinationCrs READ destinationCrs WRITE setDestinationCrs NOTIFY destinationCrsChanged )
//! Source CRS, default 4326
Q_PROPERTY( QgsCoordinateReferenceSystem sourceCrs READ sourceCrs WRITE setSourceCrs NOTIFY sourceCrsChanged )
//! Map settings, for getting transformation context
Q_PROPERTY( QgsQuickMapSettings *mapSettings MEMBER mMapSettings NOTIFY mapSettingsChanged )
public:
//! Creates new coordinate transformer
explicit QgsQuickCoordinateTransformer( QObject *parent = 0 );
//!\copydoc QgsQuickCoordinateTransformer::projectedPosition
QgsPoint projectedPosition() const;
//!\copydoc QgsQuickCoordinateTransformer::sourcePosition
QgsPoint sourcePosition() const;
//!\copydoc QgsQuickCoordinateTransformer::sourcePosition
void setSourcePosition( QgsPoint sourcePosition );
//!\copydoc QgsQuickCoordinateTransformer::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const;
//!\copydoc QgsQuickCoordinateTransformer::destinationCrs
void setDestinationCrs( const QgsCoordinateReferenceSystem &destinationCrs );
//!\copydoc QgsQuickCoordinateTransformer::sourceCrs
QgsCoordinateReferenceSystem sourceCrs() const;
//!\copydoc QgsQuickCoordinateTransformer::sourceCrs
void setSourceCrs( const QgsCoordinateReferenceSystem &sourceCrs );
signals:
//! Projected position changed
void projectedPositionChanged();
//! Source position changed
void sourcePositionChanged();
//! Destination CRS changed
void destinationCrsChanged();
//! Source CRS changed
void sourceCrsChanged();
//! Map settings changed
void mapSettingsChanged();
private:
void updatePosition();
QgsPoint mProjectedPosition;
QgsPoint mSourcePosition;
QgsCoordinateTransform mCoordinateTransform;
QgsQuickMapSettings *mMapSettings = nullptr;
};
#endif // QGSQUICKCOORDINATETRANSFORMER_H

View File

@ -0,0 +1,311 @@
/***************************************************************************
qgsquickpositionkit.cpp
--------------------------------------
Date : Dec. 2017
Copyright : (C) 2017 Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgis.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgsquickpositionkit.h"
#include "qgsquickutils.h"
#include "qgsquicksimulatedpositionsource.h"
QgsQuickPositionKit::QgsQuickPositionKit( QObject *parent )
: QObject( parent )
, mAccuracy( -1 )
, mScreenAccuracy( 2 )
, mAccuracyUnits( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ) )
, mDirection( -1 )
, mHasPosition( false )
, mIsSimulated( false )
{
connect( this, &QgsQuickPositionKit::simulatePositionLongLatRadChanged, this, &QgsQuickPositionKit::onSimulatePositionLongLatRadChanged );
connect( this, &QgsQuickPositionKit::positionChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( this, &QgsQuickPositionKit::positionChanged, this, &QgsQuickPositionKit::updateProjectedPosition );
use_gps_location();
}
QGeoPositionInfoSource *QgsQuickPositionKit::gpsSource()
{
// this should give us "true" position source
// on Linux it comes from Geoclue library
QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource( this );
if ( source->error() != QGeoPositionInfoSource::NoError )
{
QgsMessageLog::logMessage( QStringLiteral( "%1 (%2)" )
.arg( tr( "Unable to create default GPS Position Source" ) )
.arg( QString::number( ( long )source->error() ) )
, QStringLiteral( "QgsQuick" )
, Qgis::Warning );
delete source;
return nullptr;
}
else
{
return source;
}
}
QGeoPositionInfoSource *QgsQuickPositionKit::simulatedSource( double longitude, double latitude, double radius )
{
return new QgsQuickSimulatedPositionSource( this, longitude, latitude, radius );
}
void QgsQuickPositionKit::use_simulated_location( double longitude, double latitude, double radius )
{
QGeoPositionInfoSource *source = simulatedSource( longitude, latitude, radius );
mIsSimulated = true;
replacePositionSource( source );
}
void QgsQuickPositionKit::updateScreenPosition()
{
if ( !mMapSettings )
return;
mScreenPosition = mapSettings()->coordinateToScreen( projectedPosition() );
emit screenPositionChanged();
}
QString QgsQuickPositionKit::sourceAccuracyLabel()
{
if ( hasPosition() && accuracy() > 0 )
{
return QgsQuickUtils::distanceToString( accuracy(), 0 ); // e.g 1 km or 15 m or 500 mm
}
else
{
return QStringLiteral( "" );
}
}
QString QgsQuickPositionKit::sourcePositionLabel( int precision )
{
if ( hasPosition() )
{
return QgsQuickUtils::qgsPointToString( position(), precision ); // e.g -2.243, 45.441
}
else
{
return QStringLiteral( "" );
}
}
void QgsQuickPositionKit::use_gps_location()
{
QGeoPositionInfoSource *source = gpsSource();
mIsSimulated = false;
replacePositionSource( source );
}
void QgsQuickPositionKit::replacePositionSource( QGeoPositionInfoSource *source )
{
if ( mSource.get() == source )
return;
if ( mSource )
{
mSource->disconnect();
}
mSource.reset( source );
if ( mSource )
{
connect( mSource.get(), &QGeoPositionInfoSource::positionUpdated, this, &QgsQuickPositionKit::positionUpdated );
connect( mSource.get(), &QGeoPositionInfoSource::updateTimeout, this, &QgsQuickPositionKit::onUpdateTimeout );
mSource->startUpdates();
QgsDebugMsg( QStringLiteral( "Position source changed: %1" ).arg( mSource->sourceName() ) );
}
}
QgsQuickMapSettings *QgsQuickPositionKit::mapSettings() const
{
return mMapSettings;
}
void QgsQuickPositionKit::updateProjectedPosition()
{
if ( !mMapSettings )
return;
QgsPointXY srcPoint = QgsPointXY( mPosition.x(), mPosition.y() );
QgsPointXY projectedPositionXY = QgsQuickUtils::transformPoint( QgsQuickUtils::coordinateReferenceSystemFromEpsgId( 4326 ), mMapSettings->destinationCrs(), mMapSettings->transformContext(), srcPoint );
mProjectedPosition = QgsPoint( projectedPositionXY.x(), projectedPositionXY.y() );
mProjectedPosition.addZValue( mPosition.z() );
}
void QgsQuickPositionKit::positionUpdated( const QGeoPositionInfo &info )
{
if ( !info.coordinate().isValid() )
{
// keep last valid position
mHasPosition = false;
emit hasPositionChanged();
}
mPosition = QgsPoint( info.coordinate().longitude(),
info.coordinate().latitude(),
info.coordinate().altitude() ); // can be NaN
if ( info.hasAttribute( QGeoPositionInfo::HorizontalAccuracy ) )
mAccuracy = info.attribute( QGeoPositionInfo::HorizontalAccuracy );
else
mAccuracy = -1;
mScreenAccuracy = calculateScreenAccuracy();
if ( info.hasAttribute( QGeoPositionInfo::Direction ) )
mDirection = info.attribute( QGeoPositionInfo::Direction );
else
mDirection = -1;
emit positionChanged();
if ( !mHasPosition )
{
mHasPosition = true;
emit hasPositionChanged();
}
}
void QgsQuickPositionKit::onSimulatePositionLongLatRadChanged( QVector<double> simulatePositionLongLatRad )
{
if ( simulatePositionLongLatRad.size() > 2 )
{
double longitude = simulatePositionLongLatRad[0];
double latitude = simulatePositionLongLatRad[1];
double radius = simulatePositionLongLatRad[2];
QgsDebugMsg( QStringLiteral( "Use simulated position around longlat: %1, %2, %3" ).arg( longitude ).arg( latitude ).arg( radius ) );
use_simulated_location( longitude, latitude, radius );
}
else
{
QgsDebugMsg( QStringLiteral( "Unable to set simulated position due to the input errors." ) );
use_gps_location();
}
}
double QgsQuickPositionKit::calculateScreenAccuracy()
{
if ( !mMapSettings )
return 2.0;
if ( accuracy() > 0 )
{
double scpm = QgsQuickUtils::screenUnitsToMeters( mMapSettings, 1 );
if ( scpm > 0 )
return 2 * ( accuracy() / scpm );
else
return 2.0;
}
return 2.0;
}
void QgsQuickPositionKit::onUpdateTimeout()
{
if ( mHasPosition )
{
mHasPosition = false;
emit hasPositionChanged();
}
}
QPointF QgsQuickPositionKit::screenPosition() const
{
return mScreenPosition;
}
void QgsQuickPositionKit::setScreenPosition( const QPointF &screenPosition )
{
mScreenPosition = screenPosition;
}
double QgsQuickPositionKit::screenAccuracy() const
{
return mScreenAccuracy;
}
QVector<double> QgsQuickPositionKit::simulatePositionLongLatRad() const
{
return mSimulatePositionLongLatRad;
}
void QgsQuickPositionKit::setSimulatePositionLongLatRad( const QVector<double> &simulatePositionLongLatRad )
{
mSimulatePositionLongLatRad = simulatePositionLongLatRad;
emit simulatePositionLongLatRadChanged( simulatePositionLongLatRad );
}
QgsPoint QgsQuickPositionKit::projectedPosition() const
{
return mProjectedPosition;
}
bool QgsQuickPositionKit::hasPosition() const
{
return mHasPosition;
}
QgsPoint QgsQuickPositionKit::position() const
{
return mPosition;
}
qreal QgsQuickPositionKit::accuracy() const
{
return mAccuracy;
}
QString QgsQuickPositionKit::accuracyUnits() const
{
return mAccuracyUnits;
}
qreal QgsQuickPositionKit::direction() const
{
return mDirection;
}
bool QgsQuickPositionKit::simulated() const
{
return mIsSimulated;
}
void QgsQuickPositionKit::setMapSettings( QgsQuickMapSettings *mapSettings )
{
if ( mMapSettings == mapSettings )
return;
if ( mMapSettings )
{
mMapSettings->disconnect();
}
mMapSettings = mapSettings;
if ( mMapSettings )
{
connect( mMapSettings, &QgsQuickMapSettings::extentChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( mMapSettings, &QgsQuickMapSettings::destinationCrsChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( mMapSettings, &QgsQuickMapSettings::mapUnitsPerPixelChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( mMapSettings, &QgsQuickMapSettings::visibleExtentChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( mMapSettings, &QgsQuickMapSettings::outputSizeChanged, this, &QgsQuickPositionKit::updateScreenPosition );
connect( mMapSettings, &QgsQuickMapSettings::outputDpiChanged, this, &QgsQuickPositionKit::updateScreenPosition );
}
emit mapSettingsChanged();
}

View File

@ -0,0 +1,255 @@
/***************************************************************************
qgsquickpositionkit.h
--------------------------------------
Date : Dec. 2017
Copyright : (C) 2017 Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSQUICKPOSITIONKIT_H
#define QGSQUICKPOSITIONKIT_H
#include <QObject>
#include <QtPositioning>
#include "qgspoint.h"
#include "qgis_quick.h"
#include "qgsquickmapsettings.h"
#include "qgsquickcoordinatetransformer.h"
/**
* \ingroup quick
* Convenient set of tools to read GPS position and accuracy.
*
* Also, if one can use use_simulated_location to specify simulated position.
* Simulated position source generates random points in circles around the selected
* point and radius. Real GPS position is not used in this mode.
*
* \note QML Type: PositionKit
*
* \since QGIS 3.2
*/
class QUICK_EXPORT QgsQuickPositionKit : public QObject
{
Q_OBJECT
/**
* GPS position in WGS84 coords.
*/
Q_PROPERTY( QgsPoint position READ position NOTIFY positionChanged )
/**
* GPS position in map coords.
*/
Q_PROPERTY( QgsPoint projectedPosition READ projectedPosition NOTIFY positionChanged )
/**
* GPS position in pixels.
*/
Q_PROPERTY( QPointF screenPosition READ screenPosition WRITE setScreenPosition NOTIFY screenPositionChanged )
/**
* GPS position is available (position property is a valid number).
*/
Q_PROPERTY( bool hasPosition READ hasPosition NOTIFY hasPositionChanged )
/**
* GPS horizontal accuracy in accuracyUnits, -1 if not available.
*/
Q_PROPERTY( qreal accuracy READ accuracy NOTIFY positionChanged )
/**
* Screen horizontal accuracy, 2 if not available or resolution is too small.
*/
Q_PROPERTY( double screenAccuracy READ screenAccuracy NOTIFY positionChanged )
/**
* GPS horizontal accuracy units.
*/
Q_PROPERTY( QString accuracyUnits READ accuracyUnits NOTIFY positionChanged )
/**
* GPS direction, bearing in degrees clockwise from north to direction of travel. -1 if not available
*/
Q_PROPERTY( qreal direction READ direction NOTIFY positionChanged )
/**
* GPS position and accuracy is simulated (not real from GPS sensor). Default false (use real GPS)
*/
Q_PROPERTY( bool isSimulated READ simulated NOTIFY isSimulatedChanged )
/**
* Associated map settings. Should be initialized before the first use from mapcanvas map settings.
*/
Q_PROPERTY( QgsQuickMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged )
/**
* Vector containing longitude, latitude and radius of similated position. If empty, no simulated source will be used.
* e.g. [-97.36, 36.93, 2]
*/
Q_PROPERTY( QVector<double> simulatePositionLongLatRad READ simulatePositionLongLatRad WRITE setSimulatePositionLongLatRad NOTIFY simulatePositionLongLatRadChanged )
public:
//! Creates new position kit
explicit QgsQuickPositionKit( QObject *parent = 0 );
//! True if there is \copydoc QgsQuickPositionKit::position
bool hasPosition() const;
//! \copydoc QgsQuickPositionKit::position
QgsPoint position() const;
//! \copydoc QgsQuickPositionKit::projectedPosition
QgsPoint projectedPosition() const;
//! \copydoc QgsQuickPositionKit::screenPosition
QPointF screenPosition() const;
//! \copydoc QgsQuickPositionKit::screenPosition
void setScreenPosition( const QPointF &screenPosition );
//! \copydoc QgsQuickPositionKit::accuracy
qreal accuracy() const;
//! \copydoc QgsQuickPositionKit::screenAccuracy
double screenAccuracy() const;
//! \copydoc QgsQuickPositionKit::accuracyUnits
QString accuracyUnits() const;
//! \copydoc QgsQuickPositionKit::direction
qreal direction() const;
//! \copydoc QgsQuickPositionKit::isSimulated
bool simulated() const;
//! \copydoc QgsQuickPositionKit::mapSettings
void setMapSettings( QgsQuickMapSettings *mapSettings );
//! \copydoc QgsQuickPositionKit::mapSettings
QgsQuickMapSettings *mapSettings() const;
//! \copydoc QgsQuickPositionKit::simulatePositionLongLatRad
QVector<double> simulatePositionLongLatRad() const;
//! \copydoc QgsQuickPositionKit::simulatePositionLongLatRad
void setSimulatePositionLongLatRad( const QVector<double> &simulatePositionLongLatRad );
/**
* Use simulated GPS source.
*
* Simulated GPS source emulates point on circle around defined point in specified radius
*
* We do not want to have the origin point as property
* We basically want to set it once based on project/map cente and keep
* it that way regardless of mapsettings change (e.g. zoom etc)
*
* \param longitude longitude of the centre of the emulated points
* \param latitude latitude of the centre of the emulated points
* \param radius distance of emulated points from the centre (in degrees WSG84)
*/
Q_INVOKABLE void use_simulated_location( double longitude, double latitude, double radius );
/**
* Generates label for gps accuracy according set gps source. If there is no accuracy, return empty string.
*/
Q_INVOKABLE QString sourceAccuracyLabel();
/**
* Generates label for gps position according set gps source. If has no position, return empty string.
* \param precision Defines number of digits after comma.
*/
Q_INVOKABLE QString sourcePositionLabel( int precision );
/**
* Use real GPS source (not simulated)
*/
Q_INVOKABLE void use_gps_location();
/**
* Used for changing position source when simulatePositionLongLatRad is un/set.
* \param simulatePositionLongLatRad Vector containing longitute, latitute and radius.
*/
Q_INVOKABLE void onSimulatePositionLongLatRadChanged( QVector<double> simulatePositionLongLatRad );
/**
* Updates screen position according projected position.
*/
Q_INVOKABLE void updateScreenPosition();
signals:
//! source position changed
void positionChanged();
//! screenPosition changed
void screenPositionChanged();
//! hasPosition changed
void hasPositionChanged();
//! changed if source position is simulated or not
void isSimulatedChanged();
//! \copydoc QgsQuickPositionKit::mapSettings
void mapSettingsChanged();
//! \copydoc QgsQuickPositionKit::simulatePositionLongLatRad
void simulatePositionLongLatRadChanged( QVector<double> simulatePositionLongLatRad );
public slots:
private slots:
void positionUpdated( const QGeoPositionInfo &info );
void onUpdateTimeout();
protected:
//! \copydoc QgsQuickPositionKit::position
QgsPoint mPosition;
//! \copydoc QgsQuickPositionKit::projectedPosition
QgsPoint mProjectedPosition;
//! \copydoc QgsQuickPositionKit::screenPosition
QPointF mScreenPosition;
//! \copydoc QgsQuickPositionKit::accuracy
qreal mAccuracy;
//! \copydoc QgsQuickPositionKit::screenAccuracy
double mScreenAccuracy;
//! \copydoc QgsQuickPositionKit::accuracyUnits
QString mAccuracyUnits;
//! \copydoc QgsQuickPositionKit::direction
qreal mDirection;
//! \copydoc QgsQuickPositionKit::position
bool mHasPosition;
//! \copydoc QgsQuickPositionKit::isSimulated
bool mIsSimulated;
//! \copydoc QgsQuickPositionKit::simulatePositionLongLatRad
QVector<double> mSimulatePositionLongLatRad;
std::unique_ptr<QGeoPositionInfoSource> mSource;
private:
void replacePositionSource( QGeoPositionInfoSource *source );
QString calculateStatusLabel();
double calculateScreenAccuracy();
QgsQuickMapSettings *mMapSettings = nullptr; // not owned
QgsCoordinateTransform mCoordinateTransform;
QGeoPositionInfoSource *gpsSource();
QGeoPositionInfoSource *simulatedSource( double longitude, double latitude, double radius );
void updateProjectedPosition();
};
#endif // QGSQUICKPOSITIONKIT_H

View File

@ -0,0 +1,84 @@
/***************************************************************************
qgsquicksimulatedpositionsource.cpp
--------------------------------------
Date : Dec. 2017
Copyright : (C) 2017 Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsquicksimulatedpositionsource.h"
#include <QTimer>
/// @cond PRIVATE
QgsQuickSimulatedPositionSource::QgsQuickSimulatedPositionSource( QObject *parent, double longitude, double latitude, double flightRadius )
: QGeoPositionInfoSource( parent )
, mTimer( qgis::make_unique< QTimer >( this ) )
, mAngle( 0 )
, mFlightRadius( flightRadius )
, mLongitude( longitude )
, mLatitude( latitude )
{
connect( mTimer.get(), &QTimer::timeout, this, &QgsQuickSimulatedPositionSource::readNextPosition );
}
void QgsQuickSimulatedPositionSource::startUpdates()
{
int interval = updateInterval();
if ( interval < minimumUpdateInterval() )
interval = minimumUpdateInterval();
mTimer->start( interval );
readNextPosition();
}
void QgsQuickSimulatedPositionSource::stopUpdates()
{
mTimer->stop();
}
void QgsQuickSimulatedPositionSource::requestUpdate( int /*timeout*/ )
{
readNextPosition();
}
void QgsQuickSimulatedPositionSource::readNextPosition()
{
double latitude = mLatitude, longitude = mLongitude;
latitude += sin( mAngle * M_PI / 180 ) * mFlightRadius;
longitude += cos( mAngle * M_PI / 180 ) * mFlightRadius;
mAngle += 1;
QGeoCoordinate coordinate( latitude, longitude );
double altitude = std::rand() % 40 + 20; // rand altitude <20,55>m and lost (0)
if ( altitude <= 55 )
{
coordinate.setAltitude( altitude ); // 3D
}
QDateTime timestamp = QDateTime::currentDateTime();
QGeoPositionInfo info( coordinate, timestamp );
if ( info.isValid() )
{
mLastPosition = info;
info.setAttribute( QGeoPositionInfo::Direction, 360 - int( mAngle ) % 360 );
int accuracy = std::rand() % 40 + 20; // rand accuracy <20,55>m and lost (-1)
if ( accuracy > 55 )
{
accuracy = -1;
}
info.setAttribute( QGeoPositionInfo::HorizontalAccuracy, accuracy );
emit positionUpdated( info );
}
}
/// @endcond

View File

@ -0,0 +1,81 @@
/***************************************************************************
qgsquicksimulatedpositionsource.h
--------------------------------------
Date : Dec. 2017
Copyright : (C) 2017 Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSQUICKSIMULATEDPOSITIONSOURCE_H
#define QGSQUICKSIMULATEDPOSITIONSOURCE_H
/// @cond PRIVATE
//
// W A R N I N G
// -------------
//
// This file is not part of the QGIS API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
#include "qgis_quick.h"
#include <QObject>
#include <QTimer>
#include <QtPositioning>
#include <qgspoint.h>
/**
* \ingroup quick
* This is an internal (implementation) class used to generate (fake) GPS position source
* Useful for for testing purposes (e.g. testing of the application with map for different
* location then your physical (GPS) location)
*
* Simulated position source generates random points in circles around the selected
* point and radius. Real GPS position is not used in this mode.
*
* \note QML Type: not exported
*
* \since QGIS 3.2
*/
class QUICK_NO_EXPORT QgsQuickSimulatedPositionSource : public QGeoPositionInfoSource
{
Q_OBJECT
public:
QgsQuickSimulatedPositionSource( QObject *parent, double longitude, double latitude, double flightRadius );
QGeoPositionInfo lastKnownPosition( bool /*fromSatellitePositioningMethodsOnly = false*/ ) const { return mLastPosition; }
PositioningMethods supportedPositioningMethods() const { return AllPositioningMethods; }
int minimumUpdateInterval() const { return 1000; }
Error error() const { return QGeoPositionInfoSource::NoError; }
public slots:
virtual void startUpdates();
virtual void stopUpdates();
virtual void requestUpdate( int timeout = 5000 );
private slots:
void readNextPosition();
private:
std::unique_ptr< QTimer > mTimer;
QGeoPositionInfo mLastPosition;
double mAngle;
double mFlightRadius;
double mLongitude;
double mLatitude;
};
/// @endcond
#endif // QGSQUICKSIMULATEDPOSITIONSOURCE_H

View File

@ -16,6 +16,8 @@
#include <QString>
#include "qgis.h"
#include "qgscoordinatereferencesystem.h"
#include "qgscoordinatetransform.h"
#include "qgsdistancearea.h"
#include "qgslogger.h"
#include "qgsvectorlayer.h"
@ -32,7 +34,40 @@ QgsQuickUtils::QgsQuickUtils( QObject *parent )
{
}
double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels ) const
/**
* Makes QgsCoordinateReferenceSystem::fromEpsgId accessable for QML components
*/
QgsCoordinateReferenceSystem QgsQuickUtils::coordinateReferenceSystemFromEpsgId( long epsg )
{
return QgsCoordinateReferenceSystem::fromEpsgId( epsg );
}
QgsPointXY QgsQuickUtils::pointXYFactory( double x, double y ) const
{
return QgsPointXY( x, y );
}
QgsPoint QgsQuickUtils::pointFactory( double x, double y ) const
{
return QgsPoint( x, y );
}
QgsPoint QgsQuickUtils::coordinateToPoint( const QGeoCoordinate &coor ) const
{
return QgsPoint( coor.longitude(), coor.latitude(), coor.altitude() );
}
QgsPointXY QgsQuickUtils::transformPoint( const QgsCoordinateReferenceSystem &srcCrs,
const QgsCoordinateReferenceSystem &destCrs,
const QgsCoordinateTransformContext &context,
const QgsPointXY &srcPoint )
{
QgsCoordinateTransform mTransform( srcCrs, destCrs, context );
QgsPointXY pt = mTransform.transform( srcPoint );
return pt;
}
double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels )
{
if ( mapSettings == nullptr ) return 0.0;
@ -59,6 +94,41 @@ QgsQuickFeatureLayerPair QgsQuickUtils::featureFactory( const QgsFeature &featur
return QgsQuickFeatureLayerPair( feature, layer );
}
QUrl QgsQuickUtils::getThemeIcon( const QString &name )
QString path = QStringLiteral( "qrc:/%1.svg" ).arg( name );
QgsDebugMsg( QStringLiteral( "Using icon %1 from %2" ).arg( name, path ) );
return QUrl( path );
}
QString QgsQuickUtils::qgsPointToString( const QgsPoint &point, int decimals )
{
return QString( "%1, %2" ).arg( QString::number( point.x(), 'f', decimals ) ).arg( QString::number( point.y(), 'f', decimals ) );
}
QString QgsQuickUtils::distanceToString( qreal dist, int decimals )
{
if ( dist < 0 )
{
return QStringLiteral( "0 %1" ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ) );
}
if ( dist > 1000 )
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist / 1000.0, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceKilometers ) );
}
else
{
if ( dist > 1 )
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ) );
}
else
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist * 1000, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMillimeters ) );
}
}
}
QString QgsQuickUtils::dumpScreenInfo() const
{
QRect rec = QApplication::desktop()->screenGeometry();

View File

@ -19,9 +19,12 @@
#include <QObject>
#include <QString>
#include <QtPositioning/QGeoCoordinate>
#include "qgis.h"
#include "qgsmessagelog.h"
#include "qgspoint.h"
#include "qgspointxy.h"
#include "qgsquickmapsettings.h"
#include "qgsquickfeaturelayerpair.h"
@ -60,16 +63,44 @@ class QUICK_EXPORT QgsQuickUtils: public QObject
public:
//! Create new utilities
QgsQuickUtils( QObject *parent = nullptr );
//! dtor
//! Destructor
~QgsQuickUtils() = default;
//! \copydoc QgsQuickUtils::dp
qreal screenDensity() const;
/**
* Calculate the distance in meter representing baseLengthPixels pixels on the screen based on the current map settings.
* Creates crs from epsg code in QML
*/
Q_INVOKABLE double screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels ) const;
Q_INVOKABLE static QgsCoordinateReferenceSystem coordinateReferenceSystemFromEpsgId( long epsg );
/**
* Creates QgsPointXY in QML
*/
Q_INVOKABLE QgsPointXY pointXYFactory( double x, double y ) const;
/**
* Creates QgsPoint in QML
*/
Q_INVOKABLE QgsPoint pointFactory( double x, double y ) const;
/**
* Converts QGeoCoordinate to QgsPoint
*/
Q_INVOKABLE QgsPoint coordinateToPoint( const QGeoCoordinate &coor ) const;
/**
* Transforms point between different crs from QML
*/
Q_INVOKABLE static QgsPointXY transformPoint( const QgsCoordinateReferenceSystem &srcCrs,
const QgsCoordinateReferenceSystem &destCrs,
const QgsCoordinateTransformContext &context,
const QgsPointXY &srcPoint );
/**
* Calculates the distance in meter representing baseLengthPixels pixels on the screen based on the current map settings.
*/
Q_INVOKABLE static double screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels );
//! Log message in QgsMessageLog
Q_INVOKABLE void logMessage( const QString &message,
@ -86,10 +117,23 @@ class QUICK_EXPORT QgsQuickUtils: public QObject
Q_INVOKABLE QgsQuickFeatureLayerPair featureFactory( const QgsFeature &feature, QgsVectorLayer *layer = nullptr ) const;
/**
* Returns a string with information about screen size and resolution
*
* Useful to log for debugging of graphical problems on various display sizes
*/
* Returns QUrl to image from libary's /images folder.
*/
Q_INVOKABLE QUrl getThemeIcon( const QString &name );
/**
* Converts point to string with given decimals (default decimals = 3),
* e.g. -2.234521, 34.4444421 -> -2.234, 34.444
*/
Q_INVOKABLE static QString qgsPointToString( const QgsPoint &point, int decimals = 3 );
/**
* Converts distance in meters to human readable length with given decimals (default decimals = 1),
* e.g. 1222.234 m -> 1.2 km
*/
Q_INVOKABLE static QString distanceToString( qreal dist, int decimals = 1 );
//! Returns a string with information about screen size and resolution - useful for debugging
QString dumpScreenInfo() const;
private:

View File

@ -81,6 +81,7 @@ ENDMACRO (ADD_QGIS_TEST)
ADD_QGIS_TEST(qgsquickidentifykit testqgsquickidentifykit.cpp)
ADD_QGIS_TEST(qgsquickutils testqgsquickutils.cpp)
ADD_QGIS_TEST(qgsquickscalebarkit testqgsquickscalebarkit.cpp)
ADD_QGIS_TEST(qgsquickpositionkit testqgsquickpositionkit.cpp)
#############################################################

View File

@ -58,6 +58,10 @@ int main( int argc, char *argv[] )
engine.rootContext()->setContextProperty( "__project", &project );
engine.rootContext()->setContextProperty( "__layers", QVariant::fromValue( project.layerTreeRoot()->layerOrder() ) );
// Set simulated position for desktop builds
bool use_simulated_position = true;
engine.rootContext()->setContextProperty( "__use_simulated_position", use_simulated_position );
QQmlComponent component( &engine, QUrl( QStringLiteral( "qrc:/main.qml" ) ) );
QObject *object = component.create();

View File

@ -75,6 +75,15 @@ ApplicationWindow {
}
}
QgsQuick.PositionMarker {
id: positionMarker
positionKit: QgsQuick.PositionKit {
id: positionKit
mapSettings: mapCanvas.mapSettings
simulatePositionLongLatRad: __use_simulated_position ? [-97.36, 36.93, 2] : undefined
}
}
QgsQuick.ScaleBar {
id: scaleBar
y: window.height - height
@ -83,4 +92,5 @@ ApplicationWindow {
preferredWidth: 115 * QgsQuick.Utils.dp
z: 1
}
}

View File

@ -0,0 +1,63 @@
/***************************************************************************
testqgspositionkit.cpp
--------------------------------------
Date : May 2018
Copyright : (C) 2017 by Viktor Sklencar
Email : vsklencar at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QObject>
#include <QApplication>
#include <QDesktopWidget>
#include "qgsapplication.h"
#include "qgstest.h"
#include "qgis.h"
#include "qgsquickpositionkit.h"
#include "qgsquicksimulatedpositionsource.h"
#include "qgsquickutils.h"
class TestQgsQuickUtils: public QObject
{
Q_OBJECT
private slots:
void init() {} // will be called before each testfunction is executed.
void cleanup() {} // will be called after every testfunction.
void simulated_position();
private:
QgsQuickUtils utils;
QgsQuickPositionKit positionKit;
};
void TestQgsQuickUtils::simulated_position()
{
const QVector<double> initPosition( { -92.36, 38.93, 2 } );
QVERIFY( !positionKit.simulated() );
positionKit.use_simulated_location( initPosition[0], initPosition[1], initPosition[2] );
QVERIFY( positionKit.simulated() );
QVERIFY( positionKit.hasPosition() );
QVERIFY( positionKit.position().y() == initPosition[1] );
QVERIFY( positionKit.accuracy() > 0 );
const QVector<double> newPosition( { 90.36, 33.93, 3 } );
positionKit.onSimulatePositionLongLatRadChanged( newPosition );
QVERIFY( positionKit.hasPosition() );
QVERIFY( positionKit.position().y() == newPosition[1] );
positionKit.onSimulatePositionLongLatRadChanged( QVector<double>() );
QVERIFY( !positionKit.simulated() );
}
QGSTEST_MAIN( TestQgsQuickUtils )
#include "testqgsquickpositionkit.moc"

View File

@ -17,6 +17,10 @@
#include <QDesktopWidget>
#include "qgsapplication.h"
#include "qgscoordinatereferencesystem.h"
#include "qgscoordinatetransformcontext.h"
#include "qgspoint.h"
#include "qgspointxy.h"
#include "qgstest.h"
#include "qgis.h"
@ -32,6 +36,8 @@ class TestQgsQuickUtils: public QObject
void screen_density();
void dump_screen_info();
void screenUnitsToMeters();
void transformedPoint();
void formatting();
private:
QgsQuickUtils utils;
@ -62,5 +68,63 @@ void TestQgsQuickUtils::screenUnitsToMeters()
QGSCOMPARENEAR( sutm, 213, 1.0 );
}
void TestQgsQuickUtils::transformedPoint()
{
QgsPointXY pointXY = utils.pointXYFactory( 49.9, 16.3 );
QVERIFY( pointXY.x() == 49.9 );
QVERIFY( pointXY.y() == 16.3 );
QgsPoint point = utils.pointFactory( 1.0, -1.0 );
QVERIFY( point.x() == 1.0 );
QVERIFY( point.y() == -1.0 );
QgsCoordinateReferenceSystem crs3857 = QgsCoordinateReferenceSystem::fromEpsgId( 3857 );
QVERIFY( crs3857.authid() == "EPSG:3857" );
QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
QVERIFY( crsGPS.authid() == "EPSG:4326" );
QgsPointXY transformedPoint = utils.transformPoint( crsGPS,
crs3857,
QgsCoordinateTransformContext(),
pointXY );
QVERIFY( fabs( transformedPoint.x() - 5554843 ) < 1.0 );
QVERIFY( fabs( transformedPoint.y() - 1839491 ) < 1.0 );
}
void TestQgsQuickUtils::formatting()
{
QgsPoint point( -2.234521, 34.4444421 );
QString point2str = utils.qgsPointToString( point, 3 );
QVERIFY( point2str == "-2.235, 34.444" );
point2str = utils.qgsPointToString( point, 2 );
QVERIFY( point2str == "-2.23, 34.44" );
point2str = utils.qgsPointToString( point, 1 );
QVERIFY( point2str == "-2.2, 34.4" );
point2str = utils.qgsPointToString( point, 0 );
QVERIFY( point2str == "-2, 34" );
QString dist2str = utils.distanceToString( 1222.234, 2 );
QVERIFY( dist2str == "1.22 km" );
dist2str = utils.distanceToString( 1222.234, 1 );
QVERIFY( dist2str == "1.2 km" );
dist2str = utils.distanceToString( 1222.234, 0 );
QVERIFY( dist2str == "1 km" );
dist2str = utils.distanceToString( 700.22, 1 );
QVERIFY( dist2str == "700.2 m" );
dist2str = utils.distanceToString( 0.22, 0 );
QVERIFY( dist2str == "220 mm" );
dist2str = utils.distanceToString( -0.22, 0 );
QVERIFY( dist2str == "0 m" );
}
QGSTEST_MAIN( TestQgsQuickUtils )
#include "testqgsquickutils.moc"