mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Move retrieval of lists of known ellipsoids to QgsEllipsoidUtils
This commit is contained in:
parent
147bb7f1ed
commit
5f1656b8e9
@ -53,6 +53,22 @@ Associated coordinate reference system
|
||||
%End
|
||||
};
|
||||
|
||||
struct EllipsoidDefinition
|
||||
{
|
||||
QString acronym;
|
||||
%Docstring
|
||||
Acronym for ellipsoid
|
||||
%End
|
||||
QString description;
|
||||
%Docstring
|
||||
Description of ellipsoid
|
||||
%End
|
||||
QgsEllipsoidUtils::EllipsoidParameters parameters;
|
||||
%Docstring
|
||||
Ellipsoid parameters
|
||||
%End
|
||||
};
|
||||
|
||||
static EllipsoidParameters ellipsoidParameters( const QString &ellipsoid );
|
||||
%Docstring
|
||||
Returns the parameters for the specified ``ellipsoid``.
|
||||
@ -60,6 +76,22 @@ Associated coordinate reference system
|
||||
:rtype: EllipsoidParameters
|
||||
%End
|
||||
|
||||
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions();
|
||||
%Docstring
|
||||
Returns a list of the definitions for all known ellipsoids from the
|
||||
internal ellipsoid database.
|
||||
\see acronyms()
|
||||
:rtype: list of QgsEllipsoidUtils.EllipsoidDefinition
|
||||
%End
|
||||
|
||||
static QStringList acronyms();
|
||||
%Docstring
|
||||
Returns a list of all known ellipsoid acronyms from the internal
|
||||
ellipsoid database.
|
||||
\see definitions()
|
||||
:rtype: list of str
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -1805,10 +1805,6 @@ void QgsProjectProperties::populateEllipsoidList()
|
||||
//
|
||||
// Populate the ellipsoid list
|
||||
//
|
||||
sqlite3 *myDatabase = nullptr;
|
||||
const char *myTail = nullptr;
|
||||
sqlite3_stmt *myPreparedStatement = nullptr;
|
||||
int myResult;
|
||||
EllipsoidDefs myItem;
|
||||
|
||||
myItem.acronym = GEO_NONE;
|
||||
@ -1823,58 +1819,17 @@ void QgsProjectProperties::populateEllipsoidList()
|
||||
myItem.semiMinor = 6370997.0;
|
||||
mEllipsoidList.append( myItem );
|
||||
|
||||
//check the db is available
|
||||
myResult = sqlite3_open_v2( QgsApplication::srsDatabaseFilePath().toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, nullptr );
|
||||
if ( myResult )
|
||||
Q_FOREACH ( const QgsEllipsoidUtils::EllipsoidDefinition &def, QgsEllipsoidUtils::definitions() )
|
||||
{
|
||||
QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
|
||||
// XXX This will likely never happen since on open, sqlite creates the
|
||||
// database if it does not exist.
|
||||
Q_ASSERT( myResult == 0 );
|
||||
myItem.acronym = def.acronym;
|
||||
myItem.description = def.description;
|
||||
// Fall-back values
|
||||
myItem.semiMajor = 0.0;
|
||||
myItem.semiMinor = 0.0;
|
||||
myItem.semiMajor = def.parameters.semiMajor;
|
||||
myItem.semiMinor = def.parameters.semiMinor;
|
||||
mEllipsoidList.append( myItem );
|
||||
}
|
||||
|
||||
// Set up the query to retrieve the projection information needed to populate the ELLIPSOID list
|
||||
QString mySql = QStringLiteral( "select acronym, name, radius, parameter2 from tbl_ellipsoid order by name" );
|
||||
myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
|
||||
// XXX Need to free memory from the error msg if one is set
|
||||
if ( myResult == SQLITE_OK )
|
||||
{
|
||||
while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
|
||||
{
|
||||
QString para1, para2;
|
||||
myItem.acronym = ( const char * )sqlite3_column_text( myPreparedStatement, 0 );
|
||||
myItem.description = ( const char * )sqlite3_column_text( myPreparedStatement, 1 );
|
||||
|
||||
// Copied from QgsDistanecArea. Should perhaps be moved there somehow?
|
||||
// No error checking, this values are for show only, never used in calculations.
|
||||
|
||||
// Fall-back values
|
||||
myItem.semiMajor = 0.0;
|
||||
myItem.semiMinor = 0.0;
|
||||
// Crash if no column?
|
||||
para1 = ( const char * )sqlite3_column_text( myPreparedStatement, 2 );
|
||||
para2 = ( const char * )sqlite3_column_text( myPreparedStatement, 3 );
|
||||
myItem.semiMajor = para1.midRef( 2 ).toDouble();
|
||||
if ( para2.left( 2 ) == QLatin1String( "b=" ) )
|
||||
{
|
||||
myItem.semiMinor = para2.midRef( 2 ).toDouble();
|
||||
}
|
||||
else if ( para2.left( 3 ) == QLatin1String( "rf=" ) )
|
||||
{
|
||||
double invFlattening = para2.midRef( 3 ).toDouble();
|
||||
if ( invFlattening != 0.0 )
|
||||
{
|
||||
myItem.semiMinor = myItem.semiMajor - ( myItem.semiMajor / invFlattening );
|
||||
}
|
||||
}
|
||||
mEllipsoidList.append( myItem );
|
||||
}
|
||||
}
|
||||
|
||||
// close the sqlite3 statement
|
||||
sqlite3_finalize( myPreparedStatement );
|
||||
sqlite3_close( myDatabase );
|
||||
|
||||
// Add all items to selector
|
||||
|
||||
Q_FOREACH ( const EllipsoidDefs &i, mEllipsoidList )
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
QReadWriteLock QgsEllipsoidUtils::sEllipsoidCacheLock;
|
||||
QHash< QString, QgsEllipsoidUtils::EllipsoidParameters > QgsEllipsoidUtils::sEllipsoidCache;
|
||||
|
||||
QReadWriteLock QgsEllipsoidUtils::sDefinitionCacheLock;
|
||||
QList< QgsEllipsoidUtils::EllipsoidDefinition > QgsEllipsoidUtils::sDefinitionCache;
|
||||
|
||||
QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( const QString &ellipsoid )
|
||||
{
|
||||
@ -177,3 +178,71 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
|
||||
sEllipsoidCacheLock.unlock();
|
||||
return params;
|
||||
}
|
||||
|
||||
QList<QgsEllipsoidUtils::EllipsoidDefinition> QgsEllipsoidUtils::definitions()
|
||||
{
|
||||
sDefinitionCacheLock.lockForRead();
|
||||
if ( !sDefinitionCache.isEmpty() )
|
||||
{
|
||||
QList<QgsEllipsoidUtils::EllipsoidDefinition> defs = sDefinitionCache;
|
||||
sDefinitionCacheLock.unlock();
|
||||
return defs;
|
||||
}
|
||||
sDefinitionCacheLock.unlock();
|
||||
|
||||
sDefinitionCacheLock.lockForWrite();
|
||||
sqlite3 *database = nullptr;
|
||||
const char *tail = nullptr;
|
||||
sqlite3_stmt *preparedStatement = nullptr;
|
||||
int result;
|
||||
|
||||
QList<QgsEllipsoidUtils::EllipsoidDefinition> defs;
|
||||
|
||||
//check the db is available
|
||||
result = sqlite3_open_v2( QgsApplication::srsDatabaseFilePath().toUtf8().data(), &database, SQLITE_OPEN_READONLY, nullptr );
|
||||
if ( result )
|
||||
{
|
||||
QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( database ) ) );
|
||||
// XXX This will likely never happen since on open, sqlite creates the
|
||||
// database if it does not exist.
|
||||
Q_ASSERT( result == 0 );
|
||||
}
|
||||
|
||||
// Set up the query to retrieve the projection information needed to populate the ELLIPSOID list
|
||||
QString sql = QStringLiteral( "select acronym, name from tbl_ellipsoid order by name" );
|
||||
result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &preparedStatement, &tail );
|
||||
// XXX Need to free memory from the error msg if one is set
|
||||
if ( result == SQLITE_OK )
|
||||
{
|
||||
while ( sqlite3_step( preparedStatement ) == SQLITE_ROW )
|
||||
{
|
||||
EllipsoidDefinition def;
|
||||
def.acronym = ( const char * )sqlite3_column_text( preparedStatement, 0 );
|
||||
def.description = ( const char * )sqlite3_column_text( preparedStatement, 1 );
|
||||
|
||||
// use ellipsoidParameters so that result is cached
|
||||
def.parameters = ellipsoidParameters( def.acronym );
|
||||
|
||||
defs << def;
|
||||
}
|
||||
}
|
||||
|
||||
// close the sqlite3 statement
|
||||
sqlite3_finalize( preparedStatement );
|
||||
sqlite3_close( database );
|
||||
|
||||
sDefinitionCache = defs;
|
||||
sDefinitionCacheLock.unlock();
|
||||
|
||||
return defs;
|
||||
}
|
||||
|
||||
QStringList QgsEllipsoidUtils::acronyms()
|
||||
{
|
||||
QStringList result;
|
||||
Q_FOREACH ( const QgsEllipsoidUtils::EllipsoidDefinition &def, definitions() )
|
||||
{
|
||||
result << def.acronym;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "qgis_core.h"
|
||||
#include "qgis.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include <QStringList>
|
||||
|
||||
/**
|
||||
* \class QgsEllipsoidUtils
|
||||
@ -32,7 +33,7 @@ class CORE_EXPORT QgsEllipsoidUtils
|
||||
public:
|
||||
|
||||
/**
|
||||
* Contains parameter definitions for an ellipsoid.
|
||||
* Contains parameters for an ellipsoid.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
struct EllipsoidParameters
|
||||
@ -55,17 +56,47 @@ class CORE_EXPORT QgsEllipsoidUtils
|
||||
QgsCoordinateReferenceSystem crs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains definition of an ellipsoid.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
struct EllipsoidDefinition
|
||||
{
|
||||
//! Acronym for ellipsoid
|
||||
QString acronym;
|
||||
//! Description of ellipsoid
|
||||
QString description;
|
||||
//! Ellipsoid parameters
|
||||
QgsEllipsoidUtils::EllipsoidParameters parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the parameters for the specified \a ellipsoid.
|
||||
* Results are cached to allow for fast retrieval of parameters.
|
||||
*/
|
||||
static EllipsoidParameters ellipsoidParameters( const QString &ellipsoid );
|
||||
|
||||
/**
|
||||
* Returns a list of the definitions for all known ellipsoids from the
|
||||
* internal ellipsoid database.
|
||||
* \see acronyms()
|
||||
*/
|
||||
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions();
|
||||
|
||||
/**
|
||||
* Returns a list of all known ellipsoid acronyms from the internal
|
||||
* ellipsoid database.
|
||||
* \see definitions()
|
||||
*/
|
||||
static QStringList acronyms();
|
||||
|
||||
private:
|
||||
|
||||
// ellipsoid cache
|
||||
static QReadWriteLock sEllipsoidCacheLock;
|
||||
static QHash< QString, EllipsoidParameters > sEllipsoidCache;
|
||||
static QReadWriteLock sDefinitionCacheLock;
|
||||
static QList< QgsEllipsoidUtils::EllipsoidDefinition > sDefinitionCache;
|
||||
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,15 @@ class TestQgsEllipsoidUtils(unittest.TestCase):
|
||||
|
||||
# run each test twice, so that ellipsoid is fetched from cache on the second time
|
||||
|
||||
for i in range(2):
|
||||
params = QgsEllipsoidUtils.ellipsoidParameters("WGS84")
|
||||
self.assertTrue(params.valid)
|
||||
self.assertEqual(params.semiMajor, 6378137.0)
|
||||
self.assertAlmostEqual(params.semiMinor, 6356752.314245179, 5)
|
||||
self.assertAlmostEqual(params.inverseFlattening, 298.257223563, 5)
|
||||
self.assertFalse(params.useCustomParameters)
|
||||
self.assertEqual(params.crs.authid(), 'EPSG:4030')
|
||||
|
||||
for i in range(2):
|
||||
params = QgsEllipsoidUtils.ellipsoidParameters("Ganymede2000")
|
||||
self.assertTrue(params.valid)
|
||||
@ -53,6 +62,23 @@ class TestQgsEllipsoidUtils(unittest.TestCase):
|
||||
params = QgsEllipsoidUtils.ellipsoidParameters("Babies first ellipsoid!")
|
||||
self.assertFalse(params.valid)
|
||||
|
||||
def testAcronyms(self):
|
||||
self.assertTrue('WGS84' in QgsEllipsoidUtils.acronyms())
|
||||
self.assertTrue('Ganymede2000' in QgsEllipsoidUtils.acronyms())
|
||||
|
||||
def testDefinitions(self):
|
||||
defs = QgsEllipsoidUtils.definitions()
|
||||
|
||||
gany_defs = [d for d in defs if d.acronym == 'Ganymede2000'][0]
|
||||
self.assertEqual(gany_defs.acronym, 'Ganymede2000')
|
||||
self.assertEqual(gany_defs.description, 'Ganymede2000')
|
||||
self.assertTrue(gany_defs.parameters.valid)
|
||||
self.assertEqual(gany_defs.parameters.semiMajor, 2632400.0)
|
||||
self.assertEqual(gany_defs.parameters.semiMinor, 2632350.0)
|
||||
self.assertEqual(gany_defs.parameters.inverseFlattening, 52648.0)
|
||||
self.assertFalse(gany_defs.parameters.useCustomParameters)
|
||||
self.assertEqual(gany_defs.parameters.crs.authid(), '')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user