updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

View File

@@ -1,6 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2016-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,15 +14,15 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/formulas/area_formulas.hpp>
#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/authalic_radius_sqr.hpp>
#include <boost/geometry/formulas/eccentricity_sqr.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/math/special_functions/atanh.hpp>
namespace boost { namespace geometry
{
@@ -33,7 +35,6 @@ namespace strategy { namespace area
\ingroup strategies
\details Geographic area calculation by trapezoidal rule plus integral
approximation that gives the ellipsoidal correction
\tparam PointOfSegment \tparam_segment_point
\tparam FormulaPolicy Formula used to calculate azimuths
\tparam SeriesOrder The order of approximation of the geodesic integral
\tparam Spheroid The spheroid model
@@ -44,12 +45,12 @@ namespace strategy { namespace area
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
\* [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
typename PointOfSegment,
typename FormulaPolicy = strategy::andoyer,
std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
typename Spheroid = srs::spheroid<double>,
@@ -64,58 +65,67 @@ class geographic
//Select default types in case they are not set
typedef typename boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
typename select_most_precise
public:
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
typename coordinate_type<PointOfSegment>::type,
double
>::type,
CalculationType
>::type CT;
Geometry,
CalculationType
>
{};
protected :
struct spheroid_constants
{
typedef typename boost::mpl::if_c
<
boost::is_void<CalculationType>::value,
typename geometry::radius_type<Spheroid>::type,
CalculationType
>::type calc_t;
Spheroid m_spheroid;
CT const m_a2; // squared equatorial radius
CT const m_e2; // squared eccentricity
CT const m_ep2; // squared second eccentricity
CT const m_ep; // second eccentricity
CT const m_c2; // authalic radius
calc_t const m_a2; // squared equatorial radius
calc_t const m_e2; // squared eccentricity
calc_t const m_ep2; // squared second eccentricity
calc_t const m_ep; // second eccentricity
calc_t const m_c2; // squared authalic radius
inline spheroid_constants(Spheroid const& spheroid)
: m_spheroid(spheroid)
, m_a2(math::sqr(get_radius<0>(spheroid)))
, m_e2(formula::flattening<CT>(spheroid)
* (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
, m_ep2(m_e2 / (CT(1.0) - m_e2))
, m_e2(formula::eccentricity_sqr<calc_t>(spheroid))
, m_ep2(m_e2 / (calc_t(1.0) - m_e2))
, m_ep(math::sqrt(m_ep2))
, m_c2((m_a2 / CT(2.0)) +
((math::sqr(get_radius<2>(spheroid)) * boost::math::atanh(math::sqrt(m_e2)))
/ (CT(2.0) * math::sqrt(m_e2))))
, m_c2(formula_dispatch::authalic_radius_sqr
<
calc_t, Spheroid, srs_spheroid_tag
>::apply(m_a2, m_e2))
{}
};
struct area_sums
public:
template <typename Geometry>
class state
{
CT m_excess_sum;
CT m_correction_sum;
friend class geographic;
// Keep track if encircles some pole
std::size_t m_crosses_prime_meridian;
typedef typename result_type<Geometry>::type return_type;
inline area_sums()
public:
inline state()
: m_excess_sum(0)
, m_correction_sum(0)
, m_crosses_prime_meridian(0)
{}
inline CT area(spheroid_constants spheroid_const) const
{
CT result;
CT sum = spheroid_const.m_c2 * m_excess_sum
private:
inline return_type area(spheroid_constants const& spheroid_const) const
{
return_type result;
return_type sum = spheroid_const.m_c2 * m_excess_sum
+ spheroid_const.m_e2 * spheroid_const.m_a2 * m_correction_sum;
// If encircles some pole
@@ -124,13 +134,13 @@ protected :
std::size_t times_crosses_prime_meridian
= 1 + (m_crosses_prime_meridian / 2);
result = CT(2.0)
* geometry::math::pi<CT>()
result = return_type(2.0)
* geometry::math::pi<return_type>()
* spheroid_const.m_c2
* CT(times_crosses_prime_meridian)
* return_type(times_crosses_prime_meridian)
- geometry::math::abs(sum);
if (geometry::math::sign<CT>(sum) == 1)
if (geometry::math::sign<return_type>(sum) == 1)
{
result = - result;
}
@@ -143,46 +153,52 @@ protected :
return result;
}
return_type m_excess_sum;
return_type m_correction_sum;
// Keep track if encircles some pole
std::size_t m_crosses_prime_meridian;
};
public :
typedef CT return_type;
typedef PointOfSegment segment_point_type;
typedef area_sums state_type;
explicit inline geographic(Spheroid const& spheroid = Spheroid())
: m_spheroid_constants(spheroid)
{}
template <typename PointOfSegment, typename Geometry>
inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
area_sums& state) const
state<Geometry>& st) const
{
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
typedef geometry::formula::area_formulas
<
CT, SeriesOrder, ExpandEpsN
typename result_type<Geometry>::type,
SeriesOrder, ExpandEpsN
> area_formulas;
typename area_formulas::return_type_ellipsoidal result =
area_formulas::template ellipsoidal<FormulaPolicy::template inverse>
(p1, p2, m_spheroid_constants);
state.m_excess_sum += result.spherical_term;
state.m_correction_sum += result.ellipsoidal_term;
st.m_excess_sum += result.spherical_term;
st.m_correction_sum += result.ellipsoidal_term;
// Keep track whenever a segment crosses the prime meridian
geometry::formula::area_formulas<CT>
::crosses_prime_meridian(p1, p2, state);
if (area_formulas::crosses_prime_meridian(p1, p2))
{
st.m_crosses_prime_meridian++;
}
}
}
inline return_type result(area_sums const& state) const
template <typename Geometry>
inline typename result_type<Geometry>::type
result(state<Geometry> const& st) const
{
return state.area(m_spheroid_constants);
return st.area(m_spheroid_constants);
}
private:
@@ -196,10 +212,10 @@ namespace services
{
template <typename Point>
struct default_strategy<geographic_tag, Point>
template <>
struct default_strategy<geographic_tag>
{
typedef strategy::area::geographic<Point> type;
typedef strategy::area::geographic<> type;
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

View File

@@ -12,7 +12,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
@@ -56,22 +56,69 @@ public :
inline void apply(T const& lon1_rad, T const& lat1_rad,
T const& lon2_rad, T const& lat2_rad,
T& a1, T& a2) const
{
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;
>::type calc_t;
typedef typename FormulaPolicy::template inverse<calc_t, false, true, true, 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;
a2 = i_res.reverse_azimuth;
if (EnableAzimuth)
{
a1 = i_res.azimuth;
}
if (EnableReverseAzimuth)
{
a2 = i_res.reverse_azimuth;
}
}
private :
Spheroid m_spheroid;
};

View File

@@ -0,0 +1,127 @@
// Boost.Geometry
// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
// 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_BUFFER_POINT_CIRCLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP
#include <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/buffer.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Create a circular buffer around a point, on the Earth
\ingroup strategies
\details This strategy can be used as PointStrategy for the buffer algorithm.
It creates a circular buffer around a point, on the Earth. It can be applied
for points and multi_points.
\qbk{
[heading Example]
[buffer_geographic_point_circle]
[buffer_geographic_point_circle_output]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_point_circle point_circle]
\* [link geometry.reference.strategies.strategy_buffer_point_square point_square]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic_point_circle
{
public :
//! \brief Constructs the strategy
//! \param count number of points for the created circle (if count
//! is smaller than 3, count is internally set to 3)
explicit geographic_point_circle(std::size_t count = 90)
: m_count((count < 3u) ? 3u : count)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a circle around point using distance_strategy
template
<
typename Point,
typename OutputRange,
typename DistanceStrategy
>
inline void apply(Point const& point,
DistanceStrategy const& distance_strategy,
OutputRange& output_range) const
{
typedef typename boost::range_value<OutputRange>::type output_point_type;
typedef typename select_most_precise
<
typename geometry::coordinate_type<Point>::type,
typename geometry::coordinate_type<output_point_type>::type,
CalculationType
//double
>::type calculation_type;
calculation_type const buffer_distance = distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left);
typedef typename FormulaPolicy::template direct
<
calculation_type, true, false, false, false
> direct_t;
calculation_type const two_pi = geometry::math::two_pi<calculation_type>();
calculation_type const diff = two_pi / calculation_type(m_count);
// TODO: after calculation of some angles is corrected,
// we can start at 0.0
calculation_type angle = 0.001;
for (std::size_t i = 0; i < m_count; i++, angle += diff)
{
typename direct_t::result_type
dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point),
buffer_distance, angle,
m_spheroid);
output_point_type p;
set_from_radian<0>(p, dir_r.lon2);
set_from_radian<1>(p, dir_r.lat2);
output_range.push_back(p);
}
{
// Close the range
const output_point_type p = output_range.front();
output_range.push_back(p);
}
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
std::size_t m_count;
Spheroid m_spheroid;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP

View File

@@ -0,0 +1,136 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of geographic segment.
\ingroup strategies
\tparam FormulaPolicy The geodesic formulas used internally.
\tparam Spheroid The spheroid model.
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
public:
geographic()
: m_spheroid()
{}
explicit geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Point, typename AssignPolicy, typename T>
inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold) const
{
typedef typename AssignPolicy::point_type out_point_t;
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
CalculationType
>::type calc_t;
typedef typename FormulaPolicy::template direct<calc_t, true, false, false, false> direct_t;
typedef typename FormulaPolicy::template inverse<calc_t, true, true, false, false, false> inverse_t;
typename inverse_t::result_type
inv_r = inverse_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
get_as_radian<0>(p1), get_as_radian<1>(p1),
m_spheroid);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(inv_r.distance / length_threshold);
if (n <= 0)
return;
calc_t step = inv_r.distance / (n + 1);
calc_t current = step;
for (signed_size_type i = 0 ; i < n ; ++i, current += step)
{
typename direct_t::result_type
dir_r = direct_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
current, inv_r.azimuth,
m_spheroid);
out_point_t p;
set_from_radian<0>(p, dir_r.lon2);
set_from_radian<1>(p, dir_r.lat2);
geometry::detail::conversion::point_to_point
<
Point, out_point_t,
2, dimension<out_point_t>::value
>::apply(p0, p);
policy.apply(p);
}
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef strategy::densify::geographic<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP

View File

@@ -0,0 +1,141 @@
// Boost.Geometry
// Copyright (c) 2017-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_DISJOINT_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISJOINT_SEGMENT_BOX_HPP
#include <cstddef>
#include <utility>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
// NOTE: This may be temporary place for this or corresponding strategy
// It seems to be more appropriate to implement the opposite of it
// e.g. intersection::segment_box because in disjoint() algorithm
// other strategies that are used are intersection and covered_by strategies.
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
struct segment_box_geographic
{
public:
typedef Spheroid model_type;
inline segment_box_geographic()
: m_spheroid()
{}
explicit inline segment_box_geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Segment, typename Box>
struct point_in_geometry_strategy
: services::default_strategy
<
typename point_type<Segment>::type,
Box
>
{};
template <typename Segment, typename Box>
static inline typename point_in_geometry_strategy<Segment, Box>::type
get_point_in_geometry_strategy()
{
typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
return strategy_type();
}
template <typename Segment, typename Box>
inline bool apply(Segment const& segment, Box const& box) const
{
geometry::strategy::azimuth::geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> azimuth_geographic(m_spheroid);
return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid
<
geographic_tag
>::apply(segment, box,
azimuth_geographic,
strategy::normalize::spherical_point(),
strategy::covered_by::spherical_point_box(),
strategy::disjoint::spherical_box_box());
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Linear, typename Box, typename LinearTag>
struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2,
geographic_tag, geographic_tag>
{
typedef segment_box_geographic<> type;
};
template <typename Box, typename Linear, typename LinearTag>
struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1,
geographic_tag, geographic_tag>
{
typedef segment_box_geographic<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISJOINT_SEGMENT_BOX_HPP

View File

@@ -2,9 +2,10 @@
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014-2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2018.
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,18 +20,22 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/formulas/andoyer_inverse.hpp>
#include <boost/geometry/formulas/meridian_inverse.hpp>
#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
namespace boost { namespace geometry
{
@@ -38,6 +43,19 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
/*!
\brief Distance calculation for geographic coordinates on a spheroid
\ingroup strategies
\tparam FormulaPolicy Formula used to calculate azimuths
\tparam Spheroid The spheroid model
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
@@ -70,17 +88,41 @@ public :
: m_spheroid(spheroid)
{}
template <typename CT>
static inline CT apply(CT lon1, CT lat1, CT lon2, CT lat2,
Spheroid const& spheroid)
{
typedef typename formula::meridian_inverse
<
CT, strategy::default_order<FormulaPolicy>::value
> meridian_inverse;
typename meridian_inverse::result res =
meridian_inverse::apply(lon1, lat1, lon2, lat2, spheroid);
if (res.meridian)
{
return res.distance;
}
return FormulaPolicy::template inverse
<
CT, true, false, false, false, false
>::apply(lon1, lat1, lon2, lat2, spheroid).distance;
}
template <typename Point1, typename Point2>
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& point1, Point2 const& point2) const
{
return FormulaPolicy::template inverse
<
typename calculation_type<Point1, Point2>::type,
true, false, false, false, false
>::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
get_as_radian<0>(point2), get_as_radian<1>(point2),
m_spheroid).distance;
typedef typename calculation_type<Point1, Point2>::type CT;
CT lon1 = get_as_radian<0>(point1);
CT lat1 = get_as_radian<1>(point1);
CT lon2 = get_as_radian<0>(point2);
CT lat2 = get_as_radian<1>(point2);
return apply(lon1, lat1, lon2, lat2, m_spheroid);
}
inline Spheroid const& model() const

View File

@@ -0,0 +1,738 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_HPP
#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>
#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.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>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/formulas/result_direct.hpp>
#include <boost/geometry/formulas/mean_radius.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
#include <boost/geometry/io/dsv/write.hpp>
#endif
#ifndef BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS
#define BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS 100
#endif
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
#include <iostream>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy functor for distance point to segment calculation on ellipsoid
Algorithm uses direct and inverse geodesic problems as subroutines.
The algorithm approximates the distance by an iterative Newton method.
\ingroup strategies
\details Class which calculates the distance of a point to a segment, for points
on the ellipsoid
\see C.F.F.Karney - Geodesics on an ellipsoid of revolution,
https://arxiv.org/abs/1102.1215
\tparam FormulaPolicy underlying point-point distance strategy
\tparam Spheroid is the spheroidal model used
\tparam CalculationType \tparam_calculation
\tparam EnableClosestPoint computes the closest point on segment if true
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void,
bool EnableClosestPoint = false
>
class geographic_cross_track
{
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
<
typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type
>
{};
explicit geographic_cross_track(Spheroid const& spheroid = Spheroid())
: m_spheroid(spheroid)
{}
template <typename Point, typename PointOfSegment>
inline typename return_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
{
typedef typename geometry::detail::cs_angular_units<Point>::type units_type;
return (apply<units_type>(get<0>(sp1), get<1>(sp1),
get<0>(sp2), get<1>(sp2),
get<0>(p), get<1>(p),
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>
struct result_distance_point_segment
{
result_distance_point_segment()
: distance(0)
, closest_point_lon(0)
, closest_point_lat(0)
{}
CT distance;
CT closest_point_lon;
CT closest_point_lat;
};
template <typename CT>
result_distance_point_segment<CT>
static inline non_iterative_case(CT lon, CT lat, CT distance)
{
result_distance_point_segment<CT> result;
result.distance = distance;
if (EnableClosestPoint)
{
result.closest_point_lon = lon;
result.closest_point_lat = lat;
}
return result;
}
template <typename CT>
result_distance_point_segment<CT>
static inline non_iterative_case(CT lon1, CT lat1, //p1
CT lon2, CT lat2, //p2
Spheroid const& spheroid)
{
CT distance = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
::apply(lon1, lat1, lon2, lat2, spheroid);
return non_iterative_case(lon1, lat1, distance);
}
template <typename CT>
CT static inline normalize(CT g4, CT& der)
{
CT const pi = math::pi<CT>();
if (g4 < -1.25*pi)//close to -270
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
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 * 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 * math::r2d<CT>() << ", close to -90" << std::endl;
#endif
der = -der;
return -g4 - pi/2;
}
return g4 - pi/2;
}
template <typename Units, typename CT>
result_distance_point_segment<CT>
static inline apply(CT lon1, CT lat1, //p1
CT lon2, CT lat2, //p2
CT lon3, CT lat3, //query point p3
Spheroid const& spheroid)
{
typedef typename FormulaPolicy::template inverse<CT, true, true, false, true, true>
inverse_distance_azimuth_quantities_type;
typedef typename FormulaPolicy::template inverse<CT, false, true, false, false, false>
inverse_azimuth_type;
typedef typename FormulaPolicy::template inverse<CT, false, true, true, false, false>
inverse_azimuth_reverse_type;
typedef typename FormulaPolicy::template direct<CT, true, false, false, false>
direct_distance_type;
CT const earth_radius = geometry::formula::mean_radius<CT>(spheroid);
result_distance_point_segment<CT> result;
// Constants
//CT const f = geometry::formula::flattening<CT>(spheroid);
CT const pi = math::pi<CT>();
CT const half_pi = pi / CT(2);
CT const c0 = CT(0);
// Convert to radians
lon1 = math::as_radian<Units>(lon1);
lat1 = math::as_radian<Units>(lat1);
lon2 = math::as_radian<Units>(lon2);
lat2 = math::as_radian<Units>(lat2);
lon3 = math::as_radian<Units>(lon3);
lat3 = math::as_radian<Units>(lat3);
if (lon1 > lon2)
{
std::swap(lon1, lon2);
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::meridian_inverse<CT>
meridian_inverse;
bool meridian_not_crossing_pole =
meridian_inverse::meridian_not_crossing_pole
(lat1, lat2, diff);
bool meridian_crossing_pole =
meridian_inverse::meridian_crossing_pole(diff);
if (math::equals(lat1, c0) && math::equals(lat2, c0) && !meridian_crossing_pole)
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Equatorial segment" << std::endl;
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>() << ")\n";
#endif
if (lon3 <= lon1)
{
return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
}
if (lon3 >= lon2)
{
return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
}
return non_iterative_case(lon3, lat1, lon3, lat3, spheroid);
}
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 crossing pole" << std::endl;
#endif
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;
}
else
{
return d2;
}
}
CT d1 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
::apply(lon1, lat1, lon3, lat3, spheroid);
CT d3 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
::apply(lon1, lat1, lon2, lat2, spheroid);
if (geometry::math::equals(d3, c0))
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Degenerate segment" << std::endl;
std::cout << "distance between points=" << d1 << std::endl;
#endif
return non_iterative_case(lon1, lat2, d1);
}
CT d2 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
::apply(lon2, lat2, lon3, lat3, spheroid);
// Compute a12 (GEO)
geometry::formula::result_inverse<CT> res12 =
inverse_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
CT a12 = res12.azimuth;
CT a13 = inverse_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid).azimuth;
CT a312 = a13 - a12;
// 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 meridian segment" << std::endl;
#endif
return non_iterative_case(lon3, lat3, c0);
}
}
CT projection1 = cos( a312 ) * d1 / d3;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
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 < c0)
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "projection closer to p1" << std::endl;
#endif
// projection of p3 on geodesic spanned by segment (p1,p2) fall
// outside of segment on the side of p1
return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
}
CT a21 = res12.reverse_azimuth - pi;
CT a23 = inverse_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid).azimuth;
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
if (projection2 < c0)
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "projection closer to p2" << std::endl;
#endif
// projection of p3 on geodesic spanned by segment (p1,p2) fall
// outside of segment on the side of p2
return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
}
// Guess s14 (SPHERICAL) aka along-track distance
typedef geometry::model::point
<
CT, 2,
geometry::cs::spherical_equatorial<geometry::radian>
> point;
point p1 = point(lon1, lat1);
point p2 = point(lon2, lat2);
point p3 = point(lon3, lat3);
geometry::strategy::distance::cross_track<CT> cross_track(earth_radius);
CT s34 = cross_track.apply(p3, p1, p2);
geometry::strategy::distance::haversine<CT> str(earth_radius);
CT s13 = str.apply(p1, p3);
//CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius;
CT cos_frac = cos(s13/earth_radius) / cos(s34/earth_radius);
CT s14 = cos_frac >= 1 ? CT(0)
: cos_frac <= -1 ? pi * earth_radius
: acos(cos_frac) * earth_radius;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "s34=" << s34 << std::endl;
std::cout << "s13=" << s13 << std::endl;
std::cout << "s14=" << s14 << std::endl;
std::cout << "===============" << std::endl;
#endif
// Update s14 (using Newton method)
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;
// Solve the direct problem to find p4 (GEO)
res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
// Solve an inverse problem to find g4
// g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO)
CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2,
lon2, lat2, spheroid).azimuth;
res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2,
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
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(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;
std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl;
std::cout << "m34=" << m34 << std::endl;
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;
if (g4 == half_pi)
{
std::cout << "Stop msg: g4 == half_pi" << std::endl;
}
if (!dist_improve)
{
std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
}
if (delta_g4 == 0)
{
std::cout << "Stop msg: delta_g4 == 0" << std::endl;
}
if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS)
{
std::cout << "Stop msg: counter" << std::endl;
}
#endif
} while (g4 != half_pi
&& dist_improve
&& delta_g4 != 0
&& counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "distance=" << res34.distance << std::endl;
point p4(res14.lon2, res14.lat2);
CT s34_sph = str.apply(p4, p3);
std::cout << "s34(sph) =" << s34_sph << std::endl;
std::cout << "s34(geo) ="
<< inverse_distance_azimuth_quantities_type::apply(get<0>(p4), get<1>(p4), lon3, lat3, spheroid).distance
<< ", p4=(" << get<0>(p4) * math::r2d<double>() << ","
<< get<1>(p4) * math::r2d<double>() << ")"
<< std::endl;
CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance;
CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance;
CT a4 = inverse_azimuth_type::apply(get<0>(p4), get<1>(p4), lon2, lat2, spheroid).azimuth;
geometry::formula::result_direct<CT> res4 = direct_distance_type::apply(get<0>(p4), get<1>(p4), .04, a4, spheroid);
CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance;
geometry::formula::result_direct<CT> res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance;
std::cout << "s31=" << s31 << "\ns32=" << s32
<< "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d<double>() << "," << res4.lat2 * math::r2d<double>() << ")"
<< "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d<double>() << "," << res1.lat2 * math::r2d<double>() << ")"
<< std::endl;
if (res34.distance <= p4_plus && res34.distance <= p4_minus)
{
std::cout << "Closest point computed" << std::endl;
}
else
{
std::cout << "There is a closer point nearby" << std::endl;
}
#endif
return result;
}
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
//tags
template <typename FormulaPolicy>
struct tag<geographic_cross_track<FormulaPolicy> >
{
typedef strategy_tag_distance_point_segment type;
};
template
<
typename FormulaPolicy,
typename Spheroid
>
struct tag<geographic_cross_track<FormulaPolicy, Spheroid> >
{
typedef strategy_tag_distance_point_segment type;
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct tag<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> >
{
typedef strategy_tag_distance_point_segment type;
};
//return types
template <typename FormulaPolicy, typename P, typename PS>
struct return_type<geographic_cross_track<FormulaPolicy>, P, PS>
: geographic_cross_track<FormulaPolicy>::template return_type<P, PS>
{};
template
<
typename FormulaPolicy,
typename Spheroid,
typename P,
typename PS
>
struct return_type<geographic_cross_track<FormulaPolicy, Spheroid>, P, PS>
: geographic_cross_track<FormulaPolicy, Spheroid>::template return_type<P, PS>
{};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType,
typename P,
typename PS
>
struct return_type<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType>, P, PS>
: geographic_cross_track<FormulaPolicy, Spheroid, CalculationType>::template return_type<P, PS>
{};
//comparable types
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct comparable_type<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> >
{
typedef geographic_cross_track
<
FormulaPolicy, Spheroid, CalculationType
> type;
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct get_comparable<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> >
{
public :
static inline geographic_cross_track<FormulaPolicy, Spheroid, CalculationType>
apply(geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> const& strategy)
{
return strategy;
}
};
template
<
typename FormulaPolicy,
typename P,
typename PS
>
struct result_from_distance<geographic_cross_track<FormulaPolicy>, P, PS>
{
private :
typedef typename geographic_cross_track
<
FormulaPolicy
>::template return_type<P, PS>::type return_type;
public :
template <typename T>
static inline return_type
apply(geographic_cross_track<FormulaPolicy> const& , T const& distance)
{
return distance;
}
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType,
typename P,
typename PS
>
struct result_from_distance<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType>, P, PS>
{
private :
typedef typename geographic_cross_track
<
FormulaPolicy, Spheroid, CalculationType
>::template return_type<P, PS>::type return_type;
public :
template <typename T>
static inline return_type
apply(geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> const& , T const& distance)
{
return distance;
}
};
template <typename Point, typename PointOfSegment>
struct default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
geographic_tag, geographic_tag
>
{
typedef geographic_cross_track<> type;
};
template <typename PointOfSegment, typename Point>
struct default_strategy
<
segment_tag, point_tag, PointOfSegment, Point,
geographic_tag, geographic_tag
>
{
typedef typename default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
geographic_tag, geographic_tag
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_HPP

View File

@@ -0,0 +1,234 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_CROSS_TRACK_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_BOX_BOX_HPP
#include <boost/config.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy functor for distance point to box calculation
\ingroup strategies
\details Class which calculates the distance of a point to a box, for
points and boxes on a sphere or globe
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-segment distance strategy, defaults
to cross track
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic_cross_track_box_box
{
public:
// 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
<
typename distance_ps_strategy::type,
typename point_type<Box1>::type,
typename point_type<Box2>::type
>
{};
//constructor
explicit geographic_cross_track_box_box(Spheroid const& spheroid = Spheroid())
: m_spheroid(spheroid)
{}
template <typename Box1, typename Box2>
inline typename return_type<Box1, Box2>::type
apply(Box1 const& box1, Box2 const& box2) const
{
/*
#if !defined(BOOST_MSVC)
BOOST_CONCEPT_ASSERT
(
(concepts::PointSegmentDistanceStrategy
<
Strategy,
typename point_type<Box1>::type,
typename point_type<Box2>::type
>)
);
#endif
*/
typedef typename return_type<Box1, Box2>::type return_type;
return details::cross_track_box_box_generic
<return_type>::apply(box1, box2,
typename distance_pp_strategy::type(m_spheroid),
typename distance_ps_strategy::type(m_spheroid));
}
private :
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Strategy, typename Spheroid, typename CalculationType>
struct tag<geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename Strategy, typename Spheroid, typename CalculationType, typename Box1, typename Box2>
struct return_type<geographic_cross_track_box_box<Strategy, Spheroid, CalculationType>, Box1, Box2>
: geographic_cross_track_box_box
<
Strategy, Spheroid, CalculationType
>::template return_type<Box1, Box2>
{};
template <typename Strategy, typename Spheroid, typename Box1, typename Box2>
struct return_type<geographic_cross_track_box_box<Strategy, Spheroid>, Box1, Box2>
: geographic_cross_track_box_box
<
Strategy, Spheroid
>::template return_type<Box1, Box2>
{};
template <typename Strategy, typename Box1, typename Box2>
struct return_type<geographic_cross_track_box_box<Strategy>, Box1, Box2>
: geographic_cross_track_box_box
<
Strategy
>::template return_type<Box1, Box2>
{};
template <typename Strategy, typename Spheroid, typename CalculationType>
struct comparable_type<geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> >
{
typedef geographic_cross_track_box_box
<
typename comparable_type<Strategy>::type, Spheroid, CalculationType
> type;
};
template <typename Strategy, typename Spheroid, typename CalculationType>
struct get_comparable<geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> >
{
public:
static inline geographic_cross_track_box_box<Strategy, Spheroid, CalculationType>
apply(geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> const& str)
{
return str;
}
};
template <typename Strategy, typename Spheroid, typename CalculationType, typename Box1, typename Box2>
struct result_from_distance
<
geographic_cross_track_box_box<Strategy, Spheroid, CalculationType>, Box1, Box2
>
{
private:
typedef geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> this_strategy;
typedef typename this_strategy::template return_type
<
Box1, Box2
>::type return_type;
public:
template <typename T>
static inline return_type apply(this_strategy const& strategy,
T const& distance)
{
result_from_distance
<
Strategy,
typename point_type<Box1>::type,
typename point_type<Box2>::type
>::apply(strategy, distance);
}
};
template <typename Box1, typename Box2>
struct default_strategy
<
box_tag, box_tag, Box1, Box2,
geographic_tag, geographic_tag
>
{
typedef geographic_cross_track_box_box<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_BOX_BOX_HPP

View File

@@ -0,0 +1,228 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_CROSS_TRACK_POINT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
#include <boost/config.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy functor for distance point to box calculation
\ingroup strategies
\details Class which calculates the distance of a point to a box, for
points and boxes on a sphere or globe
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-segment distance strategy, defaults
to cross track
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic_cross_track_point_box
{
public:
// 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<typename distance_ps_strategy::type,
Point, typename point_type<Box>::type>
{};
//constructor
explicit geographic_cross_track_point_box(Spheroid const& spheroid = Spheroid())
: m_spheroid(spheroid)
{}
template <typename Point, typename Box>
inline typename return_type<Point, Box>::type
apply(Point const& point, Box const& box) const
{
/*
#if !defined(BOOST_MSVC)
BOOST_CONCEPT_ASSERT
(
(concepts::PointSegmentDistanceStrategy
<
Strategy, Point, typename point_type<Box>::type
>)
);
#endif
*/
typedef typename return_type<Point, Box>::type return_type;
return details::cross_track_point_box_generic
<return_type>::apply(point, box,
typename distance_ps_strategy::type(m_spheroid));
}
private :
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Strategy, typename Spheroid, typename CalculationType>
struct tag<geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename Strategy, typename Spheroid, typename CalculationType, typename P, typename Box>
struct return_type<geographic_cross_track_point_box<Strategy, Spheroid, CalculationType>, P, Box>
: geographic_cross_track_point_box
<
Strategy, Spheroid, CalculationType
>::template return_type<P, Box>
{};
template <typename Strategy, typename Spheroid, typename P, typename Box>
struct return_type<geographic_cross_track_point_box<Strategy, Spheroid>, P, Box>
: geographic_cross_track_point_box
<
Strategy, Spheroid
>::template return_type<P, Box>
{};
template <typename Strategy, typename P, typename Box>
struct return_type<geographic_cross_track_point_box<Strategy>, P, Box>
: geographic_cross_track_point_box
<
Strategy
>::template return_type<P, Box>
{};
template <typename Strategy, typename Spheroid, typename CalculationType>
struct comparable_type<geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> >
{
typedef geographic_cross_track_point_box
<
Strategy, Spheroid, CalculationType
> type;
};
template <typename Strategy, typename Spheroid, typename CalculationType>
struct get_comparable<geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> >
{
public:
static inline geographic_cross_track_point_box<Strategy, Spheroid, CalculationType>
apply(geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> const& str)
{
return str;
}
};
template <typename Strategy, typename Spheroid, typename CalculationType, typename P, typename Box>
struct result_from_distance
<
geographic_cross_track_point_box<Strategy, Spheroid, CalculationType>, P, Box
>
{
private:
typedef geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> this_strategy;
typedef typename this_strategy::template return_type
<
P, Box
>::type return_type;
public:
template <typename T>
static inline return_type apply(this_strategy const& strategy,
T const& distance)
{
result_from_distance
<
Strategy, P, typename point_type<Box>::type
>::apply(strategy, distance);
}
};
template <typename Point, typename Box>
struct default_strategy
<
point_tag, box_tag, Point, Box,
geographic_tag, geographic_tag
>
{
typedef geographic_cross_track_point_box<> type;
};
template <typename Box, typename Point>
struct default_strategy
<
box_tag, point_tag, Box, Point,
geographic_tag, geographic_tag
>
{
typedef typename default_strategy
<
point_tag, box_tag, Point, Box,
geographic_tag, geographic_tag
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_CROSS_TRACK_POINT_BOX_HPP

View File

@@ -0,0 +1,336 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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/srs/spheroid.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/distance_segment_box.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.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);
}
typedef within::spherical_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
{
return equals_point_point_strategy_type();
}
//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,
normalize::spherical_point(),
covered_by::spherical_point_box(),
disjoint::spherical_box_box());
}
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

View File

@@ -0,0 +1,116 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2016, 2018, 2019.
// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Distributed under 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_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_HPP
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/expand_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/spherical/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic
: public spherical<CalculationType>
{
public:
typedef Spheroid model_type;
inline geographic()
: m_spheroid()
{}
explicit inline geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
typedef geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
> element_envelope_strategy_type;
inline element_envelope_strategy_type get_element_envelope_strategy() const
{
return element_envelope_strategy_type(m_spheroid);
}
typedef expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
> element_expand_strategy_type;
inline element_expand_strategy_type get_element_expand_strategy() const
{
return element_expand_strategy_type(m_spheroid);
}
template <typename Point1, typename Point2, typename Box>
inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const
{
geographic_segment
<
FormulaPolicy,
Spheroid,
CalculationType
>(m_spheroid).apply(point1, point2, box);
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::geographic
<
strategy::andoyer,
geometry::srs::spheroid<double>,
CalculationType
> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_HPP

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Oracle and/or its affiliates.
// Copyright (c) 2017-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,13 +12,15 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
namespace boost { namespace geometry
{
@@ -45,11 +47,18 @@ public:
: m_spheroid(spheroid)
{}
template <typename Point1, typename Point2, typename Box>
inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const
typedef strategy::expand::spherical_box box_expand_strategy_type;
static inline box_expand_strategy_type get_box_expand_strategy()
{
Point1 p1_normalized = detail::return_normalized<Point1>(point1);
Point2 p2_normalized = detail::return_normalized<Point2>(point2);
return box_expand_strategy_type();
}
template <typename Point, typename Box>
inline void apply(Point const& point1, Point const& point2, Box& box) const
{
Point p1_normalized, p2_normalized;
strategy::normalize::spherical_point::apply(point1, p1_normalized);
strategy::normalize::spherical_point::apply(point2, p2_normalized);
geometry::strategy::azimuth::geographic
<
@@ -58,9 +67,13 @@ public:
CalculationType
> azimuth_geographic(m_spheroid);
typedef typename coordinate_system<Point1>::type::units units_type;
typedef typename geometry::detail::cs_angular_units
<
Point
>::type units_type;
detail::envelope::envelope_segment_impl
// first compute the envelope range for the first two coordinates
strategy::envelope::detail::envelope_segment_impl
<
geographic_tag
>::template apply<units_type>(geometry::get<0>(p1_normalized),
@@ -70,6 +83,12 @@ public:
box,
azimuth_geographic);
// now compute the envelope range for coordinates of
// dimension 2 and higher
strategy::envelope::detail::envelope_one_segment
<
2, dimension<Point>::value
>::apply(point1, point2, box);
}
private:
@@ -82,7 +101,7 @@ namespace services
{
template <typename CalculationType>
struct default_strategy<geographic_tag, CalculationType>
struct default_strategy<segment_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::geographic_segment
<

View File

@@ -0,0 +1,102 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Distributed under 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_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_EXPAND_SEGMENT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/expand.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/spherical/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic_segment
{
public:
inline geographic_segment()
: m_envelope_strategy()
{}
explicit inline geographic_segment(Spheroid const& spheroid)
: m_envelope_strategy(spheroid)
{}
template <typename Box, typename Segment>
inline void apply(Box& box, Segment const& segment) const
{
detail::segment_on_spheroid::apply(box, segment, m_envelope_strategy);
}
private:
strategy::envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
> m_envelope_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, geographic_tag, CalculationType>
{
typedef geographic_segment
<
strategy::andoyer,
geometry::srs::spheroid<double>,
CalculationType
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_EXPAND_SEGMENT_HPP

View File

@@ -1,6 +1,8 @@
// Boost.Geometry
// Copyright (c) 2016-2017, Oracle and/or its affiliates.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2016-2019, 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,
@@ -15,7 +17,6 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
@@ -26,16 +27,25 @@
#include <boost/geometry/formulas/andoyer_inverse.hpp>
#include <boost/geometry/formulas/sjoberg_intersection.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/formulas/unit_spheroid.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/geographic/area.hpp>
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/envelope.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side_info.hpp>
@@ -77,11 +87,12 @@ struct geographic_segments
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::winding
typedef strategy::within::geographic_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
side_strategy_type,
FormulaPolicy,
Spheroid,
CalculationType
> type;
};
@@ -94,7 +105,7 @@ struct geographic_segments
<
Geometry1, Geometry2
>::type strategy_type;
return strategy_type(get_side_strategy());
return strategy_type(m_spheroid);
}
template <typename Geometry>
@@ -102,7 +113,6 @@ struct geographic_segments
{
typedef area::geographic
<
typename point_type<Geometry>::type,
FormulaPolicy,
Order,
Spheroid,
@@ -135,39 +145,63 @@ struct geographic_segments
return strategy_type(m_spheroid);
}
typedef envelope::geographic<FormulaPolicy, Spheroid, CalculationType>
envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return envelope_strategy_type(m_spheroid);
}
typedef expand::geographic_segment<FormulaPolicy, Spheroid, CalculationType>
expand_strategy_type;
inline expand_strategy_type get_expand_strategy() const
{
return expand_strategy_type(m_spheroid);
}
typedef within::spherical_point_point point_in_point_strategy_type;
static inline point_in_point_strategy_type get_point_in_point_strategy()
{
return point_in_point_strategy_type();
}
typedef within::spherical_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
{
return equals_point_point_strategy_type();
}
typedef disjoint::spherical_box_box disjoint_box_box_strategy_type;
static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy()
{
return disjoint_box_box_strategy_type();
}
typedef disjoint::segment_box_geographic
<
FormulaPolicy, Spheroid, CalculationType
> disjoint_segment_box_strategy_type;
inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy() const
{
return disjoint_segment_box_strategy_type(m_spheroid);
}
typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
typedef expand::spherical_box expand_box_strategy_type;
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
{
typedef typename select_most_precise
<
CoordinateType, double
>::type promoted_type;
promoted_type comparable_length_a() const
{
return robust_ra.denominator();
}
promoted_type comparable_length_b() const
{
return robust_rb.denominator();
}
template <typename Point, typename Segment1, typename Segment2>
void assign_a(Point& point, Segment1 const& a, Segment2 const& b) const
{
assign(point, a, b);
}
template <typename Point, typename Segment1, typename Segment2>
void assign_b(Point& point, Segment1 const& a, Segment2 const& b) const
{
assign(point, a, b);
}
template <typename Point, typename Segment1, typename Segment2>
void assign(Point& point, Segment1 const& a, Segment2 const& b) const
void calculate(Point& point, Segment1 const& a, Segment2 const& b) const
{
if (ip_flag == ipi_inters)
{
@@ -245,7 +279,16 @@ struct geographic_segments
{
bool is_a_reversed = get<1>(a1) > get<1>(a2);
bool is_b_reversed = get<1>(b1) > get<1>(b2);
/*
typename coordinate_type<Point1>::type
const a1_lon = get<0>(a1),
const a2_lon = get<0>(a2);
typename coordinate_type<Point2>::type
const b1_lon = get<0>(b1),
const b2_lon = get<0>(b2);
bool is_a_reversed = a1_lon > a2_lon || a1_lon == a2_lon && get<1>(a1) > get<1>(a2);
bool is_b_reversed = b1_lon > b2_lon || b1_lon == b2_lon && get<1>(b1) > get<1>(b2);
*/
if (is_a_reversed)
{
std::swap(a1, a2);
@@ -280,11 +323,14 @@ private:
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type calc_t;
typedef srs::spheroid<calc_t> spheroid_type;
static const calc_t c0 = 0;
// normalized spheroid
srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
spheroid_type spheroid = formula::unit_spheroid<spheroid_type>(m_spheroid);
// TODO: check only 2 first coordinates here?
using geometry::detail::equals::equals_point_point;
bool a_is_point = equals_point_point(a1, a2);
bool b_is_point = equals_point_point(b1, b2);
@@ -316,31 +362,80 @@ private:
// TODO: no need to call inverse formula if we know that the points are equal
// distance can be set to 0 in this case and azimuth may be not calculated
bool const is_equal_a1_b1 = equals_point_point(a1, b1);
bool const is_equal_a2_b1 = equals_point_point(a2, b1);
bool is_equal_a1_b1 = equals_point_point(a1, b1);
bool is_equal_a2_b1 = equals_point_point(a2, b1);
bool degen_neq_coords = false;
inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
if (sides.same<0>())
inverse_result res_b1_b2, res_b1_a1, res_b1_a2;
if (! b_is_point)
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
if (math::equals(res_b1_b2.distance, c0))
{
b_is_point = true;
degen_neq_coords = true;
}
else
{
res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
if (math::equals(res_b1_a1.distance, c0))
{
is_equal_a1_b1 = true;
}
res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
if (math::equals(res_b1_a2.distance, c0))
{
is_equal_a2_b1 = true;
}
sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
if (sides.same<0>())
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
}
}
}
bool const is_equal_a1_b2 = equals_point_point(a1, b2);
bool is_equal_a1_b2 = equals_point_point(a1, b2);
inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
if (sides.same<1>())
inverse_result res_a1_a2, res_a1_b1, res_a1_b2;
if (! a_is_point)
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
if (math::equals(res_a1_a2.distance, c0))
{
a_is_point = true;
degen_neq_coords = true;
}
else
{
res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
if (math::equals(res_a1_b1.distance, c0))
{
is_equal_a1_b1 = true;
}
res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
if (math::equals(res_a1_b2.distance, c0))
{
is_equal_a1_b2 = true;
}
sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
if (sides.same<1>())
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
}
}
}
if(a_is_point && b_is_point)
{
return is_equal_a1_b2
? Policy::degenerate(a, true)
: Policy::disjoint()
;
}
// NOTE: at this point the segments may still be disjoint
@@ -370,11 +465,11 @@ private:
{
if (a_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed);
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, is_b_reversed, degen_neq_coords);
}
else if (b_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed);
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, is_a_reversed, degen_neq_coords);
}
else
{
@@ -383,16 +478,16 @@ private:
// use shorter segment
if (res_a1_a2.distance <= res_b1_b2.distance)
{
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2);
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, 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;
}
else
{
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2);
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, 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;
@@ -540,11 +635,13 @@ private:
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
ResultInverse const& res_a1_a2,
ResultInverse const& res_a1_bi,
bool is_other_reversed)
ResultInverse const& res_a1_b1,
ResultInverse const& res_a1_b2,
bool is_other_reversed,
bool degen_neq_coords)
{
CalcT dist_1_2, dist_1_o;
if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o))
if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_1_2, dist_1_o, degen_neq_coords))
{
return Policy::disjoint();
}
@@ -563,34 +660,53 @@ private:
// in order to make this independent from is_near()
template <typename Point1, typename Point2, typename ResultInverse, typename CalcT>
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
Point2 const& b1, Point2 const& b2, // in
Point2 const& b1, Point2 const& /*b2*/, // in
ResultInverse const& res_a1_a2, // in
ResultInverse const& res_a1_bi, // in
CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out
ResultInverse const& res_a1_b1, // in
ResultInverse const& res_a1_b2, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_b1, // out
bool degen_neq_coords = false) // in
{
dist_a1_a2 = res_a1_a2.distance;
dist_a1_bi = res_a1_bi.distance;
if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth))
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 degenerated segment near a pole
if (degen_neq_coords)
{
static CalcT const c0 = 0;
if (math::equals(res_a1_b2.distance, c0))
{
dist_a1_b1 = 0;
return true;
}
else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0))
{
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_>
@@ -617,7 +733,6 @@ private:
dist_b1_b2 = res_b1_b2.distance;
// assign the IP if some endpoints overlap
using geometry::detail::equals::equals_point_point;
if (equals_point_point(a1, b1))
{
lon = a1_lon;
@@ -814,10 +929,10 @@ 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)
{
using geometry::detail::equals::equals_point_point;
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
static CalcT const c0 = 0;
return is_near(dist) && (math::equals(dist, c0) || equals_point_point(ai, b1));
}
template <typename CalcT>
@@ -876,12 +991,11 @@ private:
ip_flag;
}
template <typename CalcT, typename SpheroidT>
static inline srs::spheroid<CalcT> normalized_spheroid(SpheroidT const& spheroid)
template <typename Point1, typename Point2>
static inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
{
return srs::spheroid<CalcT>(CalcT(1),
CalcT(get_radius<2>(spheroid)) // b/a
/ CalcT(get_radius<0>(spheroid)));
return detail::equals::equals_point_point(point1, point2,
point_in_point_strategy_type());
}
private:

View File

@@ -11,7 +11,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/formulas/geographic.hpp>

View File

@@ -0,0 +1,129 @@
// Boost.Geometry
// Copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/line_interpolate.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace line_interpolate
{
/*!
\brief Interpolate point on a geographic segment.
\ingroup strategies
\tparam FormulaPolicy The geodesic formulas used internally.
\tparam Spheroid The spheroid model.
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)]
\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
public:
geographic()
: m_spheroid()
{}
explicit geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
// point-point strategy getters
struct distance_pp_strategy
{
typedef distance::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);
}
template <typename Point, typename Fraction, typename Distance>
inline void apply(Point const& p0,
Point const& p1,
Fraction const& fraction, //fraction of segment
Point & p,
Distance const& distance) const
{
typedef typename select_calculation_type_alt
<
CalculationType,
Point
>::type calc_t;
typedef typename FormulaPolicy::template inverse
<calc_t, false, true, false, false, false> inverse_t;
calc_t azimuth = inverse_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
get_as_radian<0>(p1), get_as_radian<1>(p1),
m_spheroid).azimuth;
typedef typename FormulaPolicy::template direct
<calc_t, true, false, false, false> direct_t;
typename direct_t::result_type
dir_r = direct_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
distance * fraction, azimuth,
m_spheroid);
set_from_radian<0>(p, dir_r.lon2);
set_from_radian<1>(p, dir_r.lat2);
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef strategy::line_interpolate::geographic<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::line_interpolate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP

View File

@@ -10,9 +10,10 @@
#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>
#include <boost/geometry/formulas/vincenty_direct.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
#include <boost/mpl/assert.hpp>
@@ -24,6 +25,23 @@ namespace boost { namespace geometry { namespace strategy
struct andoyer
{
template
<
typename CT,
bool EnableCoordinates = true,
bool EnableReverseAzimuth = false,
bool EnableReducedLength = false,
bool EnableGeodesicScale = false
>
struct direct
: formula::thomas_direct
<
CT, false,
EnableCoordinates, EnableReverseAzimuth,
EnableReducedLength, EnableGeodesicScale
>
{};
template
<
typename CT,
@@ -45,6 +63,23 @@ struct andoyer
struct thomas
{
template
<
typename CT,
bool EnableCoordinates = true,
bool EnableReverseAzimuth = false,
bool EnableReducedLength = false,
bool EnableGeodesicScale = false
>
struct direct
: formula::thomas_direct
<
CT, true,
EnableCoordinates, EnableReverseAzimuth,
EnableReducedLength, EnableGeodesicScale
>
{};
template
<
typename CT,
@@ -66,6 +101,22 @@ struct thomas
struct vincenty
{
template
<
typename CT,
bool EnableCoordinates = true,
bool EnableReverseAzimuth = false,
bool EnableReducedLength = false,
bool EnableGeodesicScale = false
>
struct direct
: formula::vincenty_direct
<
CT, EnableCoordinates, EnableReverseAzimuth,
EnableReducedLength, EnableGeodesicScale
>
{};
template
<
typename CT,

View File

@@ -0,0 +1,80 @@
// Boost.Geometry
// Copyright (c) 2017 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/strategies/geographic/side.hpp>
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using winding rule in geographic coordinate system.
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam FormulaPolicy Geodesic formula policy
\tparam Spheroid Spheroid model
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic_winding
: public within::detail::spherical_winding_base
<
Point,
PointOfSegment,
side::geographic<FormulaPolicy, Spheroid, CalculationType>,
CalculationType
>
{
typedef within::detail::spherical_winding_base
<
Point,
PointOfSegment,
side::geographic<FormulaPolicy, Spheroid, CalculationType>,
CalculationType
> base_t;
public:
geographic_winding()
{}
explicit geographic_winding(Spheroid const& model)
: base_t(model)
{}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_POINT_IN_POLY_WINDING_HPP

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014-2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2018.
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -18,16 +18,20 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/envelope.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
@@ -46,6 +50,11 @@ namespace strategy { namespace side
\tparam FormulaPolicy Geodesic solution formula policy.
\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
@@ -56,6 +65,36 @@ template
class geographic
{
public:
typedef strategy::envelope::geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return envelope_strategy_type(m_model);
}
typedef strategy::disjoint::segment_box_geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> disjoint_strategy_type;
inline disjoint_strategy_type get_disjoint_strategy() const
{
return disjoint_strategy_type(m_model);
}
typedef strategy::within::spherical_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
{
return equals_point_point_strategy_type();
}
geographic()
{}