25 #if PROJ_VERSION_MAJOR>=6 30 QReadWriteLock QgsEllipsoidUtils::sEllipsoidCacheLock;
31 QHash< QString, QgsEllipsoidUtils::EllipsoidParameters > QgsEllipsoidUtils::sEllipsoidCache;
32 QReadWriteLock QgsEllipsoidUtils::sDefinitionCacheLock;
33 QList< QgsEllipsoidUtils::EllipsoidDefinition > QgsEllipsoidUtils::sDefinitionCache;
34 static bool sDisableCache =
false;
39 {
"clrk80",
"clrk80ign" },
40 {
"Adrastea2000",
"ESRI:107909"},
41 {
"Amalthea2000",
"ESRI:107910"},
42 {
"Ananke2000",
"ESRI:107911"},
43 {
"Ariel2000",
"ESRI:107945"},
44 {
"Atlas2000",
"ESRI:107926"},
45 {
"Belinda2000",
"ESRI:107946"},
46 {
"Bianca2000",
"ESRI:107947"},
47 {
"Callisto2000",
"ESRI:107912"},
48 {
"Calypso2000",
"ESRI:107927"},
49 {
"Carme2000",
"ESRI:107913"},
50 {
"Charon2000",
"ESRI:107970"},
51 {
"Cordelia2000",
"ESRI:107948"},
52 {
"Cressida2000",
"ESRI:107949"},
53 {
"Deimos2000",
"ESRI:107906"},
54 {
"Desdemona2000",
"ESRI:107950"},
55 {
"Despina2000",
"ESRI:107961"},
56 {
"Dione2000",
"ESRI:107928"},
57 {
"Elara2000",
"ESRI:107914"},
58 {
"Enceladus2000",
"ESRI:107929"},
59 {
"Epimetheus2000",
"ESRI:107930"},
60 {
"Europa2000",
"ESRI:107915"},
61 {
"Galatea2000",
"ESRI:107962"},
62 {
"Ganymede2000",
"ESRI:107916"},
63 {
"Helene2000",
"ESRI:107931"},
64 {
"Himalia2000",
"ESRI:107917"},
65 {
"Hyperion2000",
"ESRI:107932"},
66 {
"Iapetus2000",
"ESRI:107933"},
67 {
"Io2000",
"ESRI:107918"},
68 {
"Janus2000",
"ESRI:107934"},
69 {
"Juliet2000",
"ESRI:107951"},
70 {
"Jupiter2000",
"ESRI:107908"},
71 {
"Larissa2000",
"ESRI:107963"},
72 {
"Leda2000",
"ESRI:107919"},
73 {
"Lysithea2000",
"ESRI:107920"},
74 {
"Mars2000",
"ESRI:107905"},
75 {
"Mercury2000",
"ESRI:107900"},
76 {
"Metis2000",
"ESRI:107921"},
77 {
"Mimas2000",
"ESRI:107935"},
78 {
"Miranda2000",
"ESRI:107952"},
79 {
"Moon2000",
"ESRI:107903"},
80 {
"Naiad2000",
"ESRI:107964"},
81 {
"Neptune2000",
"ESRI:107960"},
82 {
"Nereid2000",
"ESRI:107965"},
83 {
"Oberon2000",
"ESRI:107953"},
84 {
"Ophelia2000",
"ESRI:107954"},
85 {
"Pan2000",
"ESRI:107936"},
86 {
"Pandora2000",
"ESRI:107937"},
87 {
"Pasiphae2000",
"ESRI:107922"},
88 {
"Phobos2000",
"ESRI:107907"},
89 {
"Phoebe2000",
"ESRI:107938"},
90 {
"Pluto2000",
"ESRI:107969"},
91 {
"Portia2000",
"ESRI:107955"},
92 {
"Prometheus2000",
"ESRI:107939"},
93 {
"Proteus2000",
"ESRI:107966"},
94 {
"Puck2000",
"ESRI:107956"},
95 {
"Rhea2000",
"ESRI:107940"},
96 {
"Rosalind2000",
"ESRI:107957"},
97 {
"Saturn2000",
"ESRI:107925"},
98 {
"Sinope2000",
"ESRI:107923"},
99 {
"Telesto2000",
"ESRI:107941"},
100 {
"Tethys2000",
"ESRI:107942"},
101 {
"Thalassa2000",
"ESRI:107967"},
102 {
"Thebe2000",
"ESRI:107924"},
103 {
"Titan2000",
"ESRI:107943"},
104 {
"Titania2000",
"ESRI:107958"},
105 {
"Triton2000",
"ESRI:107968"},
106 {
"Umbriel2000",
"ESRI:107959"},
107 {
"Uranus2000",
"ESRI:107944"},
108 {
"Venus2000",
"ESRI:107902"},
109 {
"IGNF:ELG053",
"EPSG:7030"},
110 {
"IGNF:ELG052",
"EPSG:7043"},
111 {
"IGNF:ELG102",
"EPSG:7043"},
112 {
"WGS66",
"ESRI:107001"},
113 {
"plessis",
"EPSG:7027"},
114 {
"IGNF:ELG017",
"EPSG:7027"},
115 {
"mod_airy",
"EPSG:7002"},
116 {
"IGNF:ELG037",
"EPSG:7019"},
117 {
"IGNF:ELG108",
"EPSG:7036"},
118 {
"cape",
"EPSG:7034"},
119 {
"IGNF:ELG010",
"EPSG:7011"},
120 {
"IGNF:ELG003",
"EPSG:7012"},
121 {
"IGNF:ELG004",
"EPSG:7008"},
122 {
"GSK2011",
"EPSG:1025"},
123 {
"airy",
"EPSG:7001"},
124 {
"aust_SA",
"EPSG:7003"},
125 {
"bessel",
"EPSG:7004"},
126 {
"clrk66",
"EPSG:7008"},
127 {
"clrk80ign",
"EPSG:7011"},
128 {
"evrst30",
"EPSG:7015"},
129 {
"evrstSS",
"EPSG:7016"},
130 {
"evrst48",
"EPSG:7018"},
131 {
"GRS80",
"EPSG:7019"},
132 {
"helmert",
"EPSG:7020"},
133 {
"intl",
"EPSG:7022"},
134 {
"krass",
"EPSG:7024"},
135 {
"NWL9D",
"EPSG:7025"},
136 {
"WGS84",
"EPSG:7030"},
137 {
"GRS67",
"EPSG:7036"},
138 {
"WGS72",
"EPSG:7043"},
139 {
"bess_nam",
"EPSG:7046"},
140 {
"IAU76",
"EPSG:7049"},
141 {
"sphere",
"EPSG:7052"},
142 {
"hough",
"EPSG:7053"},
143 {
"evrst69",
"EPSG:7056"},
144 {
"fschr60",
"ESRI:107002"},
145 {
"fschr68",
"ESRI:107003"},
146 {
"fschr60m",
"ESRI:107004"},
147 {
"walbeck",
"ESRI:107007"},
148 {
"IGNF:ELG001",
"EPSG:7022"},
149 {
"engelis",
"EPSG:7054"},
150 {
"evrst56",
"EPSG:7044"},
151 {
"SEasia",
"ESRI:107004"},
152 {
"SGS85",
"EPSG:7054"},
153 {
"andrae",
"PROJ:ANDRAE"},
154 {
"clrk80",
"EPSG:7034"},
156 {
"delmbr",
"PROJ:DELMBR"},
157 {
"Earth2000",
"PROJ:EARTH2000"},
158 {
"kaula",
"PROJ:KAULA"},
159 {
"lerch",
"PROJ:LERCH"},
160 {
"MERIT",
"PROJ:MERIT"},
161 {
"mprts",
"PROJ:MPRTS"},
162 {
"new_intl",
"PROJ:NEW_INTL"},
163 {
"WGS60",
"PROJ:WGS60"}
168 QString ellipsoid = e;
169 #if PROJ_VERSION_MAJOR >= 6 171 static std::once_flag initialized;
172 std::call_once( initialized, [ = ]
183 if ( !sDisableCache )
185 QHash< QString, EllipsoidParameters >::const_iterator cacheIt = sEllipsoidCache.constFind( ellipsoid );
186 if ( cacheIt != sEllipsoidCache.constEnd() )
201 if ( ellipsoid.startsWith( QLatin1String(
"PARAMETER" ) ) )
203 QStringList paramList = ellipsoid.split(
':' );
204 bool semiMajorOk, semiMinorOk;
205 double semiMajor = paramList[1].toDouble( & semiMajorOk );
206 double semiMinor = paramList[2].toDouble( & semiMinorOk );
207 if ( semiMajorOk && semiMinorOk )
216 params.
valid =
false;
220 if ( !sDisableCache )
222 sEllipsoidCache.insert( ellipsoid, params );
227 #if PROJ_VERSION_MAJOR< 6 231 QString radius, parameter2;
249 QString sql =
"select radius, parameter2 from tbl_ellipsoid where acronym='" + ellipsoid +
'\'';
250 statement = database.
prepare( sql, result );
252 if ( result == SQLITE_OK )
254 if ( statement.
step() == SQLITE_ROW )
261 if ( radius.isEmpty() || parameter2.isEmpty() )
263 QgsDebugMsg( QStringLiteral(
"setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) );
264 params.
valid =
false;
265 sEllipsoidCacheLock.lockForWrite();
266 if ( !sDisableCache )
268 sEllipsoidCache.insert( ellipsoid, params );
270 sEllipsoidCacheLock.unlock();
275 if ( radius.left( 2 ) == QLatin1String(
"a=" ) )
276 params.
semiMajor = radius.midRef( 2 ).toDouble();
279 QgsDebugMsg( QStringLiteral(
"setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) );
280 params.
valid =
false;
281 sEllipsoidCacheLock.lockForWrite();
282 if ( !sDisableCache )
284 sEllipsoidCache.insert( ellipsoid, params );
286 sEllipsoidCacheLock.unlock();
293 if ( parameter2.left( 2 ) == QLatin1String(
"b=" ) )
295 params.
semiMinor = parameter2.midRef( 2 ).toDouble();
298 else if ( parameter2.left( 3 ) == QLatin1String(
"rf=" ) )
305 QgsDebugMsg( QStringLiteral(
"setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) );
306 params.
valid =
false;
307 sEllipsoidCacheLock.lockForWrite();
308 if ( !sDisableCache )
310 sEllipsoidCache.insert( ellipsoid, params );
312 sEllipsoidCacheLock.unlock();
320 QString proj4 =
"+proj=longlat +ellps=" + ellipsoid +
" +no_defs";
326 if ( destCRS.
srsid() == 0 )
328 QString name = QStringLiteral(
" * %1 (%2)" )
329 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
336 params.
crs = destCRS;
338 sEllipsoidCacheLock.lockForWrite();
339 if ( !sDisableCache )
341 sEllipsoidCache.insert( ellipsoid, params );
343 sEllipsoidCacheLock.unlock();
346 params.
valid =
false;
349 if ( !sDisableCache )
351 sEllipsoidCache.insert( ellipsoid, params );
361 if ( !sDefinitionCache.isEmpty() )
363 QList<QgsEllipsoidUtils::EllipsoidDefinition> defs = sDefinitionCache;
368 QList<QgsEllipsoidUtils::EllipsoidDefinition> defs;
370 #if PROJ_VERSION_MAJOR>=6 374 if ( PROJ_STRING_LIST authorities = proj_get_authorities_from_database( context ) )
376 PROJ_STRING_LIST authoritiesIt = authorities;
377 while (
char *authority = *authoritiesIt )
379 if ( PROJ_STRING_LIST codes = proj_get_codes_from_database( context, authority, PJ_TYPE_ELLIPSOID, 0 ) )
381 PROJ_STRING_LIST codesIt = codes;
382 while (
char *code = *codesIt )
384 QgsProjUtils::proj_pj_unique_ptr ellipsoid( proj_create_from_database( context, authority, code, PJ_CATEGORY_ELLIPSOID, 0,
nullptr ) );
385 if ( ellipsoid.get() )
388 QString name = QString( proj_get_name( ellipsoid.get() ) );
389 def.
acronym = QStringLiteral(
"%1:%2" ).arg( authority, code );
390 name.replace(
'_',
' ' );
391 def.
description = QStringLiteral(
"%1 (%2:%3)" ).arg( name, authority, code );
393 double semiMajor, semiMinor, invFlattening;
394 int semiMinorComputed = 0;
395 if ( proj_ellipsoid_get_parameters( context, ellipsoid.get(), &semiMajor, &semiMinor, &semiMinorComputed, &invFlattening ) )
400 if ( !semiMinorComputed )
413 if ( !sDisableCache )
415 sEllipsoidCache.insert( def.acronym, def.parameters );
421 proj_string_list_destroy( codes );
426 proj_string_list_destroy( authorities );
442 Q_ASSERT( result == 0 );
446 QString sql = QStringLiteral(
"select acronym, name from tbl_ellipsoid order by name" );
447 statement = database.
prepare( sql, result );
449 if ( result == SQLITE_OK )
451 while ( statement.
step() == SQLITE_ROW )
467 collator.setCaseSensitivity( Qt::CaseInsensitive );
470 return collator.compare( a.
description, b.description ) < 0;
472 if ( !sDisableCache )
474 sDefinitionCache = defs;
486 result << def.acronym;
496 if ( !sDisableCache )
499 sDisableCache =
true;
500 sEllipsoidCache.clear();
501 sDefinitionCache.clear();
static QgsCoordinateReferenceSystem fromProj4(const QString &proj4)
Creates a CRS from a proj4 style formatted string.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used.
bool useCustomParameters
Whether custom parameters alone should be used (semiMajor/semiMinor only)
Contains definition of an ellipsoid.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QString toProj4() const
Returns a Proj4 string representation of this CRS.
Contains parameters for an ellipsoid.
static EllipsoidParameters ellipsoidParameters(const QString &ellipsoid)
Returns the parameters for the specified ellipsoid.
long saveAsUserCrs(const QString &name)
Save the proj4-string as a custom CRS.
QgsCoordinateReferenceSystem crs
Associated coordinate reference system.
QString errorMessage() const
Returns the most recent error message encountered by the database.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
bool valid
Whether ellipsoid parameters are valid.
#define QgsDebugMsgLevel(str, level)
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
const QMap< QString, QString > sProj6EllipsoidAcronymMap
QString acronym
authority:code for QGIS builds with proj version 6 or greater, or custom acronym for ellipsoid for ea...
double semiMinor
Semi-minor axis.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
void unlock()
Unlocks the lock.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
This class represents a coordinate reference system (CRS).
double inverseFlattening
Inverse flattening.
void changeMode(Mode mode)
Change the mode of the lock to mode.
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
QgsEllipsoidUtils::EllipsoidParameters parameters
Ellipsoid parameters.
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions()
Returns a list of the definitions for all known ellipsoids from the internal ellipsoid database...
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
static QStringList acronyms()
Returns a list of all known ellipsoid acronyms from the internal ellipsoid database.
long srsid() const
Returns the internal CRS ID, if available.
QString description
Description of ellipsoid.
double semiMajor
Semi-major axis.