From f579f1a449b0bf21902570a32dafc9546cb414bd Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 16 Oct 2017 11:36:57 +1000 Subject: [PATCH] Move bounds retrieval to QgsCoordinateReferenceSystem Allows reuse in scripts/plugins/etc --- python/core/qgscoordinatereferencesystem.sip | 11 +++ src/core/qgscoordinatereferencesystem.cpp | 43 ++++++++++++ src/core/qgscoordinatereferencesystem.h | 11 +++ src/gui/qgsprojectionselectiontreewidget.cpp | 69 ++++++------------- .../core/testqgscoordinatereferencesystem.cpp | 35 ++++++++++ 5 files changed, 120 insertions(+), 49 deletions(-) diff --git a/python/core/qgscoordinatereferencesystem.sip b/python/core/qgscoordinatereferencesystem.sip index ca41dfaaba0..98e1eb5b2a8 100644 --- a/python/core/qgscoordinatereferencesystem.sip +++ b/python/core/qgscoordinatereferencesystem.sip @@ -601,6 +601,17 @@ Returns whether this CRS is correctly initialized and usable :rtype: QgsUnitTypes.DistanceUnit %End + QgsRectangle bounds() const; +%Docstring + Returns the approximate bounds for the region the CRS is usable within. + + The returned bounds represent the latitude and longitude extent for the + projection in the WGS 84 CRS. + +.. versionadded:: 3.0 + :rtype: QgsRectangle +%End + void setValidationHint( const QString &html ); %Docstring diff --git a/src/core/qgscoordinatereferencesystem.cpp b/src/core/qgscoordinatereferencesystem.cpp index 27f8bb249b9..e29486cf4a8 100644 --- a/src/core/qgscoordinatereferencesystem.cpp +++ b/src/core/qgscoordinatereferencesystem.cpp @@ -1061,6 +1061,49 @@ QgsUnitTypes::DistanceUnit QgsCoordinateReferenceSystem::mapUnits() const return d->mMapUnits; } +QgsRectangle QgsCoordinateReferenceSystem::bounds() const +{ + if ( !d->mIsValid ) + return QgsRectangle(); + + //check the db is available + QString databaseFileName = QgsApplication::srsDatabaseFilePath(); + + sqlite3 *database = nullptr; + const char *tail = nullptr; + sqlite3_stmt *stmt = nullptr; + + int result = openDatabase( databaseFileName, &database ); + if ( result != SQLITE_OK ) + { + return QgsRectangle(); + } + + QString sql = QStringLiteral( "select west_bound_lon, north_bound_lat, east_bound_lon, south_bound_lat from tbl_srs " + "where srs_id=%1" ) + .arg( d->mSrsId ); + result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail ); + + QgsRectangle rect; + if ( result == SQLITE_OK ) + { + if ( sqlite3_step( stmt ) == SQLITE_ROW ) + { + double west = sqlite3_column_double( stmt, 0 ); + double north = sqlite3_column_double( stmt, 1 ); + double east = sqlite3_column_double( stmt, 2 ); + double south = sqlite3_column_double( stmt, 3 ); + rect = QgsRectangle( west, north, east, south ); + } + } + + // close the sqlite3 statement + sqlite3_finalize( stmt ); + sqlite3_close( database ); + + return rect; +} + // Mutators ----------------------------------- diff --git a/src/core/qgscoordinatereferencesystem.h b/src/core/qgscoordinatereferencesystem.h index 4e1fa5df00d..7c3cc5e4001 100644 --- a/src/core/qgscoordinatereferencesystem.h +++ b/src/core/qgscoordinatereferencesystem.h @@ -31,6 +31,7 @@ //qgis includes #include "qgis.h" #include "qgsunittypes.h" +#include "qgsrectangle.h" class QDomNode; class QDomDocument; @@ -580,6 +581,16 @@ class CORE_EXPORT QgsCoordinateReferenceSystem */ QgsUnitTypes::DistanceUnit mapUnits() const; + /** + * Returns the approximate bounds for the region the CRS is usable within. + * + * The returned bounds represent the latitude and longitude extent for the + * projection in the WGS 84 CRS. + * + * \since QGIS 3.0 + */ + QgsRectangle bounds() const; + // Mutators ----------------------------------- /** diff --git a/src/gui/qgsprojectionselectiontreewidget.cpp b/src/gui/qgsprojectionselectiontreewidget.cpp index 57379ad8cee..e4123596c22 100644 --- a/src/gui/qgsprojectionselectiontreewidget.cpp +++ b/src/gui/qgsprojectionselectiontreewidget.cpp @@ -1019,65 +1019,36 @@ long QgsProjectionSelectionTreeWidget::getLargestCrsIdMatch( const QString &sql void QgsProjectionSelectionTreeWidget::updateBoundsPreview() { - sqlite3 *database = nullptr; - const char *tail = nullptr; - sqlite3_stmt *stmt = nullptr; - QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem(); if ( !lvi || lvi->text( QgisCrsIdColumn ).isEmpty() ) return; - int result = sqlite3_open_v2( mSrsDatabaseFileName.toUtf8().data(), &database, SQLITE_OPEN_READONLY, nullptr ); - if ( result ) - { - QgsDebugMsg( QString( "Can't open * user * database: %1" ).arg( sqlite3_errmsg( database ) ) ); - //no need for assert because user db may not have been created yet + QgsCoordinateReferenceSystem currentCrs = crs(); + if ( !currentCrs.isValid() ) return; - } - QString sql = QStringLiteral( "select west_bound_lon, north_bound_lat, east_bound_lon, south_bound_lat from tbl_srs " - "where srs_id=%2" ) - .arg( lvi->text( QgisCrsIdColumn ) ); - result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail ); - - if ( result == SQLITE_OK ) + QgsRectangle rect = currentCrs.bounds(); + if ( !rect.isEmpty() ) { - if ( sqlite3_step( stmt ) == SQLITE_ROW ) - { - double west = sqlite3_column_double( stmt, 0 ); - double north = sqlite3_column_double( stmt, 1 ); - double east = sqlite3_column_double( stmt, 2 ); - double south = sqlite3_column_double( stmt, 3 ); - QgsRectangle rect( west, north, east, south ); - if ( !rect.isEmpty() ) - { - mPreviewBand->setToGeometry( QgsGeometry::fromRect( rect ), nullptr ); - mPreviewBand->setColor( QColor( 255, 0, 0, 65 ) ); - mAreaCanvas->setExtent( rect ); - mPreviewBand->show(); - mAreaCanvas->zoomOut(); - QString extentString = tr( "Extent: %1" ).arg( rect.toString( 2 ) ); - QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); - teProjection->setText( extentString + "\n" + proj4String ); - } - else - { - mPreviewBand->hide(); - mAreaCanvas->zoomToFullExtent(); - QString extentString = tr( "Extent: Extent not known" ); - QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); - teProjection->setText( extentString + "\n" + proj4String ); - } - } - + mPreviewBand->setToGeometry( QgsGeometry::fromRect( rect ), nullptr ); + mPreviewBand->setColor( QColor( 255, 0, 0, 65 ) ); + mAreaCanvas->setExtent( rect ); + mPreviewBand->show(); + mAreaCanvas->zoomOut(); + QString extentString = tr( "Extent: %1" ).arg( rect.toString( 2 ) ); + QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); + teProjection->setText( extentString + "\n" + proj4String ); + } + else + { + mPreviewBand->hide(); + mAreaCanvas->zoomToFullExtent(); + QString extentString = tr( "Extent: Extent not known" ); + QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); + teProjection->setText( extentString + "\n" + proj4String ); } - - // close the sqlite3 statement - sqlite3_finalize( stmt ); - sqlite3_close( database ); } - QStringList QgsProjectionSelectionTreeWidget::authorities() { sqlite3 *database = nullptr; diff --git a/tests/src/core/testqgscoordinatereferencesystem.cpp b/tests/src/core/testqgscoordinatereferencesystem.cpp index 55ed6257609..83839f2bc83 100644 --- a/tests/src/core/testqgscoordinatereferencesystem.cpp +++ b/tests/src/core/testqgscoordinatereferencesystem.cpp @@ -75,6 +75,7 @@ class TestQgsCoordinateReferenceSystem: public QObject void createFromProj4Invalid(); void validSrsIds(); void asVariant(); + void bounds(); private: void debugPrint( QgsCoordinateReferenceSystem &crs ); @@ -764,5 +765,39 @@ void TestQgsCoordinateReferenceSystem::asVariant() QCOMPARE( fromVar.authid(), original.authid() ); } +void TestQgsCoordinateReferenceSystem::bounds() +{ + QgsCoordinateReferenceSystem invalid; + QVERIFY( invalid.bounds().isNull() ); + + QgsCoordinateReferenceSystem crs3111( "EPSG:3111" ); + QgsRectangle bounds = crs3111.bounds(); + QGSCOMPARENEAR( bounds.xMinimum(), 140.960000, 0.0001 ); + QGSCOMPARENEAR( bounds.xMaximum(), 150.040000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMinimum(), -39.200000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMaximum(), -33.980000, 0.0001 ); + + QgsCoordinateReferenceSystem crs28356( "EPSG:28356" ); + bounds = crs28356.bounds(); + QGSCOMPARENEAR( bounds.xMinimum(), 150.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.xMaximum(), 156.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMinimum(), -58.960000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMaximum(), -13.870000, 0.0001 ); + + QgsCoordinateReferenceSystem crs3857( "EPSG:3857" ); + bounds = crs3857.bounds(); + QGSCOMPARENEAR( bounds.xMinimum(), -180.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.xMaximum(), 180.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMinimum(), -85.060000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMaximum(), 85.060000, 0.0001 ); + + QgsCoordinateReferenceSystem crs4326( "EPSG:4326" ); + bounds = crs4326.bounds(); + QGSCOMPARENEAR( bounds.xMinimum(), -180.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.xMaximum(), 180.000000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMinimum(), -90.00000, 0.0001 ); + QGSCOMPARENEAR( bounds.yMaximum(), 90.00000, 0.0001 ); +} + QGSTEST_MAIN( TestQgsCoordinateReferenceSystem ) #include "testqgscoordinatereferencesystem.moc"