Skip to content

Commit

Permalink
[feature] Add an option to cartesian measurement
Browse files Browse the repository at this point in the history
Adds an option force Cartesian measurements to the measure distance/area dialogue

Fixes #19902
  • Loading branch information
lbartoletti authored and nyalldawson committed Feb 22, 2019
1 parent db1a192 commit fbc22e2
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 59 deletions.
103 changes: 58 additions & 45 deletions src/app/qgsmeasuredialog.cpp
Expand Up @@ -79,10 +79,27 @@ QgsMeasureDialog::QgsMeasureDialog( QgsMeasureTool *tool, Qt::WindowFlags f )
connect( mUnitsCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsMeasureDialog::unitsChanged );
connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsMeasureDialog::reject );
connect( mCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsMeasureDialog::crsChanged );
connect( mCartesian, &QRadioButton::toggled, this, &QgsMeasureDialog::projChanged );

groupBox->setCollapsed( true );
}

void QgsMeasureDialog::projChanged()
{
if ( mCartesian->isChecked() )
{
mDa.setEllipsoid( GEO_NONE );
}
else
{
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
}

mTable->clear();
mTotal = 0.;
updateUi();
}

void QgsMeasureDialog::openConfigTab()
{
QgisApp::instance()->showOptionsDialog( this, QStringLiteral( "mOptionsPageMapTools" ) );
Expand All @@ -102,6 +119,9 @@ void QgsMeasureDialog::crsChanged()
{
mUnitsCombo->setEnabled( true );
}

mTable->clear();
mTotal = 0.;
updateUi();
}

Expand All @@ -116,23 +136,18 @@ void QgsMeasureDialog::updateSettings()
mMapDistanceUnits = QgsProject::instance()->crs().mapUnits();
mAreaUnits = QgsProject::instance()->areaUnits();
mDa.setSourceCrs( mCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
projChanged();

mTable->clear();
mTotal = 0;
updateUi();

if ( !mCanvas->mapSettings().destinationCrs().isValid() ||
if ( mCartesian->isChecked() || !mCanvas->mapSettings().destinationCrs().isValid() ||
( mCanvas->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
&& mDistanceUnits == QgsUnitTypes::DistanceDegrees ) )
{
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
}
else
{
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mForceCartesian = false;
}
}

Expand Down Expand Up @@ -164,6 +179,7 @@ void QgsMeasureDialog::unitsChanged( int index )
mUseMapUnits = false;
}
}

mTable->clear();
mTotal = 0.;
updateUi();
Expand All @@ -188,19 +204,6 @@ void QgsMeasureDialog::restart()

void QgsMeasureDialog::mouseMove( const QgsPointXY &point )
{
if ( !mCanvas->mapSettings().destinationCrs().isValid() ||
( mCanvas->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
&& mDistanceUnits == QgsUnitTypes::DistanceDegrees ) )
{
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
}
else
{
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mForceCartesian = false;
}

mLastMousePoint = point;
// show current distance/area while moving the point
// by creating a temporary copy of point array
Expand All @@ -217,9 +220,8 @@ void QgsMeasureDialog::mouseMove( const QgsPointXY &point )
QVector< QgsPointXY > tmpPoints = mTool->points();
QgsPointXY p1( tmpPoints.at( tmpPoints.size() - 1 ) ), p2( point );
double d = mDa.measureLine( p1, p2 );
editTotal->setText( formatDistance( mTotal + d, !mForceCartesian ) );
if ( !mForceCartesian )
d = convertLength( d, mDistanceUnits );
editTotal->setText( formatDistance( mTotal + d, mConvertToDisplayUnits ) );
d = convertLength( d, mDistanceUnits );

// Set moving
QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
Expand Down Expand Up @@ -250,7 +252,7 @@ void QgsMeasureDialog::addPoint()
if ( numPoints > 1 )
{
mTotal = mDa.measureLine( mTool->points() );
editTotal->setText( formatDistance( mTotal, !mForceCartesian ) );
editTotal->setText( formatDistance( mTotal, mConvertToDisplayUnits ) );
}
}
}
Expand Down Expand Up @@ -294,7 +296,7 @@ void QgsMeasureDialog::removeLastPoint()
}
else
{
editTotal->setText( formatDistance( mTotal, !mForceCartesian ) );
editTotal->setText( formatDistance( mTotal, mConvertToDisplayUnits ) );
}
}
}
Expand Down Expand Up @@ -359,19 +361,25 @@ void QgsMeasureDialog::updateUi()
QString toolTip = tr( "The calculations are based on:" );

mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mForceCartesian = false;
bool convertToDisplayUnits = true;
mConvertToDisplayUnits = true;

if ( mMeasureArea )
{
if ( !mCanvas->mapSettings().destinationCrs().isValid() )
if ( mCartesian->isChecked() || !mCanvas->mapSettings().destinationCrs().isValid() )
{
// no CRS => no units, newb!
toolTip += "<br> * " + tr( "No map projection set, so area is calculated using Cartesian calculations." );
toolTip += "<br> * " + tr( "Units are unknown." );
toolTip += "<br> * ";
if ( mCartesian->isChecked() )
{
toolTip += tr( "Cartesian calculation selected, so area is calculated using Cartesian calculations." );
mConvertToDisplayUnits = true;
}
else
{
toolTip += tr( "No map projection set, so area is calculated using Cartesian calculations." );
toolTip += "<br> * " + tr( "Units are unknown." );
mConvertToDisplayUnits = false;
}
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
convertToDisplayUnits = false;
}
else if ( mCanvas->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
&& ( mAreaUnits == QgsUnitTypes::AreaSquareDegrees || mAreaUnits == QgsUnitTypes::AreaUnknownUnit ) )
Expand All @@ -380,8 +388,7 @@ void QgsMeasureDialog::updateUi()
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured area are in degrees, so area is calculated using Cartesian calculations in square degrees." ).arg(
mCanvas->mapSettings().destinationCrs().description() );
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
convertToDisplayUnits = false; //not required since we will be measuring in degrees
mConvertToDisplayUnits = false; //not required since we will be measuring in degrees
}
else
{
Expand Down Expand Up @@ -436,14 +443,21 @@ void QgsMeasureDialog::updateUi()
}
else
{
if ( !mCanvas->mapSettings().destinationCrs().isValid() )
if ( mCartesian->isChecked() || !mCanvas->mapSettings().destinationCrs().isValid() )
{
// no CRS => no units, newb!
toolTip += "<br> * " + tr( "No map projection set, so distance is calculated using Cartesian calculations." );
toolTip += "<br> * " + tr( "Units are unknown." );
toolTip += "<br> * ";
if ( mCartesian->isChecked() )
{
toolTip += tr( "Cartesian calculation selected, so area is calculated using Cartesian calculations." );
mConvertToDisplayUnits = true;
}
else
{
toolTip += tr( "No map projection set, so area is calculated using Cartesian calculations." );
toolTip += "<br> * " + tr( "Units are unknown." );
mConvertToDisplayUnits = false;
}
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
convertToDisplayUnits = false;
}
else if ( mCanvas->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
&& mDistanceUnits == QgsUnitTypes::DistanceDegrees )
Expand All @@ -452,8 +466,7 @@ void QgsMeasureDialog::updateUi()
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured length are in degrees, so distance is calculated using Cartesian calculations in degrees." ).arg(
mCanvas->mapSettings().destinationCrs().description() );
mDa.setEllipsoid( GEO_NONE );
mForceCartesian = true;
convertToDisplayUnits = false; //not required since we will be measuring in degrees
mConvertToDisplayUnits = false; //not required since we will be measuring in degrees
}
else
{
Expand Down Expand Up @@ -560,7 +573,7 @@ void QgsMeasureDialog::updateUi()
{
double d = -1;
d = mDa.measureLine( p1, p2 );
if ( !mForceCartesian )
if ( mConvertToDisplayUnits )
{
if ( mDistanceUnits == QgsUnitTypes::DistanceUnknownUnit && mMapDistanceUnits != QgsUnitTypes::DistanceUnknownUnit )
d = convertLength( d, mMapDistanceUnits );
Expand All @@ -579,7 +592,7 @@ void QgsMeasureDialog::updateUi()

mTotal = mDa.measureLine( mTool->points() );
mTable->show(); // Show the table with items
editTotal->setText( formatDistance( mTotal, convertToDisplayUnits ) );
editTotal->setText( formatDistance( mTotal, mConvertToDisplayUnits ) );
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/app/qgsmeasuredialog.h
Expand Up @@ -72,6 +72,8 @@ class APP_EXPORT QgsMeasureDialog : public QDialog, private Ui::QgsMeasureBase

void crsChanged();

void projChanged();

private:

//! formats distance to most appropriate units
Expand Down Expand Up @@ -101,11 +103,8 @@ class APP_EXPORT QgsMeasureDialog : public QDialog, private Ui::QgsMeasureBase
//! Indicates whether the user chose "Map units" instead of directly selecting a unit
bool mUseMapUnits = false;

/**
* Indicates whether we need to measure distances in Cartesian instead of
* spherical coordinates, such as when measuring in degrees in a geographic CRS
*/
bool mForceCartesian = true;
//! Indicates whether we need to convert units.
bool mConvertToDisplayUnits = true;

//! Number of decimal places we want.
int mDecimalPlaces = 3;
Expand Down
29 changes: 24 additions & 5 deletions src/ui/qgsmeasurebase.ui
Expand Up @@ -21,8 +21,7 @@
</property>
<property name="windowIcon">
<iconset>
<normaloff/>
</iconset>
<normaloff>.</normaloff>.</iconset>
</property>
<layout class="QGridLayout">
<property name="leftMargin">
Expand Down Expand Up @@ -101,19 +100,19 @@
<string>Segments</string>
</property>
<property name="textAlignment">
<set>AlignRight|AlignVCenter</set>
<set>AlignTrailing|AlignVCenter</set>
</property>
</column>
</widget>
</item>
<item row="6" column="0" colspan="4">
<item row="7" column="0" colspan="4">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<item row="6" column="0" colspan="4">
<widget class="QgsCollapsibleGroupBox" name="groupBox">
<property name="title">
<string>Info</string>
Expand All @@ -132,6 +131,26 @@
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QRadioButton" name="mCartesian">
<property name="text">
<string>Cartesian</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QRadioButton" name="mEllipsoidal">
<property name="text">
<string>Ellipsoidal</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
Expand Down

0 comments on commit fbc22e2

Please sign in to comment.