Marble

GeoDataCoordinates.h
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007-2008 Inge Wallin <ingwa@kde.org>
5// SPDX-FileCopyrightText: 2008 Patrick Spendrin <ps_ml@gmx.de>
6// SPDX-FileCopyrightText: 2015 Alejandro Garcia Montoro <alejandro.garciamontoro@gmail.com>
7//
8
9
10#ifndef MARBLE_GEODATACOORDINATES_H
11#define MARBLE_GEODATACOORDINATES_H
12
13#include <QCoreApplication>
14#include <QMetaType>
15#include <QVector>
16
17#include "geodata_export.h"
18#include "MarbleGlobal.h"
19
20class QString;
21
22namespace Marble
23{
24
25class GeoDataCoordinatesPrivate;
26class Quaternion;
27
28/**
29 * @short A 3d point representation
30 *
31 * GeoDataCoordinates is the simple representation of a single three
32 * dimensional point. It can be used all through out marble as the data type
33 * for three dimensional objects. it comprises of a Quaternion for speed issues.
34 * This class was introduced to reflect the difference between a simple 3d point
35 * and the GeoDataGeometry object containing such a point. The latter is a
36 * GeoDataPoint and is simply derived from GeoDataGeometry.
37 * @see GeoDataPoint
38*/
39
40class GEODATA_EXPORT GeoDataCoordinates
41{
42 Q_DECLARE_TR_FUNCTIONS(GeoDataCoordinates)
43
44 public:
45 /**
46 * @brief enum used constructor to specify the units used
47 *
48 * Internally we always use radian for mathematical convenience.
49 * However the Marble's interfaces to the outside should default
50 * to degrees.
51 */
52 enum Unit{
53 Radian,
54 Degree
55 };
56
57 /**
58 * @brief enum used to specify the notation / numerical system
59 *
60 * For degrees there exist two notations:
61 * "Decimal" (base-10) and the "Sexagesimal DMS" (base-60) which is
62 * traditionally used in cartography. Decimal notation
63 * uses floating point numbers to specify parts of a degree. The
64 * Sexagesimal DMS notation uses integer based
65 * Degrees-(Arc)Minutes-(Arc)Seconds to describe parts of a degree.
66 */
68 Decimal, ///< "Decimal" notation (base-10)
69 DMS, ///< "Sexagesimal DMS" notation (base-60)
70 DM, ///< "Sexagesimal DM" notation (base-60)
71 UTM,
72 Astro /// < "RA and DEC" notation (used for astronomical sky coordinates)
73 };
74
75 /**
76 * @brief The BearingType enum specifies where to measure the bearing
77 * along great circle arcs
78 *
79 * When traveling along a great circle arc defined by the two points
80 * A and B, the bearing varies along the arc. The "InitialBearing" bearing
81 * corresponds to the bearing value at A, the "FinalBearing" bearing to that
82 * at B.
83 */
85 InitialBearing,
86 FinalBearing
87 };
88
89 // Type definitions
90 using Vector = QVector<GeoDataCoordinates>;
91 using PtrVector = QVector<GeoDataCoordinates *>;
92
94
95 /**
96 * @brief constructs an invalid instance
97 *
98 * Constructs an invalid instance such that calling isValid()
99 * on it will return @code false @endcode.
100 */
102
103 /**
104 * @brief create a geocoordinate from longitude and latitude
105 * @param lon longitude
106 * @param lat latitude
107 * @param alt altitude in meters (default: 0)
108 * @param unit units that lon and lat get measured in
109 * (default for Radian: north pole at pi/2, southpole at -pi/2)
110 * @param detail detail (default: 0)
111 */
112 GeoDataCoordinates( qreal lon, qreal lat, qreal alt = 0,
113 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian,
114 int detail = 0 );
115
116 virtual ~GeoDataCoordinates();
117
118 /**
119 * @brief Returns @code true @endcode if the coordinate is valid, @code false @endcode otherwise.
120 * @return whether the coordinate is valid
121 *
122 * A coordinate is valid, if at least one component has been set and the last
123 * assignment was not an invalid GeoDataCoordinates object.
124 */
125 bool isValid() const;
126
127 /**
128 * @brief (re)set the coordinates in a GeoDataCoordinates object
129 * @param lon longitude
130 * @param lat latitude
131 * @param alt altitude in meters (default: 0)
132 * @param unit units that lon and lat get measured in
133 * (default for Radian: north pole at pi/2, southpole at -pi/2)
134 */
135 void set( qreal lon, qreal lat, qreal alt = 0,
136 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
137
138 /**
139 * @brief use this function to get the longitude and latitude with one
140 * call - use the unit parameter to switch between Radian and DMS
141 * @param lon longitude
142 * @param lat latitude
143 * @param unit units that lon and lat get measured in
144 * (default for Radian: north pole at pi/2, southpole at -pi/2)
145 */
146 void geoCoordinates(qreal& lon, qreal& lat, GeoDataCoordinates::Unit unit) const;
147 void geoCoordinates(qreal& lon, qreal& lat) const;
148
149 /**
150 * @brief use this function to get the longitude, latitude and altitude
151 * with one call - use the unit parameter to switch between Radian and DMS
152 * @param lon longitude
153 * @param lat latitude
154 * @param alt altitude in meters
155 * @param unit units that lon and lat get measured in
156 * (default for Radian: north pole at pi/2, southpole at -pi/2)
157 */
158 void geoCoordinates(qreal& lon, qreal& lat, qreal& alt, GeoDataCoordinates::Unit unit) const;
159 void geoCoordinates(qreal& lon, qreal& lat, qreal& alt) const;
160
161 /**
162 * @brief set the longitude in a GeoDataCoordinates object
163 * @param lon longitude
164 * @param unit units that lon and lat get measured in
165 * (default for Radian: north pole at pi/2, southpole at -pi/2)
166 */
167 void setLongitude( qreal lon,
168 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
169
170 /**
171 * @brief retrieves the longitude of the GeoDataCoordinates object
172 * use the unit parameter to switch between Radian and DMS
173 * @param unit units that lon and lat get measured in
174 * (default for Radian: north pole at pi/2, southpole at -pi/2)
175 * @return longitude
176 */
177 qreal longitude(GeoDataCoordinates::Unit unit) const;
178 qreal longitude() const;
179
180 /**
181 * @brief retrieves the latitude of the GeoDataCoordinates object
182 * use the unit parameter to switch between Radian and DMS
183 * @param unit units that lon and lat get measured in
184 * (default for Radian: north pole at pi/2, southpole at -pi/2)
185 * @return latitude
186 */
187 qreal latitude( GeoDataCoordinates::Unit unit ) const;
188 qreal latitude() const;
189
190 /**
191 * @brief set the longitude in a GeoDataCoordinates object
192 * @param lat longitude
193 * @param unit units that lon and lat get measured in
194 * (default for Radian: north pole at pi/2, southpole at -pi/2)
195 */
196 void setLatitude( qreal lat,
197 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
198
199 /**
200 * @brief return the altitude of the Point in meters
201 */
202 qreal altitude() const;
203 /**
204 * @brief set the altitude of the Point in meters
205 * @param altitude altitude
206 */
207 void setAltitude( const qreal altitude );
208
209 /**
210 * @brief retrieves the UTM zone of the GeoDataCoordinates object.
211 * If the point is located on one of the poles (latitude < 80S or
212 * latitude > 84N) there is no UTM zone associated; in this case,
213 * 0 is returned.
214 * @return UTM zone.
215 */
216 int utmZone() const;
217
218 /**
219 * @brief retrieves the UTM easting of the GeoDataCoordinates object,
220 * in meters.
221 * @return UTM easting
222 */
223 qreal utmEasting() const;
224
225 /**
226 * @brief retrieves the UTM latitude band of the GeoDataCoordinates object
227 * @return UTM latitude band
228 */
229 QString utmLatitudeBand() const;
230
231 /**
232 * @brief retrieves the UTM northing of the GeoDataCoordinates object,
233 * in meters
234 * @return UTM northing
235 */
236 qreal utmNorthing() const;
237
238 /**
239 * @brief return the detail flag
240 * detail range: 0 for most important points, 5 for least important
241 */
242 quint8 detail() const;
243
244 /**
245 * @brief set the detail flag
246 * @param detail detail
247 */
248 void setDetail(quint8 detail);
249
250 /**
251 * @brief Rotates one coordinate around another.
252 * @param axis The coordinate that serves as a rotation axis
253 * @param angle Rotation angle
254 * @param unit Unit of the result
255 * @return The coordinate rotated in anticlockwise direction
256 */
257 GeoDataCoordinates rotateAround( const GeoDataCoordinates &axis, qreal angle, Unit unit = Radian ) const;
258
259 GeoDataCoordinates rotateAround(const Quaternion &rotAxis) const;
260
261 /**
262 * @brief Returns the bearing (true bearing, the angle between the line defined
263 * by this point and the other and the prime meridian)
264 * @param other The second point that, together with this point, defines a line
265 * @param unit Unit of the result
266 * @param type Type of the bearing
267 * @return The true bearing in the requested unit, not range normalized,
268 * in clockwise direction, with the value 0 corresponding to north
269 */
270 qreal bearing( const GeoDataCoordinates &other, Unit unit = Radian, BearingType type = InitialBearing ) const;
271
272 /**
273 * @brief Returns the coordinates of the resulting point after moving this point
274 * according to the distance and bearing parameters
275 * @param bearing the same as above
276 * @param distance the distance on a unit sphere
277 */
278 GeoDataCoordinates moveByBearing( qreal bearing, qreal distance ) const;
279
280 /**
281 * @brief return a Quaternion with the used coordinates
282 */
283 const Quaternion &quaternion() const;
284
285 /**
286 * @brief slerp (spherical linear) interpolation between this coordinate and the given target coordinate
287 * @param target Destination coordinate
288 * @param t Fraction 0..1 to weight between this and target
289 * @return Interpolated coordinate between this (t<=0.0) and target (t>=1.0)
290 */
291 GeoDataCoordinates interpolate( const GeoDataCoordinates &target, double t ) const;
292
293 /**
294 * @brief nlerp (normalized linear interpolation) between this coordinates and the given target coordinates
295 * @param target Destination coordinates
296 * @param t Fraction 0..1 to weight between this and target
297 * @return Interpolated coordinate between this (t<=0.0) and target (t>=1.0)
298 */
299 GeoDataCoordinates nlerp(const GeoDataCoordinates &target, double t) const;
300
301 /**
302 * @brief squad (spherical and quadrangle) interpolation between b and c
303 * @param before First base point
304 * @param target Third base point (second interpolation point)
305 * @param after Fourth base point
306 * @param t Offset between b (t<=0) and c (t>=1)
307 */
308 GeoDataCoordinates interpolate( const GeoDataCoordinates &before, const GeoDataCoordinates &target, const GeoDataCoordinates &after, double t ) const;
309
310 /**
311 * @brief return whether our coordinates represent a pole
312 * This method can be used to check whether the coordinate equals one of
313 * the poles.
314 */
315 bool isPole( Pole = AnyPole ) const;
316
317 /**
318 * @brief This method calculates the shortest distance between two points on a sphere.
319 * @brief See: https://en.wikipedia.org/wiki/Great-circle_distance
320 */
321 qreal sphericalDistanceTo(const GeoDataCoordinates &other) const;
322
323 /**
324 * @brief return Notation of string representation
325 */
326 static GeoDataCoordinates::Notation defaultNotation();
327
328 /**
329 * @brief set the Notation of the string representation
330 * @param notation Notation
331 */
332 static void setDefaultNotation( GeoDataCoordinates::Notation notation );
333
334 /**
335 * @brief normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
336 * @param lon longitude
337 * @param unit unit of the result
338 */
339 static qreal normalizeLon( qreal lon,
340 GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
341
342 /**
343 * @brief normalize latitude to always be in -M_PI / 2. <= lat <= +M_PI / 2 (Radian).
344 * @param lat latitude
345 * @param unit unit of the result
346 */
347 static qreal normalizeLat( qreal lat,
348 GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
349
350 /**
351 * @brief normalize both longitude and latitude at the same time
352 * This method normalizes both latitude and longitude, so that the
353 * latitude and the longitude stay within the "usual" range.
354 * NOTE: If the latitude exceeds M_PI/2 (+90.0 deg) or -M_PI/2 (-90.0 deg)
355 * then this will be interpreted as a pole traversion where the point will
356 * end up on the opposite side of the globe. Therefore the longitude will
357 * change by M_PI (180 deg).
358 * If you don't want this behaviour use both normalizeLat() and
359 * normalizeLon() instead.
360 * @param lon the longitude value
361 * @param lat the latitude value
362 * @param unit unit of the result
363 */
364 static void normalizeLonLat( qreal &lon, qreal &lat,
365 GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
366
367 /**
368 * @brief try to parse the string into a coordinate pair
369 * @param string the string
370 * @param successful becomes true if the conversion succeeds
371 * @return the geodatacoordinates
372 */
373 static GeoDataCoordinates fromString( const QString &string, bool& successful );
374
375 /**
376 * @brief return a string representation of the coordinate
377 * this is a convenience function which uses the default notation
378 */
379 QString toString() const;
380
381 /**
382 * @brief return a string with the notation given by notation
383 *
384 * @param notation set a notation different from the default one
385 * @param precision set the number of digits below degrees.
386 * The precision depends on the current notation:
387 * For Decimal representation the precision is the number of
388 * digits after the decimal point.
389 * In DMS a precision of 1 or 2 shows the arc minutes; a precision
390 * of 3 or 4 will show arc seconds. A precision beyond that will
391 * increase the number of digits after the arc second decimal point.
392 */
393 QString toString( GeoDataCoordinates::Notation notation, int precision = -1 ) const;
394
395 static QString lonToString( qreal lon, GeoDataCoordinates::Notation notation,
396 GeoDataCoordinates::Unit unit = Radian,
397 int precision = -1,
398 char format = 'f' );
399 /**
400 * @brief return a string representation of longitude of the coordinate
401 * convenience function that uses the default notation
402 */
403 QString lonToString() const;
404
405 static QString latToString( qreal lat, GeoDataCoordinates::Notation notation,
406 GeoDataCoordinates::Unit unit = Radian,
407 int precision = -1,
408 char format = 'f' );
409 /**
410 * @brief return a string representation of latitude of the coordinate
411 * convenience function that uses the default notation
412 */
413 QString latToString() const;
414
415 bool operator==(const GeoDataCoordinates &other) const;
416 bool operator!=(const GeoDataCoordinates &other) const;
417
418 GeoDataCoordinates& operator=( const GeoDataCoordinates &other );
419
420 /** Serialize the contents of the feature to @p stream. */
421 void pack(QDataStream &stream) const;
422 /** Unserialize the contents of the feature from @p stream. */
423 void unpack(QDataStream &stream);
424
425 private:
426 void detach();
427
428 GeoDataCoordinatesPrivate *d;
429
430 static GeoDataCoordinates::Notation s_notation;
431 static const GeoDataCoordinates null;
432};
433
434GEODATA_EXPORT uint qHash(const GeoDataCoordinates& coordinates );
435
436
437}
438
439Q_DECLARE_METATYPE( Marble::GeoDataCoordinates )
440
441#endif
A 3d point representation.
Notation
enum used to specify the notation / numerical system
@ DM
"Sexagesimal DM" notation (base-60)
@ DMS
"Sexagesimal DMS" notation (base-60)
@ Decimal
"Decimal" notation (base-10)
BearingType
The BearingType enum specifies where to measure the bearing along great circle arcs.
Unit
enum used constructor to specify the units used
Binds a QML item to a specific geodetic location in screen coordinates.
@ UTM
UTM.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.