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