]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGGeod.hxx
Trying to make old gcc on Jenkins happy.
[simgear.git] / simgear / math / SGGeod.hxx
1 // Copyright (C) 2006  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifndef SGGeod_H
19 #define SGGeod_H
20
21 #include <simgear/constants.h>
22
23 // #define SG_GEOD_NATIVE_DEGREE
24
25 /// Class representing a geodetic location
26 class SGGeod {
27 public:
28   /// Default constructor, initializes the instance to lat = lon = elev = 0
29   SGGeod(void);
30
31   /// Factory from angular values in radians and elevation is 0
32   static SGGeod fromRad(double lon, double lat);
33   /// Factory from angular values in degrees and elevation is 0
34   static SGGeod fromDeg(double lon, double lat);
35   /// Factory from angular values in radians and elevation in ft
36   static SGGeod fromRadFt(double lon, double lat, double elevation);
37   /// Factory from angular values in degrees and elevation in ft
38   static SGGeod fromDegFt(double lon, double lat, double elevation);
39   /// Factory from angular values in radians and elevation in m
40   static SGGeod fromRadM(double lon, double lat, double elevation);
41   /// Factory from angular values in degrees and elevation in m
42   static SGGeod fromDegM(double lon, double lat, double elevation);
43   /// Factory from an other SGGeod and a different elevation in m
44   static SGGeod fromGeodM(const SGGeod& geod, double elevation);
45   /// Factory from an other SGGeod and a different elevation in ft
46   static SGGeod fromGeodFt(const SGGeod& geod, double elevation);
47   /// Factory to convert position from a cartesian position assumed to be
48   /// in wgs84 measured in meters
49   /// Note that this conversion is relatively expensive to compute
50   static SGGeod fromCart(const SGVec3<double>& cart);
51   /// Factory to convert position from a geocentric position
52   /// Note that this conversion is relatively expensive to compute
53   static SGGeod fromGeoc(const SGGeoc& geoc);
54
55   /// Return the geodetic longitude in radians
56   double getLongitudeRad(void) const;
57   /// Set the geodetic longitude from the argument given in radians
58   void setLongitudeRad(double lon);
59
60   /// Return the geodetic longitude in degrees
61   double getLongitudeDeg(void) const;
62   /// Set the geodetic longitude from the argument given in degrees
63   void setLongitudeDeg(double lon);
64
65   /// Return the geodetic latitude in radians
66   double getLatitudeRad(void) const;
67   /// Set the geodetic latitude from the argument given in radians
68   void setLatitudeRad(double lat);
69
70   /// Return the geodetic latitude in degrees
71   double getLatitudeDeg(void) const;
72   /// Set the geodetic latitude from the argument given in degrees
73   void setLatitudeDeg(double lat);
74
75   /// Return the geodetic elevation in meters
76   double getElevationM(void) const;
77   /// Set the geodetic elevation from the argument given in meters
78   void setElevationM(double elevation);
79
80   /// Return the geodetic elevation in feet
81   double getElevationFt(void) const;
82   /// Set the geodetic elevation from the argument given in feet
83   void setElevationFt(double elevation);
84
85   /// Compare two geodetic positions for equality
86   bool operator == ( const SGGeod & other ) const;
87
88   /// check the Geod contains sane values (finite, inside appropriate
89   /// ranges for lat/lon)
90   bool isValid() const;
91 private:
92   /// This one is private since construction is not unique if you do
93   /// not know the units of the arguments. Use the factory methods for
94   /// that purpose
95   SGGeod(double lon, double lat, double elevation);
96
97   //// FIXME: wrong comment!
98   /// The actual data, angles in degrees, elevation in meters
99   /// The rationale for storing the values in degrees is that most code places
100   /// in flightgear/terragear use degrees as a nativ input and output value.
101   /// The places where it makes sense to use radians is when we convert
102   /// to other representations or compute rotation matrices. But both tasks
103   /// are computionally intensive anyway and that additional 'toRadian'
104   /// conversion does not hurt too much
105   double _lon;
106   double _lat;
107   double _elevation;
108 };
109
110 inline
111 SGGeod::SGGeod(void) :
112   _lon(0), _lat(0), _elevation(0)
113 {
114 }
115
116 inline
117 SGGeod::SGGeod(double lon, double lat, double elevation) :
118   _lon(lon), _lat(lat), _elevation(elevation)
119 {
120 }
121
122 inline
123 SGGeod
124 SGGeod::fromRad(double lon, double lat)
125 {
126 #ifdef SG_GEOD_NATIVE_DEGREE
127   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES, 0);
128 #else
129   return SGGeod(lon, lat, 0);
130 #endif
131 }
132
133 inline
134 SGGeod
135 SGGeod::fromDeg(double lon, double lat)
136 {
137 #ifdef SG_GEOD_NATIVE_DEGREE
138   return SGGeod(lon, lat, 0);
139 #else
140   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0);
141 #endif
142 }
143
144 inline
145 SGGeod
146 SGGeod::fromRadFt(double lon, double lat, double elevation)
147 {
148 #ifdef SG_GEOD_NATIVE_DEGREE
149   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
150                 elevation*SG_FEET_TO_METER);
151 #else
152   return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
153 #endif
154 }
155
156 inline
157 SGGeod
158 SGGeod::fromDegFt(double lon, double lat, double elevation)
159 {
160 #ifdef SG_GEOD_NATIVE_DEGREE
161   return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
162 #else
163   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
164                 elevation*SG_FEET_TO_METER);
165 #endif
166 }
167
168 inline
169 SGGeod
170 SGGeod::fromRadM(double lon, double lat, double elevation)
171 {
172 #ifdef SG_GEOD_NATIVE_DEGREE
173   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
174                 elevation);
175 #else
176   return SGGeod(lon, lat, elevation);
177 #endif
178 }
179
180 inline
181 SGGeod
182 SGGeod::fromDegM(double lon, double lat, double elevation)
183 {
184 #ifdef SG_GEOD_NATIVE_DEGREE
185   return SGGeod(lon, lat, elevation);
186 #else
187   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
188                 elevation);
189 #endif
190 }
191
192 inline
193 SGGeod
194 SGGeod::fromGeodM(const SGGeod& geod, double elevation)
195 {
196   return SGGeod(geod._lon, geod._lat, elevation);
197 }
198
199 inline
200 SGGeod
201 SGGeod::fromGeodFt(const SGGeod& geod, double elevation)
202 {
203   return SGGeod(geod._lon, geod._lat, elevation*SG_FEET_TO_METER);
204 }
205
206 inline
207 SGGeod
208 SGGeod::fromCart(const SGVec3<double>& cart)
209 {
210   SGGeod geod;
211   SGGeodesy::SGCartToGeod(cart, geod);
212   return geod;
213 }
214
215 inline
216 SGGeod
217 SGGeod::fromGeoc(const SGGeoc& geoc)
218 {
219   SGVec3<double> cart;
220   SGGeodesy::SGGeocToCart(geoc, cart);
221   SGGeod geod;
222   SGGeodesy::SGCartToGeod(cart, geod);
223   return geod;
224 }
225
226 inline
227 double
228 SGGeod::getLongitudeRad(void) const
229 {
230 #ifdef SG_GEOD_NATIVE_DEGREE
231   return _lon*SGD_DEGREES_TO_RADIANS;
232 #else
233   return _lon;
234 #endif
235 }
236
237 inline
238 void
239 SGGeod::setLongitudeRad(double lon)
240 {
241 #ifdef SG_GEOD_NATIVE_DEGREE
242   _lon = lon*SGD_RADIANS_TO_DEGREES;
243 #else
244   _lon = lon;
245 #endif
246 }
247
248 inline
249 double
250 SGGeod::getLongitudeDeg(void) const
251 {
252 #ifdef SG_GEOD_NATIVE_DEGREE
253   return _lon;
254 #else
255   return _lon*SGD_RADIANS_TO_DEGREES;
256 #endif
257 }
258
259 inline
260 void
261 SGGeod::setLongitudeDeg(double lon)
262 {
263 #ifdef SG_GEOD_NATIVE_DEGREE
264   _lon = lon;
265 #else
266   _lon = lon*SGD_DEGREES_TO_RADIANS;
267 #endif
268 }
269
270 inline
271 double
272 SGGeod::getLatitudeRad(void) const
273 {
274 #ifdef SG_GEOD_NATIVE_DEGREE
275   return _lat*SGD_DEGREES_TO_RADIANS;
276 #else
277   return _lat;
278 #endif
279 }
280
281 inline
282 void
283 SGGeod::setLatitudeRad(double lat)
284 {
285 #ifdef SG_GEOD_NATIVE_DEGREE
286   _lat = lat*SGD_RADIANS_TO_DEGREES;
287 #else
288   _lat = lat;
289 #endif
290 }
291
292 inline
293 double
294 SGGeod::getLatitudeDeg(void) const
295 {
296 #ifdef SG_GEOD_NATIVE_DEGREE
297   return _lat;
298 #else
299   return _lat*SGD_RADIANS_TO_DEGREES;
300 #endif
301 }
302
303 inline
304 void
305 SGGeod::setLatitudeDeg(double lat)
306 {
307 #ifdef SG_GEOD_NATIVE_DEGREE
308   _lat = lat;
309 #else
310   _lat = lat*SGD_DEGREES_TO_RADIANS;
311 #endif
312 }
313
314 inline
315 double
316 SGGeod::getElevationM(void) const
317 {
318   return _elevation;
319 }
320
321 inline
322 void
323 SGGeod::setElevationM(double elevation)
324 {
325   _elevation = elevation;
326 }
327
328 inline
329 double
330 SGGeod::getElevationFt(void) const
331 {
332   return _elevation*SG_METER_TO_FEET;
333 }
334
335 inline
336 void
337 SGGeod::setElevationFt(double elevation)
338 {
339   _elevation = elevation*SG_FEET_TO_METER;
340 }
341
342 inline
343 bool
344 SGGeod::operator == ( const SGGeod & other ) const
345 {
346   return _lon == other._lon &&
347          _lat == other._lat &&
348          _elevation == other._elevation;
349 }
350
351 inline
352 bool
353 SGGeod::isValid() const
354 {
355   if (SGMiscd::isNaN(_lon))
356       return false;
357   if (SGMiscd::isNaN(_lat))
358       return false;
359 #ifdef SG_GEOD_NATIVE_DEGREE
360   return (_lon >= -180.0) && (_lon <= 180.0) &&
361   (_lat >= -90.0) && (_lat <= 90.0);
362 #else
363   return (_lon >= -SGD_PI) && (_lon <= SGD_PI) &&
364   (_lat >= -SGD_PI_2) && (_lat <= SGD_PI_2);
365 #endif
366 }
367
368 /// Output to an ostream
369 template<typename char_type, typename traits_type>
370 inline
371 std::basic_ostream<char_type, traits_type>&
372 operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeod& g)
373 {
374   return s << "lon = " << g.getLongitudeDeg()
375            << "deg, lat = " << g.getLatitudeDeg()
376            << "deg, elev = " << g.getElevationM()
377            << "m";
378 }
379
380 #endif