diff options
Diffstat (limited to 'boost/geometry/strategies/spherical/distance_cross_track.hpp')
-rw-r--r-- | boost/geometry/strategies/spherical/distance_cross_track.hpp | 219 |
1 files changed, 81 insertions, 138 deletions
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp index 7b353020eb..a40f03dbaf 100644 --- a/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -10,6 +10,7 @@ #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP +#include <boost/config.hpp> #include <boost/concept_check.hpp> #include <boost/mpl/if.hpp> #include <boost/type_traits.hpp> @@ -18,9 +19,11 @@ #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/algorithms/detail/course.hpp> #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/spherical/distance_haversine.hpp> #include <boost/geometry/util/promote_floating_point.hpp> #include <boost/geometry/util/math.hpp> @@ -40,10 +43,8 @@ namespace strategy { namespace distance /*! \brief Strategy functor for distance point to segment calculation \ingroup strategies -\details Class which calculates the distance of a point to a segment, using latlong points +\details Class which calculates the distance of a point to a segment, for points on a sphere or globe \see http://williams.best.vwh.net/avform.htm -\tparam Point point type -\tparam PointOfSegment \tparam_segment_point \tparam CalculationType \tparam_calculation \tparam Strategy underlying point-point distance strategy, defaults to haversine @@ -55,40 +56,35 @@ namespace strategy { namespace distance */ template < - typename Point, - typename PointOfSegment = Point, typename CalculationType = void, - typename Strategy = typename services::default_strategy<point_tag, Point>::type + typename Strategy = haversine<double, CalculationType> > class cross_track { public : - typedef typename promote_floating_point - < - typename select_calculation_type - < - Point, - PointOfSegment, - CalculationType - >::type - >::type return_type; + template <typename Point, typename PointOfSegment> + struct return_type + : promote_floating_point + < + typename select_calculation_type + < + Point, + PointOfSegment, + CalculationType + >::type + > + {}; inline cross_track() - { - m_strategy = Strategy(); - m_radius = m_strategy.radius(); - } + {} - inline cross_track(return_type const& r) - : m_radius(r) - , m_strategy(r) + explicit inline cross_track(typename Strategy::radius_type const& r) + : m_strategy(r) {} inline cross_track(Strategy const& s) : m_strategy(s) - { - m_radius = m_strategy.radius(); - } + {} // It might be useful in the future @@ -96,9 +92,20 @@ public : // crosstrack(...) {} - inline return_type apply(Point const& p, - PointOfSegment const& sp1, PointOfSegment const& sp2) const + template <typename Point, typename PointOfSegment> + inline typename return_type<Point, PointOfSegment>::type + apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const { + +#if !defined(BOOST_MSVC) + BOOST_CONCEPT_ASSERT + ( + (concept::PointDistanceStrategy<Strategy, Point, PointOfSegment>) + ); +#endif + + typedef typename return_type<Point, PointOfSegment>::type return_type; + // http://williams.best.vwh.net/avform.htm#XTE return_type d1 = m_strategy.apply(sp1, p); return_type d3 = m_strategy.apply(sp1, sp2); @@ -111,10 +118,10 @@ public : return_type d2 = m_strategy.apply(sp2, p); - return_type crs_AD = course(sp1, p); - return_type crs_AB = course(sp1, sp2); + return_type crs_AD = geometry::detail::course<return_type>(sp1, p); + return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2); return_type crs_BA = crs_AB - geometry::math::pi<return_type>(); - return_type crs_BD = course(sp2, p); + return_type crs_BD = geometry::detail::course<return_type>(sp2, p); return_type d_crs1 = crs_AD - crs_AB; return_type d_crs2 = crs_BD - crs_BA; @@ -132,7 +139,7 @@ public : if(projection1 > 0.0 && projection2 > 0.0) { - return_type XTD = m_radius * geometry::math::abs( asin( sin( d1 / m_radius ) * sin( d_crs1 ) )); + return_type XTD = radius() * geometry::math::abs( asin( sin( d1 / radius() ) * sin( d_crs1 ) )); #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK std::cout << "Projection ON the segment" << std::endl; @@ -153,33 +160,12 @@ public : } } - inline return_type radius() const { return m_radius; } + inline typename Strategy::radius_type radius() const + { return m_strategy.radius(); } private : - BOOST_CONCEPT_ASSERT - ( - (geometry::concept::PointDistanceStrategy<Strategy >) - ); - - return_type m_radius; - - // Point-point distances are calculated in radians, on the unit sphere Strategy m_strategy; - - /// Calculate course (bearing) between two points. Might be moved to a "course formula" ... - inline return_type course(Point const& p1, Point const& p2) const - { - // http://williams.best.vwh.net/avform.htm#Crs - return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1); - return_type cos_p2lat = cos(get_as_radian<1>(p2)); - - // "An alternative formula, not requiring the pre-computation of d" - return atan2(sin(dlon) * cos_p2lat, - cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2)) - - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon)); - } - }; @@ -188,120 +174,65 @@ private : namespace services { -template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> -struct tag<cross_track<Point, PointOfSegment, CalculationType, Strategy> > +template <typename CalculationType, typename Strategy> +struct tag<cross_track<CalculationType, Strategy> > { typedef strategy_tag_distance_point_segment type; }; -template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> -struct return_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> > -{ - typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type type; -}; +template <typename CalculationType, typename Strategy, typename P, typename PS> +struct return_type<cross_track<CalculationType, Strategy>, P, PS> + : cross_track<CalculationType, Strategy>::template return_type<P, PS> +{}; -template -< - typename Point, - typename PointOfSegment, - typename CalculationType, - typename Strategy, - typename P, - typename PS -> -struct similar_type<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS> +template <typename CalculationType, typename Strategy> +struct comparable_type<cross_track<CalculationType, Strategy> > { - typedef cross_track<Point, PointOfSegment, CalculationType, Strategy> type; + // There is no shortcut, so the strategy itself is its comparable type + typedef cross_track<CalculationType, Strategy> type; }; template < - typename Point, - typename PointOfSegment, typename CalculationType, - typename Strategy, - typename P, - typename PS -> -struct get_similar<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS> -{ - static inline typename similar_type - < - cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS - >::type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy) - { - return cross_track<P, PS, CalculationType, Strategy>(strategy.radius()); - } -}; - - -template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> -struct comparable_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> > -{ - // Comparable type is here just the strategy - typedef typename similar_type - < - cross_track - < - Point, PointOfSegment, CalculationType, Strategy - >, Point, PointOfSegment - >::type type; -}; - - -template -< - typename Point, typename PointOfSegment, - typename CalculationType, typename Strategy > -struct get_comparable<cross_track<Point, PointOfSegment, CalculationType, Strategy> > +struct get_comparable<cross_track<CalculationType, Strategy> > { typedef typename comparable_type < - cross_track<Point, PointOfSegment, CalculationType, Strategy> + cross_track<CalculationType, Strategy> >::type comparable_type; public : - static inline comparable_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy) + static inline comparable_type apply(cross_track<CalculationType, Strategy> const& strategy) { return comparable_type(strategy.radius()); } }; -template +template < - typename Point, typename PointOfSegment, - typename CalculationType, - typename Strategy + typename CalculationType, + typename Strategy, + typename P, typename PS > -struct result_from_distance<cross_track<Point, PointOfSegment, CalculationType, Strategy> > +struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS> { private : - typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type return_type; + typedef typename cross_track<CalculationType, Strategy>::template return_type<P, PS> return_type; public : template <typename T> - static inline return_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& , T const& distance) + static inline return_type apply(cross_track<CalculationType, Strategy> const& , T const& distance) { return distance; } }; -template -< - typename Point, typename PointOfSegment, - typename CalculationType, - typename Strategy -> -struct strategy_point_point<cross_track<Point, PointOfSegment, CalculationType, Strategy> > -{ - typedef Strategy type; -}; - /* @@ -311,15 +242,13 @@ TODO: spherical polar coordinate system requires "get_as_radian_equatorial<>" template <typename Point, typename PointOfSegment, typename Strategy> struct default_strategy < - segment_tag, Point, PointOfSegment, - spherical_polar_tag, spherical_polar_tag, + segment_tag, Point, PointOfSegment, + spherical_polar_tag, spherical_polar_tag, Strategy > { typedef cross_track < - Point, - PointOfSegment, void, typename boost::mpl::if_ < @@ -338,22 +267,20 @@ struct default_strategy template <typename Point, typename PointOfSegment, typename Strategy> struct default_strategy < - segment_tag, Point, PointOfSegment, - spherical_equatorial_tag, spherical_equatorial_tag, + point_tag, segment_tag, Point, PointOfSegment, + spherical_equatorial_tag, spherical_equatorial_tag, Strategy > { typedef cross_track < - Point, - PointOfSegment, void, typename boost::mpl::if_ < boost::is_void<Strategy>, typename default_strategy < - point_tag, Point, PointOfSegment, + point_tag, point_tag, Point, PointOfSegment, spherical_equatorial_tag, spherical_equatorial_tag >::type, Strategy @@ -362,6 +289,22 @@ struct default_strategy }; +template <typename PointOfSegment, typename Point, typename Strategy> +struct default_strategy + < + segment_tag, point_tag, PointOfSegment, Point, + spherical_equatorial_tag, spherical_equatorial_tag, + Strategy + > +{ + typedef typename default_strategy + < + point_tag, segment_tag, Point, PointOfSegment, + spherical_equatorial_tag, spherical_equatorial_tag, + Strategy + >::type type; +}; + } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS |