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