File indexing completed on 2024-04-21 14:43:59
0001 /* 0002 SPDX-FileCopyrightText: 2001-2005 Jason Harris <jharris@30doradus.org> 0003 SPDX-FileCopyrightText: 2003-2005 Pablo de Vicente <p.devicente@wanadoo.es> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "geolocation.h" 0009 0010 #include "timezonerule.h" 0011 0012 GeoLocation::GeoLocation(const dms &lng, const dms &lat, const QString &name, const QString &province, const QString &country, 0013 double tz, TimeZoneRule *tzrule, double elevation, bool readOnly, int iEllips) : 0014 Longitude(lng), Latitude(lat) 0015 { 0016 Name = name; 0017 Province = province; 0018 Country = country; 0019 TimeZone = tz; 0020 TZrule = tzrule; 0021 Elevation = elevation; 0022 indexEllipsoid = iEllips; 0023 ReadOnly = readOnly; 0024 setEllipsoid(indexEllipsoid); 0025 geodToCart(); 0026 } 0027 0028 GeoLocation::GeoLocation(double x, double y, double z, const QString &name, const QString &province, 0029 const QString &country, double TZ, TimeZoneRule *tzrule, double elevation, bool readOnly, int iEllips) 0030 { 0031 PosCartX = x; 0032 PosCartY = y; 0033 PosCartZ = z; 0034 Name = name; 0035 Province = province; 0036 Country = country; 0037 TimeZone = TZ; 0038 TZrule = tzrule; 0039 Elevation = elevation; 0040 indexEllipsoid = iEllips; 0041 ReadOnly = readOnly; 0042 setEllipsoid(indexEllipsoid); 0043 cartToGeod(); 0044 } 0045 0046 QString GeoLocation::fullName() const 0047 { 0048 if (country().isEmpty()) 0049 return translatedName(); 0050 else if (province().isEmpty()) 0051 { 0052 return QString("%1, %2").arg(translatedName(), translatedCountry()); 0053 } 0054 else 0055 { 0056 return QString("%1, %2, %3").arg(translatedName(), translatedProvince(), translatedCountry()); 0057 } 0058 } 0059 0060 void GeoLocation::setEllipsoid(int i) 0061 { 0062 static const double A[] = { 6378140.0, 6378137.0, 6378137.0, 6378137.0, 6378136.0 }; 0063 static const double F[] = { 0.0033528131779, 0.0033528106812, 0.0033528131779, 0.00335281066474, 0.0033528131779 }; 0064 0065 Q_ASSERT(i >= 0 && (unsigned int)i < sizeof(A) / sizeof(A[0]) && "Index must be in bounds"); 0066 axis = A[i]; 0067 flattening = F[i]; 0068 } 0069 0070 void GeoLocation::changeEllipsoid(int index) 0071 { 0072 setEllipsoid(index); 0073 cartToGeod(); 0074 } 0075 0076 QString GeoLocation::translatedName() const 0077 { 0078 QString context; 0079 if (province().isEmpty()) 0080 { 0081 context = QString("City in %1").arg(country()); 0082 } 0083 else 0084 { 0085 context = QString("City in %1 %2").arg(province(), country()); 0086 } 0087 return Name.isEmpty() ? QString() : i18nc(context.toUtf8().data(), Name.toUtf8().data()); 0088 } 0089 0090 QString GeoLocation::translatedProvince() const 0091 { 0092 return Province.isEmpty() ? 0093 QString() : 0094 i18nc(QString("Region/state in " + country()).toUtf8().data(), Province.toUtf8().data()); 0095 } 0096 0097 QString GeoLocation::translatedCountry() const 0098 { 0099 return Country.isEmpty() ? QString() : i18nc("Country name", Country.toUtf8().data()); 0100 } 0101 0102 void GeoLocation::cartToGeod() 0103 { 0104 static const double RIT = 2.7778e-6; 0105 double e2, rpro, lat1, xn, sqrtP2, latd, sinl; 0106 0107 e2 = 2 * flattening - flattening * flattening; 0108 0109 sqrtP2 = sqrt(PosCartX * PosCartX + PosCartY * PosCartY); 0110 0111 rpro = PosCartZ / sqrtP2; 0112 latd = atan2(rpro, (1 - e2)); 0113 lat1 = 0.; 0114 0115 while (fabs(latd - lat1) > RIT) 0116 { 0117 double s1 = sin(latd); 0118 0119 lat1 = latd; 0120 xn = axis / (sqrt(1 - e2 * s1 * s1)); 0121 latd = atan2(static_cast<long double>(rpro) * (1 + e2 * xn * s1), PosCartZ); 0122 } 0123 0124 sinl = sin(latd); 0125 xn = axis / (sqrt(1 - e2 * sinl * sinl)); 0126 0127 Elevation = sqrtP2 / cos(latd) - xn; 0128 Longitude.setRadians(atan2(PosCartY, PosCartX)); 0129 Latitude.setRadians(latd); 0130 } 0131 0132 void GeoLocation::geodToCart() 0133 { 0134 double e2, xn; 0135 double sinLong, cosLong, sinLat, cosLat; 0136 0137 e2 = 2 * flattening - flattening * flattening; 0138 0139 Longitude.SinCos(sinLong, cosLong); 0140 Latitude.SinCos(sinLat, cosLat); 0141 0142 xn = axis / (sqrt(1 - e2 * sinLat * sinLat)); 0143 PosCartX = (xn + Elevation) * cosLat * cosLong; 0144 PosCartY = (xn + Elevation) * cosLat * sinLong; 0145 PosCartZ = (xn * (1 - e2) + Elevation) * sinLat; 0146 } 0147 0148 void GeoLocation::TopocentricVelocity(double vtopo[], const dms &gst) 0149 { 0150 double Wearth = 7.29211510e-5; // rads/s 0151 dms angularVEarth; 0152 0153 dms time = GSTtoLST(gst); 0154 // angularVEarth.setRadians(time.Hours()*Wearth*3600.); 0155 double se, ce; 0156 // angularVEarth.SinCos(se,ce); 0157 time.SinCos(se, ce); 0158 0159 double d0 = sqrt(PosCartX * PosCartX + PosCartY * PosCartY); 0160 // km/s 0161 vtopo[0] = -d0 * Wearth * se / 1000.; 0162 vtopo[1] = d0 * Wearth * ce / 1000.; 0163 vtopo[2] = 0.; 0164 } 0165 0166 double GeoLocation::LMST(double jd) 0167 { 0168 int divresult; 0169 double ut, tu, gmst, theta; 0170 0171 ut = (jd + 0.5) - floor(jd + 0.5); 0172 jd -= ut; 0173 tu = (jd - 2451545.) / 36525.; 0174 0175 gmst = 24110.54841 + tu * (8640184.812866 + tu * (0.093104 - tu * 6.2e-6)); 0176 divresult = (int)((gmst + 8.6400e4 * 1.00273790934 * ut) / 8.6400e4); 0177 gmst = (gmst + 8.6400e4 * 1.00273790934 * ut) - (double)divresult * 8.6400e4; 0178 theta = 2. * dms::PI * gmst / (24. * 60. * 60.); 0179 divresult = (int)((theta + Longitude.radians()) / (2. * dms::PI)); 0180 return ((theta + Longitude.radians()) - (double)divresult * 2. * dms::PI); 0181 } 0182 0183 bool GeoLocation::isReadOnly() const 0184 { 0185 return ReadOnly; 0186 } 0187 0188 void GeoLocation::setReadOnly(bool value) 0189 { 0190 ReadOnly = value; 0191 } 0192 0193 KStarsDateTime GeoLocation::UTtoLT(const KStarsDateTime &ut) const 0194 { 0195 KStarsDateTime lt = ut.addSecs(int(3600. * TZ())); 0196 // 2017-08-11 (Jasem): setUtcOffset is deprecated 0197 //lt.setUtcOffset(int(3600. * TZ())); 0198 lt.setTimeSpec(Qt::LocalTime); 0199 0200 return lt; 0201 } 0202 0203 KStarsDateTime GeoLocation::LTtoUT(const KStarsDateTime <) const 0204 { 0205 KStarsDateTime ut = lt.addSecs(int(-3600. * TZ())); 0206 ut.setTimeSpec(Qt::UTC); 0207 // 2017-08-11 (Jasem): setUtcOffset is deprecated 0208 //ut.setUtcOffset(0); 0209 0210 return ut; 0211 } 0212 0213 double GeoLocation::distanceTo(const dms &longitude, const dms &latitude) 0214 { 0215 const double R = 6378.135; 0216 0217 double diffLongitude = (Longitude - longitude).radians(); 0218 double diffLatitude = (Latitude - latitude).radians(); 0219 0220 double a = sin(diffLongitude / 2) * sin(diffLongitude / 2) + cos(Longitude.radians()) * cos(longitude.radians()) * 0221 sin(diffLatitude / 2) * sin(diffLatitude / 2); 0222 double c = 2 * atan2(sqrt(a), sqrt(1 - a)); 0223 0224 double distance = R * c; 0225 0226 return distance; 0227 }