26 #if PROJ_VERSION_MAJOR>=6
39 static
bool sDisableCache = false;
44 static const QMap< QString, QString > sProj6EllipsoidAcronymMap
46 {
"clrk80",
"clrk80ign" },
47 {
"Adrastea2000",
"ESRI:107909"},
48 {
"Amalthea2000",
"ESRI:107910"},
49 {
"Ananke2000",
"ESRI:107911"},
50 {
"Ariel2000",
"ESRI:107945"},
51 {
"Atlas2000",
"ESRI:107926"},
52 {
"Belinda2000",
"ESRI:107946"},
53 {
"Bianca2000",
"ESRI:107947"},
54 {
"Callisto2000",
"ESRI:107912"},
55 {
"Calypso2000",
"ESRI:107927"},
56 {
"Carme2000",
"ESRI:107913"},
57 {
"Charon2000",
"ESRI:107970"},
58 {
"Cordelia2000",
"ESRI:107948"},
59 {
"Cressida2000",
"ESRI:107949"},
60 {
"Deimos2000",
"ESRI:107906"},
61 {
"Desdemona2000",
"ESRI:107950"},
62 {
"Despina2000",
"ESRI:107961"},
63 {
"Dione2000",
"ESRI:107928"},
64 {
"Elara2000",
"ESRI:107914"},
65 {
"Enceladus2000",
"ESRI:107929"},
66 {
"Epimetheus2000",
"ESRI:107930"},
67 {
"Europa2000",
"ESRI:107915"},
68 {
"Galatea2000",
"ESRI:107962"},
69 {
"Ganymede2000",
"ESRI:107916"},
70 {
"Helene2000",
"ESRI:107931"},
71 {
"Himalia2000",
"ESRI:107917"},
72 {
"Hyperion2000",
"ESRI:107932"},
73 {
"Iapetus2000",
"ESRI:107933"},
74 {
"Io2000",
"ESRI:107918"},
75 {
"Janus2000",
"ESRI:107934"},
76 {
"Juliet2000",
"ESRI:107951"},
77 {
"Jupiter2000",
"ESRI:107908"},
78 {
"Larissa2000",
"ESRI:107963"},
79 {
"Leda2000",
"ESRI:107919"},
80 {
"Lysithea2000",
"ESRI:107920"},
81 {
"Mars2000",
"ESRI:107905"},
82 {
"Mercury2000",
"ESRI:107900"},
83 {
"Metis2000",
"ESRI:107921"},
84 {
"Mimas2000",
"ESRI:107935"},
85 {
"Miranda2000",
"ESRI:107952"},
86 {
"Moon2000",
"ESRI:107903"},
87 {
"Naiad2000",
"ESRI:107964"},
88 {
"Neptune2000",
"ESRI:107960"},
89 {
"Nereid2000",
"ESRI:107965"},
90 {
"Oberon2000",
"ESRI:107953"},
91 {
"Ophelia2000",
"ESRI:107954"},
92 {
"Pan2000",
"ESRI:107936"},
93 {
"Pandora2000",
"ESRI:107937"},
94 {
"Pasiphae2000",
"ESRI:107922"},
95 {
"Phobos2000",
"ESRI:107907"},
96 {
"Phoebe2000",
"ESRI:107938"},
97 {
"Pluto2000",
"ESRI:107969"},
98 {
"Portia2000",
"ESRI:107955"},
99 {
"Prometheus2000",
"ESRI:107939"},
100 {
"Proteus2000",
"ESRI:107966"},
101 {
"Puck2000",
"ESRI:107956"},
102 {
"Rhea2000",
"ESRI:107940"},
103 {
"Rosalind2000",
"ESRI:107957"},
104 {
"Saturn2000",
"ESRI:107925"},
105 {
"Sinope2000",
"ESRI:107923"},
106 {
"Telesto2000",
"ESRI:107941"},
107 {
"Tethys2000",
"ESRI:107942"},
108 {
"Thalassa2000",
"ESRI:107967"},
109 {
"Thebe2000",
"ESRI:107924"},
110 {
"Titan2000",
"ESRI:107943"},
111 {
"Titania2000",
"ESRI:107958"},
112 {
"Triton2000",
"ESRI:107968"},
113 {
"Umbriel2000",
"ESRI:107959"},
114 {
"Uranus2000",
"ESRI:107944"},
115 {
"Venus2000",
"ESRI:107902"},
116 {
"IGNF:ELG053",
"EPSG:7030"},
117 {
"IGNF:ELG052",
"EPSG:7043"},
118 {
"IGNF:ELG102",
"EPSG:7043"},
119 {
"WGS66",
"ESRI:107001"},
120 {
"plessis",
"EPSG:7027"},
121 {
"IGNF:ELG017",
"EPSG:7027"},
122 {
"mod_airy",
"EPSG:7002"},
123 {
"IGNF:ELG037",
"EPSG:7019"},
124 {
"IGNF:ELG108",
"EPSG:7036"},
125 {
"cape",
"EPSG:7034"},
126 {
"IGNF:ELG010",
"EPSG:7011"},
127 {
"IGNF:ELG003",
"EPSG:7012"},
128 {
"IGNF:ELG004",
"EPSG:7008"},
129 {
"GSK2011",
"EPSG:1025"},
130 {
"airy",
"EPSG:7001"},
131 {
"aust_SA",
"EPSG:7003"},
132 {
"bessel",
"EPSG:7004"},
133 {
"clrk66",
"EPSG:7008"},
134 {
"clrk80ign",
"EPSG:7011"},
135 {
"evrst30",
"EPSG:7015"},
136 {
"evrstSS",
"EPSG:7016"},
137 {
"evrst48",
"EPSG:7018"},
138 {
"GRS80",
"EPSG:7019"},
139 {
"helmert",
"EPSG:7020"},
140 {
"intl",
"EPSG:7022"},
141 {
"krass",
"EPSG:7024"},
142 {
"NWL9D",
"EPSG:7025"},
143 {
"WGS84",
"EPSG:7030"},
144 {
"GRS67",
"EPSG:7036"},
145 {
"WGS72",
"EPSG:7043"},
146 {
"bess_nam",
"EPSG:7046"},
147 {
"IAU76",
"EPSG:7049"},
148 {
"sphere",
"EPSG:7052"},
149 {
"hough",
"EPSG:7053"},
150 {
"evrst69",
"EPSG:7056"},
151 {
"fschr60",
"ESRI:107002"},
152 {
"fschr68",
"ESRI:107003"},
153 {
"fschr60m",
"ESRI:107004"},
154 {
"walbeck",
"ESRI:107007"},
155 {
"IGNF:ELG001",
"EPSG:7022"},
156 {
"engelis",
"EPSG:7054"},
157 {
"evrst56",
"EPSG:7044"},
158 {
"SEasia",
"ESRI:107004"},
159 {
"SGS85",
"EPSG:7054"},
160 {
"andrae",
"PROJ:ANDRAE"},
161 {
"clrk80",
"EPSG:7034"},
163 {
"delmbr",
"PROJ:DELMBR"},
164 {
"Earth2000",
"PROJ:EARTH2000"},
165 {
"kaula",
"PROJ:KAULA"},
166 {
"lerch",
"PROJ:LERCH"},
167 {
"MERIT",
"PROJ:MERIT"},
168 {
"mprts",
"PROJ:MPRTS"},
169 {
"new_intl",
"PROJ:NEW_INTL"},
170 {
"WGS60",
"PROJ:WGS60"}
173 QString ellipsoid = e;
174 #if PROJ_VERSION_MAJOR >= 6
176 static std::once_flag initialized;
177 std::call_once( initialized, [ = ]
180 ( void )definitions();
183 ellipsoid = sProj6EllipsoidAcronymMap.value( ellipsoid, ellipsoid );
185 ( void )sProj6EllipsoidAcronymMap;
191 if ( !sDisableCache )
193 QHash< QString, EllipsoidParameters >::const_iterator cacheIt = sEllipsoidCache()->constFind( ellipsoid );
194 if ( cacheIt != sEllipsoidCache()->constEnd() )
209 if ( ellipsoid.startsWith( QLatin1String(
"PARAMETER" ) ) )
211 QStringList paramList = ellipsoid.split(
':' );
212 bool semiMajorOk, semiMinorOk;
213 double semiMajor = paramList[1].toDouble( & semiMajorOk );
214 double semiMinor = paramList[2].toDouble( & semiMinorOk );
215 if ( semiMajorOk && semiMinorOk )
224 params.
valid =
false;
228 if ( !sDisableCache )
230 sEllipsoidCache()->insert( ellipsoid, params );
235 #if PROJ_VERSION_MAJOR< 6
239 QString radius, parameter2;
257 QString sql =
"select radius, parameter2 from tbl_ellipsoid where acronym='" + ellipsoid +
'\'';
258 statement = database.
prepare( sql, result );
260 if ( result == SQLITE_OK )
262 if ( statement.
step() == SQLITE_ROW )
269 if ( radius.isEmpty() || parameter2.isEmpty() )
271 QgsDebugMsg( QStringLiteral(
"setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) );
272 params.
valid =
false;
273 sEllipsoidCacheLock()->lockForWrite();
274 if ( !sDisableCache )
276 sEllipsoidCache()->insert( ellipsoid, params );
278 sEllipsoidCacheLock()->unlock();
283 if ( radius.left( 2 ) == QLatin1String(
"a=" ) )
284 params.
semiMajor = radius.midRef( 2 ).toDouble();
287 QgsDebugMsg( QStringLiteral(
"setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) );
288 params.
valid =
false;
289 sEllipsoidCacheLock()->lockForWrite();
290 if ( !sDisableCache )
292 sEllipsoidCache()->insert( ellipsoid, params );
294 sEllipsoidCacheLock()->unlock();
301 if ( parameter2.left( 2 ) == QLatin1String(
"b=" ) )
303 params.
semiMinor = parameter2.midRef( 2 ).toDouble();
306 else if ( parameter2.left( 3 ) == QLatin1String(
"rf=" ) )
313 QgsDebugMsg( QStringLiteral(
"setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) );
314 params.
valid =
false;
315 sEllipsoidCacheLock()->lockForWrite();
316 if ( !sDisableCache )
318 sEllipsoidCache()->insert( ellipsoid, params );
320 sEllipsoidCacheLock()->unlock();
328 QString proj4 =
"+proj=longlat +ellps=" + ellipsoid +
" +no_defs";
334 if ( destCRS.
srsid() == 0 )
336 QString name = QStringLiteral(
" * %1 (%2)" )
337 .arg( QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
344 params.
crs = destCRS;
346 sEllipsoidCacheLock()->lockForWrite();
347 if ( !sDisableCache )
349 sEllipsoidCache()->insert( ellipsoid, params );
351 sEllipsoidCacheLock()->unlock();
354 params.
valid =
false;
357 if ( !sDisableCache )
359 sEllipsoidCache()->insert( ellipsoid, params );
369 if ( !sDefinitionCache()->isEmpty() )
371 return *sDefinitionCache();
375 QList<QgsEllipsoidUtils::EllipsoidDefinition> defs;
377 #if PROJ_VERSION_MAJOR>=6
381 if ( PROJ_STRING_LIST authorities = proj_get_authorities_from_database( context ) )
383 PROJ_STRING_LIST authoritiesIt = authorities;
384 while (
char *authority = *authoritiesIt )
386 if ( PROJ_STRING_LIST codes = proj_get_codes_from_database( context, authority, PJ_TYPE_ELLIPSOID, 0 ) )
388 PROJ_STRING_LIST codesIt = codes;
389 while (
char *code = *codesIt )
391 QgsProjUtils::proj_pj_unique_ptr ellipsoid( proj_create_from_database( context, authority, code, PJ_CATEGORY_ELLIPSOID, 0,
nullptr ) );
392 if ( ellipsoid.get() )
395 QString name = QString( proj_get_name( ellipsoid.get() ) );
396 def.
acronym = QStringLiteral(
"%1:%2" ).arg( authority, code );
397 name.replace(
'_',
' ' );
398 def.
description = QStringLiteral(
"%1 (%2:%3)" ).arg( name, authority, code );
400 double semiMajor, semiMinor, invFlattening;
401 int semiMinorComputed = 0;
402 if ( proj_ellipsoid_get_parameters( context, ellipsoid.get(), &semiMajor, &semiMinor, &semiMinorComputed, &invFlattening ) )
407 if ( !semiMinorComputed )
420 if ( !sDisableCache )
428 proj_string_list_destroy( codes );
433 proj_string_list_destroy( authorities );
449 Q_ASSERT( result == 0 );
453 QString sql = QStringLiteral(
"select acronym, name from tbl_ellipsoid order by name" );
454 statement = database.
prepare( sql, result );
456 if ( result == SQLITE_OK )
458 while ( statement.
step() == SQLITE_ROW )
474 collator.setCaseSensitivity( Qt::CaseInsensitive );
477 return collator.compare( a.description, b.description ) < 0;
479 if ( !sDisableCache )
481 *sDefinitionCache() = defs;
490 const QList<QgsEllipsoidUtils::EllipsoidDefinition> defs =
definitions();
491 result.reserve( defs.size() );
494 result << def.acronym;
504 if ( !sDisableCache )
507 sDisableCache =
true;
508 sEllipsoidCache()->clear();
509 sDefinitionCache()->clear();
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
This class represents a coordinate reference system (CRS).
QString toProj() const
Returns a Proj string representation of this CRS.
bool createFromProj(const QString &projString, bool identify=true)
Sets this CRS by passing it a PROJ style formatted string.
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
long saveAsUserCrs(const QString &name, Format nativeFormat=FormatWkt)
Saves the CRS as a new custom ("USER") CRS.
long srsid() const
Returns the internal CRS ID, if available.
Contains utility functions for working with ellipsoids and querying the ellipsoid database.
static QList< QgsEllipsoidUtils::EllipsoidDefinition > definitions()
Returns a list of the definitions for all known ellipsoids from the internal ellipsoid database.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used.
static EllipsoidParameters ellipsoidParameters(const QString &ellipsoid)
Returns the parameters for the specified ellipsoid.
static QStringList acronyms()
Returns a list of all known ellipsoid acronyms from the internal ellipsoid database.
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).
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void unlock()
Unlocks the lock.
void changeMode(Mode mode)
Change the mode of the lock to mode.
Scoped object for logging of the runtime for a single operation or group of operations.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsEllipsoidUtils::EllipsoidDefinition > EllipsoidDefinitionCache
QHash< QString, QgsEllipsoidUtils::EllipsoidParameters > EllipsoidParamCache
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
#define QgsDebugMsgLevel(str, level)
Contains definition of an ellipsoid.
QString acronym
authority:code for QGIS builds with proj version 6 or greater, or custom acronym for ellipsoid for ea...
QString description
Description of ellipsoid.
QgsEllipsoidUtils::EllipsoidParameters parameters
Ellipsoid parameters.
Contains parameters for an ellipsoid.
double semiMajor
Semi-major axis.
bool valid
Whether ellipsoid parameters are valid.
double semiMinor
Semi-minor axis.
QgsCoordinateReferenceSystem crs
Associated coordinate reference system.
double inverseFlattening
Inverse flattening.
bool useCustomParameters
Whether custom parameters alone should be used (semiMajor/semiMinor only)