Loading...
Searching...
No Matches
geo-coordinate.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013 Magister Solutions Ltd
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Sami Rantanen <sami.rantanen@magister.fi>
19 */
20
21#include "geo-coordinate.h"
22
23#include "satellite-utils.h"
24
25#include "ns3/fatal-error.h"
26#include "ns3/log.h"
27
28#include <cmath>
29#include <ios>
30#include <istream>
31#include <ostream>
32#include <sstream>
33#include <stdint.h>
34
35NS_LOG_COMPONENT_DEFINE("geo-coordinate");
36
37namespace ns3
38{
39
41
43 double longitude,
44 double altitude,
45 ReferenceEllipsoid_t refEllipsoid,
46 bool correctIfInvalid)
47 : m_refEllipsoid(refEllipsoid)
48{
49 NS_LOG_FUNCTION(this << latitude << longitude << altitude);
50
51 Construct(latitude, longitude, altitude, correctIfInvalid);
52}
53
55 double longitude,
56 double altitude,
57 bool correctIfInvalid)
59{
60 NS_LOG_FUNCTION(this << latitude << longitude << altitude);
61
62 Construct(latitude, longitude, altitude, correctIfInvalid);
63}
64
67{
68 NS_LOG_FUNCTION(this << vector);
69
70 ConstructFromVector(vector);
71}
72
74 : m_refEllipsoid(refEllipsoid)
75{
76 NS_LOG_FUNCTION(this << vector);
77
78 ConstructFromVector(vector);
79}
80
82 : m_latitude(NAN),
83 m_longitude(NAN),
84 m_altitude(NAN),
86{
87 NS_LOG_FUNCTION(this);
88
89 Initialize();
90}
91
92void
93GeoCoordinate::Construct(double latitude, double longitude, double altitude, bool correctIfInvalid)
94{
95 NS_LOG_FUNCTION(this << latitude << longitude << altitude);
96
97 if (correctIfInvalid)
98 {
99 if (latitude > 90)
100 {
101 latitude = 180 - latitude;
102 longitude += 180;
103 }
104 if (latitude < -90)
105 {
106 latitude = -180 - latitude;
107 longitude += 180;
108 }
109
110 while (longitude > 180)
111 {
112 longitude -= 360;
113 }
114 while (longitude < -180)
115 {
116 longitude += 360;
117 }
118 }
119
120 if (IsValidLatitude(latitude) == false)
121 {
122 NS_FATAL_ERROR("Invalid latitude!!! Got " << latitude);
123 }
124
125 if (IsValidLongitude(longitude) == false)
126 {
127 NS_FATAL_ERROR("Invalid longitude!!! Got " << longitude);
128 }
129
130 if (IsValidAltitude(altitude, m_refEllipsoid) == false)
131 {
132 NS_FATAL_ERROR("Invalid altitude!!! Got " << altitude);
133 }
134
135 Initialize();
136
137 m_latitude = latitude;
138 m_longitude = longitude;
139 m_altitude = altitude;
140}
141
142Vector
144{
145 NS_LOG_FUNCTION(this);
146
147 Vector cartesian;
148 double latRads = SatUtils::DegreesToRadians(m_latitude);
149 double lonRads = SatUtils::DegreesToRadians(m_longitude);
150
151 cartesian.x =
152 (GetRadiusCurvature(latRads) + m_altitude) * std::cos(latRads) * std::cos(lonRads);
153 cartesian.y =
154 (GetRadiusCurvature(latRads) + m_altitude) * std::cos(latRads) * std::sin(lonRads);
155 cartesian.z = (GetRadiusCurvature(latRads) * (1 - m_e2Param) + m_altitude) * std::sin(latRads);
156
157 return cartesian;
158}
159
160void
162{
163 NS_LOG_FUNCTION(this);
164
165 switch (m_refEllipsoid)
166 {
167 case SPHERE:
169 break;
170
171 case WGS84:
173 break;
174
175 case GRS80:
177 break;
178
179 default:
180 NS_FATAL_ERROR("Invalid Reference Ellipsoid!!!");
181 break;
182 }
183
187}
188
189double
191{
192 NS_LOG_FUNCTION(this);
193 return m_longitude;
194}
195
196double
198{
199 NS_LOG_FUNCTION(this);
200 return m_latitude;
201}
202
203double
205{
206 NS_LOG_FUNCTION(this);
207 return m_altitude;
208}
209
210void
212{
213 NS_LOG_FUNCTION(this << longitude);
214
215 if (IsValidLongitude(longitude) == false)
216 {
217 NS_FATAL_ERROR("Invalid longitude!!!");
218 }
219
220 m_longitude = longitude;
221}
222
223void
225{
226 NS_LOG_FUNCTION(this << latitude);
227
228 if (IsValidLatitude(latitude) == false)
229 {
230 NS_FATAL_ERROR("Invalid latitude!!!");
231 }
232
233 m_latitude = latitude;
234}
235
236void
238{
239 NS_LOG_FUNCTION(this << altitude);
240
241 if (IsValidAltitude(altitude, m_refEllipsoid) == false)
242 {
243 NS_FATAL_ERROR("Invalid altitude!!!");
244 }
245
246 m_altitude = altitude;
247}
248
249void
251{
252 NS_LOG_FUNCTION(this << v);
253
254 Initialize();
255
256 // distance from the position point (P) to earth center point (origin O)
257 double op = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
258
259 if (op > 0)
260 {
261 // longitude calculation
262 double lon = std::atan(v.y / v.x);
263
264 // scale longitude between - PI and PI (-180 and 180 in degrees)
265 if (v.x != 0 || v.y != 0)
266 {
267 m_longitude = SatUtils::RadiansToDegrees(std::atan(v.y / v.x));
268
269 if (v.x < 0)
270 {
271 if (v.y > 0)
272 {
273 m_longitude = 180 + m_longitude;
274 lon = lon - M_PI;
275 }
276 else
277 {
278 m_longitude = -180 + m_longitude;
279 lon = M_PI + lon;
280 }
281 }
282 }
283
284 // Geocentric latitude
285 double latG = std::atan(v.z / (std::sqrt(v.x * v.x + v.y * v.y)));
286
287 // Geocentric latitude (of point Q, Q is intersection point of segment OP and reference
288 // ellipsoid)
289 double latQ = std::atan(v.z / ((1 - m_e2Param) * (std::sqrt(v.x * v.x + v.y * v.y))));
290
291 // calculate radius of the curvature
292 double rCurvature = GetRadiusCurvature(latQ);
293
294 // x, y, z of point Q
295 double xQ = rCurvature * std::cos(latQ) * std::cos(lon);
296 double yQ = rCurvature * std::cos(latQ) * std::sin(lon);
297 double zQ = rCurvature * (1 - m_e2Param) * std::sin(latQ);
298
299 // distance OQ
300 double oq = std::sqrt(xQ * xQ + yQ * yQ + zQ * zQ);
301
302 // distance PQ is OP - OQ
303 double pq = op - oq;
304
305 // length of the normal segment from point P of line (PO) to point T.
306 // T is intersection point of linen the PO normal and ellipsoid normal from point Q.
307 double tp = pq * std::sin(latG - latQ);
308
309 m_latitude = SatUtils::RadiansToDegrees(latQ + tp / op * std::cos(latQ - latG));
310
311 m_altitude = pq * std::cos(latQ - latG);
312 }
313}
314
315double
317{
318 return (m_equatorRadius / std::sqrt(1 - m_e2Param * std::sin(latitude) * std::sin(latitude)));
319}
320
321bool
323{
324 double polarRadius = NAN;
325
326 switch (refEllipsoid)
327 {
328 case SPHERE:
330 break;
331
332 case WGS84:
334 break;
335
336 case GRS80:
338 break;
339
340 default:
341 NS_FATAL_ERROR("Invalid polar radius value!!!");
342 break;
343 }
344
345 return ((polarRadius + altitude) >= 0);
346}
347
348std::ostream&
349operator<<(std::ostream& os, const GeoCoordinate& coordinate)
350{
351 double longitude = coordinate.GetLongitude();
352 double latitude = coordinate.GetLatitude();
353 double altitude = coordinate.GetAltitude();
354
355 os << latitude << "," << longitude << "," << altitude;
356
357 return os;
358}
359
360std::istream&
361operator>>(std::istream& is, GeoCoordinate& coordinate)
362{
363 double longitude;
364 double latitude;
365 double altitude;
366 char c1;
367 char c2;
368
369 is >> latitude >> c1 >> longitude >> c2 >> altitude;
370
371 coordinate.SetLongitude(longitude);
372 coordinate.SetLatitude(latitude);
373 coordinate.SetAltitude(altitude);
374
375 if (c1 != ',' || c2 != ',')
376 {
377 is.setstate(std::ios_base::failbit);
378 }
379 return is;
380}
381
382} // namespace ns3
GeoCoordinate class is used to store and operate with geodetic coordinates.
static constexpr double polarRadius_grs80
void SetAltitude(double altitude)
Sets altitude value of coordinate.
ReferenceEllipsoid_t m_refEllipsoid
void SetLatitude(double latitude)
Sets latitude value of coordinate.
static constexpr double polarRadius_wgs84
static bool IsValidAltitude(double altitude, ReferenceEllipsoid_t refEllipsoide)
Checks if altitude is in valid range.
double m_altitude
altitude of coordinate
double GetAltitude() const
Gets altitude value of coordinate.
void SetLongitude(double longitude)
Sets longitude value of coordinate.
double GetLatitude() const
Gets latitude value of coordinate.
GeoCoordinate(double latitude, double longitude, double altitude, bool correctIfInvalid=false)
Create GeoCoordinate from given latitude, longitude and altitude decimal degree values.
void Initialize()
This method is called to initialize needed parameters according to used reference ellipsoide.
GeoCoordinate()
Create GeoCoordinate with zero values of longitude, latitude and altitude.
static bool IsValidLongitude(double longitude)
Checks if longitude is in valid range.
double GetLongitude() const
Gets longitude value of coordinate.
static bool IsValidLatitude(double latitude)
Checks if latitude is in valid range.
Vector ToVector() const
Converts Geodetic coordinates to Cartesian coordinates.
void ConstructFromVector(const Vector &vector)
Creates Geodetic coordinates from given Cartesian coordinates.
double m_latitude
latitude of coordinate
double GetRadiusCurvature(double latitude) const
Gets the radius of curvature in the prime vertical.
static constexpr double equatorRadius
double m_longitude
longitude of coordinate
void Construct(double latitude, double longitude, double altitude, bool correctIfInvalid)
static constexpr double polarRadius_sphere
static T RadiansToDegrees(T radian)
Converts radians to degrees.
static T DegreesToRadians(T degree)
Converts degrees to radians.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
std::istream & operator>>(std::istream &is, GeoCoordinate &coordinate)
std::ostream & operator<<(std::ostream &os, const GeoCoordinate &coordinate)
ATTRIBUTE_HELPER_CPP(GeoCoordinate)