]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGGeod.hxx
Small cleanups to the SGGeo[dc] classes, provide more hooks to use them directly
[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   /// Initialize from a cartesian vector assumed to be in meters
31   /// Note that this conversion is relatively expensive to compute
32   /// depricated
33   SGGeod(const SGVec3<double>& cart);
34   /// Initialize from a geocentric position
35   /// Note that this conversion is relatively expensive to compute
36   /// depricated
37   SGGeod(const SGGeoc& geoc);
38
39   /// Factory from angular values in radians and elevation is 0
40   static SGGeod fromRad(double lon, double lat);
41   /// Factory from angular values in degrees and elevation is 0
42   static SGGeod fromDeg(double lon, double lat);
43   /// Factory from angular values in radians and elevation in ft
44   static SGGeod fromRadFt(double lon, double lat, double elevation);
45   /// Factory from angular values in degrees and elevation in ft
46   static SGGeod fromDegFt(double lon, double lat, double elevation);
47   /// Factory from angular values in radians and elevation in m
48   static SGGeod fromRadM(double lon, double lat, double elevation);
49   /// Factory from angular values in degrees and elevation in m
50   static SGGeod fromDegM(double lon, double lat, double elevation);
51   /// Factory to convert position from a cartesian position assumed to be
52   /// in wgs84 measured in meters
53   /// Note that this conversion is relatively expensive to compute
54   static SGGeod fromCart(const SGVec3<double>& cart);
55   /// Factory to convert position from a geocentric position
56   /// Note that this conversion is relatively expensive to compute
57   static SGGeod fromGeoc(const SGGeoc& geoc);
58
59   /// Return the geodetic longitude in radians
60   double getLongitudeRad(void) const;
61   /// Set the geodetic longitude from the argument given in radians
62   void setLongitudeRad(double lon);
63
64   /// Return the geodetic longitude in degrees
65   double getLongitudeDeg(void) const;
66   /// Set the geodetic longitude from the argument given in degrees
67   void setLongitudeDeg(double lon);
68
69   /// Return the geodetic latitude in radians
70   double getLatitudeRad(void) const;
71   /// Set the geodetic latitude from the argument given in radians
72   void setLatitudeRad(double lat);
73
74   /// Return the geodetic latitude in degrees
75   double getLatitudeDeg(void) const;
76   /// Set the geodetic latitude from the argument given in degrees
77   void setLatitudeDeg(double lat);
78
79   /// Return the geodetic elevation in meters
80   double getElevationM(void) const;
81   /// Set the geodetic elevation from the argument given in meters
82   void setElevationM(double elevation);
83
84   /// Return the geodetic elevation in feet
85   double getElevationFt(void) const;
86   /// Set the geodetic elevation from the argument given in feet
87   void setElevationFt(double elevation);
88
89 private:
90   /// This one is private since construction is not unique if you do
91   /// not know the units of the arguments. Use the factory methods for
92   /// that purpose
93   SGGeod(double lon, double lat, double elevation);
94
95   /// The actual data, angles in degree, elevation in meters
96   /// The rationale for storing the values in degrees is that most code places
97   /// in flightgear/terragear use degrees as a nativ input and output value.
98   /// The places where it makes sense to use radians is when we convert
99   /// to other representations or compute rotation matrices. But both tasks
100   /// are computionally intensive anyway and that additional 'toRadian'
101   /// conversion does not hurt too much
102   double _lon;
103   double _lat;
104   double _elevation;
105 };
106
107 inline
108 SGGeod::SGGeod(void) :
109   _lon(0), _lat(0), _elevation(0)
110 {
111 }
112
113 inline
114 SGGeod::SGGeod(double lon, double lat, double elevation) :
115   _lon(lon), _lat(lat), _elevation(elevation)
116 {
117 }
118
119 inline
120 SGGeod::SGGeod(const SGVec3<double>& cart)
121 {
122   SGGeodesy::SGCartToGeod(cart, *this);
123 }
124
125 inline
126 SGGeod::SGGeod(const SGGeoc& geoc)
127 {
128   SGVec3<double> cart;
129   SGGeodesy::SGGeocToCart(geoc, cart);
130   SGGeodesy::SGCartToGeod(cart, *this);
131 }
132
133 inline
134 SGGeod
135 SGGeod::fromRad(double lon, double lat)
136 {
137 #ifdef SG_GEOD_NATIVE_DEGREE
138   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES, 0);
139 #else
140   return SGGeod(lon, lat, 0);
141 #endif
142 }
143
144 inline
145 SGGeod
146 SGGeod::fromDeg(double lon, double lat)
147 {
148 #ifdef SG_GEOD_NATIVE_DEGREE
149   return SGGeod(lon, lat, 0);
150 #else
151   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0);
152 #endif
153 }
154
155 inline
156 SGGeod
157 SGGeod::fromRadFt(double lon, double lat, double elevation)
158 {
159 #ifdef SG_GEOD_NATIVE_DEGREE
160   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
161                 elevation*SG_FEET_TO_METER);
162 #else
163   return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
164 #endif
165 }
166
167 inline
168 SGGeod
169 SGGeod::fromDegFt(double lon, double lat, double elevation)
170 {
171 #ifdef SG_GEOD_NATIVE_DEGREE
172   return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
173 #else
174   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
175                 elevation*SG_FEET_TO_METER);
176 #endif
177 }
178
179 inline
180 SGGeod
181 SGGeod::fromRadM(double lon, double lat, double elevation)
182 {
183 #ifdef SG_GEOD_NATIVE_DEGREE
184   return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
185                 elevation);
186 #else
187   return SGGeod(lon, lat, elevation);
188 #endif
189 }
190
191 inline
192 SGGeod
193 SGGeod::fromDegM(double lon, double lat, double elevation)
194 {
195 #ifdef SG_GEOD_NATIVE_DEGREE
196   return SGGeod(lon, lat, elevation);
197 #else
198   return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
199                 elevation);
200 #endif
201 }
202
203 inline
204 SGGeod
205 SGGeod::fromCart(const SGVec3<double>& cart)
206 {
207   SGGeod geod;
208   SGGeodesy::SGCartToGeod(cart, geod);
209   return geod;
210 }
211
212 inline
213 SGGeod
214 SGGeod::fromGeoc(const SGGeoc& geoc)
215 {
216   SGVec3<double> cart;
217   SGGeodesy::SGGeocToCart(geoc, cart);
218   SGGeod geod;
219   SGGeodesy::SGCartToGeod(cart, geod);
220   return geod;
221 }
222
223 inline
224 double
225 SGGeod::getLongitudeRad(void) const
226 {
227 #ifdef SG_GEOD_NATIVE_DEGREE
228   return _lon*SGD_DEGREES_TO_RADIANS;
229 #else
230   return _lon;
231 #endif
232 }
233
234 inline
235 void
236 SGGeod::setLongitudeRad(double lon)
237 {
238 #ifdef SG_GEOD_NATIVE_DEGREE
239   _lon = lon*SGD_RADIANS_TO_DEGREES;
240 #else
241   _lon = lon;
242 #endif
243 }
244
245 inline
246 double
247 SGGeod::getLongitudeDeg(void) const
248 {
249 #ifdef SG_GEOD_NATIVE_DEGREE
250   return _lon;
251 #else
252   return _lon*SGD_RADIANS_TO_DEGREES;
253 #endif
254 }
255
256 inline
257 void
258 SGGeod::setLongitudeDeg(double lon)
259 {
260 #ifdef SG_GEOD_NATIVE_DEGREE
261   _lon = lon;
262 #else
263   _lon = lon*SGD_DEGREES_TO_RADIANS;
264 #endif
265 }
266
267 inline
268 double
269 SGGeod::getLatitudeRad(void) const
270 {
271 #ifdef SG_GEOD_NATIVE_DEGREE
272   return _lat*SGD_DEGREES_TO_RADIANS;
273 #else
274   return _lat;
275 #endif
276 }
277
278 inline
279 void
280 SGGeod::setLatitudeRad(double lat)
281 {
282 #ifdef SG_GEOD_NATIVE_DEGREE
283   _lat = lat*SGD_RADIANS_TO_DEGREES;
284 #else
285   _lat = lat;
286 #endif
287 }
288
289 inline
290 double
291 SGGeod::getLatitudeDeg(void) const
292 {
293 #ifdef SG_GEOD_NATIVE_DEGREE
294   return _lat;
295 #else
296   return _lat*SGD_RADIANS_TO_DEGREES;
297 #endif
298 }
299
300 inline
301 void
302 SGGeod::setLatitudeDeg(double lat)
303 {
304 #ifdef SG_GEOD_NATIVE_DEGREE
305   _lat = lat;
306 #else
307   _lat = lat*SGD_DEGREES_TO_RADIANS;
308 #endif
309 }
310
311 inline
312 double
313 SGGeod::getElevationM(void) const
314 {
315   return _elevation;
316 }
317
318 inline
319 void
320 SGGeod::setElevationM(double elevation)
321 {
322   _elevation = elevation;
323 }
324
325 inline
326 double
327 SGGeod::getElevationFt(void) const
328 {
329   return _elevation*SG_METER_TO_FEET;
330 }
331
332 inline
333 void
334 SGGeod::setElevationFt(double elevation)
335 {
336   _elevation = elevation*SG_FEET_TO_METER;
337 }
338
339 /// Output to an ostream
340 template<typename char_type, typename traits_type>
341 inline
342 std::basic_ostream<char_type, traits_type>&
343 operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeod& g)
344 {
345   return s << "lon = " << g.getLongitudeDeg()
346            << "deg, lat = " << g.getLatitudeDeg()
347            << "deg, elev = " << g.getElevationM()
348            << "m";
349 }
350
351 #endif