You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
9.0 KiB
C
285 lines
9.0 KiB
C
1 year ago
|
/***************************************************************************
|
||
|
* Copyright (C) gempa GmbH *
|
||
|
* All rights reserved. *
|
||
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||
|
* *
|
||
|
* GNU Affero General Public License Usage *
|
||
|
* This file may be used under the terms of the GNU Affero *
|
||
|
* Public License version 3.0 as published by the Free Software Foundation *
|
||
|
* and appearing in the file LICENSE included in the packaging of this *
|
||
|
* file. Please review the following information to ensure the GNU Affero *
|
||
|
* Public License version 3.0 requirements will be met: *
|
||
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||
|
* *
|
||
|
* Other Usage *
|
||
|
* Alternatively, this file may be used in accordance with the terms and *
|
||
|
* conditions contained in a signed written agreement between you and *
|
||
|
* gempa GmbH. *
|
||
|
***************************************************************************/
|
||
|
|
||
|
|
||
|
#ifndef SEISCOMP_MATH_GEO
|
||
|
#define SEISCOMP_MATH_GEO
|
||
|
|
||
|
#include <seiscomp/core.h>
|
||
|
#include <seiscomp/math/coord.h>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace Seiscomp
|
||
|
{
|
||
|
|
||
|
namespace Math
|
||
|
{
|
||
|
|
||
|
namespace Geo
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* For two points (lat1, lon1) and (lat2, lon2),
|
||
|
* the angular distance 'dist' in degrees,
|
||
|
* the azimuth 'azi1' (azimuth of point 2 seen from point 1) and
|
||
|
* the azimuth 'azi2' (azimuth of point 1 seen from point 2)
|
||
|
* are computed.
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
void delazi(double lat1, double lon1, double lat2, double lon2,
|
||
|
double *out_dist, double *out_azi1, double *out_azi2);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* For two points (lat1, lon1) and (lat2, lon2),
|
||
|
* the angular distance 'dist' in degrees,
|
||
|
* the azimuth 'azi1' (azimuth of point 2 seen from point 1) and
|
||
|
* the azimuth 'azi2' (azimuth of point 1 seen from point 2)
|
||
|
* are computed.
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
void delazi_wgs84(double lat1, double lon1, double lat2, double lon2,
|
||
|
double *out_dist, double *out_azi1, double *out_azi2);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Computes the coordinates (lat, lon) of the point which
|
||
|
* is at an azimuth of 'azi' and a distance of 'dist' as seen
|
||
|
* from the point (lat0, lon0).
|
||
|
* -> lat, lon
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
void delandaz2coord(double dist, double azi, double lat0, double lon0,
|
||
|
double *out_lat, double *out_lon);
|
||
|
|
||
|
/**
|
||
|
* Compute the intersection points between two small circles.
|
||
|
* Returns the number of intersection points found; 0 means circles don't
|
||
|
* intersect at all (or their centers coincide), 1 means both intersection
|
||
|
* points coincide, i.e. the circles just "touch" at one point, 2 is a
|
||
|
* normal intersection
|
||
|
*
|
||
|
* @returns lat, lon of intersection points my the way of latx1, lonx1, latx2,
|
||
|
* lonx2
|
||
|
*
|
||
|
* XXX Corrently the case 1 (circles "touch") is not implemented well. Best
|
||
|
* way is to test if in case 2 the intersection points are very close.
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
int scxsc(double lat1, double lon1, double r1,
|
||
|
double lat2, double lon2, double r2,
|
||
|
double *latx1, double *lonx1, double *latx2, double *lonx2,
|
||
|
double epsilon=0);
|
||
|
|
||
|
/**
|
||
|
* "Draws" a small circle
|
||
|
*
|
||
|
* Around a center point (lat0, lon0), compute n equally spaced points on a
|
||
|
* small circle with specified radius (in degrees).
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
int scdraw(double lat0, double lon0, double radius,
|
||
|
int n, double *lat, double *lon);
|
||
|
|
||
|
#define KM_OF_DEGREE 111.1329149013519096
|
||
|
|
||
|
template<typename T>
|
||
|
T deg2km(T deg) { return deg * (T)KM_OF_DEGREE; }
|
||
|
|
||
|
template<typename T>
|
||
|
T km2deg(T km) { return km / (T)KM_OF_DEGREE; }
|
||
|
|
||
|
/**
|
||
|
* Converts X, Y, Z coordinates to LTP coordinates using WGS-84 constants for
|
||
|
* the ellipsoid.
|
||
|
*
|
||
|
* For reference, The X, Y, Z coordinate system has origin at the mass center
|
||
|
* of the Earth, with Z axis along the spin axis of the Earth (+ at North pole).
|
||
|
* The +X axis emerges from the Earth at the equator-prime meridian
|
||
|
* intersection. The +Y axis defines a right-hand coordinate system, emerging
|
||
|
* from the Earth at +90 degrees longitude on the equator.
|
||
|
|
||
|
* The Local Tangential Plane (LTP) coordinates are in latitude/longitude/
|
||
|
* altitude where North latitude is + and East longitude is +. Altitude is in
|
||
|
* meters above the reference ellipsoid (which may be either above or below the
|
||
|
* local mean sea level).
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
void xyz2ltp(const double x, const double y, const double z,
|
||
|
double *lat, double *lon, double *alt);
|
||
|
|
||
|
/**
|
||
|
* Converts LTP coordinates to X, Y, Z coordinates using WGS-84 constants for
|
||
|
* the ellipsoid.
|
||
|
*
|
||
|
* For reference, The X, Y, Z coordinate system has origin at the mass center
|
||
|
* of the Earth, with Z axis along the spin axis of the Earth (+ at North pole).
|
||
|
* The +X axis emerges from the Earth at the equator-prime meridian
|
||
|
* intersection. The +Y axis defines a right-hand coordinate system, emerging
|
||
|
* from the Earth at +90 degrees longitude on the equator.
|
||
|
|
||
|
* The Local Tangential Plane (LTP) coordinates are in latitude/longitude/
|
||
|
* altitude where North latitude is + and East longitude is +. Altitude is in
|
||
|
* meters above the reference ellipsoid (which may be either above or below the
|
||
|
* local mean sea level).
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
void ltp2xyz(double lat, double lon, double alt,
|
||
|
double *x, double *y, double *z);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Finds the nearest hotspot of an array of hotspots regarding a given
|
||
|
* location.
|
||
|
*
|
||
|
* Returns the distance in degree and the azimuth seen from the location.
|
||
|
*/
|
||
|
SC_SYSTEM_CORE_API
|
||
|
const NamedCoordD*
|
||
|
nearestHotspot(double lat, double lon, double maxDist,
|
||
|
int nCoords, const NamedCoordD* coordArray,
|
||
|
double *dist, double *azi);
|
||
|
|
||
|
SC_SYSTEM_CORE_API
|
||
|
const NamedCoordD*
|
||
|
nearestHotspot(double lat, double lon, double maxDist,
|
||
|
const std::vector<NamedCoordD>& coords,
|
||
|
double *dist, double *azi);
|
||
|
|
||
|
|
||
|
SC_SYSTEM_CORE_API
|
||
|
const CityD*
|
||
|
nearestCity(double lat, double lon,
|
||
|
double maxDist, double minPopulation,
|
||
|
int nCities, const CityD* cityArray,
|
||
|
double *dist, double *azi);
|
||
|
|
||
|
SC_SYSTEM_CORE_API
|
||
|
const CityD*
|
||
|
nearestCity(double lat, double lon,
|
||
|
double maxDist, double minPopulation,
|
||
|
const std::vector<CityD>& cities,
|
||
|
double *dist, double *azi);
|
||
|
|
||
|
SC_SYSTEM_CORE_API
|
||
|
const CityD*
|
||
|
largestCity(double lat, double lon,
|
||
|
double maxDist,
|
||
|
const std::vector<CityD>& cities,
|
||
|
double *dist, double *azi);
|
||
|
|
||
|
|
||
|
class SC_SYSTEM_CORE_API PositionInterpolator {
|
||
|
public:
|
||
|
/**
|
||
|
* Constructs an interpolator between lat1,lon1 and lat2,lon2.
|
||
|
* Between both positions 'steps-2' new equidistanct positions
|
||
|
* are going to be calculated.
|
||
|
* @param lat1 Latitude of position 1
|
||
|
* @param lon1 Longitude of position 1
|
||
|
* @param lat2 Latitude of position 2
|
||
|
* @param lon2 Longitude of position 2
|
||
|
* @param steps Number of steps including position 1 and position 2
|
||
|
*/
|
||
|
PositionInterpolator(double lat1, double lon1,
|
||
|
double lat2, double lon2,
|
||
|
int steps);
|
||
|
|
||
|
/**
|
||
|
* Same as above but the number of steps depends on the
|
||
|
* distance between both positions
|
||
|
* steps = int(|pos1-pos2|*stepsDistScale)
|
||
|
* @param lat1 Latitude of position 1
|
||
|
* @param lon1 Longitude of position 1
|
||
|
* @param lat2 Latitude of position 2
|
||
|
* @param lon2 Longitude of position 2
|
||
|
* @param stepsDistScale The distance scale factor to calculate
|
||
|
* the number of steps
|
||
|
*/
|
||
|
PositionInterpolator(double lat1, double lon1,
|
||
|
double lat2, double lon2,
|
||
|
double stepsDistScale);
|
||
|
|
||
|
public:
|
||
|
PositionInterpolator& operator++();
|
||
|
PositionInterpolator operator++(int);
|
||
|
|
||
|
bool end() const;
|
||
|
|
||
|
//! Returns the distance between pos1 and pos2
|
||
|
//! given to constructor
|
||
|
double overallDistance() const;
|
||
|
|
||
|
//! Returns the current interpolation distance from pos1
|
||
|
double distance() const;
|
||
|
//! Returns the azimuth of pos2 seen from pos1
|
||
|
double azimuth() const;
|
||
|
|
||
|
//! Returns the current interpolated latitude
|
||
|
double latitude() const;
|
||
|
//! Returns the current interpolated longitude
|
||
|
double longitude() const;
|
||
|
|
||
|
private:
|
||
|
void update();
|
||
|
|
||
|
private:
|
||
|
double _lat1, _lon1;
|
||
|
double _lat2, _lon2;
|
||
|
double _dist;
|
||
|
double _azimuth;
|
||
|
double _stepDist;
|
||
|
double _currentDist;
|
||
|
double _lat, _lon;
|
||
|
|
||
|
int _nSteps;
|
||
|
int _currentStep;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline double PositionInterpolator::overallDistance() const {
|
||
|
return _dist;
|
||
|
}
|
||
|
|
||
|
inline double PositionInterpolator::distance() const {
|
||
|
return _currentDist;
|
||
|
}
|
||
|
|
||
|
inline double PositionInterpolator::azimuth() const {
|
||
|
return _azimuth;
|
||
|
}
|
||
|
|
||
|
inline double PositionInterpolator::latitude() const {
|
||
|
return _lat;
|
||
|
}
|
||
|
|
||
|
inline double PositionInterpolator::longitude() const {
|
||
|
return _lon;
|
||
|
}
|
||
|
|
||
|
|
||
|
} // namespace Seiscomp::Math::Geo
|
||
|
|
||
|
} // namespace Seiscomp::Math
|
||
|
|
||
|
} // namespace Seiscomp
|
||
|
|
||
|
#endif
|