diff options
Diffstat (limited to 'boost/geometry/strategies/geographic')
8 files changed, 517 insertions, 119 deletions
diff --git a/boost/geometry/strategies/geographic/azimuth.hpp b/boost/geometry/strategies/geographic/azimuth.hpp index b918caccea..1179050208 100644 --- a/boost/geometry/strategies/geographic/azimuth.hpp +++ b/boost/geometry/strategies/geographic/azimuth.hpp @@ -57,39 +57,68 @@ public : T const& lon2_rad, T const& lat2_rad, T& a1, T& a2) const { - typedef typename boost::mpl::if_ - < - boost::is_void<CalculationType>, T, CalculationType - >::type calc_t; - - typedef typename FormulaPolicy::template inverse<calc_t, false, true, true, false, false> inverse_type; - typedef typename inverse_type::result_type inverse_result; - inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad), - calc_t(lon2_rad), calc_t(lat2_rad), - m_spheroid); - a1 = i_res.azimuth; - a2 = i_res.reverse_azimuth; + compute<true, true>(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a2); } - template <typename T> inline void apply(T const& lon1_rad, T const& lat1_rad, T const& lon2_rad, T const& lat2_rad, T& a1) const { + compute<true, false>(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a1); + } + template <typename T> + inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a2) const + { + compute<false, true>(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a2, a2); + } + +private : + + template < + bool EnableAzimuth, + bool EnableReverseAzimuth, + typename T + > + inline void compute(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a1, T& a2) const + { typedef typename boost::mpl::if_ - < - boost::is_void<CalculationType>, T, CalculationType - >::type calc_t; + < + boost::is_void<CalculationType>, T, CalculationType + >::type calc_t; - typedef typename FormulaPolicy::template inverse<calc_t, false, true, false, false, false> inverse_type; + typedef typename FormulaPolicy::template inverse + < + calc_t, + false, + EnableAzimuth, + EnableReverseAzimuth, + false, + false + > inverse_type; typedef typename inverse_type::result_type inverse_result; inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad), calc_t(lon2_rad), calc_t(lat2_rad), m_spheroid); - a1 = i_res.azimuth; + if (EnableAzimuth) + { + a1 = i_res.azimuth; + } + if (EnableReverseAzimuth) + { + a2 = i_res.reverse_azimuth; + } } -private : Spheroid m_spheroid; }; diff --git a/boost/geometry/strategies/geographic/distance.hpp b/boost/geometry/strategies/geographic/distance.hpp index 01f766c10e..41e3cd7aaa 100644 --- a/boost/geometry/strategies/geographic/distance.hpp +++ b/boost/geometry/strategies/geographic/distance.hpp @@ -22,7 +22,7 @@ #include <boost/geometry/core/radius.hpp> #include <boost/geometry/formulas/andoyer_inverse.hpp> -#include <boost/geometry/formulas/elliptic_arc_length.hpp> +#include <boost/geometry/formulas/meridian_inverse.hpp> #include <boost/geometry/formulas/flattening.hpp> #include <boost/geometry/srs/spheroid.hpp> @@ -92,13 +92,13 @@ public : static inline CT apply(CT lon1, CT lat1, CT lon2, CT lat2, Spheroid const& spheroid) { - typedef typename formula::elliptic_arc_length + typedef typename formula::meridian_inverse < CT, strategy::default_order<FormulaPolicy>::value - > elliptic_arc_length; + > meridian_inverse; - typename elliptic_arc_length::result res = - elliptic_arc_length::apply(lon1, lat1, lon2, lat2, spheroid); + typename meridian_inverse::result res = + meridian_inverse::apply(lon1, lat1, lon2, lat2, spheroid); if (res.meridian) { @@ -125,19 +125,6 @@ public : return apply(lon1, lat1, lon2, lat2, m_spheroid); } - // points on a meridian not crossing poles - template <typename CT> - inline CT meridian(CT lat1, CT lat2) const - { - typedef typename formula::elliptic_arc_length - < - CT, strategy::default_order<FormulaPolicy>::value - > elliptic_arc_length; - - return elliptic_arc_length::meridian_not_crossing_pole_dist(lat1, lat2, - m_spheroid); - } - inline Spheroid const& model() const { return m_spheroid; diff --git a/boost/geometry/strategies/geographic/distance_cross_track.hpp b/boost/geometry/strategies/geographic/distance_cross_track.hpp index be930a3fd4..f84bb4134f 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -13,6 +13,8 @@ #include <algorithm> +#include <boost/tuple/tuple.hpp> +#include <boost/algorithm/minmax.hpp> #include <boost/config.hpp> #include <boost/concept_check.hpp> #include <boost/mpl/if.hpp> @@ -27,6 +29,7 @@ #include <boost/geometry/strategies/concepts/distance_concept.hpp> #include <boost/geometry/strategies/spherical/distance_haversine.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp> +#include <boost/geometry/strategies/geographic/distance.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> #include <boost/geometry/formulas/vincenty_direct.hpp> @@ -94,17 +97,6 @@ public : > {}; - struct distance_strategy - { - typedef geographic<FormulaPolicy, Spheroid, CalculationType> type; - }; - - inline typename distance_strategy::type get_distance_strategy() const - { - typedef typename distance_strategy::type distance_type; - return distance_type(m_spheroid); - } - explicit geographic_cross_track(Spheroid const& spheroid = Spheroid()) : m_spheroid(spheroid) {} @@ -121,6 +113,20 @@ public : m_spheroid)).distance; } + // points on a meridian not crossing poles + template <typename CT> + inline CT vertical_or_meridian(CT lat1, CT lat2) const + { + typedef typename formula::meridian_inverse + < + CT, + strategy::default_order<FormulaPolicy>::value + > meridian_inverse; + + return meridian_inverse::meridian_not_crossing_pole_dist(lat1, lat2, + m_spheroid); + } + private : template <typename CT> @@ -171,21 +177,22 @@ private : if (g4 < -1.25*pi)//close to -270 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to -270" << std::endl; + std::cout << "g4=" << g4 * math::r2d<CT>() << ", close to -270" << std::endl; #endif return g4 + 1.5 * pi; } else if (g4 > 1.25*pi)//close to 270 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to 270" << std::endl; + std::cout << "g4=" << g4 * math::r2d<CT>() << ", close to 270" << std::endl; #endif + der = -der; return - g4 + 1.5 * pi; } else if (g4 < 0 && g4 > -0.75*pi)//close to -90 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to -90" << std::endl; + std::cout << "g4=" << g4 * math::r2d<CT>() << ", close to -90" << std::endl; #endif der = -der; return -g4 - pi/2; @@ -233,21 +240,30 @@ private : std::swap(lat1, lat2); } +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << ">>\nSegment=(" << lon1 * math::r2d<CT>(); + std::cout << "," << lat1 * math::r2d<CT>(); + std::cout << "),(" << lon2 * math::r2d<CT>(); + std::cout << "," << lat2 * math::r2d<CT>(); + std::cout << ")\np=(" << lon3 * math::r2d<CT>(); + std::cout << "," << lat3 * math::r2d<CT>(); + std::cout << ")" << std::endl; +#endif + //segment on equator //Note: antipodal points on equator does not define segment on equator //but pass by the pole CT diff = geometry::math::longitude_distance_signed<geometry::radian>(lon1, lon2); - typedef typename formula::elliptic_arc_length<CT> elliptic_arc_length; + typedef typename formula::meridian_inverse<CT> + meridian_inverse; bool meridian_not_crossing_pole = - elliptic_arc_length::meridian_not_crossing_pole(lat1, lat2, diff); + meridian_inverse::meridian_not_crossing_pole + (lat1, lat2, diff); bool meridian_crossing_pole = - elliptic_arc_length::meridian_crossing_pole(diff); - - //bool meridian_crossing_pole = math::equals(math::abs(diff), pi); - //bool meridian_not_crossing_pole = math::equals(math::abs(diff), c0); + meridian_inverse::meridian_crossing_pole(diff); if (math::equals(lat1, c0) && math::equals(lat2, c0) && !meridian_crossing_pole) { @@ -271,18 +287,28 @@ private : return non_iterative_case(lon3, lat1, lon3, lat3, spheroid); } - if ( (meridian_not_crossing_pole || meridian_crossing_pole ) && lat1 > lat2) + if ( (meridian_not_crossing_pole || meridian_crossing_pole ) && std::abs(lat1) > std::abs(lat2)) { +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "Meridian segment not crossing pole" << std::endl; +#endif std::swap(lat1,lat2); } if (meridian_crossing_pole) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "Meridian segment" << std::endl; + std::cout << "Meridian segment crossing pole" << std::endl; #endif - result_distance_point_segment<CT> d1 = apply<geometry::radian>(lon1, lat1, lon1, half_pi, lon3, lat3, spheroid); - result_distance_point_segment<CT> d2 = apply<geometry::radian>(lon2, lat2, lon2, half_pi, lon3, lat3, spheroid); + CT sign_non_zero = lat3 >= c0 ? 1 : -1; + result_distance_point_segment<CT> d1 = + apply<geometry::radian>(lon1, lat1, + lon1, half_pi * sign_non_zero, + lon3, lat3, spheroid); + result_distance_point_segment<CT> d2 = + apply<geometry::radian>(lon2, lat2, + lon2, half_pi * sign_non_zero, + lon3, lat3, spheroid); if (d1.distance < d2.distance) { return d1; @@ -319,29 +345,31 @@ private : CT a312 = a13 - a12; - if (geometry::math::equals(a312, c0)) + // TODO: meridian case optimization + if (geometry::math::equals(a312, c0) && meridian_not_crossing_pole) { + boost::tuple<CT,CT> minmax_elem = boost::minmax(lat1, lat2); + if (lat3 >= minmax_elem.template get<0>() && + lat3 <= minmax_elem.template get<1>()) + { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "point on segment" << std::endl; + std::cout << "Point on meridian segment" << std::endl; #endif - return non_iterative_case(lon3, lat3, c0); + return non_iterative_case(lon3, lat3, c0); + } } CT projection1 = cos( a312 ) * d1 / d3; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "segment=(" << lon1 * math::r2d<CT>(); - std::cout << "," << lat1 * math::r2d<CT>(); - std::cout << "),(" << lon2 * math::r2d<CT>(); - std::cout << "," << lat2 * math::r2d<CT>(); - std::cout << ")\np=(" << lon3 * math::r2d<CT>(); - std::cout << "," << lat3 * math::r2d<CT>(); - std::cout << ")\na1=" << a12 * math::r2d<CT>() << std::endl; + std::cout << "a1=" << a12 * math::r2d<CT>() << std::endl; std::cout << "a13=" << a13 * math::r2d<CT>() << std::endl; std::cout << "a312=" << a312 * math::r2d<CT>() << std::endl; std::cout << "cos(a312)=" << cos(a312) << std::endl; + std::cout << "projection 1=" << projection1 << std::endl; #endif - if (projection1 < 0.0) + + if (projection1 < c0) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "projection closer to p1" << std::endl; @@ -356,15 +384,17 @@ private : CT a321 = a23 - a21; + CT projection2 = cos( a321 ) * d2 / d3; + #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "a21=" << a21 * math::r2d<CT>() << std::endl; std::cout << "a23=" << a23 * math::r2d<CT>() << std::endl; std::cout << "a321=" << a321 * math::r2d<CT>() << std::endl; std::cout << "cos(a321)=" << cos(a321) << std::endl; + std::cout << "projection 2=" << projection2 << std::endl; #endif - CT projection2 = cos( a321 ) * d2 / d3; - if (projection2 < 0.0) + if (projection2 < c0) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "projection closer to p2" << std::endl; @@ -400,13 +430,15 @@ private : #endif // Update s14 (using Newton method) - CT prev_distance = 0; + CT prev_distance; geometry::formula::result_direct<CT> res14; geometry::formula::result_inverse<CT> res34; + res34.distance = -1; int counter = 0; // robustness CT g4; CT delta_g4; + bool dist_improve = true; do{ prev_distance = res34.distance; @@ -423,23 +455,27 @@ private : lon3, lat3, spheroid); g4 = res34.azimuth - a4; - - CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit CT m34 = res34.reduced_length; CT der = (M43 / m34) * sin(g4); - // normalize (g4 - pi/2) + //normalize delta_g4 = normalize(g4, der); - s14 = s14 - delta_g4 / der; + result.distance = res34.distance; + + dist_improve = prev_distance > res34.distance || prev_distance == -1; + if (!dist_improve) + { + result.distance = prev_distance; + } #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "p4=" << res14.lon2 * math::r2d<CT>() << "," << res14.lat2 * math::r2d<CT>() << std::endl; std::cout << "a34=" << res34.azimuth * math::r2d<CT>() << std::endl; std::cout << "a4=" << a4 * math::r2d<CT>() << std::endl; - std::cout << "g4=" << g4 * math::r2d<CT>() << std::endl; + std::cout << "g4(normalized)=" << g4 * math::r2d<CT>() << std::endl; std::cout << "delta_g4=" << delta_g4 * math::r2d<CT>() << std::endl; std::cout << "der=" << der << std::endl; std::cout << "M43=" << M43 << std::endl; @@ -448,15 +484,11 @@ private : std::cout << "new_s14=" << s14 << std::endl; std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; std::cout << "---------end of step " << counter << std::endl<< std::endl; -#endif - result.distance = prev_distance; - -#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK if (g4 == half_pi) { std::cout << "Stop msg: g4 == half_pi" << std::endl; } - if (res34.distance >= prev_distance && prev_distance != 0) + if (!dist_improve) { std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl; } @@ -464,16 +496,16 @@ private : { std::cout << "Stop msg: delta_g4 == 0" << std::endl; } - if (counter == 19) + if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS) { std::cout << "Stop msg: counter" << std::endl; } #endif } while (g4 != half_pi - && (prev_distance > res34.distance || prev_distance == 0) + && dist_improve && delta_g4 != 0 - && ++counter < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS ) ; + && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "distance=" << res34.distance << std::endl; diff --git a/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp b/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp index 4f6b3b45b7..8e48fbf19a 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp @@ -61,14 +61,37 @@ template class geographic_cross_track_box_box { public: - typedef geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> Strategy; + + // point-point strategy getters + struct distance_pp_strategy + { + typedef geographic<FormulaPolicy, Spheroid, CalculationType> type; + }; + + // point-segment strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track + < + FormulaPolicy, + Spheroid, + CalculationType + > type; + }; template <typename Box1, typename Box2> - struct return_type - : services::return_type<Strategy, typename point_type<Box1>::type, typename point_type<Box2>::type> + struct return_type : services::return_type + < + typename distance_ps_strategy::type, + typename point_type<Box1>::type, + typename point_type<Box2>::type + > {}; - inline geographic_cross_track_box_box() + //constructor + + explicit geographic_cross_track_box_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) {} template <typename Box1, typename Box2> @@ -90,8 +113,12 @@ public: */ typedef typename return_type<Box1, Box2>::type return_type; return details::cross_track_box_box_generic - <return_type>::apply(box1, box2, Strategy()); + <return_type>::apply(box1, box2, + typename distance_pp_strategy::type(m_spheroid), + typename distance_ps_strategy::type(m_spheroid)); } +private : + Spheroid m_spheroid; }; diff --git a/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp b/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp index 016427428c..4508d5acb5 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp @@ -62,14 +62,22 @@ template class geographic_cross_track_point_box { public: - typedef geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> Strategy; + // point-point strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> type; + }; template <typename Point, typename Box> struct return_type - : services::return_type<Strategy, Point, typename point_type<Box>::type> + : services::return_type<typename distance_ps_strategy::type, + Point, typename point_type<Box>::type> {}; - inline geographic_cross_track_point_box() + //constructor + + explicit geographic_cross_track_point_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) {} template <typename Point, typename Box> @@ -91,8 +99,12 @@ public: typedef typename return_type<Point, Box>::type return_type; return details::cross_track_point_box_generic - <return_type>::apply(point, box, Strategy()); + <return_type>::apply(point, box, + typename distance_ps_strategy::type(m_spheroid)); } + +private : + Spheroid m_spheroid; }; diff --git a/boost/geometry/strategies/geographic/distance_segment_box.hpp b/boost/geometry/strategies/geographic/distance_segment_box.hpp new file mode 100644 index 0000000000..6bde78ca27 --- /dev/null +++ b/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -0,0 +1,311 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// 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) + +#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP + +#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp> + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace distance +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid<double>, + typename CalculationType = void +> +struct geographic_segment_box +{ + template <typename PointOfSegment, typename PointOfBox> + struct return_type + : promote_floating_point + < + typename select_calculation_type + < + PointOfSegment, + PointOfBox, + CalculationType + >::type + > + {}; + + // point-point strategy getters + struct distance_pp_strategy + { + typedef geographic<FormulaPolicy, Spheroid, CalculationType> type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + typedef typename distance_pp_strategy::type distance_type; + return distance_type(m_spheroid); + } + // point-segment strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track + < + FormulaPolicy, + Spheroid, + CalculationType + > type; + }; + + inline typename distance_ps_strategy::type get_distance_ps_strategy() const + { + typedef typename distance_ps_strategy::type distance_type; + return distance_type(m_spheroid); + } + + //constructor + + explicit geographic_segment_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) + {} + + // methods + + template <typename LessEqual, typename ReturnType, + typename SegmentPoint, typename BoxPoint> + inline ReturnType segment_below_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right) const + { + typedef typename azimuth::geographic + < + FormulaPolicy, + Spheroid, + CalculationType + > azimuth_strategy_type; + azimuth_strategy_type az_strategy(m_spheroid); + + typedef typename envelope::geographic_segment + < + FormulaPolicy, + Spheroid, + CalculationType + > envelope_segment_strategy_type; + envelope_segment_strategy_type es_strategy(m_spheroid); + + return generic_segment_box::segment_below_of_box + < + LessEqual, + ReturnType + >(p0,p1,top_left,top_right,bottom_left,bottom_right, + geographic_segment_box<FormulaPolicy, Spheroid, CalculationType>(), + az_strategy, es_strategy); + } + + template <typename SPoint, typename BPoint> + static void mirror(SPoint& p0, + SPoint& p1, + BPoint& bottom_left, + BPoint& bottom_right, + BPoint& top_left, + BPoint& top_right) + { + + generic_segment_box::mirror(p0, p1, + bottom_left, bottom_right, + top_left, top_right); + } + +private : + Spheroid m_spheroid; +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +//tags + +template <typename FormulaPolicy> +struct tag<geographic_segment_box<FormulaPolicy> > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid +> +struct tag<geographic_segment_box<FormulaPolicy, Spheroid> > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct tag<geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> > +{ + typedef strategy_tag_distance_segment_box type; +}; + +// return types + +template <typename FormulaPolicy, typename PS, typename PB> +struct return_type<geographic_segment_box<FormulaPolicy>, PS, PB> + : geographic_segment_box<FormulaPolicy>::template return_type<PS, PB> +{}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename PS, + typename PB +> +struct return_type<geographic_segment_box<FormulaPolicy, Spheroid>, PS, PB> + : geographic_segment_box<FormulaPolicy, Spheroid>::template return_type<PS, PB> +{}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + typename PS, + typename PB +> +struct return_type<geographic_segment_box<FormulaPolicy, Spheroid, CalculationType>, PS, PB> + : geographic_segment_box<FormulaPolicy, Spheroid, CalculationType>::template return_type<PS, PB> +{}; + +//comparable types + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct comparable_type<geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> > +{ + typedef geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + > type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct get_comparable<geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> > +{ + typedef typename comparable_type + < + geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> + >::type comparable_type; +public : + static inline comparable_type + apply(geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> const& ) + { + return comparable_type(); + } +}; + +// result from distance + +template +< + typename FormulaPolicy, + typename PS, + typename PB +> +struct result_from_distance<geographic_segment_box<FormulaPolicy>, PS, PB> +{ +private : + typedef typename geographic_segment_box + < + FormulaPolicy + >::template return_type<PS, PB>::type return_type; +public : + template <typename T> + static inline return_type + apply(geographic_segment_box<FormulaPolicy> const& , T const& distance) + { + return distance; + } +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + typename PS, + typename PB +> +struct result_from_distance<geographic_segment_box<FormulaPolicy, Spheroid, CalculationType>, PS, PB> +{ +private : + typedef typename geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + >::template return_type<PS, PB>::type return_type; +public : + template <typename T> + static inline return_type + apply(geographic_segment_box<FormulaPolicy, Spheroid, CalculationType> const& , T const& distance) + { + return distance; + } +}; + + +// default strategies + +template <typename Segment, typename Box> +struct default_strategy + < + segment_tag, box_tag, Segment, Box, + geographic_tag, geographic_tag + > +{ + typedef geographic_segment_box<> type; +}; + +template <typename Box, typename Segment> +struct default_strategy + < + box_tag, segment_tag, Box, Segment, + geographic_tag, geographic_tag + > +{ + typedef typename default_strategy + < + segment_tag, box_tag, Segment, Box, + geographic_tag, geographic_tag + >::type type; +}; + +} +#endif + +}} // namespace strategy::distance + +}} // namespace boost::geometry +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp index b017097f3e..76c83bb534 100644 --- a/boost/geometry/strategies/geographic/intersection.hpp +++ b/boost/geometry/strategies/geographic/intersection.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2016-2017, Oracle and/or its affiliates. +// Copyright (c) 2016-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -425,7 +425,7 @@ private: if (res_a1_a2.distance <= res_b1_b2.distance) { calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_a1_a2, dist_a1_b1); - calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2); + calculate_collinear_data(a1, a2, b2, b1, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2); dist_b1_b2 = dist_a1_b2 - dist_a1_b1; dist_b1_a1 = -dist_a1_b1; dist_b1_a2 = dist_a1_a2 - dist_a1_b1; @@ -433,7 +433,7 @@ private: else { calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, dist_b1_b2, dist_b1_a1); - calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2); + calculate_collinear_data(b1, b2, a2, a1, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2); dist_a1_a2 = dist_b1_a2 - dist_b1_a1; dist_a1_b1 = -dist_b1_a1; dist_a1_b2 = dist_b1_b2 - dist_b1_a1; @@ -611,48 +611,48 @@ private: ResultInverse const& res_a1_b1, // in ResultInverse const& res_a1_b2, // in CalcT& dist_a1_a2, // out - CalcT& dist_a1_bi, // out + CalcT& dist_a1_b1, // out bool degen_neq_coords = false) // in { dist_a1_a2 = res_a1_a2.distance; - dist_a1_bi = res_a1_b1.distance; + dist_a1_b1 = res_a1_b1.distance; if (! same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth)) { - dist_a1_bi = -dist_a1_bi; + dist_a1_b1 = -dist_a1_b1; } - // if i1 is close to a1 and b1 or b2 is equal to a1 - if (is_endpoint_equal(dist_a1_bi, a1, b1, b2)) + // if b1 is close a1 + if (is_endpoint_equal(dist_a1_b1, a1, b1)) { - dist_a1_bi = 0; + dist_a1_b1 = 0; return true; } - // or i1 is close to a2 and b1 or b2 is equal to a2 - else if (is_endpoint_equal(dist_a1_a2 - dist_a1_bi, a2, b1, b2)) + // if b1 is close a2 + else if (is_endpoint_equal(dist_a1_a2 - dist_a1_b1, a2, b1)) { - dist_a1_bi = dist_a1_a2; + dist_a1_b1 = dist_a1_a2; return true; } - // check the other endpoint of a very short segment near the pole + // check the other endpoint of degenerated segment near a pole if (degen_neq_coords) { static CalcT const c0 = 0; if (math::equals(res_a1_b2.distance, c0)) { - dist_a1_bi = 0; + dist_a1_b1 = 0; return true; } else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0)) { - dist_a1_bi = dist_a1_a2; + dist_a1_b1 = dist_a1_a2; return true; } } // or i1 is on b - return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment(); + return segment_ratio<CalcT>(dist_a1_b1, dist_a1_a2).on_segment(); } template <typename Point1, typename Point2, typename CalcT, typename ResultInverse, typename Spheroid_> @@ -876,11 +876,11 @@ private: template <typename CalcT, typename P1, typename P2> static inline bool is_endpoint_equal(CalcT const& dist, - P1 const& ai, P2 const& b1, P2 const& b2) + P1 const& ai, P2 const& b1) { static CalcT const c0 = 0; using geometry::detail::equals::equals_point_point; - return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0)); + return is_near(dist) && (math::equals(dist, c0) || equals_point_point(ai, b1)); } template <typename CalcT> diff --git a/boost/geometry/strategies/geographic/parameters.hpp b/boost/geometry/strategies/geographic/parameters.hpp index 4896e42e8d..92ebe08f2a 100644 --- a/boost/geometry/strategies/geographic/parameters.hpp +++ b/boost/geometry/strategies/geographic/parameters.hpp @@ -10,7 +10,6 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP - #include <boost/geometry/formulas/andoyer_inverse.hpp> #include <boost/geometry/formulas/thomas_direct.hpp> #include <boost/geometry/formulas/thomas_inverse.hpp> @@ -26,7 +25,6 @@ namespace boost { namespace geometry { namespace strategy struct andoyer { - //TODO: this should be replaced by an andoyer direct formula template < typename CT, @@ -38,7 +36,8 @@ struct andoyer struct direct : formula::thomas_direct < - CT, EnableCoordinates, EnableReverseAzimuth, + CT, false, + EnableCoordinates, EnableReverseAzimuth, EnableReducedLength, EnableGeodesicScale > {}; @@ -75,7 +74,8 @@ struct thomas struct direct : formula::thomas_direct < - CT, EnableCoordinates, EnableReverseAzimuth, + CT, true, + EnableCoordinates, EnableReverseAzimuth, EnableReducedLength, EnableGeodesicScale > {}; |