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

KDE's Doxygen guidelines are available online.