Files
pip/libs/main/geo/pigeoposition.h

405 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file pigeoposition.h
* \ingroup Geo
* \~\brief
* \~english Class for geo position storage and conversions
* \~russian Класс для хранения географической позиции и преобразований
*/
/*
PIP - Platform Independent Primitives
Class for geo position storage and conversions
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIGEOPOSITION_H
#define PIGEOPOSITION_H
#include "piellipsoidmodel.h"
#include "pimathvector.h"
//! \~english Geographical position class
//! \~russian Класс географической позиции
class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d {
public:
//! \~english Coordinate system types
//! \~russian Типы систем координат
enum CoordinateSystem {
Unknown = 0, //!< Unknown coordinate system
Geodetic, //!< Geodetic latitude, longitude, and height above ellipsoid
Geocentric, //!< Geocentric (regular spherical coordinates)
Cartesian, //!< Cartesian (Earth-centered, Earth-fixed)
Spherical //!< Spherical coordinates (theta,phi,radius)
};
//! \~english One centimeter tolerance
//! \~russian Допуск один сантиметр
static const double one_cm_tolerance;
//! \~english One millimeter tolerance
//! \~russian Допуск один миллиметр
static const double one_mm_tolerance;
//! \~english One micron tolerance
//! \~russian Допуск один микрон
static const double one_um_tolerance;
//! \~english Default position tolerance (default 1mm)
//! \~russian Допуск позиции по умолчанию (по умолчанию 1мм)
static double position_tolerance;
//! \~english Set position tolerance
//! \~russian Установить допуск позиции
//! \param tol New tolerance value
//! \return Previous tolerance value
static double setPositionTolerance(const double tol) {
position_tolerance = tol;
return position_tolerance;
}
//! \~english Get position tolerance
//! \~russian Получить допуск позиции
static double getPositionTolerance() { return position_tolerance; }
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PIGeoPosition();
//! \~english Constructor with coordinates
//! \~russian Конструктор с координатами
//! \param a First coordinate
//! \param b Second coordinate
//! \param c Third coordinate
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Constructor from vector
//! \~russian Конструктор из вектора
//! \param v Vector with coordinates
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Transform to specified coordinate system
//! \~russian Преобразовать в указанную систему координат
//! \param sys Target coordinate system
//! \return Reference to this position
PIGeoPosition & transformTo(CoordinateSystem sys);
//! \~english Convert to geodetic coordinates
//! \~russian Преобразовать в геодезические координаты
PIGeoPosition & asGeodetic() {
transformTo(Geodetic);
return *this;
}
//! \~english Convert to geodetic coordinates using specified ellipsoid
//! \~russian Преобразовать в геодезические координаты с указанным эллипсоидом
//! \param ell Ellipsoid model to use
//! \return Reference to this position
PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) {
setEllipsoidModel(ell);
transformTo(Geodetic);
return *this;
}
//! \~english Convert to ECEF (cartesian) coordinates
//! \~russian Преобразовать в координаты ECEF (декартовы)
PIGeoPosition & asECEF() {
transformTo(Cartesian);
return *this;
}
//! \~english Get X coordinate (or first coordinate in Cartesian)
//! \~russian Получить координату X (или первую координату в Декартовой)
double x() const;
//! \~english Get Y coordinate (or second coordinate in Cartesian)
//! \~russian Получить координату Y (или вторую координату в Декартовой)
double y() const;
//! \~english Get Z coordinate (or third coordinate in Cartesian)
//! \~russian Получить координату Z (или третью координату в Декартовой)
double z() const;
//! \~english Get geodetic latitude in degrees
//! \~russian Получить геодезическую широту в градусах
double latitudeGeodetic() const;
//! \~english Get geocentric latitude in degrees
//! \~russian Получить геоцентрическую широту в градусах
double latitudeGeocentric() const;
//! \~english Get longitude in degrees
//! \~russian Получить долготу в градусах
double longitude() const;
//! \~english Get theta (angle from Z axis) in degrees
//! \~russian Получить тета (угол от оси Z) в градусах
double theta() const;
//! \~english Get phi (angle in XY plane from X axis) in degrees
//! \~russian Получить фи (угол в плоскости XY от оси X) в градусах
double phi() const;
//! \~english Get radius (distance from Earth center)
//! \~russian Получить радиус (расстояние от центра Земли)
double radius() const;
//! \~english Get height above ellipsoid
//! \~russian Получить высоту над эллипсоидом
double height() const;
//! \~english Set ellipsoid model for this position
//! \~russian Установить модель эллипсоида для этой позиции
//! \param ell Ellipsoid model
void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; }
//! \~english Set position from geodetic coordinates
//! \~russian Установить позицию из геодезических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param ht Height above ellipsoid
//! \param ell Ellipsoid model (default WGS84)
//! \return Reference to this position
PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Set position from geocentric coordinates
//! \~russian Установить позицию из геоцентрических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setGeocentric(double lat, double lon, double rad);
//! \~english Set position from spherical coordinates
//! \~russian Установить позицию из сферических координат
//! \param theta Angle from Z axis in degrees
//! \param phi Angle in XY plane from X axis in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setSpherical(double theta, double phi, double rad);
//! \~english Set position from ECEF coordinates
//! \~russian Установить позицию из координат ECEF
//! \param x X coordinate in meters
//! \param y Y coordinate in meters
//! \param z Z coordinate in meters
//! \return Reference to this position
PIGeoPosition & setECEF(double x, double y, double z);
//! \~english Convert spherical to Cartesian coordinates
//! \~russian Преобразовать сферические в декартовы координаты
//! \param tpr Input spherical (theta, phi, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz);
//! \~english Convert Cartesian to spherical coordinates
//! \~russian Преобразовать декартовы в сферические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param tpr Output spherical (theta, phi, radius)
static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr);
//! \~english Convert Cartesian (ECEF) to geodetic coordinates
//! \~russian Преобразовать декартовы (ECEF) в геодезические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz,
PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Convert geodetic to Cartesian (ECEF) coordinates
//! \~russian Преобразовать геодезические в декартовы (ECEF) координаты
//! \param llh Input geodetic (latitude, longitude, height)
//! \param xyz Output Cartesian (x, y, z)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToCartesian(const PIMathVectorT3d & llh,
PIMathVectorT3d & xyz,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Convert Cartesian (ECEF) to geocentric coordinates
//! \~russian Преобразовать декартовы (ECEF) в геоцентрические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llr Output geocentric (latitude, longitude, radius)
static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr);
//! \~english Convert geocentric to Cartesian (ECEF)
//! \~russian Преобразовать геоцентрические в декартовы (ECEF)
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz);
//! \~english Convert geocentric to geodetic
//! \~russian Преобразовать геоцентрические в геодезические
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr,
PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Convert geodetic to geocentric
//! \~russian Преобразовать геодезические в геоцентрические
//! \param llh Input geodetic (latitude, longitude, height)
//! \param llr Output geocentric (latitude, longitude, radius)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh,
PIMathVectorT3d & llr,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Compute radius of ellipsoid at given latitude
//! \~russian Вычислить радиус эллипсоида на заданной широте
//! \param geolat Geodetic latitude in degrees
//! \param ell Ellipsoid model (default WGS84)
//! \return Radius in meters
static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Compute radius of ellipsoid at current position
//! \~russian Вычислить радиус эллипсоида в текущей позиции
double radiusEarth() const {
PIGeoPosition p(*this);
p.transformTo(PIGeoPosition::Geodetic);
return PIGeoPosition::radiusEarth((*this)[0], p.el);
}
//! \~english Compute range between two positions
//! \~russian Вычислить расстояние между двумя позициями
//! \param a First position
//! \param b Second position
//! \return Range in meters
static double range(const PIGeoPosition & a, const PIGeoPosition & b);
//! \~english Compute range from this position to another
//! \~russian Вычислить расстояние от этой позиции до другой
//! \param p Target position
//! \return Range in meters
double range(const PIGeoPosition & p) const { return range((*this), p); }
//! \~english Compute elevation angle to target position
//! \~russian Вычислить угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevation(const PIGeoPosition & p) const;
//! \~english Compute geodetic elevation angle to target position
//! \~russian Вычислить геодезический угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevationGeodetic(const PIGeoPosition & p) const;
//! \~english Compute azimuth angle to target position
//! \~russian Вычислить азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuth(const PIGeoPosition & p) const;
//! \~english Compute geodetic azimuth angle to target position
//! \~russian Вычислить геодезический азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuthGeodetic(const PIGeoPosition & p) const;
//! \~english Get radius of curvature of the meridian
//! \~russian Получить радиус кривизны меридиана
//! \return Radius in meters
double getCurvMeridian() const;
//! \~english Get radius of curvature in the prime vertical
//! \~russian Получить радиус кривизны в вертикале
//! \return Radius in meters
double getCurvPrimeVertical() const;
//! \~english Get as PIMathVectorT3d
//! \~russian Получить как PIMathVectorT3d
//! \return Reference to underlying vector
const PIMathVectorT3d & vector() const { return *this; }
//! \~english Assignment from vector
//! \~russian Присваивание из вектора
PIGeoPosition & operator=(const PIMathVectorT3d & v);
//! \~english Subtraction
//! \~russian Вычитание
PIGeoPosition & operator-=(const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
PIGeoPosition & operator+=(const PIGeoPosition & right);
//! \~english Subtraction
//! \~russian Вычитание
friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Scalar multiplication
//! \~russian Умножение на скаляр
friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale);
friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale);
//! \~english Equality comparison
//! \~russian Сравнение на равенство
bool operator==(const PIGeoPosition & right) const;
//! \~english Inequality comparison
//! \~russian Сравнение на неравенство
bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); }
private:
void initialize(PIMathVectorT3d v, CoordinateSystem sys = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
PIEllipsoidModel el;
CoordinateSystem s;
};
inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian);
r.transformTo(PIGeoPosition::Cartesian);
l -= r;
return l;
}
inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian);
r.transformTo(PIGeoPosition::Cartesian);
l += r;
return l;
}
inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) {
PIMathVectorT3d tmp(right);
tmp *= scale;
return PIGeoPosition(tmp);
}
inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) {
return operator*(scale, left);
}
inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) {
return operator*(double(scale), right);
}
inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) {
return operator*(double(scale), left);
}
#endif // PIGEOPOSITION_H