summaryrefslogtreecommitdiff
path: root/boost/geometry/strategies/spherical/distance_cross_track.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/strategies/spherical/distance_cross_track.hpp')
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp199
1 files changed, 110 insertions, 89 deletions
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
index f543a01c58..d9af409885 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -24,6 +24,7 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -36,7 +37,6 @@
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
@@ -50,6 +50,82 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+ template <typename CalculationType>
+ struct compute_cross_track_pair
+ {
+ template <typename Point, typename PointOfSegment>
+ static inline auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2)
+ {
+ CalculationType lon1 = geometry::get_as_radian<0>(sp1);
+ CalculationType lat1 = geometry::get_as_radian<1>(sp1);
+ CalculationType lon2 = geometry::get_as_radian<0>(sp2);
+ CalculationType lat2 = geometry::get_as_radian<1>(sp2);
+ CalculationType lon = geometry::get_as_radian<0>(p);
+ CalculationType lat = geometry::get_as_radian<1>(p);
+
+ CalculationType const crs_AD = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ false
+ >(lon1, lat1, lon, lat).azimuth;
+
+ auto result = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ true
+ >(lon1, lat1, lon2, lat2);
+
+ CalculationType crs_AB = result.azimuth;
+ CalculationType crs_BA = result.reverse_azimuth -
+ geometry::math::pi<CalculationType>();
+
+ CalculationType crs_BD = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ false
+ >(lon2, lat2, lon, lat).azimuth;
+
+ CalculationType d_crs1 = crs_AD - crs_AB;
+ CalculationType d_crs2 = crs_BD - crs_BA;
+
+ return std::pair<CalculationType, CalculationType>(d_crs1, d_crs2);
+ }
+ };
+
+ struct compute_cross_track_distance
+ {
+ template <typename CalculationType>
+ static inline auto apply(CalculationType const& d_crs1,
+ CalculationType const& d1)
+ {
+ CalculationType const half(0.5);
+ CalculationType const quarter(0.25);
+
+ CalculationType sin_d_crs1 = sin(d_crs1);
+ /*
+ This is the straightforward obvious way to continue:
+
+ return_type discriminant
+ = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;
+ return 0.5 - 0.5 * math::sqrt(discriminant);
+
+ Below we optimize the number of arithmetic operations
+ and account for numerical robustness:
+ */
+ CalculationType d1_x_sin = d1 * sin_d_crs1;
+ CalculationType d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
+ return d / (half + math::sqrt(quarter - d));
+ }
+ };
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
namespace comparable
{
@@ -159,7 +235,7 @@ namespace comparable
The distance d1 needed when the projection of the point D is within the
segment must be the true distance. However, comparable::haversine<>
returns a comparable distance instead of the one needed.
- To remedy this, we implicitly compute what is needed.
+ To remedy this, we implicitly compute what is needed.
More precisely, we need to compute sin(true_d1):
sin(true_d1) = sin(2 * asin(sqrt(d1)))
@@ -343,7 +419,7 @@ public:
>
{};
- typedef typename Strategy::radius_type radius_type;
+ using radius_type = typename Strategy::radius_type;
cross_track() = default;
@@ -372,7 +448,7 @@ public:
);
#endif
- typedef typename return_type<Point, PointOfSegment>::type return_type;
+ using return_type = typename return_type<Point, PointOfSegment>::type;
// http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p);
@@ -386,31 +462,12 @@ public:
return_type d2 = m_strategy.apply(sp2, p);
- return_type lon1 = geometry::get_as_radian<0>(sp1);
- return_type lat1 = geometry::get_as_radian<1>(sp1);
- return_type lon2 = geometry::get_as_radian<0>(sp2);
- return_type lat2 = geometry::get_as_radian<1>(sp2);
- return_type lon = geometry::get_as_radian<0>(p);
- return_type lat = geometry::get_as_radian<1>(p);
-
- return_type crs_AD = geometry::formula::spherical_azimuth<return_type, false>
- (lon1, lat1, lon, lat).azimuth;
-
- geometry::formula::result_spherical<return_type> result =
- geometry::formula::spherical_azimuth<return_type, true>
- (lon1, lat1, lon2, lat2);
- return_type crs_AB = result.azimuth;
- return_type crs_BA = result.reverse_azimuth - geometry::math::pi<return_type>();
-
- return_type crs_BD = geometry::formula::spherical_azimuth<return_type, false>
- (lon2, lat2, lon, lat).azimuth;
-
- return_type d_crs1 = crs_AD - crs_AB;
- return_type d_crs2 = crs_BD - crs_BA;
+ auto d_crs_pair = detail::compute_cross_track_pair<return_type>::apply(
+ p, sp1, sp2);
// d1, d2, d3 are in principle not needed, only the sign matters
- return_type projection1 = cos( d_crs1 ) * d1 / d3;
- return_type projection2 = cos( d_crs2 ) * d2 / d3;
+ return_type projection1 = cos(d_crs_pair.first) * d1 / d3;
+ return_type projection2 = cos(d_crs_pair.second) * d2 / d3;
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
@@ -441,30 +498,14 @@ public:
<< " d2: " << (d2 * radius())
<< std::endl;
#endif
- return_type const half(0.5);
- return_type const quarter(0.25);
-
- return_type sin_d_crs1 = sin(d_crs1);
- /*
- This is the straightforward obvious way to continue:
-
- return_type discriminant
- = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;
- return 0.5 - 0.5 * math::sqrt(discriminant);
-
- Below we optimize the number of arithmetic operations
- and account for numerical robustness:
- */
- return_type d1_x_sin = d1 * sin_d_crs1;
- return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
- return d / (half + math::sqrt(quarter - d));
+ return detail::compute_cross_track_distance::apply(
+ d_crs_pair.first, d1);
}
else
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Projection OUTSIDE the segment" << std::endl;
#endif
-
// Return shortest distance, project either on point sp1 or sp2
return return_type( (std::min)( d1 , d2 ) );
}
@@ -508,27 +549,6 @@ template
class cross_track
{
public :
- typedef within::spherical_point_point equals_point_point_strategy_type;
-
- typedef intersection::spherical_segments
- <
- CalculationType
- > relate_segment_segment_strategy_type;
-
- static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
- {
- return relate_segment_segment_strategy_type();
- }
-
- typedef within::spherical_winding
- <
- void, void, CalculationType
- > point_in_geometry_strategy_type;
-
- static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
- {
- return point_in_geometry_strategy_type();
- }
template <typename Point, typename PointOfSegment>
struct return_type
@@ -543,7 +563,7 @@ public :
>
{};
- typedef typename Strategy::radius_type radius_type;
+ using radius_type = typename Strategy::radius_type;
inline cross_track()
{}
@@ -562,8 +582,9 @@ public :
template <typename Point, typename PointOfSegment>
- inline typename return_type<Point, PointOfSegment>::type
- apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ inline auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2) const
{
#if !defined(BOOST_MSVC)
@@ -572,13 +593,13 @@ public :
(concepts::PointDistanceStrategy<Strategy, Point, PointOfSegment>)
);
#endif
- typedef typename return_type<Point, PointOfSegment>::type return_type;
- typedef cross_track<CalculationType, Strategy> this_type;
+ using return_type = typename return_type<Point, PointOfSegment>::type;
+ using this_type = cross_track<CalculationType, Strategy>;
- typedef typename services::comparable_type
+ using comparable_type = typename services::comparable_type
<
this_type
- >::type comparable_type;
+ >::type;
comparable_type cstrategy
= services::get_comparable<this_type>::apply(m_strategy);
@@ -611,7 +632,7 @@ namespace services
template <typename CalculationType, typename Strategy>
struct tag<cross_track<CalculationType, Strategy> >
{
- typedef strategy_tag_distance_point_segment type;
+ using type = strategy_tag_distance_point_segment;
};
@@ -624,10 +645,10 @@ struct return_type<cross_track<CalculationType, Strategy>, P, PS>
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track<CalculationType, Strategy> >
{
- typedef comparable::cross_track
+ using type = comparable::cross_track
<
CalculationType, typename comparable_type<Strategy>::type
- > type;
+ > ;
};
@@ -638,10 +659,10 @@ template
>
struct get_comparable<cross_track<CalculationType, Strategy> >
{
- typedef typename comparable_type
+ using comparable_type = typename comparable_type
<
cross_track<CalculationType, Strategy>
- >::type comparable_type;
+ >::type;
public :
static inline comparable_type
apply(cross_track<CalculationType, Strategy> const& strategy)
@@ -661,10 +682,10 @@ template
struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS>
{
private :
- typedef typename cross_track
+ using return_type = typename cross_track
<
CalculationType, Strategy
- >::template return_type<P, PS>::type return_type;
+ >::template return_type<P, PS>::type;
public :
template <typename T>
static inline return_type
@@ -679,7 +700,7 @@ public :
template <typename RadiusType, typename CalculationType>
struct tag<comparable::cross_track<RadiusType, CalculationType> >
{
- typedef strategy_tag_distance_point_segment type;
+ using type = strategy_tag_distance_point_segment;
};
@@ -701,7 +722,7 @@ struct return_type<comparable::cross_track<RadiusType, CalculationType>, P, PS>
template <typename RadiusType, typename CalculationType>
struct comparable_type<comparable::cross_track<RadiusType, CalculationType> >
{
- typedef comparable::cross_track<RadiusType, CalculationType> type;
+ using type = comparable::cross_track<RadiusType, CalculationType>;
};
@@ -709,7 +730,7 @@ template <typename RadiusType, typename CalculationType>
struct get_comparable<comparable::cross_track<RadiusType, CalculationType> >
{
private :
- typedef comparable::cross_track<RadiusType, CalculationType> this_type;
+ using this_type = comparable::cross_track<RadiusType, CalculationType>;
public :
static inline this_type apply(this_type const& input)
{
@@ -731,8 +752,8 @@ struct result_from_distance
>
{
private :
- typedef comparable::cross_track<RadiusType, CalculationType> strategy_type;
- typedef typename return_type<strategy_type, P, PS>::type return_type;
+ using strategy_type = comparable::cross_track<RadiusType, CalculationType>;
+ using return_type = typename return_type<strategy_type, P, PS>::type;
public :
template <typename T>
static inline return_type apply(strategy_type const& strategy,
@@ -783,7 +804,7 @@ struct default_strategy
Strategy
>
{
- typedef cross_track
+ using type = cross_track
<
void,
std::conditional_t
@@ -796,7 +817,7 @@ struct default_strategy
>::type,
Strategy
>
- > type;
+ >;
};
@@ -808,12 +829,12 @@ struct default_strategy
Strategy
>
{
- typedef typename default_strategy
+ using type = typename default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
- >::type type;
+ >::type;
};