]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGGeod.hxx
Allow geocentric distance computations to return radians.
[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 #ifndef NO_OPENSCENEGRAPH_INTERFACE
24 #include <osg/Matrix>
25 #endif
26
27 // #define SG_GEOD_NATIVE_DEGREE
28
29 /// Class representing a geodetic location
30 class SGGeod {
31 public:
32   /// Default constructor, initializes the instance to lat = lon = elev = 0
33   SGGeod(void);
34
35   /// Factory from angular values in radians and elevation is 0
36   static SGGeod fromRad(double lon, double lat);
37   /// Factory from angular values in degrees and elevation is 0
38   static SGGeod fromDeg(double lon, double lat);
39   /// Factory from angular values in radians and elevation in ft
40   static SGGeod fromRadFt(double lon, double lat, double elevation);
41   /// Factory from angular values in degrees and elevation in ft
42   static SGGeod fromDegFt(double lon, double lat, double elevation);
43   /// Factory from angular values in radians and elevation in m
44   static SGGeod fromRadM(double lon, double lat, double elevation);
45   /// Factory from angular values in degrees and elevation in m
46   static SGGeod fromDegM(double lon, double lat, double elevation);
47   /// Factory from an other SGGeod and a different elevation in m
48   static SGGeod fromGeodM(const SGGeod& geod, double elevation);
49   /// Factory from an other SGGeod and a different elevation in ft
50   static SGGeod fromGeodFt(const SGGeod& geod, 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 #ifndef NO_OPENSCENEGRAPH_INTERFACE
90   // Create a local coordinate frame in the earth-centered frame of
91   // reference. X points north, Z points down.
92   // makeSimulationFrameRelative() only includes rotation.
93   osg::Matrix makeSimulationFrameRelative() const;
94   osg::Matrix makeSimulationFrame() const;
95
96   // Create a Z-up local coordinate frame in the earth-centered frame
97   // of reference. This is what scenery models, etc. expect.
98   // makeZUpFrameRelative() only includes rotation.
99   osg::Matrix makeZUpFrameRelative() const;
100   osg::Matrix makeZUpFrame() const;
101 #endif
102 private:
103   /// This one is private since construction is not unique if you do
104   /// not know the units of the arguments. Use the factory methods for
105   /// that purpose
106   SGGeod(double lon, double lat, double elevation);
107
108   //// FIXME: wrong comment!
109   /// The actual data, angles in degrees, elevation in meters
110   /// The rationale for storing the values in degrees is that most code places
111   /// in flightgear/terragear use degrees as a nativ input and output value.
112   /// The places where it makes sense to use radians is when we convert
113   /// to other representations or compute rotation matrices. But both tasks
114   /// are computionally intensive anyway and that additional 'toRadian'
115   /// conversion does not hurt too much
116   double _lon;
117   double _lat;
118   double _elevation;
119 };
120
121 inline
122 SGGeod::SGGeod(void) :
123   _lon(0), _lat(0), _elevation(0)
124 {
125 }
126
127 inline
128 SGGeod::SGGeod(double lon, double lat, double elevation) :
129   _lon(lon), _lat(lat), _elevation(elevation)
130 {
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::fromGeodM(const SGGeod& geod, double elevation)
206 {
207   return SGGeod(geod._lon, geod._lat, elevation);
208 }
209
210 inline
211 SGGeod
212 SGGeod::fromGeodFt(const SGGeod& geod, double elevation)
213 {
214   return SGGeod(geod._lon, geod._lat, elevation*SG_FEET_TO_METER);
215 }
216
217 inline
218 SGGeod
219 SGGeod::fromCart(const SGVec3<double>& cart)
220 {
221   SGGeod geod;
222   SGGeodesy::SGCartToGeod(cart, geod);
223   return geod;
224 }
225
226 inline
227 SGGeod
228 SGGeod::fromGeoc(const SGGeoc& geoc)
229 {
230   SGVec3<double> cart;
231   SGGeodesy::SGGeocToCart(geoc, cart);
232   SGGeod geod;
233   SGGeodesy::SGCartToGeod(cart, geod);
234   return geod;
235 }
236
237 inline
238 double
239 SGGeod::getLongitudeRad(void) const
240 {
241 #ifdef SG_GEOD_NATIVE_DEGREE
242   return _lon*SGD_DEGREES_TO_RADIANS;
243 #else
244   return _lon;
245 #endif
246 }
247
248 inline
249 void
250 SGGeod::setLongitudeRad(double lon)
251 {
252 #ifdef SG_GEOD_NATIVE_DEGREE
253   _lon = lon*SGD_RADIANS_TO_DEGREES;
254 #else
255   _lon = lon;
256 #endif
257 }
258
259 inline
260 double
261 SGGeod::getLongitudeDeg(void) const
262 {
263 #ifdef SG_GEOD_NATIVE_DEGREE
264   return _lon;
265 #else
266   return _lon*SGD_RADIANS_TO_DEGREES;
267 #endif
268 }
269
270 inline
271 void
272 SGGeod::setLongitudeDeg(double lon)
273 {
274 #ifdef SG_GEOD_NATIVE_DEGREE
275   _lon = lon;
276 #else
277   _lon = lon*SGD_DEGREES_TO_RADIANS;
278 #endif
279 }
280
281 inline
282 double
283 SGGeod::getLatitudeRad(void) const
284 {
285 #ifdef SG_GEOD_NATIVE_DEGREE
286   return _lat*SGD_DEGREES_TO_RADIANS;
287 #else
288   return _lat;
289 #endif
290 }
291
292 inline
293 void
294 SGGeod::setLatitudeRad(double lat)
295 {
296 #ifdef SG_GEOD_NATIVE_DEGREE
297   _lat = lat*SGD_RADIANS_TO_DEGREES;
298 #else
299   _lat = lat;
300 #endif
301 }
302
303 inline
304 double
305 SGGeod::getLatitudeDeg(void) const
306 {
307 #ifdef SG_GEOD_NATIVE_DEGREE
308   return _lat;
309 #else
310   return _lat*SGD_RADIANS_TO_DEGREES;
311 #endif
312 }
313
314 inline
315 void
316 SGGeod::setLatitudeDeg(double lat)
317 {
318 #ifdef SG_GEOD_NATIVE_DEGREE
319   _lat = lat;
320 #else
321   _lat = lat*SGD_DEGREES_TO_RADIANS;
322 #endif
323 }
324
325 inline
326 double
327 SGGeod::getElevationM(void) const
328 {
329   return _elevation;
330 }
331
332 inline
333 void
334 SGGeod::setElevationM(double elevation)
335 {
336   _elevation = elevation;
337 }
338
339 inline
340 double
341 SGGeod::getElevationFt(void) const
342 {
343   return _elevation*SG_METER_TO_FEET;
344 }
345
346 inline
347 void
348 SGGeod::setElevationFt(double elevation)
349 {
350   _elevation = elevation*SG_FEET_TO_METER;
351 }
352
353 /// Output to an ostream
354 template<typename char_type, typename traits_type>
355 inline
356 std::basic_ostream<char_type, traits_type>&
357 operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeod& g)
358 {
359   return s << "lon = " << g.getLongitudeDeg()
360            << "deg, lat = " << g.getLatitudeDeg()
361            << "deg, elev = " << g.getElevationM()
362            << "m";
363 }
364
365 #endif