mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
[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:
parent
6596d872b6
commit
d83a7698e2
@ -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>
|
||||
|
1
images/themes/default/mActionMeasureBearing.svg
Normal file
1
images/themes/default/mActionMeasureBearing.svg
Normal 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 |
@ -86,6 +86,7 @@ set(QGIS_APP_SRCS
|
||||
qgsmaptoolhtmlannotation.cpp
|
||||
qgsmaptoolidentifyaction.cpp
|
||||
qgsmaptoolmeasureangle.cpp
|
||||
qgsmaptoolmeasurebearing.cpp
|
||||
qgsmaptoolmovefeature.cpp
|
||||
qgsmaptooloffsetcurve.cpp
|
||||
qgsmaptooloffsetpointsymbol.cpp
|
||||
|
@ -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 ) );
|
||||
|
@ -56,6 +56,7 @@ class QgsAppMapTools
|
||||
MeasureDistance,
|
||||
MeasureArea,
|
||||
MeasureAngle,
|
||||
MeasureBearing,
|
||||
AddFeature,
|
||||
CircularStringCurvePoint,
|
||||
CircularStringRadius,
|
||||
|
@ -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 ¤tPage, 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 ¤tPage )
|
||||
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 );
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
188
src/app/qgsmaptoolmeasurebearing.cpp
Normal file
188
src/app/qgsmaptoolmeasurebearing.cpp
Normal 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 );
|
||||
}
|
72
src/app/qgsmaptoolmeasurebearing.h
Normal file
72
src/app/qgsmaptoolmeasurebearing.h
Normal 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
|
@ -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>
|
||||
|
@ -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)
|
||||
|
160
tests/src/app/testqgsmeasurebearingtool.cpp
Normal file
160
tests/src/app/testqgsmeasurebearingtool.cpp
Normal 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"
|
Loading…
x
Reference in New Issue
Block a user