// Boost.Geometry (aka GGL, Generic Geometry Library) // // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Point Example - showing geographic (latitude longitude) points #include #include #include #include #include // Formula to get the course (direction) between two points. // This might be a GGL-function in the future. template inline double get_course(P1 const& p1, P2 const& p2) { double const& lat1 = boost::geometry::get_as_radian<1>(p1); double const& lon1 = boost::geometry::get_as_radian<0>(p1); double const& lat2 = boost::geometry::get_as_radian<1>(p2); double const& lon2 = boost::geometry::get_as_radian<0>(p2); // http://williams.best.vwh.net/avform.htm#Crs return atan2(sin(lon1-lon2)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon1-lon2)); } // Formula to calculate the point at a distance/angle from another point // This might be a GGL-function in the future. template inline void point_at_distance(P1 const& p1, double distance, double tc, double radius, P2& p2) { double const two_pi = 2.0 * boost::geometry::math::pi(); double earth_perimeter = radius * two_pi; ; double d = (distance / earth_perimeter) * two_pi; double const& lat1 = boost::geometry::get_as_radian<1>(p1); double const& lon1 = boost::geometry::get_as_radian<0>(p1); // http://williams.best.vwh.net/avform.htm#LL double lat = asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc)); double dlon = atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat)); double lon = lon1 - dlon; boost::geometry::set_from_radian<1>(p2, lat); boost::geometry::set_from_radian<0>(p2, lon); } int main() { using namespace boost::geometry; typedef model::ll::point latlon_point; latlon_point paris; // Assign coordinates to the latlong point, using the methods lat and lon // Paris 48 52' 0" N, 2 19' 59" E paris.lat(dms(48, 52, 0)); paris.lon(dms(2, 19, 59)); std::cout << "Paris: " << boost::geometry::dsv(paris) << std::endl; // Constructor using explicit latitude/longitude // Lima 12 2' 36" S, 77 1' 42" W latlon_point lima( latitude<>(dms(12, 2, 36)), longitude<>(dms(77, 1, 42))); std::cout << "Lima: " << boost::geometry::dsv(lima) << std::endl; // Construction with parse utiity latlon_point amsterdam = parse("52 22'23\"N", "4 53'32\"E"); std::cout << "Amsterdam: " << boost::geometry::dsv(amsterdam) << std::endl; // Calculate the distance using the default strategy (Andoyer), and Vincenty std::cout << std::setprecision(9); std::cout << "Distance Paris-Lima, Andoyer (default) " << 0.001 * distance(paris, lima) << " km" << std::endl; std::cout << "Distance Paris-Lima, Vincenty " << 0.001 * distance(paris, lima, strategy::distance::vincenty()) << " km" << std::endl; // Using great circle (=haversine), this is less precise because earth is not a sphere double const average_earth_radius = 6372795.0; std::cout << "Distance Paris-Lima, great circle " << 0.001 * distance(paris, lima, strategy::distance::haversine(average_earth_radius)) << " km" << std::endl; // Convert a latlong point to radians. This might be convenient, although algorithms // are transparent on degree/radians model::ll::point paris_rad; transform(paris, paris_rad); std::cout << "Paris in radians: " << boost::geometry::dsv(paris_rad) << std::endl; model::ll::point amsterdam_rad; transform(amsterdam, amsterdam_rad); std::cout << "Amsterdam in radians: " << boost::geometry::dsv(amsterdam_rad) << std::endl; std::cout << "Distance Paris-Amsterdam, (degree) " << 0.001 * distance(paris, amsterdam) << " km" << std::endl; std::cout << "Distance Paris-Amsterdam, (radian) " << 0.001 * distance(paris_rad, amsterdam_rad) << " km" << std::endl; std::cout << "Distance Paris-Amsterdam, (mixed) " << 0.001 * distance(paris, amsterdam_rad) << " km" << std::endl; // Other way round: have Amsterdam and go 430 km to the south (i.e. first calculate direction) double tc = get_course(amsterdam, paris); std::cout << "Course: " << (tc * boost::geometry::math::r2d()) << std::endl; latlon_point paris_calculated; point_at_distance(amsterdam, 430 * 1000.0, tc, average_earth_radius, paris_calculated); std::cout << "Paris calculated (degree): " << boost::geometry::dsv(paris_calculated) << std::endl; return 0; }