summaryrefslogtreecommitdiff
path: root/boost/geometry/strategies/geographic
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/strategies/geographic')
-rw-r--r--boost/geometry/strategies/geographic/azimuth.hpp67
-rw-r--r--boost/geometry/strategies/geographic/distance.hpp23
-rw-r--r--boost/geometry/strategies/geographic/distance_cross_track.hpp134
-rw-r--r--boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp37
-rw-r--r--boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp20
-rw-r--r--boost/geometry/strategies/geographic/distance_segment_box.hpp311
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp36
-rw-r--r--boost/geometry/strategies/geographic/parameters.hpp8
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
>
{};