123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- //==============================================================================
- //
- // Algorithm - the algorithm module
- //
- // Copyright (C) 2018 Dick van Oudheusden
- //
- // This library 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 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
- // Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public
- // License along with this library; if not, write to the Free
- // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- //
- //==============================================================================
- #include <cmath>
- #include "Algorithm.h"
- namespace gpx
- {
- double deg2rad(double deg)
- {
- return (deg * M_PI) / 180.0;
- }
- double rad2deg(double rad)
- {
- return (rad * 180.0) / M_PI;
- }
- // http://www.movable-type.co.uk/scripts/latlong.html
- // distance in metres
- double calcDistance(double lat1deg, double lon1deg, double lat2deg, double lon2deg)
- {
- const double R = 6371E3; // m
- double lat1rad = deg2rad(lat1deg);
- double lon1rad = deg2rad(lon1deg);
- double lat2rad = deg2rad(lat2deg);
- double lon2rad = deg2rad(lon2deg);
- double dlat = lat2rad - lat1rad;
- double dlon = lon2rad - lon1rad;
- double a = sin(dlat / 2.0) * sin(dlat / 2.0) + cos(lat1rad) * cos(lat2rad) * sin(dlon / 2.0) * sin(dlon / 2.0);
- double c = 2.0 * atan2(sqrt(a), sqrt(1.0 - a));
- return c * R;
- }
- // std::cout << "Distance: " << gpx::calcDistance(50.06639, -5.71472, 58.64389, -3.07000) << std::endl; // 968853.52
- // bearing in rads
- double calcBearing(double lat1deg, double lon1deg, double lat2deg, double lon2deg)
- {
- double lat1rad = deg2rad(lat1deg);
- double lon1rad = deg2rad(lon1deg);
- double lat2rad = deg2rad(lat2deg);
- double lon2rad = deg2rad(lon2deg);
- double dlon = lon2rad - lon1rad;
- double y = sin(dlon) * cos(lat2rad);
- double x = cos(lat1rad) * sin(lat2rad) - sin(lat1rad) * cos(lat2rad) * cos(dlon);
- return atan2(y, x);
- }
- // std::cout << "Bearing: " << gpx::calcBearing(50.06639, -5.71472, 58.64389, -3.07000) << std::endl; // 0.16
- double calcBearingInDeg(double lat1deg, double lon1deg, double lat2deg, double lon2deg)
- {
- return std::fmod((gpx::calcBearing(lat1deg, lon1deg, lat2deg, lon2deg) * 180.0) / M_PI + 360.0, 360.0);
- }
- // crosstrack distance in metres from point3 to the point1-point2 line
- double calcCrosstrack(double lat1deg, double lon1deg, double lat2deg, double lon2deg, double lat3deg, double lon3deg)
- {
- const double R = 6371E3; // m
- double distance13 = calcDistance(lat1deg, lon1deg, lat3deg, lon3deg) / R;
- double bearing13 = calcBearing(lat1deg, lon1deg, lat3deg, lon3deg);
- double bearing12 = calcBearing(lat1deg, lon1deg, lat2deg, lon2deg);
- return asin(sin(distance13) * sin(bearing13 - bearing12)) * R;
- }
- // std::cout << "Crosstrack:" << gpx::calcCrosstrack(53.3206, -1.7297, 53.1887, 0.1334, 53.2611, -0.7972) << std::endl; // -307.55
- }
|