349 lines
8.1 KiB
C++
349 lines
8.1 KiB
C++
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
|
|
#ifndef SGGeoc_H
|
|
#define SGGeoc_H
|
|
|
|
#include <simgear/constants.h>
|
|
|
|
// #define SG_GEOC_NATIVE_DEGREE
|
|
|
|
/// Class representing a geocentric location
|
|
class SGGeoc {
|
|
public:
|
|
/// Default constructor, initializes the instance to lat = lon = lat = 0
|
|
SGGeoc(void);
|
|
|
|
/// Factory from angular values in radians and radius in ft
|
|
static SGGeoc fromRadFt(double lon, double lat, double radius);
|
|
/// Factory from angular values in degrees and radius in ft
|
|
static SGGeoc fromDegFt(double lon, double lat, double radius);
|
|
/// Factory from angular values in radians and radius in m
|
|
static SGGeoc fromRadM(double lon, double lat, double radius);
|
|
/// Factory from angular values in degrees and radius in m
|
|
static SGGeoc fromDegM(double lon, double lat, double radius);
|
|
/// Factory to convert position from a cartesian position assumed to be
|
|
/// in wgs84 measured in meters
|
|
/// Note that this conversion is relatively expensive to compute
|
|
static SGGeoc fromCart(const SGVec3<double>& cart);
|
|
/// Factory to convert position from a geodetic position
|
|
/// Note that this conversion is relatively expensive to compute
|
|
static SGGeoc fromGeod(const SGGeod& geod);
|
|
|
|
/// Return the geocentric longitude in radians
|
|
double getLongitudeRad(void) const;
|
|
/// Set the geocentric longitude from the argument given in radians
|
|
void setLongitudeRad(double lon);
|
|
|
|
/// Return the geocentric longitude in degrees
|
|
double getLongitudeDeg(void) const;
|
|
/// Set the geocentric longitude from the argument given in degrees
|
|
void setLongitudeDeg(double lon);
|
|
|
|
/// Return the geocentric latitude in radians
|
|
double getLatitudeRad(void) const;
|
|
/// Set the geocentric latitude from the argument given in radians
|
|
void setLatitudeRad(double lat);
|
|
|
|
/// Return the geocentric latitude in degrees
|
|
double getLatitudeDeg(void) const;
|
|
/// Set the geocentric latitude from the argument given in degrees
|
|
void setLatitudeDeg(double lat);
|
|
|
|
/// Return the geocentric radius in meters
|
|
double getRadiusM(void) const;
|
|
/// Set the geocentric radius from the argument given in meters
|
|
void setRadiusM(double radius);
|
|
|
|
/// Return the geocentric radius in feet
|
|
double getRadiusFt(void) const;
|
|
/// Set the geocentric radius from the argument given in feet
|
|
void setRadiusFt(double radius);
|
|
|
|
SGGeoc advanceRadM(double course, double distance) const;
|
|
static double courseRad(const SGGeoc& from, const SGGeoc& to);
|
|
static double courseDeg(const SGGeoc& from, const SGGeoc& to);
|
|
static double distanceM(const SGGeoc& from, const SGGeoc& to);
|
|
|
|
// Compare two geocentric positions for equality
|
|
bool operator == ( const SGGeoc & other ) const;
|
|
private:
|
|
/// This one is private since construction is not unique if you do
|
|
/// not know the units of the arguments, use the factory methods for
|
|
/// that purpose
|
|
SGGeoc(double lon, double lat, double radius);
|
|
|
|
/// The actual data, angles in degree, radius in meters
|
|
/// The rationale for storing the values in degrees is that most code places
|
|
/// in flightgear/terragear use degrees as a nativ input and output value.
|
|
/// The places where it makes sense to use radians is when we convert
|
|
/// to other representations or compute rotation matrices. But both tasks
|
|
/// are computionally intensive anyway and that additional 'toRadian'
|
|
/// conversion does not hurt too much
|
|
double _lon;
|
|
double _lat;
|
|
double _radius;
|
|
};
|
|
|
|
inline
|
|
SGGeoc::SGGeoc(void) :
|
|
_lon(0), _lat(0), _radius(0)
|
|
{
|
|
}
|
|
|
|
inline
|
|
SGGeoc::SGGeoc(double lon, double lat, double radius) :
|
|
_lon(lon), _lat(lat), _radius(radius)
|
|
{
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromRadFt(double lon, double lat, double radius)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return SGGeoc(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
|
|
radius*SG_FEET_TO_METER);
|
|
#else
|
|
return SGGeoc(lon, lat, radius*SG_FEET_TO_METER);
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromDegFt(double lon, double lat, double radius)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return SGGeoc(lon, lat, radius*SG_FEET_TO_METER);
|
|
#else
|
|
return SGGeoc(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
|
|
radius*SG_FEET_TO_METER);
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromRadM(double lon, double lat, double radius)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return SGGeoc(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
|
|
radius);
|
|
#else
|
|
return SGGeoc(lon, lat, radius);
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromDegM(double lon, double lat, double radius)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return SGGeoc(lon, lat, radius);
|
|
#else
|
|
return SGGeoc(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
|
|
radius);
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromCart(const SGVec3<double>& cart)
|
|
{
|
|
SGGeoc geoc;
|
|
SGGeodesy::SGCartToGeoc(cart, geoc);
|
|
return geoc;
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::fromGeod(const SGGeod& geod)
|
|
{
|
|
SGVec3<double> cart;
|
|
SGGeodesy::SGGeodToCart(geod, cart);
|
|
SGGeoc geoc;
|
|
SGGeodesy::SGCartToGeoc(cart, geoc);
|
|
return geoc;
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getLongitudeRad(void) const
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return _lon*SGD_DEGREES_TO_RADIANS;
|
|
#else
|
|
return _lon;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setLongitudeRad(double lon)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
_lon = lon*SGD_RADIANS_TO_DEGREES;
|
|
#else
|
|
_lon = lon;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getLongitudeDeg(void) const
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return _lon;
|
|
#else
|
|
return _lon*SGD_RADIANS_TO_DEGREES;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setLongitudeDeg(double lon)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
_lon = lon;
|
|
#else
|
|
_lon = lon*SGD_DEGREES_TO_RADIANS;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getLatitudeRad(void) const
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return _lat*SGD_DEGREES_TO_RADIANS;
|
|
#else
|
|
return _lat;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setLatitudeRad(double lat)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
_lat = lat*SGD_RADIANS_TO_DEGREES;
|
|
#else
|
|
_lat = lat;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getLatitudeDeg(void) const
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
return _lat;
|
|
#else
|
|
return _lat*SGD_RADIANS_TO_DEGREES;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setLatitudeDeg(double lat)
|
|
{
|
|
#ifdef SG_GEOC_NATIVE_DEGREE
|
|
_lat = lat;
|
|
#else
|
|
_lat = lat*SGD_DEGREES_TO_RADIANS;
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getRadiusM(void) const
|
|
{
|
|
return _radius;
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setRadiusM(double radius)
|
|
{
|
|
_radius = radius;
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::getRadiusFt(void) const
|
|
{
|
|
return _radius*SG_METER_TO_FEET;
|
|
}
|
|
|
|
inline
|
|
void
|
|
SGGeoc::setRadiusFt(double radius)
|
|
{
|
|
_radius = radius*SG_FEET_TO_METER;
|
|
}
|
|
|
|
inline
|
|
SGGeoc
|
|
SGGeoc::advanceRadM(double course, double distance) const
|
|
{
|
|
SGGeoc result;
|
|
SGGeodesy::advanceRadM(*this, course, distance, result);
|
|
return result;
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::courseRad(const SGGeoc& from, const SGGeoc& to)
|
|
{
|
|
return SGGeodesy::courseRad(from, to);
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::courseDeg(const SGGeoc& from, const SGGeoc& to)
|
|
{
|
|
return SGMiscd::rad2deg(courseRad(from, to));
|
|
}
|
|
|
|
inline
|
|
double
|
|
SGGeoc::distanceM(const SGGeoc& from, const SGGeoc& to)
|
|
{
|
|
return SGGeodesy::distanceM(from, to);
|
|
}
|
|
|
|
inline
|
|
bool
|
|
SGGeoc::operator == ( const SGGeoc & other ) const
|
|
{
|
|
return _lon == other._lon &&
|
|
_lat == other._lat &&
|
|
_radius == other._radius;
|
|
}
|
|
|
|
/// Output to an ostream
|
|
template<typename char_type, typename traits_type>
|
|
inline
|
|
std::basic_ostream<char_type, traits_type>&
|
|
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeoc& g)
|
|
{
|
|
return s << "lon = " << g.getLongitudeDeg()
|
|
<< ", lat = " << g.getLatitudeDeg()
|
|
<< ", radius = " << g.getRadiusM();
|
|
}
|
|
|
|
#endif
|