[feature] Add a "measure bearing" map tool

This tool behaves similarly to the existing "measure angle" map tool,
but requires the user only to click two points on the map and displays
the bearing between these points.
This commit is contained in:
Nyall Dawson 2021-06-15 08:20:24 +10:00
parent 6596d872b6
commit d83a7698e2
14 changed files with 492 additions and 15 deletions

View File

@ -920,6 +920,7 @@
<file>themes/default/mIconFolderOpenParams.svg</file>
<file>themes/default/mIconFolderLinkParams.svg</file>
<file>themes/default/mIconFolderHomeParams.svg</file>
<file>themes/default/mActionMeasureBearing.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>

View File

@ -0,0 +1 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M 11.764707,14.807559 C 8.4665509,12.921897 8.6275419,12.93651 5.4599056,12.56332 l -0.029936,9.128173 c 1.8820661,-2.316719 4.7029074,-6.243469 6.3347374,-6.883934 z" fill="#c7c7c7"/><path d="M5.4922111 22.006402L5.4762203 3.9992377M5.4922111 22.006402L14.748994 9.069822" stroke="#415a75" fill="none"/><path d="M 12.492216,15.506403 C 9.4922159,13.00641 7.9922159,12.506409 3.9922111,12.506409" stroke="#6d97c4" stroke-linecap="square" fill="none"/><path d="M 5.4366968,1.4048512 8.2272949,7.9944063 H 2.6460998 Z" fill="#415a75" paint-order="stroke fill markers"/><circle cx="19.384918" cy="6.0672107" r="1.9237912" fill="none" stroke="#5b5b5c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" paint-order="stroke fill markers"/></svg>

After

Width:  |  Height:  |  Size: 831 B

View File

@ -86,6 +86,7 @@ set(QGIS_APP_SRCS
qgsmaptoolhtmlannotation.cpp
qgsmaptoolidentifyaction.cpp
qgsmaptoolmeasureangle.cpp
qgsmaptoolmeasurebearing.cpp
qgsmaptoolmovefeature.cpp
qgsmaptooloffsetcurve.cpp
qgsmaptooloffsetpointsymbol.cpp

View File

@ -29,6 +29,7 @@
#include "qgsmaptoolcircle3points.h"
#include "qgsmaptoolcircle2tangentspoint.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgsmaptoolmeasurebearing.h"
#include "qgsmaptoolformannotation.h"
#include "qgsmaptoolsvgannotation.h"
#include "qgsmaptoolcircularstringcurvepoint.h"
@ -120,6 +121,7 @@ QgsAppMapTools::QgsAppMapTools( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockW
mTools.insert( Tool::MeasureDistance, new QgsMeasureTool( canvas, false /* area */ ) );
mTools.insert( Tool::MeasureArea, new QgsMeasureTool( canvas, true /* area */ ) );
mTools.insert( Tool::MeasureAngle, new QgsMapToolMeasureAngle( canvas ) );
mTools.insert( Tool::MeasureBearing, new QgsMapToolMeasureBearing( canvas ) );
mTools.insert( Tool::TextAnnotation, new QgsMapToolTextAnnotation( canvas ) );
mTools.insert( Tool::FormAnnotation, new QgsMapToolFormAnnotation( canvas ) );
mTools.insert( Tool::HtmlAnnotation, new QgsMapToolHtmlAnnotation( canvas ) );

View File

@ -56,6 +56,7 @@ class QgsAppMapTools
MeasureDistance,
MeasureArea,
MeasureAngle,
MeasureBearing,
AddFeature,
CircularStringCurvePoint,
CircularStringRadius,

View File

@ -457,6 +457,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmaptoolidentifyaction.h"
#include "qgsmaptoolpinlabels.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgsmaptoolmeasurebearing.h"
#include "qgsmaptoolrotatepointsymbols.h"
#include "qgsmaptooldigitizefeature.h"
#include "qgsmaptooloffsetpointsymbol.h"
@ -2643,6 +2644,7 @@ void QgisApp::createActions()
connect( mActionMeasure, &QAction::triggered, this, &QgisApp::measure );
connect( mActionMeasureArea, &QAction::triggered, this, &QgisApp::measureArea );
connect( mActionMeasureAngle, &QAction::triggered, this, &QgisApp::measureAngle );
connect( mActionMeasureBearing, &QAction::triggered, this, [ = ] { setMapTool( mMapTools->mapTool( QgsAppMapTools::MeasureBearing ) ); } );
connect( mActionZoomFullExtent, &QAction::triggered, this, &QgisApp::zoomFull );
connect( mActionZoomToLayer, &QAction::triggered, this, &QgisApp::zoomToLayerExtent );
connect( mActionZoomToLayers, &QAction::triggered, this, &QgisApp::zoomToLayerExtent );
@ -2951,6 +2953,7 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionMeasure );
mMapToolGroup->addAction( mActionMeasureArea );
mMapToolGroup->addAction( mActionMeasureAngle );
mMapToolGroup->addAction( mActionMeasureBearing );
mMapToolGroup->addAction( mActionAddFeature );
mMapToolGroup->addAction( mActionCircularStringCurvePoint );
mMapToolGroup->addAction( mActionCircularStringRadius );
@ -3396,6 +3399,7 @@ void QgisApp::createToolBars()
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionMeasure );
bt->addAction( mActionMeasureArea );
bt->addAction( mActionMeasureBearing );
bt->addAction( mActionMeasureAngle );
QAction *defMeasureAction = mActionMeasure;
@ -3408,6 +3412,9 @@ void QgisApp::createToolBars()
defMeasureAction = mActionMeasureArea;
break;
case 2:
defMeasureAction = mActionMeasureBearing;
break;
case 3:
defMeasureAction = mActionMeasureAngle;
break;
}
@ -4078,6 +4085,7 @@ void QgisApp::setTheme( const QString &themeName )
mActionMeasure->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasure.svg" ) ) );
mActionMeasureArea->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasureArea.svg" ) ) );
mActionMeasureAngle->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasureAngle.svg" ) ) );
mActionMeasureBearing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasureBearing.svg" ) ) );
mActionMapTips->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapTips.svg" ) ) );
mActionShowBookmarkManager->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowBookmarks.svg" ) ) );
mActionShowBookmarks->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowBookmarks.svg" ) ) );
@ -4297,6 +4305,7 @@ void QgisApp::setupCanvasTools()
mMapTools->mapTool( QgsAppMapTools::MeasureDistance )->setAction( mActionMeasure );
mMapTools->mapTool( QgsAppMapTools::MeasureArea )->setAction( mActionMeasureArea );
mMapTools->mapTool( QgsAppMapTools::MeasureAngle )->setAction( mActionMeasureAngle );
mMapTools->mapTool( QgsAppMapTools::MeasureBearing )->setAction( mActionMeasureBearing );
mMapTools->mapTool( QgsAppMapTools::TextAnnotation )->setAction( mActionTextAnnotation );
mMapTools->mapTool( QgsAppMapTools::FormAnnotation )->setAction( mActionFormAnnotation );
mMapTools->mapTool( QgsAppMapTools::HtmlAnnotation )->setAction( mActionHtmlAnnotation );
@ -12678,6 +12687,7 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString &currentPage, in
mMapTools->mapTool< QgsMeasureTool >( QgsAppMapTools::MeasureDistance )->updateSettings();
mMapTools->mapTool< QgsMeasureTool >( QgsAppMapTools::MeasureArea )->updateSettings();
mMapTools->mapTool< QgsMapToolMeasureAngle >( QgsAppMapTools::MeasureAngle )->updateSettings();
mMapTools->mapTool< QgsMapToolMeasureBearing >( QgsAppMapTools::MeasureBearing )->updateSettings();
#ifdef HAVE_3D
const QList< Qgs3DMapCanvasDockWidget * > canvases3D = findChildren< Qgs3DMapCanvasDockWidget * >();
@ -14599,6 +14609,7 @@ void QgisApp::projectProperties( const QString &currentPage )
mMapTools->mapTool< QgsMeasureTool >( QgsAppMapTools::MeasureDistance )->updateSettings();
mMapTools->mapTool< QgsMeasureTool >( QgsAppMapTools::MeasureArea )->updateSettings();
mMapTools->mapTool< QgsMapToolMeasureAngle >( QgsAppMapTools::MeasureAngle )->updateSettings();
mMapTools->mapTool< QgsMapToolMeasureBearing >( QgsAppMapTools::MeasureBearing )->updateSettings();
// Set the window title.
setTitleBarText_( *this );

View File

@ -19,26 +19,36 @@
#include "qgsunittypes.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgssettings.h"
#include "qgsprojectdisplaysettings.h"
#include "qgsproject.h"
#include "qgsbearingnumericformat.h"
#include <cmath>
QgsDisplayAngle::QgsDisplayAngle( QgsMapToolMeasureAngle *tool, Qt::WindowFlags f )
QgsDisplayAngle::QgsDisplayAngle( QgsMapTool *tool, Qt::WindowFlags f )
: QDialog( tool->canvas()->topLevelWidget(), f )
, mTool( tool )
{
setupUi( this );
}
void QgsDisplayAngle::setValueInRadians( double value )
void QgsDisplayAngle::setAngleInRadians( double value )
{
mValue = value;
updateUi();
}
void QgsDisplayAngle::updateUi()
{
QgsSettings settings;
QgsUnitTypes::AngleUnit unit = QgsUnitTypes::decodeAngleUnit( settings.value( QStringLiteral( "qgis/measure/angleunits" ), QgsUnitTypes::encodeUnit( QgsUnitTypes::AngleDegrees ) ).toString() );
int decimals = settings.value( QStringLiteral( "qgis/measure/decimalplaces" ), 3 ).toInt();
mAngleLineEdit->setText( QgsUnitTypes::formatAngle( mValue * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AngleRadians, unit ), decimals, unit ) );
}
void QgsDisplayAngle::setBearingInRadians( double value )
{
mValue = value;
const double degrees = value * 180.0 / M_PI;
QgsNumericFormatContext context;
const QString valueAsText = QgsProject::instance()->displaySettings()->bearingFormat()->formatDouble( degrees, context );
mAngleLineEdit->setText( valueAsText );
}

View File

@ -19,7 +19,7 @@
#include "ui_qgsdisplayanglebase.h"
#include "qgis_app.h"
class QgsMapToolMeasureAngle;
class QgsMapTool;
//! A class that displays results of angle measurements with the proper unit
class APP_EXPORT QgsDisplayAngle: public QDialog, private Ui::QgsDisplayAngleBase
@ -27,23 +27,35 @@ class APP_EXPORT QgsDisplayAngle: public QDialog, private Ui::QgsDisplayAngleBas
Q_OBJECT
public:
QgsDisplayAngle( QgsMapToolMeasureAngle *tool = nullptr, Qt::WindowFlags f = Qt::WindowFlags() );
QgsDisplayAngle( QgsMapTool *tool = nullptr, Qt::WindowFlags f = Qt::WindowFlags() );
/**
* Sets the measured angle value (in radians). The value is going to
* be converted to degrees / gon automatically if necessary.
*/
void setValueInRadians( double value );
void setAngleInRadians( double value );
/**
* Sets the measured bearing (in radians).
*/
void setBearingInRadians( double value );
/**
* Returns the current angular value (in radians)
*/
double value() const { return mValue; }
/**
* Returns the current value, as a string.
*/
QString text() const { return mAngleLineEdit->text(); }
private:
//! pointer to tool which owns this dialog
QgsMapToolMeasureAngle *mTool = nullptr;
QgsMapTool *mTool = nullptr;
//! The value we're showing
double mValue = 0.0;
//! Updates UI according to user settings.
void updateUi();
};
#endif // QGSDISPLAYANGLE_H

View File

@ -80,7 +80,7 @@ void QgsMapToolMeasureAngle::canvasMoveEvent( QgsMapMouseEvent *e )
}
}
mResultDisplay->setValueInRadians( resultAngle );
mResultDisplay->setAngleInRadians( resultAngle );
}
}
@ -210,7 +210,7 @@ void QgsMapToolMeasureAngle::updateSettings()
}
}
mResultDisplay->setValueInRadians( resultAngle );
mResultDisplay->setAngleInRadians( resultAngle );
}
void QgsMapToolMeasureAngle::configureDistanceArea()

View File

@ -0,0 +1,188 @@
/***************************************************************************
qgsmaptoolmeasurebearing.cpp
------------------------
begin : June 2021
copyright : (C) 2021 by Nyall Dawson
email : nyall dot dawson 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 "qgsmaptoolmeasurebearing.h"
#include "qgsdisplayangle.h"
#include "qgsdistancearea.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaptopixel.h"
#include "qgsproject.h"
#include "qgsrubberband.h"
#include "qgssnappingutils.h"
#include "qgssettings.h"
#include "qgssnapindicator.h"
#include "qgsmapmouseevent.h"
#include <cmath>
QgsMapToolMeasureBearing::QgsMapToolMeasureBearing( QgsMapCanvas *canvas )
: QgsMapTool( canvas )
, mSnapIndicator( new QgsSnapIndicator( canvas ) )
{
mToolName = tr( "Measure bearing" );
connect( canvas, &QgsMapCanvas::destinationCrsChanged,
this, &QgsMapToolMeasureBearing::updateSettings );
}
QgsMapToolMeasureBearing::~QgsMapToolMeasureBearing()
{
stopMeasuring();
}
void QgsMapToolMeasureBearing::canvasMoveEvent( QgsMapMouseEvent *e )
{
QgsPointXY point = e->snapPoint();
mSnapIndicator->setMatch( e->mapPointMatch() );
if ( !mRubberBand || mAnglePoints.empty() || mAnglePoints.size() >= 2 )
{
return;
}
mRubberBand->movePoint( point );
if ( mAnglePoints.size() == 1 )
{
if ( !mResultDisplay->isVisible() )
{
mResultDisplay->move( e->pos() - QPoint( 100, 100 ) );
mResultDisplay->show();
}
const double bearing = mDa.bearing( mAnglePoints.at( 0 ), point );
mResultDisplay->setBearingInRadians( bearing );
}
}
void QgsMapToolMeasureBearing::canvasReleaseEvent( QgsMapMouseEvent *e )
{
// if we clicked the right button we cancel the operation, unless it's the "final" click
if ( e->button() == Qt::RightButton && mAnglePoints.size() != 1 )
{
stopMeasuring();
return;
}
//add points until we have two
if ( mAnglePoints.size() == 2 )
{
mAnglePoints.clear();
}
if ( mAnglePoints.empty() )
{
if ( !mResultDisplay )
{
mResultDisplay = new QgsDisplayAngle( this );
mResultDisplay->setWindowFlags( mResultDisplay->windowFlags() | Qt::Tool );
mResultDisplay->setWindowTitle( tr( "Bearing" ) );
connect( mResultDisplay, &QDialog::rejected, this, &QgsMapToolMeasureBearing::stopMeasuring );
}
configureDistanceArea();
createRubberBand();
}
if ( mAnglePoints.size() < 2 )
{
QgsPointXY newPoint = e->snapPoint();
mAnglePoints.push_back( newPoint );
mRubberBand->addPoint( newPoint );
}
}
void QgsMapToolMeasureBearing::keyPressEvent( QKeyEvent *e )
{
if ( e->key() == Qt::Key_Escape )
{
stopMeasuring();
}
else if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
{
if ( !mAnglePoints.empty() && mRubberBand )
{
if ( mAnglePoints.size() == 1 )
{
//removing first point, so restart everything
stopMeasuring();
}
else
{
//remove second last point from line band, and last point from points band
mRubberBand->removePoint( -2, true );
mAnglePoints.removeLast();
}
}
// Override default shortcut management in MapCanvas
e->ignore();
}
}
void QgsMapToolMeasureBearing::stopMeasuring()
{
delete mRubberBand;
mRubberBand = nullptr;
delete mResultDisplay;
mResultDisplay = nullptr;
mAnglePoints.clear();
}
void QgsMapToolMeasureBearing::activate()
{
QgsMapTool::activate();
}
void QgsMapToolMeasureBearing::deactivate()
{
mSnapIndicator->setMatch( QgsPointLocator::Match() );
stopMeasuring();
QgsMapTool::deactivate();
}
void QgsMapToolMeasureBearing::createRubberBand()
{
delete mRubberBand;
mRubberBand = new QgsRubberBand( mCanvas, QgsWkbTypes::LineGeometry );
QgsSettings settings;
int myRed = settings.value( QStringLiteral( "qgis/default_measure_color_red" ), 180 ).toInt();
int myGreen = settings.value( QStringLiteral( "qgis/default_measure_color_green" ), 180 ).toInt();
int myBlue = settings.value( QStringLiteral( "qgis/default_measure_color_blue" ), 180 ).toInt();
mRubberBand->setColor( QColor( myRed, myGreen, myBlue, 100 ) );
mRubberBand->setWidth( 3 );
}
void QgsMapToolMeasureBearing::updateSettings()
{
if ( mAnglePoints.size() != 2 )
return;
if ( !mResultDisplay )
return;
configureDistanceArea();
const double bearing = mDa.bearing( mAnglePoints.at( 0 ), mAnglePoints.at( 1 ) );
mResultDisplay->setBearingInRadians( bearing );
}
void QgsMapToolMeasureBearing::configureDistanceArea()
{
QString ellipsoidId = QgsProject::instance()->ellipsoid();
mDa.setSourceCrs( mCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
mDa.setEllipsoid( ellipsoidId );
}

View File

@ -0,0 +1,72 @@
/***************************************************************************
qgsmaptoolmeasurebearing.h
------------------------
begin : June 2021
copyright : (C) 2021 by Nyall Dawson
email : nyall dot dawson 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 QGSMAPTOOLMEASUREBEARING_H
#define QGSMAPTOOLMEASUREBEARING_H
#include "qgsmaptool.h"
#include "qgspointxy.h"
#include "qgsdistancearea.h"
#include "qgis_app.h"
class QgsDisplayAngle;
class QgsRubberBand;
class QgsSnapIndicator;
//! Map tool to measure bearing between two points
class APP_EXPORT QgsMapToolMeasureBearing: public QgsMapTool
{
Q_OBJECT
public:
QgsMapToolMeasureBearing( QgsMapCanvas *canvas );
~QgsMapToolMeasureBearing() override;
Flags flags() const override { return QgsMapTool::AllowZoomRect; }
void canvasMoveEvent( QgsMapMouseEvent *e ) override;
void canvasReleaseEvent( QgsMapMouseEvent *e ) override;
void keyPressEvent( QKeyEvent *e ) override;
void activate() override;
void deactivate() override;
private:
//! Points defining the angle (three for measuring)
QList<QgsPointXY> mAnglePoints;
QgsRubberBand *mRubberBand = nullptr;
QgsDisplayAngle *mResultDisplay = nullptr;
//! Creates a new rubber band and deletes the old one
void createRubberBand();
//! Tool for measuring
QgsDistanceArea mDa;
std::unique_ptr<QgsSnapIndicator> mSnapIndicator;
public slots:
//! Recalculate angle if projection state changed
void updateSettings();
private slots:
//! Deletes the rubber band and the dialog
void stopMeasuring();
//! Configures distance area objects with ellipsoid / output crs
void configureDistanceArea();
friend class TestQgsMeasureBearingTool;
};
#endif // QGSMAPTOOLMEASUREBEARING_H

View File

@ -97,6 +97,7 @@
</property>
<addaction name="mActionMeasure"/>
<addaction name="mActionMeasureArea"/>
<addaction name="mActionMeasureBearing"/>
<addaction name="mActionMeasureAngle"/>
</widget>
<widget class="QMenu" name="mMenuDecorations">
@ -3533,9 +3534,25 @@ Shows placeholders for labels which could not be placed, e.g. due to overlaps wi
<string>Toggles stream digitizing mode</string>
</property>
</action>
<action name="mActionMeasureBearing">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionMeasureBearing.svg</normaloff>:/images/themes/default/mActionMeasureBearing.svg</iconset>
</property>
<property name="text">
<string>Measure Bearing</string>
</property>
<property name="toolTip">
<string>Measure Bearing</string>
</property>
</action>
</widget>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -79,6 +79,7 @@ ADD_QGIS_TEST(maptoolregularpolygontest testqgsmaptoolregularpolygon.cpp)
ADD_QGIS_TEST(maptoolsplitpartstest testqgsmaptoolsplitparts.cpp)
ADD_QGIS_TEST(maptoolsplitfeaturestest testqgsmaptoolsplitfeatures.cpp)
ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp)
ADD_QGIS_TEST(measurebearingtool testqgsmeasurebearingtool.cpp)
ADD_QGIS_TEST(vertextool testqgsvertextool.cpp)
ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp)
ADD_QGIS_TEST(maptoolreverselinetest testqgsmaptoolreverseline.cpp)

View File

@ -0,0 +1,160 @@
/***************************************************************************
testqgsmeasurebearingtool.cpp
----------------------
Date : 2021-06-15
Copyright : (C) 2021 by Nyall Dawson
Email : nyall dot dawson 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 "qgstest.h"
#include "qgisapp.h"
#include "qgsapplication.h"
#include "qgsvectorlayer.h"
#include "qgsfeature.h"
#include "qgsgeometry.h"
#include "qgsvectordataprovider.h"
#include "qgsmeasuretool.h"
#include "qgsmeasuredialog.h"
#include "qgsproject.h"
#include "qgsmapcanvas.h"
#include "qgsunittypes.h"
#include "qgsmaptoolmeasurebearing.h"
#include "testqgsmaptoolutils.h"
#include "qgsdisplayangle.h"
/**
* \ingroup UnitTests
* This is a unit test for the measure bearing tool
*/
class TestQgsMeasureBearingTool : public QObject
{
Q_OBJECT
public:
TestQgsMeasureBearingTool();
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init() {} // will be called before each testfunction is executed.
void cleanup() {} // will be called after every testfunction.
void testBearingCartesian();
void testBearingEllipsoid();
private:
QgisApp *mQgisApp = nullptr;
QgsMapCanvas *mCanvas = nullptr;
};
TestQgsMeasureBearingTool::TestQgsMeasureBearingTool() = default;
//runs before all tests
void TestQgsMeasureBearingTool::initTestCase()
{
qDebug() << "TestQgisAppClipboard::initTestCase()";
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
// Set up the QgsSettings environment
QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
mQgisApp = new QgisApp();
mCanvas = new QgsMapCanvas();
mCanvas->setFrameStyle( QFrame::NoFrame );
mCanvas->resize( 50, 50 );
mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) ) );
mCanvas->setExtent( QgsRectangle( -11554312, -5082786, 15123372, 11957046 ) );
mCanvas->show(); // to make the canvas resize
mCanvas->hide();
// enforce C locale because the tests expect it
// (decimal separators / thousand separators)
QLocale::setDefault( QLocale::c() );
}
//runs after all tests
void TestQgsMeasureBearingTool::cleanupTestCase()
{
delete mCanvas;
QgsApplication::exitQgis();
}
void TestQgsMeasureBearingTool::testBearingCartesian()
{
// set project CRS and set ellipsoid to none, so that Cartesian calculations are performed
QgsCoordinateReferenceSystem srs( QStringLiteral( "EPSG:3857" ) );
QgsProject::instance()->setCrs( srs );
QgsProject::instance()->setEllipsoid( QString() );
QgsMapToolMeasureBearing *mapTool = new QgsMapToolMeasureBearing( mCanvas ) ;
mCanvas->setMapTool( mapTool );
QVERIFY( !mapTool->mResultDisplay );
TestQgsMapToolUtils tools( mapTool );
tools.mouseMove( 8749058, 1916460 );
tools.mouseClick( 8749058, 1916460, Qt::LeftButton );
tools.mouseMove( 14498439, -2694154 );
QVERIFY( mapTool->mResultDisplay );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), 2.1995926132, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "126.027373\u00B0E" ) );
tools.mouseClick( 14498439, -2694154, Qt::LeftButton );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), 2.1995926132, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "126.027373\u00B0E" ) );
tools.mouseMove( 555496, 3291312 );
tools.mouseClick( 555496, 3291312, Qt::LeftButton );
tools.mouseMove( -611045, 5082786 );
tools.mouseClick( -611045, 5082786, Qt::LeftButton );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), -0.5880026035, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "33.690068\u00B0W" ) );
}
void TestQgsMeasureBearingTool::testBearingEllipsoid()
{
// set project CRS and ellipsoid
QgsCoordinateReferenceSystem srs( QStringLiteral( "EPSG:3857" ) );
QgsProject::instance()->setCrs( srs );
QgsProject::instance()->setEllipsoid( QStringLiteral( "EPSG:7030" ) );
QgsMapToolMeasureBearing *mapTool = new QgsMapToolMeasureBearing( mCanvas ) ;
mCanvas->setMapTool( mapTool );
QVERIFY( !mapTool->mResultDisplay );
TestQgsMapToolUtils tools( mapTool );
tools.mouseMove( 8749058, 1916460 );
tools.mouseClick( 8749058, 1916460, Qt::LeftButton );
tools.mouseMove( 14498439, -2694154 );
QVERIFY( mapTool->mResultDisplay );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), 2.1679949043, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "124.216958\u00B0E" ) );
tools.mouseClick( 14498439, -2694154, Qt::LeftButton );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), 2.1679949043, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "124.216958\u00B0E" ) );
tools.mouseMove( 555496, 3291312 );
tools.mouseClick( 555496, 3291312, Qt::LeftButton );
tools.mouseMove( -611045, 5082786 );
tools.mouseClick( -611045, 5082786, Qt::LeftButton );
QGSCOMPARENEAR( mapTool->mResultDisplay->value(), -0.5448498177, 0.001 );
QCOMPARE( mapTool->mResultDisplay->text(), QStringLiteral( "31.217595\u00B0W" ) );
}
QGSTEST_MAIN( TestQgsMeasureBearingTool )
#include "testqgsmeasurebearingtool.moc"