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 {
56 Radian,
57 Degree
58 };
59
60 /**
61 * @brief enum used to specify the notation / numerical system
62 *
63 * For degrees there exist two notations:
64 * "Decimal" (base-10) and the "Sexagesimal DMS" (base-60) which is
65 * traditionally used in cartography. Decimal notation
66 * uses floating point numbers to specify parts of a degree. The
67 * Sexagesimal DMS notation uses integer based
68 * Degrees-(Arc)Minutes-(Arc)Seconds to describe parts of a degree.
69 */
70 enum Notation {
71 Decimal, ///< "Decimal" notation (base-10)
72 DMS, ///< "Sexagesimal DMS" notation (base-60)
73 DM, ///< "Sexagesimal DM" notation (base-60)
74 UTM,
75 Astro /// < "RA and DEC" notation (used for astronomical sky coordinates)
76 };
77
78 /**
79 * @brief The BearingType enum specifies where to measure the bearing
80 * along great circle arcs
81 *
82 * When traveling along a great circle arc defined by the two points
83 * A and B, the bearing varies along the arc. The "InitialBearing" bearing
84 * corresponds to the bearing value at A, the "FinalBearing" bearing to that
85 * at B.
86 */
88 InitialBearing,
89 FinalBearing
90 };
91
92 // Type definitions
93 using Vector = QList<GeoDataCoordinates>;
94 using PtrVector = QList<GeoDataCoordinates *>;
95
97
98 /**
99 * @brief constructs an invalid instance
100 *
101 * Constructs an invalid instance such that calling isValid()
102 * on it will return @code false @endcode.
103 */
105
106 /**
107 * @brief create a geocoordinate from longitude and latitude
108 * @param lon longitude
109 * @param lat latitude
110 * @param alt altitude in meters (default: 0)
111 * @param unit units that lon and lat get measured in
112 * (default for Radian: north pole at pi/2, southpole at -pi/2)
113 * @param detail detail (default: 0)
114 */
115 GeoDataCoordinates(qreal lon, qreal lat, qreal alt = 0, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian, int detail = 0);
116
117 virtual ~GeoDataCoordinates();
118
119 /**
120 * @brief Returns @code true @endcode if the coordinate is valid, @code false @endcode otherwise.
121 * @return whether the coordinate is valid
122 *
123 * A coordinate is valid, if at least one component has been set and the last
124 * assignment was not an invalid GeoDataCoordinates object.
125 */
126 bool isValid() const;
127
128 /**
129 * @brief (re)set the coordinates in a GeoDataCoordinates object
130 * @param lon longitude
131 * @param lat latitude
132 * @param alt altitude in meters (default: 0)
133 * @param unit units that lon and lat get measured in
134 * (default for Radian: north pole at pi/2, southpole at -pi/2)
135 */
136 void set(qreal lon, qreal lat, qreal alt = 0, 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, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian);
168
169 /**
170 * @brief retrieves the longitude of the GeoDataCoordinates object
171 * use the unit parameter to switch between Radian and DMS
172 * @param unit units that lon and lat get measured in
173 * (default for Radian: north pole at pi/2, southpole at -pi/2)
174 * @return longitude
175 */
176 qreal longitude(GeoDataCoordinates::Unit unit) const;
177 qreal longitude() const;
178
179 /**
180 * @brief retrieves the latitude of the GeoDataCoordinates object
181 * use the unit parameter to switch between Radian and DMS
182 * @param unit units that lon and lat get measured in
183 * (default for Radian: north pole at pi/2, southpole at -pi/2)
184 * @return latitude
185 */
186 qreal latitude(GeoDataCoordinates::Unit unit) const;
187 qreal latitude() const;
188
189 /**
190 * @brief set the longitude in a GeoDataCoordinates object
191 * @param lat longitude
192 * @param unit units that lon and lat get measured in
193 * (default for Radian: north pole at pi/2, southpole at -pi/2)
194 */
195 void setLatitude(qreal lat, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian);
196
197 /**
198 * @brief return the altitude of the Point in meters
199 */
200 qreal altitude() const;
201 /**
202 * @brief set the altitude of the Point in meters
203 * @param altitude altitude
204 */
205 void setAltitude(const qreal altitude);
206
207 /**
208 * @brief retrieves the UTM zone of the GeoDataCoordinates object.
209 * If the point is located on one of the poles (latitude < 80S or
210 * latitude > 84N) there is no UTM zone associated; in this case,
211 * 0 is returned.
212 * @return UTM zone.
213 */
214 int utmZone() const;
215
216 /**
217 * @brief retrieves the UTM easting of the GeoDataCoordinates object,
218 * in meters.
219 * @return UTM easting
220 */
221 qreal utmEasting() const;
222
223 /**
224 * @brief retrieves the UTM latitude band of the GeoDataCoordinates object
225 * @return UTM latitude band
226 */
227 QString utmLatitudeBand() const;
228
229 /**
230 * @brief retrieves the UTM northing of the GeoDataCoordinates object,
231 * in meters
232 * @return UTM northing
233 */
234 qreal utmNorthing() const;
235
236 /**
237 * @brief return the detail flag
238 * detail range: 0 for most important points, 5 for least important
239 */
240 quint8 detail() const;
241
242 /**
243 * @brief set the detail flag
244 * @param detail detail
245 */
246 void setDetail(quint8 detail);
247
248 /**
249 * @brief Rotates one coordinate around another.
250 * @param axis The coordinate that serves as a rotation axis
251 * @param angle Rotation angle
252 * @param unit Unit of the result
253 * @return The coordinate rotated in anticlockwise direction
254 */
255 GeoDataCoordinates rotateAround(const GeoDataCoordinates &axis, qreal angle, Unit unit = Radian) const;
256
257 GeoDataCoordinates rotateAround(const Quaternion &rotAxis) const;
258
259 /**
260 * @brief Returns the bearing (true bearing, the angle between the line defined
261 * by this point and the other and the prime meridian)
262 * @param other The second point that, together with this point, defines a line
263 * @param unit Unit of the result
264 * @param type Type of the bearing
265 * @return The true bearing in the requested unit, not range normalized,
266 * in clockwise direction, with the value 0 corresponding to north
267 */
268 qreal bearing(const GeoDataCoordinates &other, Unit unit = Radian, BearingType type = InitialBearing) const;
269
270 /**
271 * @brief Returns the coordinates of the resulting point after moving this point
272 * according to the distance and bearing parameters
273 * @param bearing the same as above
274 * @param distance the distance on a unit sphere
275 */
276 GeoDataCoordinates moveByBearing(qreal bearing, qreal distance) const;
277
278 /**
279 * @brief return a Quaternion with the used coordinates
280 */
281 const Quaternion &quaternion() const;
282
283 /**
284 * @brief slerp (spherical linear) interpolation between this coordinate and the given target coordinate
285 * @param target Destination coordinate
286 * @param t Fraction 0..1 to weight between this and target
287 * @return Interpolated coordinate between this (t<=0.0) and target (t>=1.0)
288 */
289 GeoDataCoordinates interpolate(const GeoDataCoordinates &target, double t) const;
290
291 /**
292 * @brief nlerp (normalized linear interpolation) between this coordinates and the given target coordinates
293 * @param target Destination coordinates
294 * @param t Fraction 0..1 to weight between this and target
295 * @return Interpolated coordinate between this (t<=0.0) and target (t>=1.0)
296 */
297 GeoDataCoordinates nlerp(const GeoDataCoordinates &target, double t) const;
298
299 /**
300 * @brief squad (spherical and quadrangle) interpolation between b and c
301 * @param before First base point
302 * @param target Third base point (second interpolation point)
303 * @param after Fourth base point
304 * @param t Offset between b (t<=0) and c (t>=1)
305 */
306 GeoDataCoordinates interpolate(const GeoDataCoordinates &before, const GeoDataCoordinates &target, const GeoDataCoordinates &after, double t) const;
307
308 /**
309 * @brief return whether our coordinates represent a pole
310 * This method can be used to check whether the coordinate equals one of
311 * the poles.
312 */
313 bool isPole(Pole = AnyPole) const;
314
315 /**
316 * @brief This method calculates the shortest distance between two points on a sphere.
317 * @brief See: https://en.wikipedia.org/wiki/Great-circle_distance
318 */
319 qreal sphericalDistanceTo(const GeoDataCoordinates &other) const;
320
321 /**
322 * @brief return Notation of string representation
323 */
324 static GeoDataCoordinates::Notation defaultNotation();
325
326 /**
327 * @brief set the Notation of the string representation
328 * @param notation Notation
329 */
330 static void setDefaultNotation(GeoDataCoordinates::Notation notation);
331
332 /**
333 * @brief normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
334 * @param lon longitude
335 * @param unit unit of the result
336 */
337 static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit = GeoDataCoordinates::Radian);
338
339 /**
340 * @brief normalize latitude to always be in -M_PI / 2. <= lat <= +M_PI / 2 (Radian).
341 * @param lat latitude
342 * @param unit unit of the result
343 */
344 static qreal normalizeLat(qreal lat, GeoDataCoordinates::Unit = GeoDataCoordinates::Radian);
345
346 /**
347 * @brief normalize both longitude and latitude at the same time
348 * This method normalizes both latitude and longitude, so that the
349 * latitude and the longitude stay within the "usual" range.
350 * NOTE: If the latitude exceeds M_PI/2 (+90.0 deg) or -M_PI/2 (-90.0 deg)
351 * then this will be interpreted as a pole traversion where the point will
352 * end up on the opposite side of the globe. Therefore the longitude will
353 * change by M_PI (180 deg).
354 * If you don't want this behaviour use both normalizeLat() and
355 * normalizeLon() instead.
356 * @param lon the longitude value
357 * @param lat the latitude value
358 * @param unit unit of the result
359 */
360 static void normalizeLonLat(qreal &lon, qreal &lat, GeoDataCoordinates::Unit = GeoDataCoordinates::Radian);
361
362 /**
363 * @brief try to parse the string into a coordinate pair
364 * @param string the string
365 * @param successful becomes true if the conversion succeeds
366 * @return the geodatacoordinates
367 */
368 static GeoDataCoordinates fromString(const QString &string, bool &successful);
369
370 /**
371 * @brief return a string representation of the coordinate
372 * this is a convenience function which uses the default notation
373 */
374 QString toString() const;
375
376 /**
377 * @brief return a string with the notation given by notation
378 *
379 * @param notation set a notation different from the default one
380 * @param precision set the number of digits below degrees.
381 * The precision depends on the current notation:
382 * For Decimal representation the precision is the number of
383 * digits after the decimal point.
384 * In DMS a precision of 1 or 2 shows the arc minutes; a precision
385 * of 3 or 4 will show arc seconds. A precision beyond that will
386 * increase the number of digits after the arc second decimal point.
387 */
388 QString toString(GeoDataCoordinates::Notation notation, int precision = -1) const;
389
390 static QString lonToString(qreal lon, GeoDataCoordinates::Notation notation, GeoDataCoordinates::Unit unit = Radian, int precision = -1, char format = 'f');
391 /**
392 * @brief return a string representation of longitude of the coordinate
393 * convenience function that uses the default notation
394 */
395 QString lonToString() const;
396
397 static QString latToString(qreal lat, GeoDataCoordinates::Notation notation, GeoDataCoordinates::Unit unit = Radian, int precision = -1, char format = 'f');
398 /**
399 * @brief return a string representation of latitude of the coordinate
400 * convenience function that uses the default notation
401 */
402 QString latToString() const;
403
404 bool operator==(const GeoDataCoordinates &other) const;
405 bool operator!=(const GeoDataCoordinates &other) const;
406
407 GeoDataCoordinates &operator=(const GeoDataCoordinates &other);
408
409 /** Serialize the contents of the feature to @p stream. */
410 void pack(QDataStream &stream) const;
411 /** Unserialize the contents of the feature from @p stream. */
412 void unpack(QDataStream &stream);
413
414private:
415 void detach();
416
417 GeoDataCoordinatesPrivate *d;
418
419 static GeoDataCoordinates::Notation s_notation;
420 static const GeoDataCoordinates null;
421};
422
423GEODATA_EXPORT size_t qHash(const GeoDataCoordinates &coordinates);
424
425}
426
427Q_DECLARE_METATYPE(Marble::GeoDataCoordinates)
428
429#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 Mon Nov 18 2024 12:15:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.