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