Skip to content

Commit 5f1656b

Browse files
committed
Move retrieval of lists of known ellipsoids to QgsEllipsoidUtils
1 parent 147bb7f commit 5f1656b

File tree

5 files changed

+169
-56
lines changed

5 files changed

+169
-56
lines changed

python/core/qgsellipsoidutils.sip

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,45 @@ Associated coordinate reference system
5353
%End
5454
};
5555

56+
struct EllipsoidDefinition
57+
{
58+
QString acronym;
59+
%Docstring
60+
Acronym for ellipsoid
61+
%End
62+
QString description;
63+
%Docstring
64+
Description of ellipsoid
65+
%End
66+
QgsEllipsoidUtils::EllipsoidParameters parameters;
67+
%Docstring
68+
Ellipsoid parameters
69+
%End
70+
};
71+
5672
static EllipsoidParameters ellipsoidParameters( const QString &ellipsoid );
5773
%Docstring
5874
Returns the parameters for the specified ``ellipsoid``.
5975
Results are cached to allow for fast retrieval of parameters.
6076
:rtype: EllipsoidParameters
6177
%End
6278

79+
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions();
80+
%Docstring
81+
Returns a list of the definitions for all known ellipsoids from the
82+
internal ellipsoid database.
83+
\see acronyms()
84+
:rtype: list of QgsEllipsoidUtils.EllipsoidDefinition
85+
%End
86+
87+
static QStringList acronyms();
88+
%Docstring
89+
Returns a list of all known ellipsoid acronyms from the internal
90+
ellipsoid database.
91+
\see definitions()
92+
:rtype: list of str
93+
%End
94+
6395
};
6496

6597

src/app/qgsprojectproperties.cpp

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,10 +1805,6 @@ void QgsProjectProperties::populateEllipsoidList()
18051805
//
18061806
// Populate the ellipsoid list
18071807
//
1808-
sqlite3 *myDatabase = nullptr;
1809-
const char *myTail = nullptr;
1810-
sqlite3_stmt *myPreparedStatement = nullptr;
1811-
int myResult;
18121808
EllipsoidDefs myItem;
18131809

18141810
myItem.acronym = GEO_NONE;
@@ -1823,58 +1819,17 @@ void QgsProjectProperties::populateEllipsoidList()
18231819
myItem.semiMinor = 6370997.0;
18241820
mEllipsoidList.append( myItem );
18251821

1826-
//check the db is available
1827-
myResult = sqlite3_open_v2( QgsApplication::srsDatabaseFilePath().toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, nullptr );
1828-
if ( myResult )
1822+
Q_FOREACH ( const QgsEllipsoidUtils::EllipsoidDefinition &def, QgsEllipsoidUtils::definitions() )
18291823
{
1830-
QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) );
1831-
// XXX This will likely never happen since on open, sqlite creates the
1832-
// database if it does not exist.
1833-
Q_ASSERT( myResult == 0 );
1824+
myItem.acronym = def.acronym;
1825+
myItem.description = def.description;
1826+
// Fall-back values
1827+
myItem.semiMajor = 0.0;
1828+
myItem.semiMinor = 0.0;
1829+
myItem.semiMajor = def.parameters.semiMajor;
1830+
myItem.semiMinor = def.parameters.semiMinor;
1831+
mEllipsoidList.append( myItem );
18341832
}
1835-
1836-
// Set up the query to retrieve the projection information needed to populate the ELLIPSOID list
1837-
QString mySql = QStringLiteral( "select acronym, name, radius, parameter2 from tbl_ellipsoid order by name" );
1838-
myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1839-
// XXX Need to free memory from the error msg if one is set
1840-
if ( myResult == SQLITE_OK )
1841-
{
1842-
while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1843-
{
1844-
QString para1, para2;
1845-
myItem.acronym = ( const char * )sqlite3_column_text( myPreparedStatement, 0 );
1846-
myItem.description = ( const char * )sqlite3_column_text( myPreparedStatement, 1 );
1847-
1848-
// Copied from QgsDistanecArea. Should perhaps be moved there somehow?
1849-
// No error checking, this values are for show only, never used in calculations.
1850-
1851-
// Fall-back values
1852-
myItem.semiMajor = 0.0;
1853-
myItem.semiMinor = 0.0;
1854-
// Crash if no column?
1855-
para1 = ( const char * )sqlite3_column_text( myPreparedStatement, 2 );
1856-
para2 = ( const char * )sqlite3_column_text( myPreparedStatement, 3 );
1857-
myItem.semiMajor = para1.midRef( 2 ).toDouble();
1858-
if ( para2.left( 2 ) == QLatin1String( "b=" ) )
1859-
{
1860-
myItem.semiMinor = para2.midRef( 2 ).toDouble();
1861-
}
1862-
else if ( para2.left( 3 ) == QLatin1String( "rf=" ) )
1863-
{
1864-
double invFlattening = para2.midRef( 3 ).toDouble();
1865-
if ( invFlattening != 0.0 )
1866-
{
1867-
myItem.semiMinor = myItem.semiMajor - ( myItem.semiMajor / invFlattening );
1868-
}
1869-
}
1870-
mEllipsoidList.append( myItem );
1871-
}
1872-
}
1873-
1874-
// close the sqlite3 statement
1875-
sqlite3_finalize( myPreparedStatement );
1876-
sqlite3_close( myDatabase );
1877-
18781833
// Add all items to selector
18791834

18801835
Q_FOREACH ( const EllipsoidDefs &i, mEllipsoidList )

src/core/qgsellipsoidutils.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
QReadWriteLock QgsEllipsoidUtils::sEllipsoidCacheLock;
2323
QHash< QString, QgsEllipsoidUtils::EllipsoidParameters > QgsEllipsoidUtils::sEllipsoidCache;
24-
24+
QReadWriteLock QgsEllipsoidUtils::sDefinitionCacheLock;
25+
QList< QgsEllipsoidUtils::EllipsoidDefinition > QgsEllipsoidUtils::sDefinitionCache;
2526

2627
QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( const QString &ellipsoid )
2728
{
@@ -177,3 +178,71 @@ QgsEllipsoidUtils::EllipsoidParameters QgsEllipsoidUtils::ellipsoidParameters( c
177178
sEllipsoidCacheLock.unlock();
178179
return params;
179180
}
181+
182+
QList<QgsEllipsoidUtils::EllipsoidDefinition> QgsEllipsoidUtils::definitions()
183+
{
184+
sDefinitionCacheLock.lockForRead();
185+
if ( !sDefinitionCache.isEmpty() )
186+
{
187+
QList<QgsEllipsoidUtils::EllipsoidDefinition> defs = sDefinitionCache;
188+
sDefinitionCacheLock.unlock();
189+
return defs;
190+
}
191+
sDefinitionCacheLock.unlock();
192+
193+
sDefinitionCacheLock.lockForWrite();
194+
sqlite3 *database = nullptr;
195+
const char *tail = nullptr;
196+
sqlite3_stmt *preparedStatement = nullptr;
197+
int result;
198+
199+
QList<QgsEllipsoidUtils::EllipsoidDefinition> defs;
200+
201+
//check the db is available
202+
result = sqlite3_open_v2( QgsApplication::srsDatabaseFilePath().toUtf8().data(), &database, SQLITE_OPEN_READONLY, nullptr );
203+
if ( result )
204+
{
205+
QgsDebugMsg( QString( "Can't open database: %1" ).arg( sqlite3_errmsg( database ) ) );
206+
// XXX This will likely never happen since on open, sqlite creates the
207+
// database if it does not exist.
208+
Q_ASSERT( result == 0 );
209+
}
210+
211+
// Set up the query to retrieve the projection information needed to populate the ELLIPSOID list
212+
QString sql = QStringLiteral( "select acronym, name from tbl_ellipsoid order by name" );
213+
result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &preparedStatement, &tail );
214+
// XXX Need to free memory from the error msg if one is set
215+
if ( result == SQLITE_OK )
216+
{
217+
while ( sqlite3_step( preparedStatement ) == SQLITE_ROW )
218+
{
219+
EllipsoidDefinition def;
220+
def.acronym = ( const char * )sqlite3_column_text( preparedStatement, 0 );
221+
def.description = ( const char * )sqlite3_column_text( preparedStatement, 1 );
222+
223+
// use ellipsoidParameters so that result is cached
224+
def.parameters = ellipsoidParameters( def.acronym );
225+
226+
defs << def;
227+
}
228+
}
229+
230+
// close the sqlite3 statement
231+
sqlite3_finalize( preparedStatement );
232+
sqlite3_close( database );
233+
234+
sDefinitionCache = defs;
235+
sDefinitionCacheLock.unlock();
236+
237+
return defs;
238+
}
239+
240+
QStringList QgsEllipsoidUtils::acronyms()
241+
{
242+
QStringList result;
243+
Q_FOREACH ( const QgsEllipsoidUtils::EllipsoidDefinition &def, definitions() )
244+
{
245+
result << def.acronym;
246+
}
247+
return result;
248+
}

src/core/qgsellipsoidutils.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgis_core.h"
2020
#include "qgis.h"
2121
#include "qgscoordinatereferencesystem.h"
22+
#include <QStringList>
2223

2324
/**
2425
* \class QgsEllipsoidUtils
@@ -32,7 +33,7 @@ class CORE_EXPORT QgsEllipsoidUtils
3233
public:
3334

3435
/**
35-
* Contains parameter definitions for an ellipsoid.
36+
* Contains parameters for an ellipsoid.
3637
* \since QGIS 3.0
3738
*/
3839
struct EllipsoidParameters
@@ -55,17 +56,47 @@ class CORE_EXPORT QgsEllipsoidUtils
5556
QgsCoordinateReferenceSystem crs;
5657
};
5758

59+
/**
60+
* Contains definition of an ellipsoid.
61+
* \since QGIS 3.0
62+
*/
63+
struct EllipsoidDefinition
64+
{
65+
//! Acronym for ellipsoid
66+
QString acronym;
67+
//! Description of ellipsoid
68+
QString description;
69+
//! Ellipsoid parameters
70+
QgsEllipsoidUtils::EllipsoidParameters parameters;
71+
};
72+
5873
/**
5974
* Returns the parameters for the specified \a ellipsoid.
6075
* Results are cached to allow for fast retrieval of parameters.
6176
*/
6277
static EllipsoidParameters ellipsoidParameters( const QString &ellipsoid );
6378

79+
/**
80+
* Returns a list of the definitions for all known ellipsoids from the
81+
* internal ellipsoid database.
82+
* \see acronyms()
83+
*/
84+
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions();
85+
86+
/**
87+
* Returns a list of all known ellipsoid acronyms from the internal
88+
* ellipsoid database.
89+
* \see definitions()
90+
*/
91+
static QStringList acronyms();
92+
6493
private:
6594

6695
// ellipsoid cache
6796
static QReadWriteLock sEllipsoidCacheLock;
6897
static QHash< QString, EllipsoidParameters > sEllipsoidCache;
98+
static QReadWriteLock sDefinitionCacheLock;
99+
static QList< QgsEllipsoidUtils::EllipsoidDefinition > sDefinitionCache;
69100

70101
};
71102

tests/src/python/test_qgsellipsoidutils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ def testParams(self):
2929

3030
# run each test twice, so that ellipsoid is fetched from cache on the second time
3131

32+
for i in range(2):
33+
params = QgsEllipsoidUtils.ellipsoidParameters("WGS84")
34+
self.assertTrue(params.valid)
35+
self.assertEqual(params.semiMajor, 6378137.0)
36+
self.assertAlmostEqual(params.semiMinor, 6356752.314245179, 5)
37+
self.assertAlmostEqual(params.inverseFlattening, 298.257223563, 5)
38+
self.assertFalse(params.useCustomParameters)
39+
self.assertEqual(params.crs.authid(), 'EPSG:4030')
40+
3241
for i in range(2):
3342
params = QgsEllipsoidUtils.ellipsoidParameters("Ganymede2000")
3443
self.assertTrue(params.valid)
@@ -53,6 +62,23 @@ def testParams(self):
5362
params = QgsEllipsoidUtils.ellipsoidParameters("Babies first ellipsoid!")
5463
self.assertFalse(params.valid)
5564

65+
def testAcronyms(self):
66+
self.assertTrue('WGS84' in QgsEllipsoidUtils.acronyms())
67+
self.assertTrue('Ganymede2000' in QgsEllipsoidUtils.acronyms())
68+
69+
def testDefinitions(self):
70+
defs = QgsEllipsoidUtils.definitions()
71+
72+
gany_defs = [d for d in defs if d.acronym == 'Ganymede2000'][0]
73+
self.assertEqual(gany_defs.acronym, 'Ganymede2000')
74+
self.assertEqual(gany_defs.description, 'Ganymede2000')
75+
self.assertTrue(gany_defs.parameters.valid)
76+
self.assertEqual(gany_defs.parameters.semiMajor, 2632400.0)
77+
self.assertEqual(gany_defs.parameters.semiMinor, 2632350.0)
78+
self.assertEqual(gany_defs.parameters.inverseFlattening, 52648.0)
79+
self.assertFalse(gany_defs.parameters.useCustomParameters)
80+
self.assertEqual(gany_defs.parameters.crs.authid(), '')
81+
5682

5783
if __name__ == '__main__':
5884
unittest.main()

0 commit comments

Comments
 (0)