Marble

GeoDataCoordinates.h
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <[email protected]>
4 // SPDX-FileCopyrightText: 2007-2008 Inge Wallin <[email protected]>
5 // SPDX-FileCopyrightText: 2008 Patrick Spendrin <[email protected]>
6 // SPDX-FileCopyrightText: 2015 Alejandro Garcia Montoro <[email protected]>
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 
20 class QString;
21 
22 namespace Marble
23 {
24 
25 class GeoDataCoordinatesPrivate;
26 class 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 
40 class 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  */
67  enum Notation{
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  */
84  enum BearingType {
85  InitialBearing,
86  FinalBearing
87  };
88 
89  // Type definitions
90  using Vector = QVector<GeoDataCoordinates>;
91  using PtrVector = QVector<GeoDataCoordinates *>;
92 
93  GeoDataCoordinates( const GeoDataCoordinates& other );
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 
434 GEODATA_EXPORT uint qHash(const GeoDataCoordinates& coordinates );
435 
436 
437 }
438 
439 Q_DECLARE_METATYPE( Marble::GeoDataCoordinates )
440 
441 #endif
A 3d point representation.
@ AnyPole
Any pole.
Definition: MarbleGlobal.h:140
@ DMS
"Sexagesimal DMS" notation (base-60)
@ UTM
UTM.
Definition: MarbleGlobal.h:60
@ DM
"Sexagesimal DM" notation (base-60)
@ Decimal
"Decimal" notation (base-10)
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
Binds a QML item to a specific geodetic location in screen coordinates.
BearingType
The BearingType enum specifies where to measure the bearing along great circle arcs.
Unit
enum used constructor to specify the units used
Notation
enum used to specify the notation / numerical system
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 03:53:49 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.