Skip to content

Commit 899888d

Browse files
committed
[FEATURE] Allow setting project CRS to "no projection"
This replaces the older "OTF off" setting. If a project has no projection set, then the following things happen: - no reprojection is done while rendering - features are just drawn using their raw coordinates - ellipsoid, distance and area units, and coordinate display are locked out. - all measurements are done in unknown map units, and no conversion is possible. As well as addressing the use cases in which users disabled OTF reprojection, this setting may also be useful for users who use QGIS to create "non-earth" maps, such as RPG or fantasy maps, or for microscopic analysis, or some other local reference system not related to earth based projections.
1 parent 3c7c65e commit 899888d

11 files changed

+249
-98
lines changed

src/app/qgisapp.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -10268,11 +10268,20 @@ void QgisApp::removeWebToolBarIcon( QAction *qAction )
1026810268

1026910269
void QgisApp::updateCrsStatusBar()
1027010270
{
10271-
mOnTheFlyProjectionStatusButton->setText( mMapCanvas->mapSettings().destinationCrs().authid() );
10271+
if ( QgsProject::instance()->crs().isValid() )
10272+
{
10273+
mOnTheFlyProjectionStatusButton->setText( QgsProject::instance()->crs().authid() );
1027210274

10273-
mOnTheFlyProjectionStatusButton->setToolTip(
10274-
tr( "Current CRS: %1" ).arg( mMapCanvas->mapSettings().destinationCrs().description() ) );
10275-
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconProjectionEnabled.svg" ) ) );
10275+
mOnTheFlyProjectionStatusButton->setToolTip(
10276+
tr( "Current CRS: %1" ).arg( mMapCanvas->mapSettings().destinationCrs().description() ) );
10277+
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconProjectionEnabled.svg" ) ) );
10278+
}
10279+
else
10280+
{
10281+
mOnTheFlyProjectionStatusButton->setText( QString() );
10282+
mOnTheFlyProjectionStatusButton->setToolTip( tr( "No projection" ) );
10283+
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconProjectionDisabled.svg" ) ) );
10284+
}
1027610285
}
1027710286

1027810287
void QgisApp::destinationCrsChanged()

src/app/qgsmeasuredialog.cpp

+58-7
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,20 @@ QgsMeasureDialog::QgsMeasureDialog( QgsMeasureTool* tool, Qt::WindowFlags f )
5555
else
5656
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsProject::instance()->distanceUnits() ) );
5757

58+
if ( !mTool->canvas()->mapSettings().destinationCrs().isValid() )
59+
{
60+
mUnitsCombo->setEnabled( false );
61+
if ( mMeasureArea )
62+
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsUnitTypes::DistanceUnknownUnit ) );
63+
else
64+
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsUnitTypes::AreaUnknownUnit ) );
65+
}
66+
5867
updateSettings();
5968

6069
connect( mUnitsCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( unitsChanged( int ) ) );
6170
connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
71+
connect( mTool->canvas(), &QgsMapCanvas::destinationCrsChanged, this, &QgsMeasureDialog::crsChanged );
6272

6373
groupBox->setCollapsed( true );
6474
}
@@ -68,6 +78,23 @@ void QgsMeasureDialog::openConfigTab()
6878
QgisApp::instance()->showOptionsDialog( this, QStringLiteral( "mOptionsPageMapTools" ) );
6979
}
7080

81+
void QgsMeasureDialog::crsChanged()
82+
{
83+
if ( !mTool->canvas()->mapSettings().destinationCrs().isValid() )
84+
{
85+
mUnitsCombo->setEnabled( false );
86+
if ( mMeasureArea )
87+
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsUnitTypes::DistanceUnknownUnit ) );
88+
else
89+
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsUnitTypes::AreaUnknownUnit ) );
90+
}
91+
else
92+
{
93+
mUnitsCombo->setEnabled( true );
94+
}
95+
updateUi();
96+
}
97+
7198
void QgsMeasureDialog::updateSettings()
7299
{
73100
QSettings settings;
@@ -268,8 +295,16 @@ void QgsMeasureDialog::updateUi()
268295

269296
if ( mMeasureArea )
270297
{
271-
if ( mTool->canvas()->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
272-
&& ( mAreaUnits == QgsUnitTypes::AreaSquareDegrees || mAreaUnits == QgsUnitTypes::AreaUnknownUnit ) )
298+
if ( !mTool->canvas()->mapSettings().destinationCrs().isValid() )
299+
{
300+
// no CRS => no units, newb!
301+
toolTip += "<br> * " + tr( "No map projection set, so area is calculated using cartesian calculations." );
302+
toolTip += "<br> * " + tr( "Units are unknown." );
303+
forceCartesian = true;
304+
convertToDisplayUnits = false;
305+
}
306+
else if ( mTool->canvas()->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
307+
&& ( mAreaUnits == QgsUnitTypes::AreaSquareDegrees || mAreaUnits == QgsUnitTypes::AreaUnknownUnit ) )
273308
{
274309
//both source and destination units are degrees
275310
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured area are in degrees, so area is calculated using cartesian calculations in square degrees." ).arg(
@@ -294,7 +329,7 @@ void QgsMeasureDialog::updateUi()
294329
toolTip += tr( "Area is calculated in %1, based on project CRS (%2)." ).arg( QgsUnitTypes::toString( resultUnit ),
295330
mTool->canvas()->mapSettings().destinationCrs().description() );
296331
}
297-
setWindowTitle( tr( "Measure (OTF on)" ) );
332+
setWindowTitle( tr( "Measure" ) );
298333

299334
if ( QgsUnitTypes::unitType( resultUnit ) == QgsUnitTypes::Geographic &&
300335
QgsUnitTypes::unitType( mAreaUnits ) == QgsUnitTypes::Standard )
@@ -330,8 +365,16 @@ void QgsMeasureDialog::updateUi()
330365
}
331366
else
332367
{
333-
if ( mTool->canvas()->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
334-
&& mDistanceUnits == QgsUnitTypes::DistanceDegrees )
368+
if ( !mTool->canvas()->mapSettings().destinationCrs().isValid() )
369+
{
370+
// no CRS => no units, newb!
371+
toolTip += "<br> * " + tr( "No map projection set, so distance is calculated using cartesian calculations." );
372+
toolTip += "<br> * " + tr( "Units are unknown." );
373+
forceCartesian = true;
374+
convertToDisplayUnits = false;
375+
}
376+
else if ( mTool->canvas()->mapSettings().destinationCrs().mapUnits() == QgsUnitTypes::DistanceDegrees
377+
&& mDistanceUnits == QgsUnitTypes::DistanceDegrees )
335378
{
336379
//both source and destination units are degrees
337380
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured length are in degrees, so distance is calculated using cartesian calculations in degrees." ).arg(
@@ -356,7 +399,7 @@ void QgsMeasureDialog::updateUi()
356399
toolTip += tr( "Distance is calculated in %1, based on project CRS (%2)." ).arg( QgsUnitTypes::toString( resultUnit ),
357400
mTool->canvas()->mapSettings().destinationCrs().description() );
358401
}
359-
setWindowTitle( tr( "Measure (OTF on)" ) );
402+
setWindowTitle( tr( "Measure" ) );
360403

361404
if ( QgsUnitTypes::unitType( resultUnit ) == QgsUnitTypes::Geographic &&
362405
QgsUnitTypes::unitType( mDistanceUnits ) == QgsUnitTypes::Standard )
@@ -402,7 +445,14 @@ void QgsMeasureDialog::updateUi()
402445
else
403446
{
404447
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( mDistanceUnits ) );
405-
mTable->setHeaderLabels( QStringList( tr( "Segments [%1]" ).arg( QgsUnitTypes::toString( mDistanceUnits ) ) ) );
448+
if ( mDistanceUnits != QgsUnitTypes::DistanceUnknownUnit )
449+
{
450+
mTable->setHeaderLabels( QStringList( tr( "Segments [%1]" ).arg( QgsUnitTypes::toString( mDistanceUnits ) ) ) );
451+
}
452+
else
453+
{
454+
mTable->setHeaderLabels( QStringList( tr( "Segments" ) ) );
455+
}
406456
}
407457

408458
if ( mMeasureArea )
@@ -481,6 +531,7 @@ void QgsMeasureDialog::repopulateComboBoxUnits( bool isArea )
481531
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMiles ), QgsUnitTypes::DistanceMiles );
482532
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceDegrees ), QgsUnitTypes::DistanceDegrees );
483533
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceNauticalMiles ), QgsUnitTypes::DistanceNauticalMiles );
534+
mUnitsCombo->addItem( tr( "map units" ), QgsUnitTypes::DistanceUnknownUnit );
484535
}
485536
}
486537

src/app/qgsmeasuredialog.h

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class APP_EXPORT QgsMeasureDialog : public QDialog, private Ui::QgsMeasureBase
7272
//! Open configuration tab
7373
void openConfigTab();
7474

75+
void crsChanged();
76+
7577
private:
7678

7779
//! formats distance to most appropriate units

src/app/qgsmeasuretool.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ QgsMeasureTool::QgsMeasureTool( QgsMapCanvas* canvas, bool measureArea )
5353
mDialog->setWindowFlags( mDialog->windowFlags() | Qt::Tool );
5454
mDialog->restorePosition();
5555

56-
connect( canvas, SIGNAL( destinationCrsChanged() ),
57-
this, SLOT( updateSettings() ) );
56+
connect( canvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsMeasureTool::updateSettings );
5857
}
5958

6059
QgsMeasureTool::~QgsMeasureTool()
@@ -81,7 +80,8 @@ void QgsMeasureTool::activate()
8180

8281
// If we suspect that they have data that is projected, yet the
8382
// map CRS is set to a geographic one, warn them.
84-
if ( mCanvas->mapSettings().destinationCrs().isGeographic() &&
83+
if ( mCanvas->mapSettings().destinationCrs().isValid() &&
84+
mCanvas->mapSettings().destinationCrs().isGeographic() &&
8585
( mCanvas->extent().height() > 360 ||
8686
mCanvas->extent().width() > 720 ) )
8787
{
@@ -129,7 +129,7 @@ void QgsMeasureTool::updateSettings()
129129
mRubberBandPoints->setColor( QColor( myRed, myGreen, myBlue, 150 ) );
130130

131131
// Reproject the points to the new destination CoordinateReferenceSystem
132-
if ( mRubberBand->size() > 0 && mDestinationCrs != mCanvas->mapSettings().destinationCrs() )
132+
if ( mRubberBand->size() > 0 && mDestinationCrs != mCanvas->mapSettings().destinationCrs() && mCanvas->mapSettings().destinationCrs().isValid() )
133133
{
134134
QList<QgsPoint> points = mPoints;
135135
bool lastDone = mDone;

0 commit comments

Comments
 (0)