1 /*
2     SPDX-FileCopyrightText: 2001-2005 Jason Harris <jharris@30doradus.org>
3     SPDX-FileCopyrightText: 2003-2005 Pablo de Vicente <p.devicente@wanadoo.es>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #pragma once
9 
10 #include <KLocalizedString>
11 
12 #include "cachingdms.h"
13 #include "timezonerule.h"
14 #include "kstarsdatetime.h"
15 
16 /**
17  * @class GeoLocation
18  * Contains all relevant information for specifying a location
19  * on Earth: City Name, State/Province name, Country Name,
20  * Longitude, Latitude, Elevation, Time Zone, and Daylight Savings
21  * Time rule.
22  *
23  * @short Relevant data about an observing location on Earth.
24  * @author Jason Harris
25  * @version 1.0
26  */
27 class GeoLocation
28 {
29     public:
30         /** Constructor using dms objects to specify longitude and latitude.
31              * @param lng the longitude
32              * @param lat the latitude
33              * @param name the name of the city/town/location
34              * @param province the name of the province/US state
35              * @param country the name of the country
36              * @param TZ the base time zone offset from Greenwich, UK
37              * @param TZrule pointer to the daylight savings time rule
38              * @param elevation the elevation above sea level (in meters)
39              * @param readOnly whether the location is read only or updatable.
40              * @param iEllips type of geodetic ellipsoid model
41              */
42         GeoLocation(const dms &lng, const dms &lat, const QString &name = "Nowhere", const QString &province = "Nowhere",
43                     const QString &country = "Nowhere", double TZ = 0, TimeZoneRule *TZrule = nullptr,
44                     double elevation = -10, bool readOnly = false, int iEllips = 4);
45 
46         /** Constructor using doubles to specify X, Y and Z referred to the center of the Earth.
47              * @param x the x-position, in m
48              * @param y the y-position, in m
49              * @param z the z-position, in m
50              * @param name the name of the city/town/location
51              * @param province the name of the province/US state
52              * @param country the name of the country
53              * @param TZ the base time zone offset from Greenwich, UK
54              * @param TZrule pointer to the daylight savings time rule
55              * @param elevation the elevation above sea level (in meters)
56              * @param readOnly whether the location is read only or updatable.
57              * @param iEllips type of geodetic ellipsoid model
58              */
59         GeoLocation(double x, double y, double z, const QString &name = "Nowhere", const QString &province = "Nowhere",
60                     const QString &country = "Nowhere", double TZ = 0, TimeZoneRule *TZrule = nullptr,
61                     double elevation = -10, bool readOnly = false, int iEllips = 4);
62 
63         /** @return pointer to the longitude dms object */
lng()64         const CachingDms *lng() const
65         {
66             return &Longitude;
67         }
68 
69         /** @return pointer to the latitude dms object */
lat()70         const CachingDms *lat() const
71         {
72             return &Latitude;
73         }
74 
75         /** @return elevation above seal level (meters) */
elevation()76         double elevation() const
77         {
78             return Elevation;
79         }
80 
81         /** @return X position in m */
xPos()82         double xPos() const
83         {
84             return PosCartX;
85         }
86 
87         /** @return Y position in m */
yPos()88         double yPos() const
89         {
90             return PosCartY;
91         }
92 
93         /** @return Z position in m */
zPos()94         double zPos() const
95         {
96             return PosCartZ;
97         }
98 
99         /** @return index identifying the geodetic ellipsoid model */
ellipsoid()100         int ellipsoid() const
101         {
102             return indexEllipsoid;
103         }
104 
105         /** @return untranslated City name */
name()106         QString name() const
107         {
108             return Name;
109         }
110 
111         /** @return translated City name */
112         QString translatedName() const;
113 
114         /** @return untranslated Province name */
province()115         QString province() const
116         {
117             return Province;
118         }
119 
120         /** @return translated Province name */
121         QString translatedProvince() const;
122 
123         /** @return untranslated Country name */
country()124         QString country() const
125         {
126             return Country;
127         }
128 
129         /** @return translated Country name */
130         QString translatedCountry() const;
131 
132         /** @return comma-separated city, province, country names (each localized) */
133         QString fullName() const;
134 
135         /** @return time zone without DST correction */
TZ0()136         double TZ0() const
137         {
138             return TimeZone;
139         }
140 
141         /** @return time zone, including any DST correction. */
TZ()142         double TZ() const
143         {
144             if (TZrule)
145                 return TimeZone + TZrule->deltaTZ();
146             return TimeZone;
147         }
148 
149         /** @return pointer to time zone rule object */
tzrule()150         TimeZoneRule *tzrule()
151         {
152             return TZrule;
153         }
154 
155         /** Set Time zone.
156              * @param value the new time zone */
setTZ0(double value)157         void setTZ0(double value)
158         {
159             TimeZone = value;
160         }
161 
162         /** Set Time zone rule.
163              * @param value pointer to the new time zone rule */
setTZRule(TimeZoneRule * value)164         void setTZRule(TimeZoneRule *value)
165         {
166             TZrule = value;
167         }
168 
169         /** Set longitude according to dms argument.
170              * @param l the new longitude */
setLong(const dms & l)171         void setLong(const dms &l)
172         {
173             Longitude = l;
174             geodToCart();
175         }
176 
177         /** Set latitude according to dms argument.
178              * @param l the new latitude
179              */
setLat(const dms & l)180         void setLat(const dms &l)
181         {
182             Latitude = l;
183             geodToCart();
184         }
185 
186         /** Set elevation above sea level
187              * @param hg the new elevation (meters)
188              */
setElevation(double hg)189         void setElevation(double hg)
190         {
191             Elevation = hg;
192             geodToCart();
193         }
194 
195         /** Set X
196              * @param x the new x-position (meters)
197              */
setXPos(double x)198         void setXPos(double x)
199         {
200             PosCartX = x;
201             cartToGeod();
202         }
203         /** Set Y
204              * @param y the new y-position (meters)
205              */
setYPos(double y)206         void setYPos(double y)
207         {
208             PosCartY = y;
209             cartToGeod();
210         }
211         /** Set Z
212              * @param z the new z-position (meters)
213              */
setZPos(double z)214         void setZPos(double z)
215         {
216             PosCartZ = z;
217             cartToGeod();
218         }
219 
220         /** Update Latitude, Longitude and Height according to new ellipsoid. These are
221              * computed from XYZ which do NOT change on changing the ellipsoid.
222              * @param i index to identify the ellipsoid
223              */
224         void changeEllipsoid(int i);
225 
226         /** Set City name according to argument.
227              * @param n new city name
228              */
setName(const QString & n)229         void setName(const QString &n)
230         {
231             Name = n;
232         }
233 
234         /** Set Province name according to argument.
235              * @param n new province name
236              */
setProvince(const QString & n)237         void setProvince(const QString &n)
238         {
239             Province = n;
240         }
241 
242         /** Set Country name according to argument.
243              * @param n new country name
244              */
setCountry(const QString & n)245         void setCountry(const QString &n)
246         {
247             Country = n;
248         }
249 
250         /** Converts from cartesian coordinates in meters to longitude,
251              * latitude and height on a standard geoid for the Earth. The
252              * geoid is characterized by two parameters: the semimajor axis
253              * and the flattening.
254              *
255              * @note The astronomical zenith is defined as the perpendicular to
256              * the real geoid. The geodetic zenith is the perpendicular to the
257              * standard geoid. Both zeniths differ due to local gravitational
258              * anomalies.
259              *
260              * Algorithm is from "GPS Satellite Surveying", A. Leick, page 184.
261              */
262         void cartToGeod();
263 
264         /** Converts from longitude, latitude and height on a standard
265              * geoid of the Earth to cartesian coordinates in meters. The geoid
266              * is characterized by two parameters: the semimajor axis and the
267              * flattening.
268              *
269              * @note The astronomical zenith is defined as the perpendicular to
270              * the real geoid. The geodetic zenith is the perpendicular to the
271              * standard geoid. Both zeniths differ due to local gravitational
272              * anomalies.
273              *
274              * Algorithm is from "GPS Satellite Surveying", A. Leick, page 184.
275              */
276         void geodToCart();
277 
278         /** The geoid is an elliposid which fits the shape of the Earth. It is
279              * characterized by two parameters: the semimajor axis and the
280              * flattening.
281              *
282              * @param i is the index which allows to identify the parameters for the
283              * chosen elliposid. 1="IAU76", 2="GRS80", 3="MERIT83", 4="WGS84",
284              * 5="IERS89".
285              */
286         void setEllipsoid(int i);
287 
288         /**
289          * @brief distanceTo Return the distance in km from this location to the given longitude and latitude
290          * @param longitude Target site longitude
291          * @param latitude Target site latitude
292          * @return distance in kilometers between this site and the target site.
293          */
294         double distanceTo(const dms &longitude, const dms &latitude);
295 
GSTtoLST(const dms & gst)296         dms GSTtoLST(const dms &gst) const
297         {
298             return dms(gst.Degrees() + Longitude.Degrees());
299         }
LSTtoGST(const dms & lst)300         dms LSTtoGST(const dms &lst) const
301         {
302             return dms(lst.Degrees() - Longitude.Degrees());
303         }
304 
305         KStarsDateTime UTtoLT(const KStarsDateTime &ut) const;
306         KStarsDateTime LTtoUT(const KStarsDateTime &lt) const;
307 
308         /** Computes the velocity in km/s of an observer on the surface of the Earth
309              * referred to a system whose origin is the center of the Earth. The X and
310              * Y axis are contained in the equator and the X axis is towards the nodes
311              * line. The Z axis is along the poles.
312              *
313              * @param vtopo[] Topocentric velocity. The resultant velocity is available
314              *        in this array.
315              * @param gt Greenwich sideral time for which we want to compute the topocentric velocity.
316              */
317         void TopocentricVelocity(double vtopo[], const dms &gt);
318 
319         /** @return Local Mean Sidereal Time.
320              * @param jd Julian date
321              */
322         double LMST(double jd);
323 
324         bool isReadOnly() const;
325         void setReadOnly(bool value);
326 
327     private:
328         CachingDms Longitude, Latitude;
329         QString Name, Province, Country;
330         TimeZoneRule *TZrule;
331         double TimeZone, Elevation;
332         double axis, flattening;
333         long double PosCartX, PosCartY, PosCartZ;
334         int indexEllipsoid;
335         bool ReadOnly;
336 };
337