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 )
422 sEllipsoidCache()->insert( def.acronym, def.parameters );
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();