Skip to content

Commit

Permalink
[feature] Add a "measure bearing" map tool
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nyalldawson committed Jun 18, 2021
1 parent 6596d87 commit d83a769
Show file tree
Hide file tree
Showing 14 changed files with 492 additions and 15 deletions.
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions images/themes/default/mActionMeasureBearing.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -86,6 +86,7 @@ set(QGIS_APP_SRCS
qgsmaptoolhtmlannotation.cpp
qgsmaptoolidentifyaction.cpp
qgsmaptoolmeasureangle.cpp
qgsmaptoolmeasurebearing.cpp
qgsmaptoolmovefeature.cpp
qgsmaptooloffsetcurve.cpp
qgsmaptooloffsetpointsymbol.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/app/maptools/qgsappmaptools.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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 ) );
Expand Down
1 change: 1 addition & 0 deletions src/app/maptools/qgsappmaptools.h
Expand Up @@ -56,6 +56,7 @@ class QgsAppMapTools
MeasureDistance,
MeasureArea,
MeasureAngle,
MeasureBearing,
AddFeature,
CircularStringCurvePoint,
CircularStringRadius,
Expand Down
11 changes: 11 additions & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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;
Expand All @@ -3408,6 +3412,9 @@ void QgisApp::createToolBars()
defMeasureAction = mActionMeasureArea;
break;
case 2:
defMeasureAction = mActionMeasureBearing;
break;
case 3:
defMeasureAction = mActionMeasureAngle;
break;
}
Expand Down Expand Up @@ -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" ) ) );
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 * >();
Expand Down Expand Up @@ -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 );
Expand Down
22 changes: 16 additions & 6 deletions src/app/qgsdisplayangle.cpp
Expand Up @@ -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 );
}
26 changes: 19 additions & 7 deletions src/app/qgsdisplayangle.h
Expand Up @@ -19,31 +19,43 @@
#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
{
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
4 changes: 2 additions & 2 deletions src/app/qgsmaptoolmeasureangle.cpp
Expand Up @@ -80,7 +80,7 @@ void QgsMapToolMeasureAngle::canvasMoveEvent( QgsMapMouseEvent *e )
}
}

mResultDisplay->setValueInRadians( resultAngle );
mResultDisplay->setAngleInRadians( resultAngle );
}
}

Expand Down Expand Up @@ -210,7 +210,7 @@ void QgsMapToolMeasureAngle::updateSettings()
}
}

mResultDisplay->setValueInRadians( resultAngle );
mResultDisplay->setAngleInRadians( resultAngle );
}

void QgsMapToolMeasureAngle::configureDistanceArea()
Expand Down

0 comments on commit d83a769

Please sign in to comment.