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