35using namespace Qt::StringLiterals;
45static
bool sDisableCache = false;
50 static const QMap< QString, QString > sProj6EllipsoidAcronymMap {
51 {
"clrk80",
"clrk80ign" },
52 {
"Adrastea2000",
"ESRI:107909" },
53 {
"Amalthea2000",
"ESRI:107910" },
54 {
"Ananke2000",
"ESRI:107911" },
55 {
"Ariel2000",
"ESRI:107945" },
56 {
"Atlas2000",
"ESRI:107926" },
57 {
"Belinda2000",
"ESRI:107946" },
58 {
"Bianca2000",
"ESRI:107947" },
59 {
"Callisto2000",
"ESRI:107912" },
60 {
"Calypso2000",
"ESRI:107927" },
61 {
"Carme2000",
"ESRI:107913" },
62 {
"Charon2000",
"ESRI:107970" },
63 {
"Cordelia2000",
"ESRI:107948" },
64 {
"Cressida2000",
"ESRI:107949" },
65 {
"Deimos2000",
"ESRI:107906" },
66 {
"Desdemona2000",
"ESRI:107950" },
67 {
"Despina2000",
"ESRI:107961" },
68 {
"Dione2000",
"ESRI:107928" },
69 {
"Elara2000",
"ESRI:107914" },
70 {
"Enceladus2000",
"ESRI:107929" },
71 {
"Epimetheus2000",
"ESRI:107930" },
72 {
"Europa2000",
"ESRI:107915" },
73 {
"Galatea2000",
"ESRI:107962" },
74 {
"Ganymede2000",
"ESRI:107916" },
75 {
"Helene2000",
"ESRI:107931" },
76 {
"Himalia2000",
"ESRI:107917" },
77 {
"Hyperion2000",
"ESRI:107932" },
78 {
"Iapetus2000",
"ESRI:107933" },
79 {
"Io2000",
"ESRI:107918" },
80 {
"Janus2000",
"ESRI:107934" },
81 {
"Juliet2000",
"ESRI:107951" },
82 {
"Jupiter2000",
"ESRI:107908" },
83 {
"Larissa2000",
"ESRI:107963" },
84 {
"Leda2000",
"ESRI:107919" },
85 {
"Lysithea2000",
"ESRI:107920" },
86 {
"Mars2000",
"ESRI:107905" },
87 {
"Mercury2000",
"ESRI:107900" },
88 {
"Metis2000",
"ESRI:107921" },
89 {
"Mimas2000",
"ESRI:107935" },
90 {
"Miranda2000",
"ESRI:107952" },
91 {
"Moon2000",
"ESRI:107903" },
92 {
"Naiad2000",
"ESRI:107964" },
93 {
"Neptune2000",
"ESRI:107960" },
94 {
"Nereid2000",
"ESRI:107965" },
95 {
"Oberon2000",
"ESRI:107953" },
96 {
"Ophelia2000",
"ESRI:107954" },
97 {
"Pan2000",
"ESRI:107936" },
98 {
"Pandora2000",
"ESRI:107937" },
99 {
"Pasiphae2000",
"ESRI:107922" },
100 {
"Phobos2000",
"ESRI:107907" },
101 {
"Phoebe2000",
"ESRI:107938" },
102 {
"Pluto2000",
"ESRI:107969" },
103 {
"Portia2000",
"ESRI:107955" },
104 {
"Prometheus2000",
"ESRI:107939" },
105 {
"Proteus2000",
"ESRI:107966" },
106 {
"Puck2000",
"ESRI:107956" },
107 {
"Rhea2000",
"ESRI:107940" },
108 {
"Rosalind2000",
"ESRI:107957" },
109 {
"Saturn2000",
"ESRI:107925" },
110 {
"Sinope2000",
"ESRI:107923" },
111 {
"Telesto2000",
"ESRI:107941" },
112 {
"Tethys2000",
"ESRI:107942" },
113 {
"Thalassa2000",
"ESRI:107967" },
114 {
"Thebe2000",
"ESRI:107924" },
115 {
"Titan2000",
"ESRI:107943" },
116 {
"Titania2000",
"ESRI:107958" },
117 {
"Triton2000",
"ESRI:107968" },
118 {
"Umbriel2000",
"ESRI:107959" },
119 {
"Uranus2000",
"ESRI:107944" },
120 {
"Venus2000",
"ESRI:107902" },
121 {
"IGNF:ELG053",
"EPSG:7030" },
122 {
"IGNF:ELG052",
"EPSG:7043" },
123 {
"IGNF:ELG102",
"EPSG:7043" },
124 {
"WGS66",
"ESRI:107001" },
125 {
"plessis",
"EPSG:7027" },
126 {
"IGNF:ELG017",
"EPSG:7027" },
127 {
"mod_airy",
"EPSG:7002" },
128 {
"IGNF:ELG037",
"EPSG:7019" },
129 {
"IGNF:ELG108",
"EPSG:7036" },
130 {
"cape",
"EPSG:7034" },
131 {
"IGNF:ELG010",
"EPSG:7011" },
132 {
"IGNF:ELG003",
"EPSG:7012" },
133 {
"IGNF:ELG004",
"EPSG:7008" },
134 {
"GSK2011",
"EPSG:1025" },
135 {
"airy",
"EPSG:7001" },
136 {
"aust_SA",
"EPSG:7003" },
137 {
"bessel",
"EPSG:7004" },
138 {
"clrk66",
"EPSG:7008" },
139 {
"clrk80ign",
"EPSG:7011" },
140 {
"evrst30",
"EPSG:7015" },
141 {
"evrstSS",
"EPSG:7016" },
142 {
"evrst48",
"EPSG:7018" },
143 {
"GRS80",
"EPSG:7019" },
144 {
"helmert",
"EPSG:7020" },
145 {
"intl",
"EPSG:7022" },
146 {
"krass",
"EPSG:7024" },
147 {
"NWL9D",
"EPSG:7025" },
148 {
"WGS84",
"EPSG:7030" },
149 {
"GRS67",
"EPSG:7036" },
150 {
"WGS72",
"EPSG:7043" },
151 {
"bess_nam",
"EPSG:7046" },
152 {
"IAU76",
"EPSG:7049" },
153 {
"sphere",
"EPSG:7052" },
154 {
"hough",
"EPSG:7053" },
155 {
"evrst69",
"EPSG:7056" },
156 {
"fschr60",
"ESRI:107002" },
157 {
"fschr68",
"ESRI:107003" },
158 {
"fschr60m",
"ESRI:107004" },
159 {
"walbeck",
"ESRI:107007" },
160 {
"IGNF:ELG001",
"EPSG:7022" },
161 {
"engelis",
"EPSG:7054" },
162 {
"evrst56",
"EPSG:7044" },
163 {
"SEasia",
"ESRI:107004" },
164 {
"SGS85",
"EPSG:7054" },
165 {
"andrae",
"PROJ:ANDRAE" },
166 {
"clrk80",
"EPSG:7034" },
167 {
"CPM",
"PROJ:CPM" },
168 {
"delmbr",
"PROJ:DELMBR" },
169 {
"Earth2000",
"PROJ:EARTH2000" },
170 {
"kaula",
"PROJ:KAULA" },
171 {
"lerch",
"PROJ:LERCH" },
172 {
"MERIT",
"PROJ:MERIT" },
173 {
"mprts",
"PROJ:MPRTS" },
174 {
"new_intl",
"PROJ:NEW_INTL" },
175 {
"WGS60",
"PROJ:WGS60" }
178 QString ellipsoid = e;
180 static std::once_flag initialized;
181 std::call_once( initialized, [] {
186 ellipsoid = sProj6EllipsoidAcronymMap.value( ellipsoid, ellipsoid );
191 if ( !sDisableCache )
193 const QHash< QString, EllipsoidParameters >::const_iterator cacheIt = sEllipsoidCache()->constFind( ellipsoid );
194 if ( cacheIt != sEllipsoidCache()->constEnd() )
209 if ( ellipsoid.startsWith(
"PARAMETER"_L1 ) )
211 QStringList paramList = ellipsoid.split(
':' );
212 bool semiMajorOk, semiMinorOk;
213 const double semiMajor = paramList[1].toDouble( &semiMajorOk );
214 const double semiMinor = paramList[2].toDouble( &semiMinorOk );
215 if ( semiMajorOk && semiMinorOk )
225 params.
valid =
false;
229 if ( !sDisableCache )
231 sEllipsoidCache()->insert( ellipsoid, params );
235 params.
valid =
false;
238 if ( !sDisableCache )
240 sEllipsoidCache()->insert( ellipsoid, params );
249 if ( !sDefinitionCache()->isEmpty() )
251 return *sDefinitionCache();
255 QList<QgsEllipsoidUtils::EllipsoidDefinition> defs;
260 if ( PROJ_STRING_LIST authorities = proj_get_authorities_from_database( context ) )
262 PROJ_STRING_LIST authoritiesIt = authorities;
263 while (
char *authority = *authoritiesIt )
265 if ( PROJ_STRING_LIST codes = proj_get_codes_from_database( context, authority, PJ_TYPE_ELLIPSOID, 0 ) )
267 PROJ_STRING_LIST codesIt = codes;
268 while (
char *code = *codesIt )
274 QString name = QString( proj_get_name( ellipsoid.get() ) );
275 def.
acronym = u
"%1:%2"_s.arg( authority, code );
276 name.replace(
'_',
' ' );
277 def.
description = u
"%1 (%2:%3)"_s.arg( name, authority, code );
279 def.
celestialBodyName = proj_get_celestial_body_name( context, ellipsoid.get() );
281 double semiMajor, semiMinor, invFlattening;
282 int semiMinorComputed = 0;
283 if ( proj_ellipsoid_get_parameters( context, ellipsoid.get(), &semiMajor, &semiMinor, &semiMinorComputed, &invFlattening ) )
288 if ( !semiMinorComputed )
301 if ( !sDisableCache )
309 proj_string_list_destroy( codes );
314 proj_string_list_destroy( authorities );
319 collator.setCaseSensitivity( Qt::CaseInsensitive );
321 if ( !sDisableCache )
323 *sDefinitionCache() = defs;
332 const QList<QgsEllipsoidUtils::EllipsoidDefinition> defs =
definitions();
333 result.reserve( defs.size() );
336 result << def.acronym;
351 if ( !sDisableCache )
354 sDisableCache =
true;
355 sEllipsoidCache()->clear();
356 sDefinitionCache()->clear();
362 const QVector3D right = normalRight.normalized();
363 const QVector3D up = normalUp.normalized();
366 const QVector3D forward = QVector3D::crossProduct( up, right ).normalized();
370 const float matData[9] = { right.x(), forward.x(), up.x(), right.y(), forward.y(), up.y(), right.z(), forward.z(), up.z() };
371 const QMatrix3x3 rotMatrix( matData );
372 return QQuaternion::fromRotationMatrix( rotMatrix );
377 QgsVector3D up( position.
x() / ( semiMajorAxis * semiMajorAxis ), position.
y() / ( semiMajorAxis * semiMajorAxis ), position.
z() / ( semiMinorAxis * semiMinorAxis ) );
381 if ( east.
length() < 1e-6 )
static QgsCoordinateReferenceSystemRegistry * coordinateReferenceSystemRegistry()
Returns the application's coordinate reference system (CRS) registry, which handles known CRS definit...
QList< QgsCelestialBody > celestialBodies() const
Returns a list of all known celestial bodies.
bool createFromProj(const QString &projString, bool identify=true)
Sets this CRS by passing it a PROJ style formatted string.
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 QQuaternion ellipsoidEastNorthUpRotation(const QgsVector3D &position, double semiMajorAxis, double semiMinorAxis)
Returns a rotation quaternion for the east-north-up (ENU) reference frame at position on the ellipsoi...
static QList< QgsCelestialBody > celestialBodies()
Returns a list of all known celestial bodies.
static void invalidateCache(bool disableCache=false)
Clears the internal cache used.
static QQuaternion quaternionFromNormalUpRight(const QVector3D &normalUp, const QVector3D &normalRight)
Builds a rotation quaternion from an "up" direction and a "right" direction, with the remaining basis...
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 PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
std::unique_ptr< PJ, ProjPJDeleter > proj_pj_unique_ptr
Scoped Proj PJ object.
A convenience class that simplifies locking and unlocking QReadWriteLocks.
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.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
QVector3D toVector3D() const
Converts the current object to QVector3D.
double x() const
Returns X coordinate.
void normalize()
Normalizes the current vector in place.
double length() const
Returns the length of the vector.
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)
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 celestialBodyName
Name of the associated celestial body (e.g.
QString description
Description of ellipsoid.
QgsEllipsoidUtils::EllipsoidParameters parameters
Ellipsoid parameters.
Contains parameters for an ellipsoid.
double semiMajor
Semi-major axis, in meters.
bool valid
Whether ellipsoid parameters are valid.
double semiMinor
Semi-minor axis, in meters.
QgsCoordinateReferenceSystem crs
Associated coordinate reference system.
double inverseFlattening
Inverse flattening.
bool useCustomParameters
Whether custom parameters alone should be used (semiMajor/semiMinor only).