update boost on linux

This commit is contained in:
Bassem Girgis
2019-08-10 16:06:25 -05:00
parent 76ad52be58
commit 861b918727
5363 changed files with 483306 additions and 116507 deletions

View File

@@ -68,7 +68,7 @@ public :
return negative() ? -1 : 1;
}
//! Returns true if distance is negative
//! Returns true if distance is negative (aka deflate)
inline bool negative() const
{
return m_distance < 0;

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 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
@@ -22,18 +22,17 @@
#include <algorithm>
#include <vector>
#include <boost/range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/views/reversible_view.hpp>
@@ -193,9 +192,6 @@ static inline void sort(Range& range)
/*!
\brief Graham scan strategy to calculate convex hull
\ingroup strategies
\note Completely reworked version inspired on the sources listed below
\see http://www.ddj.com/architect/201806315
\see http://marknelson.us/2007/08/22/convex
*/
template <typename InputGeometry, typename OutputPoint>
class graham_andrew

View File

@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018 Oracle and/or its affiliates.
// 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.
@@ -15,10 +19,12 @@
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
#include <boost/array.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/within.hpp>
@@ -59,16 +65,17 @@ struct decide_covered_by
// This strategy is not suitable for boxes in non-cartesian CSes having edges
// longer than 180deg because e.g. the SSF formula picks the side of the closer
// longitude, so for long edges the side is the opposite.
template <typename Point, typename Box, typename Decide = decide_within>
template <typename Decide = decide_within>
struct point_in_box_by_side
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Box>::type
>::type side_strategy_type;
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Box>::type
>::type side_strategy_type;
// Create (counterclockwise) array of points, the fifth one closes it
// Every point should be on the LEFT side (=1), or ON the border (=0),
// So >= 1 or >= 0
@@ -78,7 +85,7 @@ struct point_in_box_by_side
bool result = true;
side_strategy_type strategy;
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
for (int i = 1; i < 5; i++)
{

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017 Oracle and/or its affiliates.
// Copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,10 +12,12 @@
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
namespace boost { namespace geometry
@@ -26,51 +28,32 @@ namespace strategy { namespace within
template
<
typename Point1, typename Point2
typename Point1, typename Point2,
typename CSTag = typename cs_tag<Point1>::type
>
struct point_in_point
{
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
return detail::equals::equals_point_point(point1, point2);
}
};
: strategy::within::cartesian_point_point
{};
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, spherical_equatorial_tag>
: strategy::within::spherical_point_point
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, spherical_polar_tag>
: strategy::within::spherical_point_point
{};
namespace services
{
template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
};
} // namespace services
#endif
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, geographic_tag>
: strategy::within::spherical_point_point
{};
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry

View File

@@ -36,8 +36,6 @@ namespace strategy { namespace within
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
\note but totally revised afterwards, especially for cases on segments
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
\qbk{

View File

@@ -18,14 +18,15 @@
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
namespace boost { namespace geometry
@@ -34,292 +35,63 @@ namespace boost { namespace geometry
namespace strategy { namespace within
{
// 1 deg or pi/180 rad
template <typename Point,
typename CalculationType = typename coordinate_type<Point>::type>
struct winding_small_angle
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
typedef typename coordinate_system<Point>::type cs_t;
typedef math::detail::constants_on_spheroid
template
<
typename Point,
typename PointOfSegment,
typename CalculationType,
typename CSTag = typename tag_cast
<
typename cs_tag<Point>::type,
spherical_tag
>::type
>
struct winding_base_type
{
BOOST_MPL_ASSERT_MSG(false,
NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM,
(CSTag));
};
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, cartesian_tag>
{
typedef within::cartesian_winding<Point, PointOfSegment, CalculationType> type;
};
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
CalculationType,
typename cs_t::units
> constants;
static inline CalculationType apply()
{
return constants::half_period() / CalculationType(180);
}
Point,
PointOfSegment,
typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type,
CalculationType
> type;
};
// Fix for https://svn.boost.org/trac/boost/ticket/9628
// For floating point coordinates, the <D> coordinate of a point is compared
// with the segment's points using some EPS. If the coordinates are "equal"
// the sides are calculated. Therefore we can treat a segment as a long areal
// geometry having some width. There is a small ~triangular area somewhere
// between the segment's effective area and a segment's line used in sides
// calculation where the segment is on the one side of the line but on the
// other side of a segment (due to the width).
// Below picture assuming D = 1, if D = 0 horiz<->vert, E<->N, RIGHT<->UP.
// For the s1 of a segment going NE the real side is RIGHT but the point may
// be detected as LEFT, like this:
// RIGHT
// ___----->
// ^ O Pt __ __
// EPS __ __
// v__ __ BUT DETECTED AS LEFT OF THIS LINE
// _____7
// _____/
// _____/
// In the code below actually D = 0, so segments are nearly-vertical
// Called when the point is on the same level as one of the segment's points
// but the point is not aligned with a vertical segment
template <typename CSTag>
struct winding_side_equal
{
typedef typename strategy::side::services::default_strategy
<
CSTag
>::type strategy_side_type;
template <typename Point, typename PointOfSegment>
static inline int apply(Point const& point,
PointOfSegment const& se,
int count)
{
typedef typename coordinate_type<PointOfSegment>::type scoord_t;
typedef typename coordinate_system<PointOfSegment>::type::units units_t;
if (math::equals(get<1>(point), get<1>(se)))
return 0;
// Create a horizontal segment intersecting the original segment's endpoint
// equal to the point, with the derived direction (E/W).
PointOfSegment ss1, ss2;
set<1>(ss1, get<1>(se));
set<0>(ss1, get<0>(se));
set<1>(ss2, get<1>(se));
scoord_t ss20 = get<0>(se);
if (count > 0)
{
ss20 += winding_small_angle<PointOfSegment>::apply();
}
else
{
ss20 -= winding_small_angle<PointOfSegment>::apply();
}
math::normalize_longitude<units_t>(ss20);
set<0>(ss2, ss20);
// Check the side using this vertical segment
return strategy_side_type::apply(ss1, ss2, point);
}
};
// The optimization for cartesian
template <>
struct winding_side_equal<cartesian_tag>
{
template <typename Point, typename PointOfSegment>
static inline int apply(Point const& point,
PointOfSegment const& se,
int count)
{
// NOTE: for D=0 the signs would be reversed
return math::equals(get<1>(point), get<1>(se)) ?
0 :
get<1>(point) < get<1>(se) ?
// assuming count is equal to 1 or -1
-count : // ( count > 0 ? -1 : 1) :
count; // ( count > 0 ? 1 : -1) ;
}
};
template <typename Point,
typename CalculationType,
typename CSTag = typename cs_tag<Point>::type>
struct winding_check_touch
{
typedef CalculationType calc_t;
typedef typename coordinate_system<Point>::type::units units_t;
typedef math::detail::constants_on_spheroid<CalculationType, units_t> constants;
template <typename PointOfSegment, typename State>
static inline int apply(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
State& state,
bool& eq1,
bool& eq2)
{
calc_t const pi = constants::half_period();
calc_t const pi2 = pi / calc_t(2);
calc_t const px = get<0>(point);
calc_t const s1x = get<0>(seg1);
calc_t const s2x = get<0>(seg2);
calc_t const py = get<1>(point);
calc_t const s1y = get<1>(seg1);
calc_t const s2y = get<1>(seg2);
// NOTE: lat in {-90, 90} and arbitrary lon
// it doesn't matter what lon it is if it's a pole
// so e.g. if one of the segment endpoints is a pole
// then only the other lon matters
bool eq1_strict = math::equals(s1x, px);
bool eq2_strict = math::equals(s2x, px);
eq1 = eq1_strict // lon strictly equal to s1
|| math::equals(s1y, pi2) || math::equals(s1y, -pi2); // s1 is pole
eq2 = eq2_strict // lon strictly equal to s2
|| math::equals(s2y, pi2) || math::equals(s2y, -pi2); // s2 is pole
// segment overlapping pole
calc_t s1x_anti = s1x + constants::half_period();
math::normalize_longitude<units_t, calc_t>(s1x_anti);
bool antipodal = math::equals(s2x, s1x_anti);
if (antipodal)
{
eq1 = eq2 = eq1 || eq2;
// segment overlapping pole and point is pole
if (math::equals(py, pi2) || math::equals(py, -pi2))
{
eq1 = eq2 = true;
}
}
// Both equal p -> segment vertical
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
{
// segment endpoints on the same sides of the globe
if (! antipodal
// p's lat between segment endpoints' lats
? (s1y <= py && s2y >= py) || (s2y <= py && s1y >= py)
// going through north or south pole?
: (pi - s1y - s2y <= pi
? (eq1_strict && s1y <= py) || (eq2_strict && s2y <= py) // north
|| math::equals(py, pi2) // point on north pole
: (eq1_strict && s1y >= py) || (eq2_strict && s2y >= py)) // south
|| math::equals(py, -pi2) // point on south pole
)
{
state.m_touches = true;
}
return true;
}
return false;
}
};
// The optimization for cartesian
template <typename Point, typename CalculationType>
struct winding_check_touch<Point, CalculationType, cartesian_tag>
{
typedef CalculationType calc_t;
template <typename PointOfSegment, typename State>
static inline bool apply(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
State& state,
bool& eq1,
bool& eq2)
{
calc_t const px = get<0>(point);
calc_t const s1x = get<0>(seg1);
calc_t const s2x = get<0>(seg2);
eq1 = math::equals(s1x, px);
eq2 = math::equals(s2x, px);
// Both equal p -> segment vertical
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
{
calc_t const py = get<1>(point);
calc_t const s1y = get<1>(seg1);
calc_t const s2y = get<1>(seg2);
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
{
state.m_touches = true;
}
return true;
}
return false;
}
};
// Called if point is not aligned with a vertical segment
template <typename Point,
typename CalculationType,
typename CSTag = typename cs_tag<Point>::type>
struct winding_calculate_count
{
typedef CalculationType calc_t;
typedef typename coordinate_system<Point>::type::units units_t;
static inline bool greater(calc_t const& l, calc_t const& r)
{
calc_t diff = l - r;
math::normalize_longitude<units_t, calc_t>(diff);
return diff > calc_t(0);
}
static inline int apply(calc_t const& p,
calc_t const& s1, calc_t const& s2,
bool eq1, bool eq2)
{
// Probably could be optimized by avoiding normalization for some comparisons
// e.g. s1 > p could be calculated from p > s1
// If both segment endpoints were poles below checks wouldn't be enough
// but this means that either both are the same or that they are N/S poles
// and therefore the segment is not valid.
// If needed (eq1 && eq2 ? 0) could be returned
return
eq1 ? (greater(s2, p) ? 1 : -1) // Point on level s1, E/W depending on s2
: eq2 ? (greater(s1, p) ? -1 : 1) // idem
: greater(p, s1) && greater(s2, p) ? 2 // Point between s1 -> s2 --> E
: greater(p, s2) && greater(s1, p) ? -2 // Point between s2 -> s1 --> W
: 0;
}
};
// The optimization for cartesian
template <typename Point, typename CalculationType>
struct winding_calculate_count<Point, CalculationType, cartesian_tag>
{
typedef CalculationType calc_t;
static inline int apply(calc_t const& p,
calc_t const& s1, calc_t const& s2,
bool eq1, bool eq2)
{
return
eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W
: 0;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Within detection using winding rule
\brief Within detection using winding rule. Side strategy used internally is
choosen based on Point's coordinate system.
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam SideStrategy Side strategy
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
\note but totally revised afterwards, especially for cases on segments
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
\qbk{
[heading See also]
@@ -330,199 +102,32 @@ template
<
typename Point,
typename PointOfSegment = Point,
typename SideStrategy = typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type,
typename CalculationType = void
>
class winding
{
typedef typename select_calculation_type
: public within::detail::winding_base_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
public :
friend class winding;
template <typename P, typename CT, typename CST>
friend struct winding_check_touch;
inline counter()
: m_count(0)
, m_touches(false)
{}
};
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state, bool& eq1, bool& eq2)
{
if (winding_check_touch<Point, calculation_type>
::apply(point, seg1, seg2, state, eq1, eq2))
{
return 0;
}
calculation_type const p = get<0>(point);
calculation_type const s1 = get<0>(seg1);
calculation_type const s2 = get<0>(seg2);
return winding_calculate_count<Point, calculation_type>
::apply(p, s1, s2, eq1, eq2);
}
Point, PointOfSegment, CalculationType
>::type
{
typedef typename within::detail::winding_base_type
<
Point, PointOfSegment, CalculationType
>::type base_t;
public:
winding()
winding() {}
template <typename Model>
explicit winding(Model const& model)
: base_t(model)
{}
explicit winding(SideStrategy const& side_strategy)
: m_side_strategy(side_strategy)
{}
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state) const
{
typedef typename cs_tag<Point>::type cs_t;
bool eq1 = false;
bool eq2 = false;
boost::ignore_unused(eq2);
int count = check_segment(point, s1, s2, state, eq1, eq2);
if (count != 0)
{
int side = 0;
if (count == 1 || count == -1)
{
side = winding_side_equal<cs_t>::apply(point, eq1 ? s1 : s2, count);
}
else // count == 2 || count == -2
{
// 1 left, -1 right
side = m_side_strategy.apply(s1, s2, point);
}
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for down, 2 for up (or -1/1)
// Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * count > 0)
{
state.m_count += count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.code();
}
private:
SideStrategy m_side_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry

View File

@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -14,35 +15,76 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area { namespace services
namespace strategy { namespace area
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// If user specified a CalculationType, use that type, whatever it is
// and whatever the Geometry is.
// Else, use Geometry's coordinate-type promoted to double if needed.
template
<
typename Geometry,
typename CalculationType
>
struct result_type
{
typedef CalculationType type;
};
template
<
typename Geometry
>
struct result_type<Geometry, void>
: select_most_precise
<
typename coordinate_type<Geometry>::type,
double
>
{};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
namespace services
{
/*!
\brief Traits class binding a default area strategy to a coordinate system
\ingroup area
\tparam Tag tag of coordinate system
\tparam PointOfSegment point-type
*/
template <typename Tag, typename PointOfSegment>
template <typename Tag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE
, (types<PointOfSegment>)
false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM
, (types<Tag>)
);
};
}}} // namespace strategy::area::services
} // namespace services
}} // namespace strategy::area
}} // namespace boost::geometry

View File

@@ -0,0 +1,116 @@
// Boost.Geometry
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// 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_AREA_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/select_sequence_element.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/variant/variant_fwd.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of area function
\ingroup area
\note The return-type is defined by Geometry and Strategy
*/
template
<
typename Geometry,
typename Strategy = default_strategy
>
struct area_result
: Strategy::template result_type<Geometry>
{};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>
struct area_result<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy>
: geometry::area_result
<
typename geometry::util::select_sequence_element
<
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
>::type,
Strategy
>
{};
template <typename Geometry>
struct area_result<Geometry, default_strategy>
: geometry::area_result
<
Geometry,
typename geometry::strategy::area::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type
>
{};
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace area
{
template <typename Curr, typename Next>
struct pred_more_precise_default_area_result
{
typedef typename geometry::area_result<Curr, default_strategy>::type curr_result_t;
typedef typename geometry::area_result<Next, default_strategy>::type next_result_t;
typedef typename boost::mpl::if_c
<
boost::is_same
<
curr_result_t,
typename geometry::select_most_precise
<
curr_result_t,
next_result_t
>::type
>::value,
Curr,
Next
>::type type;
};
}} // namespace detail::area
#endif //DOXYGEN_NO_DETAIL
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct area_result<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, default_strategy>
: geometry::area_result
<
typename geometry::util::select_sequence_element
<
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
geometry::detail::area::pred_more_precise_default_area_result
>::type,
default_strategy
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP

View File

@@ -0,0 +1,147 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016, 2017, 2018.
// Modifications copyright (c) 2016-2018, Oracle and/or its affiliates.
// 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.
// 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_CARTESIAN_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP
#include <boost/mpl/if.hpp>
//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Cartesian area calculation
\ingroup strategies
\details Calculates cartesian area using the trapezoidal rule
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class cartesian
{
public :
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
Geometry,
CalculationType
>
{};
template <typename Geometry>
class state
{
friend class cartesian;
typedef typename result_type<Geometry>::type return_type;
public:
inline state()
: sum(0)
{
// Strategy supports only 2D areas
assert_dimension<Geometry, 2>();
}
private:
inline return_type area() const
{
return_type const two = 2;
return sum / two;
}
return_type sum;
};
template <typename PointOfSegment, typename Geometry>
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
state<Geometry>& st)
{
typedef typename state<Geometry>::return_type return_type;
// Below formulas are equivalent, however the two lower ones
// suffer less from accuracy loss for great values of coordinates.
// See: https://svn.boost.org/trac/boost/ticket/11928
// SUM += x2 * y1 - x1 * y2;
// state.sum += detail::determinant<return_type>(p2, p1);
// SUM += (x2 - x1) * (y2 + y1)
//state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
// * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
// SUM += (x1 + x2) * (y1 - y2)
st.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
}
template <typename Geometry>
static inline typename result_type<Geometry>::type
result(state<Geometry>& st)
{
return st.area();
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::area::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP

View File

@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016, 2017.
// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
@@ -20,133 +21,9 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
#include <boost/mpl/if.hpp>
//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Area calculation for cartesian points
\ingroup strategies
\details Calculates area using the Surveyor's formula, a well-known
triangulation algorithm
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename PointOfSegment,
typename CalculationType = void
>
class surveyor
{
public :
// If user specified a calculation type, use that type,
// whatever it is and whatever the point-type is.
// Else, use the pointtype, but at least double
typedef typename
boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
typename select_most_precise
<
typename coordinate_type<PointOfSegment>::type,
double
>::type,
CalculationType
>::type return_type;
private :
class summation
{
friend class surveyor;
return_type sum;
public :
inline summation() : sum(return_type())
{
// Strategy supports only 2D areas
assert_dimension<PointOfSegment, 2>();
}
inline return_type area() const
{
return_type result = sum;
return_type const two = 2;
result /= two;
return result;
}
};
public :
typedef summation state_type;
typedef PointOfSegment segment_point_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
summation& state)
{
// Below formulas are equivalent, however the two lower ones
// suffer less from accuracy loss for great values of coordinates.
// See: https://svn.boost.org/trac/boost/ticket/11928
// SUM += x2 * y1 - x1 * y2;
// state.sum += detail::determinant<return_type>(p2, p1);
// SUM += (x2 - x1) * (y2 + y1)
//state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
// * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
// SUM += (x1 + x2) * (y1 - y2)
state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
}
static inline return_type result(summation const& state)
{
return state.area();
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point>
struct default_strategy<cartesian_tag, Point>
{
typedef strategy::area::surveyor<Point> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
// keep this file for now, for backward compatibility
// functionality-wise, make it equivalent to boost/geometry/strategies/cartesian/area.hpp
#include <boost/geometry/strategies/cartesian/area.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// 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
@@ -13,6 +13,8 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
namespace boost { namespace geometry
{

View File

@@ -2,6 +2,11 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,16 +14,13 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
namespace boost { namespace geometry
{

View File

@@ -2,10 +2,11 @@
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2018.
// Modifications copyright (c) 2015, 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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
@@ -16,12 +17,15 @@
#include <cstddef>
#include <boost/range.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
@@ -46,6 +50,7 @@ namespace strategy { namespace buffer
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_point_square point_square]
\* [link geometry.reference.strategies.strategy_buffer_geographic_point_circle geographic_point_circle]
}
*/
class point_circle

View File

@@ -1,5 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,12 +16,11 @@
#include <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -39,6 +45,7 @@ namespace strategy { namespace buffer
[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_geographic_point_circle geographic_point_circle]
}
*/
class point_square

View File

@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
@@ -23,6 +24,7 @@
#include <cstddef>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -53,7 +55,7 @@ private :
class sum
{
friend class average;
std::size_t count;
signed_size_type count;
PointCentroid centroid;
public :

View File

@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2018.
// Modifications copyright (c) 2015, 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -31,6 +31,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>

View File

@@ -0,0 +1,134 @@
// 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_CARTESIAN_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of cartesian segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class cartesian
{
public:
template <typename Point, typename AssignPolicy, typename T>
static inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold)
{
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 model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t;
calc_point_t cp0, cp1;
geometry::detail::conversion::convert_point_to_point(p0, cp0);
geometry::detail::conversion::convert_point_to_point(p1, cp1);
// dir01 = xy1 - xy0
calc_point_t dir01 = cp1;
geometry::subtract_point(dir01, cp0);
calc_t const dot01 = geometry::dot_product(dir01, dir01);
calc_t const len = math::sqrt(dot01);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(len / length_threshold);
if (n <= 0)
{
return;
}
// NOTE: Normalization will not work for integral coordinates
// normalize
//geometry::divide_value(dir01, len);
calc_t step = len / (n + 1);
calc_t d = step;
for (signed_size_type i = 0 ; i < n ; ++i, d += step)
{
// pd = xy0 + d * dir01
calc_point_t pd = dir01;
// without normalization
geometry::multiply_value(pd, calc_t(i + 1));
geometry::divide_value(pd, calc_t(n + 1));
// with normalization
//geometry::multiply_value(pd, d);
geometry::add_point(pd, cp0);
// NOTE: Only needed if types calc_point_t and out_point_t are different
// otherwise pd could simply be passed into policy
out_point_t p;
assert_dimension_equal<calc_point_t, out_point_t>();
geometry::detail::conversion::convert_point_to_point(pd, p);
policy.apply(p);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::densify::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP

View File

@@ -0,0 +1,112 @@
// 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) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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.
// 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_CARTESIAN_DISJOINT_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Box1, typename Box2,
std::size_t Dimension = 0,
std::size_t DimensionCount = dimension<Box1>::value
>
struct box_box
{
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
{
return true;
}
if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
{
return true;
}
return box_box
<
Box1, Box2,
Dimension + 1, DimensionCount
>::apply(box1, box2);
}
};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, DimensionCount, DimensionCount>
{
static inline bool apply(Box1 const& , Box2 const& )
{
return false;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct cartesian_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return detail::box_box<Box1, Box2>::apply(box1, box2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Box1, typename Box2, int TopDim1, int TopDim2>
struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, cartesian_tag, cartesian_tag>
{
typedef disjoint::cartesian_box_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP

View File

@@ -8,8 +8,9 @@
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -293,16 +294,14 @@ struct segment_box
namespace services
{
// Currently used in all coordinate systems
template <typename Linear, typename Box, typename LinearTag>
struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2>
struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
template <typename Box, typename Linear, typename LinearTag>
struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1>
struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};

View File

@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, 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 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.
@@ -21,6 +22,7 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_void.hpp>
@@ -35,6 +37,7 @@
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
@@ -75,6 +78,8 @@ template
class projected_point
{
public :
typedef within::cartesian_point_point equals_point_point_strategy_type;
// The three typedefs below are necessary to calculate distances
// from segments defined in integer coordinates.
@@ -94,8 +99,6 @@ public :
>
{};
public :
template <typename Point, typename PointOfSegment>
inline typename calculation_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
@@ -137,7 +140,7 @@ public :
subtract_point(w, projected);
Strategy strategy;
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
calculation_type const zero = calculation_type();
calculation_type const c1 = dot_product(w, v);
@@ -159,6 +162,13 @@ public :
return strategy.apply(p, projected);
}
template <typename CT>
inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
{
return lat1 - lat2;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

View File

@@ -24,6 +24,7 @@
#include <algorithm>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -194,7 +195,7 @@ public :
subtract_point(w, projected);
Strategy strategy;
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
typename result_type<Point, PointOfSegment>::type result;

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// 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.
@@ -17,6 +22,8 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>

View File

@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, 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 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.
@@ -21,6 +22,9 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -29,7 +33,6 @@
namespace boost { namespace geometry
{

View File

@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, 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 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.
@@ -21,6 +22,9 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>

View File

@@ -0,0 +1,203 @@
// 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_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
struct cartesian_segment_box
{
template <typename PointOfSegment, typename PointOfBox>
struct calculation_type
: promote_floating_point
<
typename strategy::distance::services::return_type
<
Strategy,
PointOfSegment,
PointOfBox
>::type
>
{};
// point-point strategy getters
struct distance_pp_strategy
{
typedef Strategy type;
};
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
{
return typename distance_pp_strategy::type();
}
// point-segment strategy getters
struct distance_ps_strategy
{
typedef projected_point<CalculationType, Strategy> type;
};
inline typename distance_ps_strategy::type get_distance_ps_strategy() const
{
return typename distance_ps_strategy::type();
}
typedef within::cartesian_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();
}
template <typename LessEqual, typename ReturnType,
typename SegmentPoint, typename BoxPoint>
inline ReturnType segment_below_of_box(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const&,
BoxPoint const&,
BoxPoint const&,
BoxPoint const& bottom_right) const
{
return geometry::detail::distance::segment_to_box_2D
<
ReturnType,
SegmentPoint,
BoxPoint,
cartesian_segment_box<CalculationType, Strategy>
>::template call_above_of_box
<
typename LessEqual::other
>(p1, p0, bottom_right, *this);
}
template <typename SPoint, typename BPoint>
static void mirror(SPoint&,
SPoint&,
BPoint&,
BPoint&,
BPoint&,
BPoint&)
{}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<cartesian_segment_box<CalculationType, Strategy> >
{
typedef strategy_tag_distance_segment_box type;
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct return_type<cartesian_segment_box<CalculationType, Strategy>, PS, PB>
: cartesian_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<cartesian_segment_box<CalculationType, Strategy> >
{
// Define a cartesian_segment_box strategy with its underlying point-point
// strategy being comparable
typedef cartesian_segment_box
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<cartesian_segment_box<CalculationType, Strategy> >
{
typedef typename comparable_type
<
cartesian_segment_box<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(cartesian_segment_box<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct result_from_distance<cartesian_segment_box<CalculationType, Strategy>, PS, PB>
{
private :
typedef typename return_type<
cartesian_segment_box
<
CalculationType,
Strategy
>,
PS,
PB
>::type return_type;
public :
template <typename T>
static inline return_type apply(cartesian_segment_box<CalculationType,
Strategy> const& ,
T const& value)
{
Strategy s;
return result_from_distance<Strategy, PS, PB>::apply(s, value);
}
};
template <typename Segment, typename Box>
struct default_strategy
<
segment_tag, box_tag, Segment, Box,
cartesian_tag, cartesian_tag
>
{
typedef cartesian_segment_box<> type;
};
template <typename Box, typename Segment>
struct default_strategy
<
box_tag, segment_tag, Box, Segment,
cartesian_tag, cartesian_tag
>
{
typedef typename default_strategy
<
segment_tag, box_tag, Segment, Box,
cartesian_tag, cartesian_tag
>::type type;
};
}
#endif
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP

View File

@@ -0,0 +1,153 @@
// 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.
// 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
// 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_CARTESIAN_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template <typename CalculationType = void>
class cartesian
{
public:
typedef cartesian_point element_envelope_strategy_type;
static inline element_envelope_strategy_type get_element_envelope_strategy()
{
return element_envelope_strategy_type();
}
typedef expand::cartesian_point element_expand_strategy_type;
static inline element_expand_strategy_type get_element_expand_strategy()
{
return element_expand_strategy_type();
}
typedef expand::cartesian_box box_expand_strategy_type;
static inline box_expand_strategy_type get_box_expand_strategy()
{
return box_expand_strategy_type();
}
// Linestring, Ring, Polygon
template <typename Range>
static inline typename boost::range_iterator<Range const>::type begin(Range const& range)
{
return boost::begin(range);
}
template <typename Range>
static inline typename boost::range_iterator<Range const>::type end(Range const& range)
{
return boost::end(range);
}
// MultiLinestring, MultiPolygon
template <typename Box>
struct multi_state
{
multi_state()
: m_initialized(false)
{}
void apply(Box const& single_box)
{
if (! m_initialized)
{
m_box = single_box;
m_initialized = true;
}
else
{
box_expand_strategy_type::apply(m_box, single_box);
}
}
void result(Box & box)
{
if (m_initialized)
{
box = m_box;
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
private:
bool m_initialized;
Box m_box;
};
// Segment
template <typename Point1, typename Point2, typename Box>
static inline void apply(Point1 const& point1, Point2 const& point2,
Box& box)
{
cartesian_segment<CalculationType>::apply(point1, point2, box);
}
// Box
template <typename BoxIn, typename Box>
static inline void apply(BoxIn const& box_in, Box& box)
{
cartesian_box::apply(box_in, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP

View File

@@ -0,0 +1,119 @@
// 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-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_CARTESIAN_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
std::size_t Index,
std::size_t Dimension,
std::size_t DimensionCount
>
struct envelope_indexed_box
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
Dimension,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace envelope
{
struct cartesian_box
{
template<typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
geometry::detail::envelope::envelope_indexed_box
<
min_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
geometry::detail::envelope::envelope_indexed_box
<
max_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_box type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,59 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018, Oracle and/or its affiliates.
// 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_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/strategies/cartesian/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class cartesian_multipoint
{
public:
template <typename MultiPoint, typename Box>
static inline void apply(MultiPoint const& multipoint, Box& mbr)
{
geometry::detail::envelope::envelope_range::apply(multipoint, mbr, cartesian<>());
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<multi_point_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_multipoint type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,111 @@
// 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, 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_CARTESIAN_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_point
{
template <std::size_t Index, typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
detail::indexed_point_view<Box, Index> box_corner(mbr);
detail::conversion::point_to_point
<
Point,
detail::indexed_point_view<Box, Index>,
Dimension,
DimensionCount
>::apply(point, box_corner);
}
template <typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace envelope
{
struct cartesian_point
{
template <typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
geometry::detail::envelope::envelope_one_point
<
0, dimension<Point>::value
>::apply(point, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_point type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_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
@@ -11,39 +11,61 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
#include <boost/geometry/strategies/cartesian/expand_point.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
namespace boost { namespace geometry { namespace strategy { namespace envelope
{
namespace strategy { namespace envelope
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_segment
{
template<typename Point, typename Box>
static inline void apply(Point const& p1,
Point const& p2,
Box& mbr)
{
geometry::detail::envelope::envelope_one_point
<
Dimension, DimensionCount
>::apply(p1, mbr);
strategy::expand::detail::point_loop
<
Dimension, DimensionCount
>::apply(mbr, p2);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class cartesian_segment
{
public :
template <typename Point1, typename Point2, typename Box>
inline void
apply(Point1 const& point1, Point2 const& point2, Box& box) const
public:
template <typename Point, typename Box>
static inline void apply(Point const& point1, Point const& point2, Box& box)
{
geometry::detail::envelope::envelope_one_segment
<
0,
dimension<Point1>::value
>
::apply(point1,
point2,
box,
strategy::envelope::cartesian_segment<CalculationType>());
strategy::envelope::detail::envelope_one_segment
<
0,
dimension<Point>::value
>::apply(point1, point2, box);
}
};
@@ -54,7 +76,7 @@ namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_segment<CalculationType> type;
};

View File

@@ -0,0 +1,69 @@
// 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.
// Modifications copyright (c) 2015-2017, 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_CARTESIAN_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/strategies/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
struct cartesian_box
{
template <typename BoxOut, typename BoxIn>
static void apply(BoxOut & box_out, BoxIn const& box_in)
{
geometry::detail::expand::expand_indexed
<
0, dimension<BoxIn>::value
>::apply(box_out, box_in);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, cartesian_tag, CalculationType>
{
typedef cartesian_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP

View File

@@ -0,0 +1,125 @@
// 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-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
// 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_CARTESIAN_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_loop
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& source)
{
typedef typename select_coordinate_type
<
Point, Box
>::type coordinate_type;
std::less<coordinate_type> less;
std::greater<coordinate_type> greater;
coordinate_type const coord = get<Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
point_loop<Dimension + 1, DimensionCount>::apply(box, source);
}
};
template <std::size_t DimensionCount>
struct point_loop<DimensionCount, DimensionCount>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct cartesian_point
{
template <typename Box, typename Point>
static void apply(Box & box, Point const& point)
{
expand::detail::point_loop
<
0, dimension<Point>::value
>::apply(box, point);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, cartesian_tag, CalculationType>
{
typedef cartesian_point type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP

View File

@@ -0,0 +1,71 @@
// 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_CARTESIAN_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/strategies/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
class cartesian_segment
{
public:
template <typename Box, typename Segment>
static void apply(Box & box, Segment const& segment)
{
geometry::detail::expand::expand_indexed
<
0, dimension<Segment>::value
>::apply(box, segment);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
{
typedef cartesian_segment type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP

View File

@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2016, 2017.
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2016, 2017, 2018, 2019.
// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,9 +33,15 @@
#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
#include <boost/geometry/strategies/cartesian/area.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/envelope.hpp>
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -80,11 +86,10 @@ struct cartesian_segments
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::winding
typedef strategy::within::cartesian_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
side_strategy_type,
CalculationType
> type;
};
@@ -103,9 +108,8 @@ struct cartesian_segments
template <typename Geometry>
struct area_strategy
{
typedef area::surveyor
typedef area::cartesian
<
typename point_type<Geometry>::type,
CalculationType
> type;
};
@@ -133,9 +137,55 @@ struct cartesian_segments
return strategy_type();
}
typedef envelope::cartesian<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
typedef expand::cartesian_segment expand_strategy_type;
static inline expand_strategy_type get_expand_strategy()
{
return expand_strategy_type();
}
typedef within::cartesian_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::cartesian_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::cartesian_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 disjoint_segment_box_strategy_type;
static inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy()
{
return disjoint_segment_box_strategy_type();
}
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
typedef expand::cartesian_box expand_box_strategy_type;
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
{
private :
typedef typename select_most_precise
<
CoordinateType, double
@@ -190,6 +240,45 @@ struct cartesian_segments
>(numerator * dy_promoted / denominator));
}
public :
template <typename Point, typename Segment1, typename Segment2>
void calculate(Point& point, Segment1 const& a, Segment2 const& b) const
{
bool use_a = true;
// Prefer one segment if one is on or near an endpoint
bool const a_near_end = robust_ra.near_end();
bool const b_near_end = robust_rb.near_end();
if (a_near_end && ! b_near_end)
{
use_a = true;
}
else if (b_near_end && ! a_near_end)
{
use_a = false;
}
else
{
// Prefer shorter segment
promoted_type const len_a = comparable_length_a();
promoted_type const len_b = comparable_length_b();
if (len_b < len_a)
{
use_a = false;
}
// else use_a is true but was already assigned like that
}
if (use_a)
{
assign_a(point, a, b);
}
else
{
assign_b(point, a, b);
}
}
CoordinateType dx_a, dy_a;
CoordinateType dx_b, dy_b;
SegmentRatio robust_ra;
@@ -267,12 +356,12 @@ struct cartesian_segments
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
using geometry::detail::equals::equals_point_point;
bool const a_is_point = equals_point_point(robust_a1, robust_a2);
bool const b_is_point = equals_point_point(robust_b1, robust_b2);
bool const a_is_point = equals_point_point(robust_a1, robust_a2, point_in_point_strategy_type());
bool const b_is_point = equals_point_point(robust_b1, robust_b2, point_in_point_strategy_type());
if(a_is_point && b_is_point)
{
return equals_point_point(robust_a1, robust_b2)
return equals_point_point(robust_a1, robust_b2, point_in_point_strategy_type())
? Policy::degenerate(a, true)
: Policy::disjoint()
;

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_CARTESIAN_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_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/strategies/line_interpolate.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace line_interpolate
{
/*!
\brief Interpolate point on a cartesian segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\tparam DistanceStrategy The underlying point-point distance strategy
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename DistanceStrategy = distance::pythagoras<CalculationType>
>
class cartesian
{
public:
// point-point strategy getters
struct distance_pp_strategy
{
typedef DistanceStrategy type;
};
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
{
typedef typename distance_pp_strategy::type distance_type;
return distance_type();
}
template <typename Point, typename Fraction, typename Distance>
inline void apply(Point const& p0,
Point const& p1,
Fraction const& fraction,
Point & p,
Distance const&) const
{
typedef typename select_calculation_type_alt
<
CalculationType,
Point
>::type calc_t;
typedef model::point
<
calc_t,
geometry::dimension<Point>::value,
cs::cartesian
> calc_point_t;
calc_point_t cp0, cp1;
geometry::detail::conversion::convert_point_to_point(p0, cp0);
geometry::detail::conversion::convert_point_to_point(p1, cp1);
//segment convex combination: p0*fraction + p1*(1-fraction)
Fraction const one_minus_fraction = 1-fraction;
for_each_coordinate(cp1, detail::value_operation
<
Fraction,
std::multiplies
>(fraction));
for_each_coordinate(cp0, detail::value_operation
<
Fraction,
std::multiplies
>(one_minus_fraction));
for_each_coordinate(cp1, detail::point_operation
<
calc_point_t,
std::plus
>(cp0));
assert_dimension_equal<calc_point_t, Point>();
geometry::detail::conversion::convert_point_to_point(cp1, p);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::line_interpolate::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::line_interpolate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP

View File

@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2017.
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015-2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
@@ -33,6 +34,10 @@ namespace boost { namespace geometry { namespace strategy
namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct within_coord
{
template <typename Value1, typename Value2>
@@ -101,7 +106,7 @@ struct longitude_range
<
Value1, Value2
>::type calc_t;
typedef typename coordinate_system<Geometry>::type::units units_t;
typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
if (CoordCheck::apply(value, min_value, max_value))
@@ -142,18 +147,16 @@ struct covered_by_range<Geometry, 0, spherical_tag>
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename Point,
typename Box,
typename CSTag, // cartesian_tag or spherical_tag
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_point_box_loop
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t;
if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point),
if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point),
get<min_corner, Dimension>(box),
get<max_corner, Dimension>(box))
)
@@ -164,7 +167,7 @@ struct relate_point_box_loop
return relate_point_box_loop
<
SubStrategy,
Point, Box,
CSTag,
Dimension + 1, DimensionCount
>::apply(point, box);
}
@@ -174,78 +177,119 @@ struct relate_point_box_loop
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename Point,
typename Box,
typename CSTag,
std::size_t DimensionCount
>
struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount>
struct relate_point_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
{
template <typename Point, typename Box>
static inline bool apply(Point const& , Box const& )
{
return true;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename Point,
typename Box,
template <typename, std::size_t, typename> class SubStrategy = within_range
>
struct point_in_box
struct cartesian_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return relate_point_box_loop
return detail::relate_point_box_loop
<
SubStrategy,
Point, Box,
0, dimension<Point>::type::value
detail::within_range,
cartesian_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
struct spherical_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return detail::relate_point_box_loop
<
detail::within_range,
spherical_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef within::cartesian_point_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef within::spherical_point_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace within
namespace covered_by
{
struct cartesian_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return within::detail::relate_point_box_loop
<
within::detail::covered_by_range,
cartesian_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
struct spherical_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return within::detail::relate_point_box_loop
<
within::detail::covered_by_range,
spherical_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace within { namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box<Point, Box> type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef within::point_in_box<Point, Box> type;
};
}} // namespace within::services
namespace covered_by { namespace services
namespace services
{
@@ -258,11 +302,7 @@ struct default_strategy
cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box
<
Point, Box,
within::covered_by_range
> type;
typedef covered_by::cartesian_point_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
@@ -275,20 +315,17 @@ struct default_strategy
spherical_tag, spherical_tag
>
{
typedef within::point_in_box
<
Point, Box,
within::covered_by_range
> type;
typedef covered_by::spherical_point_box type;
};
}} // namespace covered_by::services
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace covered_by
}}} // namespace boost::geometry::strategy

View File

@@ -0,0 +1,124 @@
// 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) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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.
// 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_CARTESIAN_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_point_generic
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return false;
}
return
point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
}
};
template <std::size_t DimensionCount>
struct point_point_generic<DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const&, Point2 const& )
{
return true;
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace within
{
struct cartesian_point_point
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
return geometry::detail::within::point_point_generic
<
0, dimension<Point1>::type::value
>::apply(point1, point2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::cartesian_point_point type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::cartesian_point_point type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// 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.
@@ -15,6 +20,7 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// 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.
@@ -15,6 +20,7 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>

View File

@@ -0,0 +1,310 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// 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.
// 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_CARTESIAN_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using winding rule in cartesian coordinate system.
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class cartesian_winding
{
typedef side::side_by_triangle<CalculationType> side_strategy_type;
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
public :
friend class cartesian_winding;
inline counter()
: m_count(0)
, m_touches(false)
{}
};
public:
typedef typename side_strategy_type::envelope_strategy_type envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return side_strategy_type::get_envelope_strategy();
}
typedef typename side_strategy_type::disjoint_strategy_type disjoint_strategy_type;
static inline disjoint_strategy_type get_disjoint_strategy()
{
return side_strategy_type::get_disjoint_strategy();
}
typedef typename side_strategy_type::equals_point_point_strategy_type equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
{
return side_strategy_type::get_equals_point_point_strategy();
}
typedef disjoint::cartesian_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 covered_by::cartesian_point_box disjoint_point_box_strategy_type;
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
static inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state)
{
bool eq1 = false;
bool eq2 = false;
int count = check_segment(point, s1, s2, state, eq1, eq2);
if (count != 0)
{
int side = 0;
if (count == 1 || count == -1)
{
side = side_equal(point, eq1 ? s1 : s2, count);
}
else // count == 2 || count == -2
{
// 1 left, -1 right
side = side_strategy_type::apply(s1, s2, point);
}
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for left, 2 for right (or -1/1)
// Side positive thus means RIGHT and LEFTSIDE or LEFT and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * count > 0)
{
state.m_count += count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.code();
}
private:
static inline int check_segment(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2)
{
if (check_touch(point, seg1, seg2, state, eq1, eq2))
{
return 0;
}
return calculate_count(point, seg1, seg2, eq1, eq2);
}
static inline bool check_touch(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2)
{
calculation_type const px = get<0>(point);
calculation_type const s1x = get<0>(seg1);
calculation_type const s2x = get<0>(seg2);
eq1 = math::equals(s1x, px);
eq2 = math::equals(s2x, px);
// Both equal p -> segment vertical
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
{
calculation_type const py = get<1>(point);
calculation_type const s1y = get<1>(seg1);
calculation_type const s2y = get<1>(seg2);
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
{
state.m_touches = true;
}
return true;
}
return false;
}
static inline int calculate_count(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
bool eq1, bool eq2)
{
calculation_type const p = get<0>(point);
calculation_type const s1 = get<0>(seg1);
calculation_type const s2 = get<0>(seg2);
return eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W
: 0;
}
static inline int side_equal(Point const& point,
PointOfSegment const& se,
int count)
{
// NOTE: for D=0 the signs would be reversed
return math::equals(get<1>(point), get<1>(se)) ?
0 :
get<1>(point) < get<1>(se) ?
// assuming count is equal to 1 or -1
-count : // ( count > 0 ? -1 : 1) :
count; // ( count > 0 ? 1 : -1) ;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef cartesian_winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef cartesian_winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef within::cartesian_winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef within::cartesian_winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP

View File

@@ -4,10 +4,11 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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.
@@ -26,9 +27,13 @@
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/envelope.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
@@ -66,6 +71,25 @@ class side_by_triangle
};
public :
typedef strategy::envelope::cartesian<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
typedef strategy::disjoint::segment_box disjoint_strategy_type;
static inline disjoint_strategy_type get_disjoint_strategy()
{
return disjoint_strategy_type();
}
typedef strategy::within::cartesian_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();
}
// Template member function, because it is not always trivial
// or convenient to explicitly mention the typenames in the
@@ -149,9 +173,9 @@ public :
// For robustness purposes, first check if any two points are
// the same; in this case simply return that the points are
// collinear
if (geometry::detail::equals::equals_point_point(p1, p2)
|| geometry::detail::equals::equals_point_point(p1, p)
|| geometry::detail::equals::equals_point_point(p2, p))
if (equals_point_point(p1, p2)
|| equals_point_point(p1, p)
|| equals_point_point(p2, p))
{
return PromotedType(0);
}
@@ -166,10 +190,11 @@ public :
// arguments, we cyclically permute them so that the first
// argument is always the lexicographically smallest point.
geometry::detail::relate::less less;
if (less(p, p1))
typedef compare::cartesian<compare::less> less;
if (less::apply(p, p1))
{
if (less(p, p2))
if (less::apply(p, p2))
{
// p is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
@@ -181,7 +206,7 @@ public :
}
}
if (less(p1, p2))
if (less::apply(p1, p2))
{
// p1 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
@@ -240,6 +265,13 @@ public :
: -1;
}
private:
template <typename P1, typename P2>
static inline bool equals_point_point(P1 const& p1, P2 const& p2)
{
typedef equals_point_point_strategy_type strategy_t;
return geometry::detail::equals::equals_point_point(p1, p2, strategy_t());
}
};

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2019.
// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -118,6 +118,7 @@ struct multiplicable_integral
return b < a;
}
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
template <typename CmpVal>
void check_value(CmpVal const& cmp_val) const
{
@@ -125,6 +126,7 @@ struct multiplicable_integral
CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls));
BOOST_GEOMETRY_ASSERT(cmp_val == val);
}
#endif // BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
};
} // namespace detail

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
// 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.
@@ -15,155 +20,204 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
#include <cstddef>
#include <functional>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/min.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
/*!
\brief Traits class binding a comparing strategy to a coordinate system
\ingroup util
\tparam Tag tag of coordinate system of point-type
\tparam Direction direction to compare on: 1 for less (-> ascending order)
and -1 for greater (-> descending order)
\tparam Point point-type
\tparam CoordinateSystem coordinate sytem of point
\tparam Dimension: the dimension to compare on
*/
template
<
typename Tag,
int Direction,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare
{
typedef strategy::not_implemented type;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// For compare we add defaults specializations,
// because they defaultly redirect to std::less / greater / equal_to
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, 1, Point, CoordinateSystem, Dimension>
{
typedef std::less<typename coordinate_type<Point>::type> type;
};
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, -1, Point, CoordinateSystem, Dimension>
{
typedef std::greater<typename coordinate_type<Point>::type> type;
};
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, 0, Point, CoordinateSystem, Dimension>
{
typedef std::equal_to<typename coordinate_type<Point>::type> type;
};
#endif
namespace strategy { namespace compare
{
/*!
\brief Default strategy, indicates the default strategy for comparisons
\details The default strategy for comparisons defer in most cases
to std::less (for ascending) and std::greater (for descending).
However, if a spherical coordinate system is used, and comparison
is done on longitude, it will take another strategy handling circular
*/
struct default_strategy {};
struct less
{
template <typename T1, typename T2>
static inline bool apply(T1 const& l, T2 const& r)
{
return l < r;
}
};
struct greater
{
template <typename T1, typename T2>
static inline bool apply(T1 const& l, T2 const& r)
{
return l > r;
}
};
struct equal_to
{
template <typename T1, typename T2>
static inline bool apply(T1 const& , T2 const& )
{
return false;
}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Type>
struct is_default : boost::false_type
{};
template <>
struct is_default<default_strategy> : boost::true_type
{};
/*!
\brief Meta-function to select strategy
\details If "default_strategy" is specified, it will take the
traits-registered class for the specified coordinate system.
If another strategy is explicitly specified, it takes that one.
*/
template
<
typename Strategy,
int Direction,
typename Point,
std::size_t Dimension
typename ComparePolicy,
std::size_t Dimension,
std::size_t DimensionCount
>
struct select_strategy
struct compare_loop
{
typedef typename
boost::mpl::if_
<
is_default<Strategy>,
typename strategy_compare
<
typename cs_tag<Point>::type,
Direction,
Point,
typename coordinate_system<Point>::type,
Dimension
>::type,
Strategy
>::type type;
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
typename geometry::coordinate_type<Point1>::type const&
cleft = geometry::get<Dimension>(left);
typename geometry::coordinate_type<Point2>::type const&
cright = geometry::get<Dimension>(right);
if (math::equals(cleft, cright))
{
return compare_loop
<
ComparePolicy,
Dimension + 1, DimensionCount
>::apply(left, right);
}
else
{
return ComparePolicy::apply(cleft, cright);
}
}
};
template
<
typename ComparePolicy,
std::size_t DimensionCount
>
struct compare_loop<ComparePolicy, DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& , Point2 const& )
{
// On coming here, points are equal.
// Return false for less/greater.
return false;
}
};
template
<
std::size_t DimensionCount
>
struct compare_loop<strategy::compare::equal_to, DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& , Point2 const& )
{
// On coming here, points are equal.
// Return true for equal_to.
return true;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace strategy::compare
template
<
typename ComparePolicy,
int Dimension = -1
>
struct cartesian
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::compare_loop
<
ComparePolicy, Dimension, Dimension + 1
>::apply(left, right);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
template
<
typename ComparePolicy
>
struct cartesian<ComparePolicy, -1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::compare_loop
<
ComparePolicy,
0,
boost::mpl::min
<
geometry::dimension<Point1>,
geometry::dimension<Point2>
>::type::value
>::apply(left, right);
}
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename ComparePolicy,
typename Point1,
typename Point2 = Point1,
int Dimension = -1,
typename CSTag1 = typename cs_tag<Point1>::type,
typename CSTag2 = typename cs_tag<Point2>::type
>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false,
NOT_IMPLEMENTED_FOR_THESE_TYPES,
(types<CSTag1, CSTag2>)
);
};
template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy<ComparePolicy, Point1, Point2, Dimension, cartesian_tag, cartesian_tag>
{
typedef compare::cartesian<ComparePolicy, Dimension> type;
};
} // namespace services
}} // namespace strategy compare
}} // namespace boost::geometry

View File

@@ -3,6 +3,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018 Oracle and/or its affiliates.
// 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.
@@ -16,6 +21,9 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry { namespace concepts
@@ -26,19 +34,16 @@ namespace boost { namespace geometry { namespace concepts
\brief Checks strategy for area
\ingroup area
*/
template <typename Strategy>
template <typename Geometry, typename Strategy>
class AreaStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type,
typedef typename Strategy::state_type state_type;
// 1) must define state template,
typedef typename Strategy::template state<Geometry> state_type;
// 2) must define return_type,
typedef typename Strategy::return_type return_type;
// 3) must define point_type, of polygon (segments)
typedef typename Strategy::segment_point_type spoint_type;
// 2) must define result_type template,
typedef typename Strategy::template result_type<Geometry>::type return_type;
struct check_methods
{
@@ -47,15 +52,14 @@ class AreaStrategy
Strategy const* str = 0;
state_type *st = 0;
// 4) must implement a method apply with the following signature
spoint_type const* sp = 0;
// 3) must implement a method apply with the following signature
typename geometry::point_type<Geometry>::type const* sp = 0;
str->apply(*sp, *sp, *st);
// 5) must implement a static method result with the following signature
// 4) must implement a static method result with the following signature
return_type r = str->result(*st);
boost::ignore_unused_variable_warning(r);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused(r, str);
}
};

View File

@@ -17,7 +17,7 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
namespace boost { namespace geometry { namespace concepts
{
@@ -58,8 +58,7 @@ class CentroidStrategy
point_type *c = 0;
bool r = str->result(*st, *c);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(r);
boost::ignore_unused(str, r);
}
};

View File

@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, 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 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.
@@ -33,6 +34,7 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>

View File

@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018 Oracle and/or its affiliates.
// 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.
@@ -17,8 +21,16 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/box_concept.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/util/parameter_type_of.hpp>
@@ -93,9 +105,7 @@ class WithinStrategyPolygonal
bool b = str->apply(*p, *sp, *sp, *st);
int r = str->result(*st);
boost::ignore_unused_variable_warning(r);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused(r, b, str);
}
};
@@ -108,7 +118,7 @@ public :
#endif
};
template <typename Strategy>
template <typename Point, typename Box, typename Strategy>
class WithinStrategyPointBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
@@ -158,8 +168,7 @@ class WithinStrategyPointBox
bool b = str->apply(*p, *bx);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused(b, str);
}
};
@@ -167,7 +176,7 @@ class WithinStrategyPointBox
public :
BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
{
checker::apply(&Strategy::apply);
checker::apply(&Strategy::template apply<Point, Box>);
}
#endif
};
@@ -222,8 +231,7 @@ class WithinStrategyBoxBox
bool b = str->apply(*b1, *b2);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused(b, str);
}
};
@@ -244,26 +252,36 @@ namespace within
namespace dispatch
{
template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
template
<
typename Geometry1, typename Geometry2,
typename FirstTag, typename SecondTag, typename CastedTag,
typename Strategy
>
struct check_within
{};
template <typename AnyTag, typename Strategy>
struct check_within<point_tag, AnyTag, areal_tag, Strategy>
template
<
typename Geometry1, typename Geometry2,
typename AnyTag,
typename Strategy
>
struct check_within<Geometry1, Geometry2, point_tag, AnyTag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );
};
template <typename Strategy>
struct check_within<point_tag, box_tag, areal_tag, Strategy>
template <typename Geometry1, typename Geometry2, typename Strategy>
struct check_within<Geometry1, Geometry2, point_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) );
BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Geometry1, Geometry2, Strategy>) );
};
template <typename Strategy>
struct check_within<box_tag, box_tag, areal_tag, Strategy>
template <typename Geometry1, typename Geometry2, typename Strategy>
struct check_within<Geometry1, Geometry2, box_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );
};
@@ -277,11 +295,19 @@ struct check_within<box_tag, box_tag, areal_tag, Strategy>
\brief Checks, in compile-time, the concept of any within-strategy
\ingroup concepts
*/
template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
template <typename Geometry1, typename Geometry2, typename Strategy>
inline void check()
{
dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c;
boost::ignore_unused_variable_warning(c);
dispatch::check_within
<
Geometry1,
Geometry2,
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
> c;
boost::ignore_unused(c);
}

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// 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.
@@ -14,6 +19,7 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/tags.hpp>

View File

@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -15,10 +16,7 @@
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/area_result.hpp>
namespace boost { namespace geometry
@@ -33,16 +31,8 @@ namespace boost { namespace geometry
template <typename Geometry>
struct default_area_result
{
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
typedef typename strategy_type::return_type type;
};
: area_result<Geometry>
{};
}} // namespace boost::geometry

View File

@@ -0,0 +1,42 @@
// Boost.Geometry
// Copyright (c) 2017, 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_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_CS
, (types<CSTag>)
);
};
} // namespace services
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP

View File

@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2017, Oracle and/or its affiliates.
// 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,
@@ -37,7 +38,9 @@ template
typename Tag1 = typename geometry::tag<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type,
int TopDim1 = geometry::topological_dimension<Geometry1>::value,
int TopDim2 = geometry::topological_dimension<Geometry2>::value
int TopDim2 = geometry::topological_dimension<Geometry2>::value,
typename CsTag1 = typename cs_tag<Geometry1>::type,
typename CsTag2 = typename cs_tag<Geometry2>::type
>
struct default_strategy
: relate::services::default_strategy
@@ -74,13 +77,6 @@ struct default_strategy<Box, MultiPoint, box_tag, multi_point_tag, 2, 0>
>
{};
template <typename Box1, typename Box2>
struct default_strategy<Box1, Box2, box_tag, box_tag, 2, 2>
{
// dummy strategy which will be ignored
typedef geometry::default_strategy type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// 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
@@ -23,16 +23,17 @@ namespace strategy { namespace envelope { namespace services
/*!
\brief Traits class binding a default envelope strategy to a coordinate system
\ingroup util
\tparam Tag tag of geometry
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
template <typename CSTag, typename CalculationType = void>
template <typename Tag, typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPE
, (types<CSTag>)
, (types<Tag, CSTag>)
);
};

View File

@@ -0,0 +1,45 @@
// Boost.Geometry
// Copyright (c) 2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// 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_EXPAND_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand { namespace services
{
/*!
\brief Traits class binding a default envelope strategy to a coordinate system
\ingroup util
\tparam Tag tag of geometry
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
template <typename Tag, typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPE
, (types<Tag, CSTag>)
);
};
}}} // namespace strategy::expand::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP

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()
{}

View File

@@ -0,0 +1,42 @@
// 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_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace line_interpolate
{
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_CS
, (types<CSTag>)
);
};
} // namespace services
}} // namespace strategy::line_interpolate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_HPP

View File

@@ -0,0 +1,268 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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_NORMALIZE_HPP
#define BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP
#include <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace normalize
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct do_nothing
{
template <typename GeometryIn, typename GeometryOut>
static inline void apply(GeometryIn const&, GeometryOut&)
{
}
};
template <std::size_t Dimension, std::size_t DimensionCount>
struct assign_loop
{
template <typename CoordinateType, typename PointIn, typename PointOut>
static inline void apply(CoordinateType const& longitude,
CoordinateType const& latitude,
PointIn const& point_in,
PointOut& point_out)
{
geometry::set<Dimension>(point_out, boost::numeric_cast
<
typename coordinate_type<PointOut>::type
>(geometry::get<Dimension>(point_in)));
assign_loop
<
Dimension + 1, DimensionCount
>::apply(longitude, latitude, point_in, point_out);
}
};
template <std::size_t DimensionCount>
struct assign_loop<DimensionCount, DimensionCount>
{
template <typename CoordinateType, typename PointIn, typename PointOut>
static inline void apply(CoordinateType const&,
CoordinateType const&,
PointIn const&,
PointOut&)
{
}
};
template <std::size_t DimensionCount>
struct assign_loop<0, DimensionCount>
{
template <typename CoordinateType, typename PointIn, typename PointOut>
static inline void apply(CoordinateType const& longitude,
CoordinateType const& latitude,
PointIn const& point_in,
PointOut& point_out)
{
geometry::set<0>(point_out, boost::numeric_cast
<
typename coordinate_type<PointOut>::type
>(longitude));
assign_loop
<
1, DimensionCount
>::apply(longitude, latitude, point_in, point_out);
}
};
template <std::size_t DimensionCount>
struct assign_loop<1, DimensionCount>
{
template <typename CoordinateType, typename PointIn, typename PointOut>
static inline void apply(CoordinateType const& longitude,
CoordinateType const& latitude,
PointIn const& point_in,
PointOut& point_out)
{
geometry::set<1>(point_out, boost::numeric_cast
<
typename coordinate_type<PointOut>::type
>(latitude));
assign_loop
<
2, DimensionCount
>::apply(longitude, latitude, point_in, point_out);
}
};
template <typename PointIn, typename PointOut, bool IsEquatorial = true>
struct normalize_point
{
static inline void apply(PointIn const& point_in, PointOut& point_out)
{
typedef typename coordinate_type<PointIn>::type in_coordinate_type;
in_coordinate_type longitude = geometry::get<0>(point_in);
in_coordinate_type latitude = geometry::get<1>(point_in);
math::normalize_spheroidal_coordinates
<
typename geometry::detail::cs_angular_units<PointIn>::type,
IsEquatorial,
in_coordinate_type
>(longitude, latitude);
assign_loop
<
0, dimension<PointIn>::value
>::apply(longitude, latitude, point_in, point_out);
}
};
template <typename BoxIn, typename BoxOut, bool IsEquatorial = true>
class normalize_box
{
template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>
static inline void apply_to_coordinates(CoordinateInType& lon_min,
CoordinateInType& lat_min,
CoordinateInType& lon_max,
CoordinateInType& lat_max,
BoxIn const& box_in,
BoxOut& box_out)
{
geometry::detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out);
assign_loop
<
0, dimension<BoxIn>::value
>::apply(lon_min,
lat_min,
geometry::detail::indexed_point_view
<
BoxIn const, min_corner
>(box_in),
p_min_out);
geometry::detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out);
assign_loop
<
0, dimension<BoxIn>::value
>::apply(lon_max,
lat_max,
geometry::detail::indexed_point_view
<
BoxIn const, max_corner
>(box_in),
p_max_out);
}
public:
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
{
typedef typename coordinate_type<BoxIn>::type in_coordinate_type;
in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in);
in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in);
in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in);
in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in);
math::normalize_spheroidal_box_coordinates
<
typename geometry::detail::cs_angular_units<BoxIn>::type,
IsEquatorial,
in_coordinate_type
>(lon_min, lat_min, lon_max, lat_max);
apply_to_coordinates
<
typename geometry::detail::cs_angular_units<BoxIn>::type,
typename geometry::detail::cs_angular_units<BoxOut>::type
>(lon_min, lat_min, lon_max, lat_max, box_in, box_out);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct cartesian_point
: detail::do_nothing
{};
struct cartesian_box
: detail::do_nothing
{};
struct spherical_point
{
template <typename PointIn, typename PointOut>
static inline void apply(PointIn const& point_in, PointOut& point_out)
{
detail::normalize_point
<
PointIn, PointOut,
boost::mpl::not_
<
boost::is_same
<
typename cs_tag<PointIn>::type,
spherical_polar_tag
>
>::value
>::apply(point_in, point_out);
}
};
struct spherical_box
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
{
detail::normalize_box
<
BoxIn, BoxOut,
boost::mpl::not_
<
boost::is_same
<
typename cs_tag<BoxIn>::type,
spherical_polar_tag
>
>::value
>::apply(box_in, box_out);
}
};
}} // namespace strategy::normalize
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP

View File

@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// 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.
@@ -15,6 +20,8 @@
#define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
#include <boost/mpl/assert.hpp>
#include <boost/geometry/strategies/tags.hpp>

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
@@ -13,9 +15,9 @@
#include <boost/geometry/formulas/area_formulas.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
namespace boost { namespace geometry
@@ -24,11 +26,12 @@ namespace boost { namespace geometry
namespace strategy { namespace area
{
/*!
\brief Spherical area calculation
\ingroup strategies
\details Calculates area on the surface of a sphere using the trapezoidal rule
\tparam PointOfSegment \tparam_segment_point
\tparam RadiusTypeOrSphere \tparam_radius_or_sphere
\tparam CalculationType \tparam_calculation
\qbk{
@@ -38,7 +41,7 @@ namespace strategy { namespace area
*/
template
<
typename PointOfSegment,
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical
@@ -46,34 +49,35 @@ class spherical
// Enables special handling of long segments
static const bool LongSegment = false;
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 excess_sum
template <typename Geometry>
class state
{
CT m_sum;
friend class spherical;
// Keep track if encircles some pole
size_t m_crosses_prime_meridian;
typedef typename result_type<Geometry>::type return_type;
inline excess_sum()
public:
inline state()
: m_sum(0)
, m_crosses_prime_meridian(0)
{}
template <typename SphereType>
inline CT area(SphereType sphere) const
private:
template <typename RadiusType>
inline return_type area(RadiusType const& r) const
{
CT result;
CT radius = geometry::get_radius<0>(sphere);
return_type result;
return_type radius = r;
// Encircles pole
if(m_crosses_prime_meridian % 2 == 1)
@@ -81,12 +85,12 @@ protected :
size_t times_crosses_prime_meridian
= 1 + (m_crosses_prime_meridian / 2);
result = CT(2)
* geometry::math::pi<CT>()
result = return_type(2)
* geometry::math::pi<return_type>()
* times_crosses_prime_meridian
- geometry::math::abs(m_sum);
if(geometry::math::sign<CT>(m_sum) == 1)
if(geometry::math::sign<return_type>(m_sum) == 1)
{
result = - result;
}
@@ -99,53 +103,62 @@ protected :
return result;
}
return_type m_sum;
// Keep track if encircles some pole
size_t m_crosses_prime_meridian;
};
public :
typedef CT return_type;
typedef PointOfSegment segment_point_type;
typedef excess_sum state_type;
typedef geometry::srs::sphere<CT> sphere_type;
// For backward compatibility reasons the radius is set to 1
inline spherical()
: m_sphere(1.0)
: m_radius(1.0)
{}
template <typename T>
explicit inline spherical(geometry::srs::sphere<T> const& sphere)
: m_sphere(geometry::get_radius<0>(sphere))
{}
explicit inline spherical(CT const& radius)
: m_sphere(radius)
template <typename RadiusOrSphere>
explicit inline spherical(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
template <typename PointOfSegment, typename Geometry>
inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
excess_sum& state) const
state<Geometry>& st) const
{
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
typedef geometry::formula::area_formulas
<
typename result_type<Geometry>::type
> area_formulas;
state.m_sum += geometry::formula::area_formulas
<CT>::template spherical<LongSegment>(p1, p2);
st.m_sum += area_formulas::template spherical<LongSegment>(p1, p2);
// 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(excess_sum const& state) const
template <typename Geometry>
inline typename result_type<Geometry>::type
result(state<Geometry> const& st) const
{
return state.area(m_sphere);
return st.area(m_radius);
}
private :
/// srs Sphere
sphere_type m_sphere;
typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -154,17 +167,17 @@ namespace services
{
template <typename Point>
struct default_strategy<spherical_equatorial_tag, Point>
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef strategy::area::spherical<Point> type;
typedef strategy::area::spherical<> type;
};
// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
template <typename Point>
struct default_strategy<spherical_polar_tag, Point>
template <>
struct default_strategy<spherical_polar_tag>
{
typedef strategy::area::spherical<Point> type;
typedef strategy::area::spherical<> type;
};
} // namespace services

View File

@@ -37,9 +37,44 @@ public :
{}
template <typename T>
static inline void apply(T const& lon1_rad, T const& lat1_rad,
T const& lon2_rad, T const& lat2_rad,
T& a1, T& a2)
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_
<
@@ -47,14 +82,22 @@ public :
>::type calc_t;
geometry::formula::result_spherical<calc_t>
result = geometry::formula::spherical_azimuth<calc_t, true>(
calc_t(lon1_rad), calc_t(lat1_rad),
calc_t(lon2_rad), calc_t(lat2_rad));
result = geometry::formula::spherical_azimuth
<
calc_t,
EnableReverseAzimuth
>(calc_t(lon1_rad), calc_t(lat1_rad),
calc_t(lon2_rad), calc_t(lat2_rad));
a1 = result.azimuth;
a2 = result.reverse_azimuth;
if (EnableAzimuth)
{
a1 = result.azimuth;
}
if (EnableReverseAzimuth)
{
a2 = result.reverse_azimuth;
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

View File

@@ -0,0 +1,322 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// 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_SPHERICAL_COMPARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
#include <boost/mpl/if.hpp>
#include <boost/mpl/min.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace compare
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t I, typename P>
static inline typename geometry::coordinate_type<P>::type
get(P const& p, boost::true_type /*same units*/)
{
return geometry::get<I>(p);
}
template <std::size_t I, typename P>
static inline typename geometry::coordinate_type<P>::type
get(P const& p, boost::false_type /*different units*/)
{
return geometry::get_as_radian<I>(p);
}
template
<
typename ComparePolicy,
typename Point1,
typename Point2,
std::size_t DimensionCount
>
struct spherical_latitude
{
typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
template <typename T1, typename T2>
static inline bool apply(Point1 const& left, Point2 const& right,
T1 const& l1, T2 const& r1)
{
// latitudes equal
if (math::equals(l1, r1))
{
return compare::detail::compare_loop
<
ComparePolicy, 2, DimensionCount
>::apply(left, right);
}
else
{
return ComparePolicy::apply(l1, r1);
}
}
static inline bool apply(Point1 const& left, Point2 const& right)
{
coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
return apply(left, right, l1, r1);
}
};
template
<
typename ComparePolicy,
typename Point1,
typename Point2
>
struct spherical_latitude<ComparePolicy, Point1, Point2, 1>
{
template <typename T1, typename T2>
static inline bool apply(Point1 const& left, Point2 const& right,
T1 const& , T2 const& )
{
return apply(left, right);
}
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::compare_loop
<
ComparePolicy, 1, 1
>::apply(left, right);
}
};
template
<
typename ComparePolicy,
typename Point1,
typename Point2,
std::size_t DimensionCount
>
struct spherical_longitude
{
typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
typedef typename boost::mpl::if_<same_units_type, units1_type, geometry::radian>::type units_type;
static const bool is_equatorial = ! boost::is_same
<
typename geometry::cs_tag<Point1>::type,
geometry::spherical_polar_tag
>::value;
static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
coordinate2_type const& r0,
bool & is_left_at,
bool & is_right_at)
{
is_left_at = math::is_longitude_antimeridian<units_type>(l0);
is_right_at = math::is_longitude_antimeridian<units_type>(r0);
return is_left_at && is_right_at;
}
static inline bool apply(Point1 const& left, Point2 const& right)
{
// if units are different the coordinates are in radians
coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
bool is_left_at_antimeridian = false;
bool is_right_at_antimeridian = false;
// longitudes equal
if (math::equals(l0, r0)
// both at antimeridian
|| are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
// both at pole
|| (math::equals(l1, r1)
&& math::is_latitude_pole<units_type, is_equatorial>(l1)))
{
return spherical_latitude
<
ComparePolicy, Point1, Point2, DimensionCount
>::apply(left, right, l1, r1);
}
// if left is at antimeridian and right is not at antimeridian
// then left is greater than right
else if (is_left_at_antimeridian)
{
// less/equal_to -> false, greater -> true
return ComparePolicy::apply(1, 0);
}
// if right is at antimeridian and left is not at antimeridian
// then left is lesser than right
else if (is_right_at_antimeridian)
{
// less -> true, equal_to/greater -> false
return ComparePolicy::apply(0, 1);
}
else
{
return ComparePolicy::apply(l0, r0);
}
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Compare strategy for spherical coordinates
\ingroup strategies
\tparam Point point-type
\tparam Dimension dimension
*/
template
<
typename ComparePolicy,
int Dimension = -1
>
struct spherical
: cartesian<ComparePolicy, Dimension>
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// all dimensions starting from longitude
template <typename ComparePolicy>
struct spherical<ComparePolicy, -1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::spherical_longitude
<
ComparePolicy,
Point1,
Point2,
boost::mpl::min
<
geometry::dimension<Point1>,
geometry::dimension<Point2>
>::type::value
>::apply(left, right);
}
};
// only longitudes (and latitudes to check poles)
template <typename ComparePolicy>
struct spherical<ComparePolicy, 0>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::spherical_longitude
<
ComparePolicy, Point1, Point2, 1
>::apply(left, right);
}
};
// only latitudes
template <typename ComparePolicy>
struct spherical<ComparePolicy, 1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::spherical_latitude
<
ComparePolicy, Point1, Point2, 2
>::apply(left, right);
}
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
ComparePolicy, Point1, Point2, Dimension,
spherical_polar_tag, spherical_polar_tag
>
{
typedef compare::spherical<ComparePolicy, Dimension> type;
};
template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
ComparePolicy, Point1, Point2, Dimension,
spherical_equatorial_tag, spherical_equatorial_tag
>
{
typedef compare::spherical<ComparePolicy, Dimension> type;
};
template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
ComparePolicy, Point1, Point2, Dimension,
geographic_tag, geographic_tag
>
{
typedef compare::spherical<ComparePolicy, Dimension> type;
};
} // namespace services
}} // namespace strategy::compare
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP

View File

@@ -1,152 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 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_SPHERICAL_COMPARE_SPHERICAL_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace compare
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units>
struct shift
{
};
template <>
struct shift<degree>
{
static inline double full() { return 360.0; }
static inline double half() { return 180.0; }
};
template <>
struct shift<radian>
{
static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }
static inline double half() { return boost::math::constants::pi<double>(); }
};
} // namespace detail
#endif
/*!
\brief Compare (in one direction) strategy for spherical coordinates
\ingroup strategies
\tparam Point point-type
\tparam Dimension dimension
*/
template <typename CoordinateType, typename Units, typename Compare>
struct circular_comparator
{
static inline CoordinateType put_in_range(CoordinateType const& c,
double min_border, double max_border)
{
CoordinateType value = c;
while (value < min_border)
{
value += detail::shift<Units>::full();
}
while (value > max_border)
{
value -= detail::shift<Units>::full();
}
return value;
}
inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
{
Compare compare;
// Check situation that one of them is e.g. std::numeric_limits.
static const double full = detail::shift<Units>::full();
double mx = 10.0 * full;
if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
{
// do normal comparison, using circular is not useful
return compare(c1, c2);
}
static const double half = full / 2.0;
CoordinateType v1 = put_in_range(c1, -half, half);
CoordinateType v2 = put_in_range(c2, -half, half);
// Two coordinates on a circle are
// at max <= half a circle away from each other.
// So if it is more, shift origin.
CoordinateType diff = geometry::math::abs(v1 - v2);
if (diff > half)
{
v1 = put_in_range(v1, 0, full);
v2 = put_in_range(v2, 0, full);
}
return compare(v1, v2);
}
};
}} // namespace strategy::compare
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// Specialize for the longitude (dim 0)
template
<
typename Point,
template<typename> class CoordinateSystem,
typename Units
>
struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef strategy::compare::circular_comparator
<
coordinate_type,
Units,
std::less<coordinate_type>
> type;
};
template
<
typename Point,
template<typename> class CoordinateSystem,
typename Units
>
struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef strategy::compare::circular_comparator
<
coordinate_type,
Units,
std::greater<coordinate_type>
> type;
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP

View File

@@ -0,0 +1,144 @@
// Boost.Geometry
// Copyright (c) 2017-2019, 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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/cross_product.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/arithmetic/normalize.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/formulas/spherical.hpp>
#include <boost/geometry/formulas/interpolate_point_spherical.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of spherical segment.
\ingroup strategies
\tparam RadiusTypeOrSphere \tparam_radius_or_sphere
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical
{
public:
// For consistency with area strategy the radius is set to 1
inline spherical()
: m_radius(1.0)
{}
template <typename RadiusOrSphere>
explicit inline spherical(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
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;
calc_t angle01;
formula::interpolate_point_spherical<calc_t> formula;
formula.compute_angle(p0, p1, angle01);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(angle01 * m_radius / length_threshold);
if (n <= 0)
return;
formula.compute_axis(p0, angle01);
calc_t step = angle01 / (n + 1);
calc_t a = step;
for (signed_size_type i = 0 ; i < n ; ++i, a += step)
{
out_point_t p;
formula.compute_point(a, p);
geometry::detail::conversion::point_to_point
<
Point, out_point_t,
2, dimension<out_point_t>::value
>::apply(p0, p);
policy.apply(p);
}
}
private:
typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef strategy::densify::spherical<> 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,134 @@
// 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) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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.
// 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_SPHERICAL_DISJOINT_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct box_box_on_spheroid
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
typedef typename geometry::select_most_precise
<
typename coordinate_type<Box1>::type,
typename coordinate_type<Box2>::type
>::type calc_t;
typedef typename geometry::detail::cs_angular_units<Box1>::type units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
calc_t const b1_min = get<min_corner, 0>(box1);
calc_t const b1_max = get<max_corner, 0>(box1);
calc_t const b2_min = get<min_corner, 0>(box2);
calc_t const b2_max = get<max_corner, 0>(box2);
// min <= max <=> diff >= 0
calc_t const diff1 = b1_max - b1_min;
calc_t const diff2 = b2_max - b2_min;
// check the intersection if neither box cover the whole globe
if (diff1 < constants::period() && diff2 < constants::period())
{
// calculate positive longitude translation with b1_min as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
calc_t b2_max_transl = b2_min_transl - constants::period() + diff2;
// if the translation is too close then use the original point
// note that math::abs(b2_max_transl - b2_max) takes values very
// close to k*2*constants::period() for k=0,1,2,...
if (math::abs(b2_max_transl - b2_max) < constants::period() / 2)
{
b2_max_transl = b2_max;
}
if (b2_min_transl > b1_max // b2_min right of b1_max
&& b2_max_transl < b1_min) // b2_max left of b1_min
{
return true;
}
}
return box_box
<
Box1, Box2, 1
>::apply(box1, box2);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct spherical_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return detail::box_box_on_spheroid::apply(box1, box2);
}
};
namespace services
{
template <typename Box1, typename Box2, int TopDim1, int TopDim2>
struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_equatorial_tag, spherical_equatorial_tag>
{
typedef disjoint::spherical_box_box type;
};
template <typename Box1, typename Box2, int TopDim1, int TopDim2>
struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_polar_tag, spherical_polar_tag>
{
typedef disjoint::spherical_box_box type;
};
template <typename Box1, typename Box2, int TopDim1, int TopDim2>
struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, geographic_tag, geographic_tag>
{
typedef disjoint::spherical_box_box type;
};
} // namespace services
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP

View File

@@ -0,0 +1,116 @@
// 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_SPHERICAL_DISJOINT_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_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>
// TODO: spherical_point_box currently defined in the same file as cartesian
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/azimuth.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.
struct segment_box_spherical
{
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>
static inline bool apply(Segment const& segment, Box const& box)
{
typedef typename point_type<Segment>::type segment_point_type;
typedef typename coordinate_type<segment_point_type>::type CT;
geometry::strategy::azimuth::spherical<CT> azimuth_strategy;
return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid
<
spherical_equatorial_tag
>::apply(segment, box,
azimuth_strategy,
strategy::normalize::spherical_point(),
strategy::covered_by::spherical_point_box(),
strategy::disjoint::spherical_box_box());
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Linear, typename Box, typename LinearTag>
struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2,
spherical_equatorial_tag, spherical_equatorial_tag>
{
typedef segment_box_spherical type;
};
template <typename Box, typename Linear, typename LinearTag>
struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1,
spherical_equatorial_tag, spherical_equatorial_tag>
{
typedef segment_box_spherical type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_SEGMENT_BOX_HPP

View File

@@ -2,10 +2,12 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, 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 Menelaos Karavelas, 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
@@ -26,11 +28,12 @@
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/course.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
@@ -327,6 +330,8 @@ template
class cross_track
{
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
@@ -353,7 +358,6 @@ public :
: m_strategy(s)
{}
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
@@ -373,19 +377,6 @@ public :
typedef typename return_type<Point, PointOfSegment>::type return_type;
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
<< crs_AD * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "
<< crs_AB * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "
<< crs_BD * geometry::math::r2d << std::endl;
std::cout << "Projection AD-AB " << projection1 << " : "
<< d_crs1 * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Projection BD-BA " << projection2 << " : "
<< d_crs2 * geometry::math::r2d<return_type>() << std::endl;
#endif
// http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p);
return_type d3 = m_strategy.apply(sp1, sp2);
@@ -398,10 +389,25 @@ public :
return_type d2 = m_strategy.apply(sp2, p);
return_type crs_AD = geometry::detail::course<return_type>(sp1, p);
return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2);
return_type crs_BA = crs_AB - geometry::math::pi<return_type>();
return_type crs_BD = geometry::detail::course<return_type>(sp2, p);
return_type lon1 = geometry::get_as_radian<0>(sp1);
return_type lat1 = geometry::get_as_radian<1>(sp1);
return_type lon2 = geometry::get_as_radian<0>(sp2);
return_type lat2 = geometry::get_as_radian<1>(sp2);
return_type lon = geometry::get_as_radian<0>(p);
return_type lat = geometry::get_as_radian<1>(p);
return_type crs_AD = geometry::formula::spherical_azimuth<return_type, false>
(lon1, lat1, lon, lat).azimuth;
geometry::formula::result_spherical<return_type> result =
geometry::formula::spherical_azimuth<return_type, true>
(lon1, lat1, lon2, lat2);
return_type crs_AB = result.azimuth;
return_type crs_BA = result.reverse_azimuth - geometry::math::pi<return_type>();
return_type crs_BD = geometry::formula::spherical_azimuth<return_type, false>
(lon2, lat2, lon, lat).azimuth;
return_type d_crs1 = crs_AD - crs_AB;
return_type d_crs2 = crs_BD - crs_BA;
@@ -409,6 +415,24 @@ public :
return_type projection1 = cos( d_crs1 ) * d1 / d3;
return_type projection2 = cos( d_crs2 ) * d2 / d3;
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
<< crs_AD * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "
<< crs_AB * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Course " << dsv(sp2) << " to " << dsv(sp1) << " "
<< crs_BA * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "
<< crs_BD * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Projection AD-AB " << projection1 << " : "
<< d_crs1 * geometry::math::r2d<return_type>() << std::endl;
std::cout << "Projection BD-BA " << projection2 << " : "
<< d_crs2 * geometry::math::r2d<return_type>() << std::endl;
std::cout << " d1: " << (d1 )
<< " d2: " << (d2 )
<< std::endl;
#endif
if (projection1 > 0.0 && projection2 > 0.0)
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
@@ -449,6 +473,12 @@ public :
}
}
template <typename T1, typename T2>
inline radius_type vertical_or_meridian(T1 lat1, T2 lat2) const
{
return m_strategy.radius() * (lat1 - lat2);
}
inline typename Strategy::radius_type radius() const
{ return m_strategy.radius(); }
@@ -481,6 +511,8 @@ template
class cross_track
{
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
@@ -507,7 +539,6 @@ public :
: m_strategy(s)
{}
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
@@ -540,6 +571,12 @@ public :
return c * radius();
}
template <typename T1, typename T2>
inline radius_type vertical_or_meridian(T1 lat1, T2 lat2) const
{
return m_strategy.radius() * (lat1 - lat2);
}
inline typename Strategy::radius_type radius() const
{ return m_strategy.radius(); }

View File

@@ -0,0 +1,474 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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
// 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_SPHERICAL_DISTANCE_CROSS_TRACK_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_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/spherical/distance_cross_track.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
namespace details
{
template <typename ReturnType>
class cross_track_box_box_generic
{
public :
template <typename Point, typename PPStrategy, typename PSStrategy>
ReturnType static inline diagonal_case(Point topA,
Point topB,
Point bottomA,
Point bottomB,
bool north_shortest,
bool non_overlap,
PPStrategy pp_strategy,
PSStrategy ps_strategy)
{
if (north_shortest && non_overlap)
{
return pp_strategy.apply(topA, bottomB);
}
if (north_shortest && !non_overlap)
{
return ps_strategy.apply(topA, topB, bottomB);
}
if (!north_shortest && non_overlap)
{
return pp_strategy.apply(bottomA, topB);
}
return ps_strategy.apply(bottomA, topB, bottomB);
}
template
<
typename Box1,
typename Box2,
typename PPStrategy,
typename PSStrategy
>
ReturnType static inline apply (Box1 const& box1,
Box2 const& box2,
PPStrategy pp_strategy,
PSStrategy ps_strategy)
{
// this method assumes that the coordinates of the point and
// the box are normalized
typedef typename point_type<Box1>::type box_point_type1;
typedef typename point_type<Box2>::type box_point_type2;
box_point_type1 bottom_left1, bottom_right1, top_left1, top_right1;
geometry::detail::assign_box_corners(box1,
bottom_left1, bottom_right1,
top_left1, top_right1);
box_point_type2 bottom_left2, bottom_right2, top_left2, top_right2;
geometry::detail::assign_box_corners(box2,
bottom_left2, bottom_right2,
top_left2, top_right2);
ReturnType lon_min1 = geometry::get_as_radian<0>(bottom_left1);
ReturnType const lat_min1 = geometry::get_as_radian<1>(bottom_left1);
ReturnType lon_max1 = geometry::get_as_radian<0>(top_right1);
ReturnType const lat_max1 = geometry::get_as_radian<1>(top_right1);
ReturnType lon_min2 = geometry::get_as_radian<0>(bottom_left2);
ReturnType const lat_min2 = geometry::get_as_radian<1>(bottom_left2);
ReturnType lon_max2 = geometry::get_as_radian<0>(top_right2);
ReturnType const lat_max2 = geometry::get_as_radian<1>(top_right2);
ReturnType const two_pi = math::two_pi<ReturnType>();
// Test which sides of the boxes are closer and if boxes cross
// antimeridian
bool right_wrap;
if (lon_min2 > 0 && lon_max2 < 0) // box2 crosses antimeridian
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(box2 crosses antimeridian)";
#endif
right_wrap = lon_min2 - lon_max1 < lon_min1 - lon_max2;
lon_max2 += two_pi;
if (lon_min1 > 0 && lon_max1 < 0) // both boxes crosses antimeridian
{
lon_max1 += two_pi;
}
}
else if (lon_min1 > 0 && lon_max1 < 0) // only box1 crosses antimeridian
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(box1 crosses antimeridian)";
#endif
return apply(box2, box1, pp_strategy, ps_strategy);
}
else
{
right_wrap = lon_max1 <= lon_min2
? lon_min2 - lon_max1 < two_pi - (lon_max2 - lon_min1)
: lon_min1 - lon_max2 > two_pi - (lon_max1 - lon_min2);
}
// Check1: if box2 crosses the band defined by the
// minimum and maximum longitude of box1; if yes, determine
// if the box2 is above, below or intersects/is inside box1 and compute
// the distance (easy in this case)
bool lon_min12 = lon_min1 <= lon_min2;
bool right = lon_max1 <= lon_min2;
bool left = lon_min1 >= lon_max2;
bool lon_max12 = lon_max1 <= lon_max2;
if ((lon_min12 && !right)
|| (!left && !lon_max12)
|| (!lon_min12 && lon_max12))
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(up-down)\n";
#endif
if (lat_min1 > lat_max2)
{
return geometry::strategy::distance::services::result_from_distance
<
PSStrategy, box_point_type1, box_point_type2
>::apply(ps_strategy, ps_strategy
.vertical_or_meridian(lat_min1, lat_max2));
}
else if (lat_max1 < lat_min2)
{
return geometry::strategy::distance::services::result_from_distance
<
PSStrategy, box_point_type1, box_point_type2
>::apply(ps_strategy, ps_strategy
.vertical_or_meridian(lat_min2, lat_max1));
}
else
{
//BOOST_GEOMETRY_ASSERT(plat >= lat_min && plat <= lat_max);
return ReturnType(0);
}
}
// Check2: if box2 is right/left of box1
// the max lat of box2 should be less than the max lat of box1
bool bottom_max;
ReturnType top_common = (std::min)(lat_max1, lat_max2);
ReturnType bottom_common = (std::max)(lat_min1, lat_min2);
// true if the closest points are on northern hemisphere
bool north_shortest = top_common + bottom_common > 0;
// true if box bands do not overlap
bool non_overlap = top_common < bottom_common;
if (north_shortest)
{
bottom_max = lat_max1 >= lat_max2;
}
else
{
bottom_max = lat_min1 <= lat_min2;
}
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(diagonal)";
#endif
if (bottom_max && !right_wrap)
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(bottom left)";
#endif
return diagonal_case(top_right2, top_left1,
bottom_right2, bottom_left1,
north_shortest, non_overlap,
pp_strategy, ps_strategy);
}
if (bottom_max && right_wrap)
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(bottom right)";
#endif
return diagonal_case(top_left2, top_right1,
bottom_left2, bottom_right1,
north_shortest, non_overlap,
pp_strategy, ps_strategy);
}
if (!bottom_max && !right_wrap)
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(top left)";
#endif
return diagonal_case(top_left1, top_right2,
bottom_left1, bottom_right2,
north_shortest, non_overlap,
pp_strategy, ps_strategy);
}
if (!bottom_max && right_wrap)
{
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX
std::cout << "(top right)";
#endif
return diagonal_case(top_right1, top_left2,
bottom_right1, bottom_left2,
north_shortest, non_overlap,
pp_strategy, ps_strategy);
}
return ReturnType(0);
}
};
} //namespace details
/*!
\brief Strategy functor for distance box to box calculation
\ingroup strategies
\details Class which calculates the distance of a box to a box, for
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 CalculationType = void,
typename Strategy = haversine<double, CalculationType>
>
class cross_track_box_box
{
public:
template <typename Box1, typename Box2>
struct return_type
: services::return_type<Strategy,
typename point_type<Box1>::type,
typename point_type<Box2>::type>
{};
typedef typename Strategy::radius_type radius_type;
// strategy getters
// point-segment strategy getters
struct distance_ps_strategy
{
typedef cross_track<CalculationType, Strategy> type;
};
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type pp_comparable_strategy;
typedef typename boost::mpl::if_
<
boost::is_same
<
pp_comparable_strategy,
Strategy
>,
typename strategy::distance::services::comparable_type
<
typename distance_ps_strategy::type
>::type,
typename distance_ps_strategy::type
>::type ps_strategy_type;
// constructors
inline cross_track_box_box()
{}
explicit inline cross_track_box_box(typename Strategy::radius_type const& r)
: m_strategy(r)
{}
inline cross_track_box_box(Strategy const& s)
: m_strategy(s)
{}
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
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::PointDistanceStrategy
<
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,
m_strategy,
ps_strategy_type(m_strategy));
}
inline typename Strategy::radius_type radius() const
{
return m_strategy.radius();
}
private:
Strategy m_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<cross_track_box_box<CalculationType, Strategy> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename CalculationType, typename Strategy, typename Box1, typename Box2>
struct return_type<cross_track_box_box<CalculationType, Strategy>, Box1, Box2>
: cross_track_box_box
<
CalculationType, Strategy
>::template return_type<Box1, Box2>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track_box_box<CalculationType, Strategy> >
{
typedef cross_track_box_box
<
CalculationType, typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<cross_track_box_box<CalculationType, Strategy> >
{
typedef cross_track_box_box<CalculationType, Strategy> this_strategy;
typedef typename comparable_type<this_strategy>::type comparable_type;
public:
static inline comparable_type apply(this_strategy const& strategy)
{
return comparable_type(strategy.radius());
}
};
template <typename CalculationType, typename Strategy, typename Box1, typename Box2>
struct result_from_distance
<
cross_track_box_box<CalculationType, Strategy>, Box1, Box2
>
{
private:
typedef cross_track_box_box<CalculationType, Strategy> 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)
{
Strategy s(strategy.radius());
return result_from_distance
<
Strategy,
typename point_type<Box1>::type,
typename point_type<Box2>::type
>::apply(s, distance);
}
};
// define cross_track_box_box<default_point_segment_strategy> as
// default box-box strategy for the spherical equatorial coordinate system
template <typename Box1, typename Box2, typename Strategy>
struct default_strategy
<
box_tag, box_tag, Box1, Box2,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
>
{
typedef cross_track_box_box
<
void,
typename boost::mpl::if_
<
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, point_tag,
typename point_type<Box1>::type, typename point_type<Box2>::type,
spherical_equatorial_tag, spherical_equatorial_tag
>::type,
Strategy
>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_BOX_BOX_HPP

View File

@@ -4,11 +4,12 @@
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2017.
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -42,92 +43,46 @@ 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 CalculationType = void,
typename Strategy = cross_track<CalculationType>
>
class cross_track_point_box
namespace details
{
public:
template <typename Point, typename Box>
struct return_type
: services::return_type<Strategy, Point, typename point_type<Box>::type>
{};
typedef typename Strategy::radius_type radius_type;
template <typename ReturnType>
class cross_track_point_box_generic
{
public :
inline cross_track_point_box()
{}
explicit inline cross_track_point_box(typename Strategy::radius_type const& r)
: m_ps_strategy(r)
{}
inline cross_track_point_box(Strategy const& s)
: m_ps_strategy(s)
{}
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
template <typename Point, typename Box>
inline typename return_type<Point, Box>::type
apply(Point const& point, Box const& box) const
template
<
typename Point,
typename Box,
typename Strategy
>
ReturnType static inline apply (Point const& point,
Box const& box,
Strategy ps_strategy)
{
#if !defined(BOOST_MSVC)
BOOST_CONCEPT_ASSERT
(
(concepts::PointSegmentDistanceStrategy
<
Strategy, Point, typename point_type<Box>::type
>)
);
#endif
// this method assumes that the coordinates of the point and
// the box are normalized
typedef typename return_type<Point, Box>::type return_type;
typedef typename point_type<Box>::type box_point_type;
// TODO: This strategy as well as other cross-track strategies
// and therefore e.g. spherical within(Point, Box) may not work
// properly for a Box degenerated to a Segment or Point
box_point_type bottom_left, bottom_right, top_left, top_right;
geometry::detail::assign_box_corners(box,
bottom_left, bottom_right,
top_left, top_right);
return_type const plon = geometry::get_as_radian<0>(point);
return_type const plat = geometry::get_as_radian<1>(point);
ReturnType const plon = geometry::get_as_radian<0>(point);
ReturnType const plat = geometry::get_as_radian<1>(point);
return_type const lon_min = geometry::get_as_radian<0>(bottom_left);
return_type const lat_min = geometry::get_as_radian<1>(bottom_left);
return_type const lon_max = geometry::get_as_radian<0>(top_right);
return_type const lat_max = geometry::get_as_radian<1>(top_right);
ReturnType const lon_min = geometry::get_as_radian<0>(bottom_left);
ReturnType const lat_min = geometry::get_as_radian<1>(bottom_left);
ReturnType const lon_max = geometry::get_as_radian<0>(top_right);
ReturnType const lat_max = geometry::get_as_radian<1>(top_right);
return_type const pi = math::pi<return_type>();
return_type const two_pi = math::two_pi<return_type>();
ReturnType const pi = math::pi<ReturnType>();
ReturnType const two_pi = math::two_pi<ReturnType>();
typedef typename point_type<Box>::type box_point_type;
// First check if the point is within the band defined by the
// minimum and maximum longitude of the box; if yes, determine
@@ -142,22 +97,24 @@ public:
{
if (plat > lat_max)
{
return services::result_from_distance
<
Strategy, Point, box_point_type
>::apply(m_ps_strategy, radius() * (plat - lat_max));
return geometry::strategy::distance::services::result_from_distance
<
Strategy, Point, box_point_type
>::apply(ps_strategy, ps_strategy
.vertical_or_meridian(plat, lat_max));
}
else if (plat < lat_min)
{
return services::result_from_distance
<
Strategy, Point, box_point_type
>::apply(m_ps_strategy, radius() * (lat_min - plat));
return geometry::strategy::distance::services::result_from_distance
<
Strategy, Point, box_point_type
>::apply(ps_strategy, ps_strategy
.vertical_or_meridian(lat_min, plat));
}
else
{
BOOST_GEOMETRY_ASSERT(plat >= lat_min && plat <= lat_max);
return return_type(0);
return ReturnType(0);
}
}
@@ -169,14 +126,14 @@ public:
// (1) is midway between the meridians of the left and right
// meridians of the box, and
// (2) does not intersect the box
return_type const two = 2.0;
ReturnType const two = 2.0;
bool use_left_segment;
if (lon_max > pi)
{
// the box crosses the antimeridian
// midway longitude = lon_min - (lon_min + (lon_max - 2 * pi)) / 2;
return_type const lon_midway = (lon_min - lon_max) / two + pi;
ReturnType const lon_midway = (lon_min - lon_max) / two + pi;
BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);
use_left_segment = plon > lon_midway;
@@ -185,8 +142,8 @@ public:
{
// the box does not cross the antimeridian
return_type const lon_sum = lon_min + lon_max;
if (math::equals(lon_sum, return_type(0)))
ReturnType const lon_sum = lon_min + lon_max;
if (math::equals(lon_sum, ReturnType(0)))
{
// special case: the box is symmetric with respect to
// the prime meridian; the midway meridian is the antimeridian
@@ -196,7 +153,7 @@ public:
else
{
// midway long. = lon_min - (2 * pi - (lon_max - lon_min)) / 2;
return_type lon_midway = (lon_min + lon_max) / two - pi;
ReturnType lon_midway = (lon_min + lon_max) / two - pi;
// normalize the midway longitude
if (lon_midway > pi)
@@ -212,23 +169,119 @@ public:
// if lon_sum is positive the midway meridian is left
// of the box, or right of the box otherwise
use_left_segment = lon_sum > 0
? (plon < lon_min && plon >= lon_midway)
: (plon <= lon_max || plon > lon_midway);
? (plon < lon_min && plon >= lon_midway)
: (plon <= lon_max || plon > lon_midway);
}
}
return use_left_segment
? m_ps_strategy.apply(point, bottom_left, top_left)
: m_ps_strategy.apply(point, bottom_right, top_right);
? ps_strategy.apply(point, bottom_left, top_left)
: ps_strategy.apply(point, bottom_right, top_right);
}
};
} //namespace details
/*!
\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-point distance strategy
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename Strategy = haversine<double, CalculationType>
>
class cross_track_point_box
{
public:
template <typename Point, typename Box>
struct return_type
: services::return_type<Strategy, Point, typename point_type<Box>::type>
{};
typedef typename Strategy::radius_type radius_type;
// strategy getters
// point-segment strategy getters
struct distance_ps_strategy
{
typedef cross_track<CalculationType, Strategy> type;
};
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type pp_comparable_strategy;
typedef typename boost::mpl::if_
<
boost::is_same
<
pp_comparable_strategy,
Strategy
>,
typename strategy::distance::services::comparable_type
<
typename distance_ps_strategy::type
>::type,
typename distance_ps_strategy::type
>::type ps_strategy_type;
// constructors
inline cross_track_point_box()
{}
explicit inline cross_track_point_box(typename Strategy::radius_type const& r)
: m_strategy(r)
{}
inline cross_track_point_box(Strategy const& s)
: m_strategy(s)
{}
// methods
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
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::PointDistanceStrategy
<
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,
ps_strategy_type(m_strategy));
}
inline typename Strategy::radius_type radius() const
{
return m_ps_strategy.radius();
return m_strategy.radius();
}
private:
Strategy m_ps_strategy;
Strategy m_strategy;
};
@@ -324,7 +377,7 @@ struct default_strategy
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, segment_tag,
point_tag, point_tag,
Point, typename point_type<Box>::type,
spherical_equatorial_tag, spherical_equatorial_tag
>::type,

View File

@@ -2,6 +2,12 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017, 2018.
// Modifications 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)
@@ -10,16 +16,18 @@
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
@@ -40,7 +48,7 @@ namespace comparable
// - applying asin (which is strictly (monotone) increasing)
template
<
typename RadiusType,
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class haversine
@@ -59,10 +67,21 @@ public :
>
{};
typedef RadiusType radius_type;
typedef typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type radius_type;
explicit inline haversine(RadiusType const& r = 1.0)
: m_radius(r)
inline haversine()
: m_radius(1.0)
{}
template <typename RadiusOrSphere>
explicit inline haversine(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
template <typename Point1, typename Point2>
@@ -75,7 +94,7 @@ public :
);
}
inline RadiusType radius() const
inline radius_type radius() const
{
return m_radius;
}
@@ -90,7 +109,7 @@ private :
+ cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
}
RadiusType m_radius;
radius_type m_radius;
};
@@ -101,7 +120,7 @@ private :
\brief Distance calculation for spherical coordinates
on a perfect sphere using haversine
\ingroup strategies
\tparam RadiusType \tparam_radius
\tparam RadiusTypeOrSphere \tparam_radius_or_sphere
\tparam CalculationType \tparam_calculation
\author Adapted from: http://williams.best.vwh.net/avform.htm
\see http://en.wikipedia.org/wiki/Great-circle_distance
@@ -112,22 +131,19 @@ A mathematically equivalent formula, which is less subject
to rounding error for short distances is:
d=2*asin(sqrt((sin((lat1-lat2) / 2))^2
+ cos(lat1)*cos(lat2)*(sin((lon1-lon2) / 2))^2))
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename RadiusType,
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class haversine
{
typedef comparable::haversine<RadiusType, CalculationType> comparable_type;
typedef comparable::haversine<RadiusTypeOrSphere, CalculationType> comparable_type;
public :
template <typename Point1, typename Point2>
@@ -135,14 +151,28 @@ public :
: services::return_type<comparable_type, Point1, Point2>
{};
typedef RadiusType radius_type;
typedef typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type radius_type;
/*!
\brief Default constructor, radius set to 1.0 for the unit sphere
*/
inline haversine()
: m_radius(1.0)
{}
/*!
\brief Constructor
\param radius radius of the sphere, defaults to 1.0 for the unit sphere
\param radius_or_sphere radius of the sphere or sphere model
*/
inline haversine(RadiusType const& radius = 1.0)
: m_radius(radius)
template <typename RadiusOrSphere>
explicit inline haversine(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
/*!
@@ -165,13 +195,13 @@ public :
\brief access to radius value
\return the radius
*/
inline RadiusType radius() const
inline radius_type radius() const
{
return m_radius;
}
private :
RadiusType m_radius;
radius_type m_radius;
};

View File

@@ -0,0 +1,371 @@
// 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_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
struct generic_segment_box
{
template
<
typename LessEqual,
typename ReturnType,
typename SegmentPoint,
typename BoxPoint,
typename SegmentBoxStrategy,
typename AzimuthStrategy,
typename EnvelopeSegmentStrategy,
typename NormalizePointStrategy,
typename DisjointPointBoxStrategy,
typename DisjointBoxBoxStrategy
>
static inline ReturnType segment_below_of_box(
SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const&,
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
SegmentBoxStrategy const& sb_strategy,
AzimuthStrategy const& az_strategy,
EnvelopeSegmentStrategy const& es_strategy,
NormalizePointStrategy const& np_strategy,
DisjointPointBoxStrategy const& dpb_strategy,
DisjointBoxBoxStrategy const& dbb_strategy)
{
ReturnType result;
typename LessEqual::other less_equal;
typedef geometry::model::segment<SegmentPoint> Segment;
typedef typename cs_tag<Segment>::type segment_cs_type;
typedef geometry::detail::disjoint::
disjoint_segment_box_sphere_or_spheroid<segment_cs_type>
disjoint_sb;
typedef typename disjoint_sb::disjoint_info disjoint_info_type;
Segment seg(p0, p1);
geometry::model::box<BoxPoint> input_box;
geometry::set_from_radian<geometry::min_corner, 0>
(input_box, geometry::get_as_radian<0>(bottom_left));
geometry::set_from_radian<geometry::min_corner, 1>
(input_box, geometry::get_as_radian<1>(bottom_left));
geometry::set_from_radian<geometry::max_corner, 0>
(input_box, geometry::get_as_radian<0>(top_right));
geometry::set_from_radian<geometry::max_corner, 1>
(input_box, geometry::get_as_radian<1>(top_right));
SegmentPoint p_max;
disjoint_info_type disjoint_result = disjoint_sb::
apply(seg, input_box, p_max,
az_strategy, np_strategy, dpb_strategy, dbb_strategy);
if (disjoint_result == disjoint_info_type::intersect) //intersect
{
return 0;
}
// disjoint but vertex not computed
if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
{
typedef typename coordinate_type<SegmentPoint>::type CT;
geometry::model::box<SegmentPoint> mbr;
geometry::envelope(seg, mbr, es_strategy);
CT lon1 = geometry::get_as_radian<0>(p0);
CT lat1 = geometry::get_as_radian<1>(p0);
CT lon2 = geometry::get_as_radian<0>(p1);
CT lat2 = geometry::get_as_radian<1>(p1);
if (lon1 > lon2)
{
std::swap(lon1, lon2);
std::swap(lat1, lat2);
}
CT vertex_lat;
CT lat_sum = lat1 + lat2;
if (lat_sum > CT(0))
{
vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
} else {
vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
}
CT alp1;
az_strategy.apply(lon1, lat1, lon2, lat2, alp1);
CT vertex_lon = geometry::formula::vertex_longitude
<
CT,
segment_cs_type
>::apply(lon1, lat1, lon2, lat2,
vertex_lat, alp1, az_strategy);
geometry::set_from_radian<0>(p_max, vertex_lon);
geometry::set_from_radian<1>(p_max, vertex_lat);
}
//otherwise disjoint and vertex computed inside disjoint
if (less_equal(geometry::get_as_radian<0>(bottom_left),
geometry::get_as_radian<0>(p_max)))
{
result = boost::numeric_cast<ReturnType>(typename
SegmentBoxStrategy::distance_ps_strategy::type().apply(bottom_left, p0, p1));
}
else
{
result = geometry::detail::distance::segment_to_box_2D
<
ReturnType,
SegmentPoint,
BoxPoint,
SegmentBoxStrategy
>::template call_above_of_box
<
typename LessEqual::other
>(p1, p0, p_max, bottom_right, sb_strategy);
}
return result;
}
template <typename SPoint, typename BPoint>
static void mirror(SPoint& p0,
SPoint& p1,
BPoint& bottom_left,
BPoint& bottom_right,
BPoint& top_left,
BPoint& top_right)
{
//if segment's vertex is the southest point then mirror geometries
if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
{
BPoint bl = bottom_left;
BPoint br = bottom_right;
geometry::set<1>(p0, geometry::get<1>(p0) * -1);
geometry::set<1>(p1, geometry::get<1>(p1) * -1);
geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1);
geometry::set<1>(top_left, geometry::get<1>(bl) * -1);
geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1);
geometry::set<1>(top_right, geometry::get<1>(br) * -1);
}
}
};
//===========================================================================
template
<
typename CalculationType = void,
typename Strategy = haversine<double, CalculationType>
>
struct spherical_segment_box
{
template <typename PointOfSegment, typename PointOfBox>
struct calculation_type
: promote_floating_point
<
typename strategy::distance::services::return_type
<
Strategy,
PointOfSegment,
PointOfBox
>::type
>
{};
// strategy getters
// point-point strategy getters
struct distance_pp_strategy
{
typedef Strategy type;
};
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
{
return typename distance_pp_strategy::type();
}
// point-segment strategy getters
struct distance_ps_strategy
{
typedef cross_track<CalculationType, Strategy> type;
};
inline typename distance_ps_strategy::type get_distance_ps_strategy() const
{
return typename distance_ps_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();
}
// 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::spherical<CalculationType> azimuth_strategy_type;
azimuth_strategy_type az_strategy;
typedef typename envelope::spherical_segment<CalculationType>
envelope_segment_strategy_type;
envelope_segment_strategy_type es_strategy;
return generic_segment_box::segment_below_of_box
<
LessEqual,
ReturnType
>(p0,p1,top_left,top_right,bottom_left,bottom_right,
spherical_segment_box<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);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<spherical_segment_box<CalculationType, Strategy> >
{
typedef strategy_tag_distance_segment_box type;
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct return_type<spherical_segment_box<CalculationType, Strategy>, PS, PB>
: spherical_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
{
// Define a cartesian_segment_box strategy with its underlying point-segment
// strategy being comparable
typedef spherical_segment_box
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
{
typedef typename comparable_type
<
spherical_segment_box<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
{
private :
typedef typename return_type<
spherical_segment_box
<
CalculationType,
Strategy
>,
PS,
PB
>::type return_type;
public :
template <typename T>
static inline return_type apply(spherical_segment_box<CalculationType,
Strategy> const& ,
T const& value)
{
Strategy s;
return result_from_distance<Strategy, PS, PB>::apply(s, value);
}
};
template <typename Segment, typename Box>
struct default_strategy
<
segment_tag, box_tag, Segment, Box,
spherical_equatorial_tag, spherical_equatorial_tag
>
{
typedef spherical_segment_box<> type;
};
template <typename Box, typename Segment>
struct default_strategy
<
box_tag, segment_tag, Box, Segment,
spherical_equatorial_tag, spherical_equatorial_tag
>
{
typedef typename default_strategy
<
segment_tag, box_tag, Segment, Box,
spherical_equatorial_tag, spherical_equatorial_tag
>::type type;
};
}
#endif
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP

View File

@@ -0,0 +1,146 @@
// 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.
// 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
// 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_SPHERICAL_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_HPP
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
#include <boost/geometry/strategies/spherical/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template <typename CalculationType = void>
class spherical
{
public:
typedef spherical_segment<CalculationType> element_envelope_strategy_type;
static inline element_envelope_strategy_type get_element_envelope_strategy()
{
return element_envelope_strategy_type();
}
typedef expand::spherical_segment<CalculationType> element_expand_strategy_type;
static inline element_expand_strategy_type get_element_expand_strategy()
{
return element_expand_strategy_type();
}
typedef strategy::expand::spherical_box box_expand_strategy_type;
static inline box_expand_strategy_type get_box_expand_strategy()
{
return box_expand_strategy_type();
}
// Linestring, Ring, Polygon
template <typename Range>
static inline geometry::segment_iterator<Range const> begin(Range const& range)
{
return geometry::segments_begin(range);
}
template <typename Range>
static inline geometry::segment_iterator<Range const> end(Range const& range)
{
return geometry::segments_end(range);
}
// MultiLinestring, MultiPolygon
template <typename Box>
struct multi_state
{
void apply(Box const& single_box)
{
m_boxes.push_back(single_box);
}
void result(Box & box)
{
if (!m_boxes.empty())
{
geometry::detail::envelope::envelope_range_of_boxes::apply(m_boxes, box);
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
private:
std::vector<Box> m_boxes;
};
// Segment
template <typename Point1, typename Point2, typename Box>
static inline void apply(Point1 const& point1, Point2 const& point2,
Box& box)
{
spherical_segment<CalculationType>::apply(point1, point2, box);
}
// Box
template <typename BoxIn, typename Box>
static inline void apply(BoxIn const& box_in, Box& box)
{
spherical_box::apply(box_in, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical<CalculationType> type;
};
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_HPP

View File

@@ -0,0 +1,145 @@
// 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-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_SPHERICAL_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
std::size_t Index,
std::size_t DimensionCount
>
struct envelope_indexed_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
// transform() does not work with boxes of dimension higher
// than 2; to account for such boxes we transform the min/max
// points of the boxes using the indexed_point_view
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
// first transform the units
transform_units(box_in_corner, mbr_corner);
// now transform the remaining coordinates
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
2,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace envelope
{
struct spherical_box
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
BoxIn box_in_normalized = box_in;
if (!is_inverse_spheroidal_coordinates(box_in))
{
strategy::normalize::spherical_box::apply(box_in, box_in_normalized);
}
geometry::detail::envelope::envelope_indexed_box_on_spheroid
<
min_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
geometry::detail::envelope::envelope_indexed_box_on_spheroid
<
max_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,379 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#include <cstddef>
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
#include <boost/geometry/strategies/spherical/envelope_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class spherical_multipoint
{
private:
template <std::size_t Dim>
struct coordinate_less
{
template <typename Point>
inline bool operator()(Point const& point1, Point const& point2) const
{
return math::smaller(geometry::get<Dim>(point1),
geometry::get<Dim>(point2));
}
};
template <typename Constants, typename MultiPoint, typename OutputIterator>
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
bool& has_south_pole,
bool& has_north_pole,
OutputIterator oit)
{
typedef typename boost::range_value<MultiPoint>::type point_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
// analyze point coordinates:
// (1) normalize point coordinates
// (2) check if any point is the north or the south pole
// (3) put all non-pole points in a container
//
// notice that at this point in the algorithm, we have at
// least two points on the spheroid
has_south_pole = false;
has_north_pole = false;
for (iterator_type it = boost::begin(multipoint);
it != boost::end(multipoint);
++it)
{
point_type point;
normalize::spherical_point::apply(*it, point);
if (math::equals(geometry::get<1>(point),
Constants::min_latitude()))
{
has_south_pole = true;
}
else if (math::equals(geometry::get<1>(point),
Constants::max_latitude()))
{
has_north_pole = true;
}
else
{
*oit++ = point;
}
}
}
template <typename SortedRange, typename Value>
static inline Value maximum_gap(SortedRange const& sorted_range,
Value& max_gap_left,
Value& max_gap_right)
{
typedef typename boost::range_iterator
<
SortedRange const
>::type iterator_type;
iterator_type it1 = boost::begin(sorted_range), it2 = it1;
++it2;
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
Value max_gap = max_gap_right - max_gap_left;
for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
{
Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
if (math::larger(gap, max_gap))
{
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
max_gap = gap;
}
}
return max_gap;
}
template
<
typename Constants,
typename PointRange,
typename LongitudeLess,
typename CoordinateType
>
static inline void get_min_max_longitudes(PointRange& range,
LongitudeLess const& lon_less,
CoordinateType& lon_min,
CoordinateType& lon_max)
{
typedef typename boost::range_iterator
<
PointRange const
>::type iterator_type;
// compute min and max longitude values
std::pair<iterator_type, iterator_type> min_max_longitudes
= boost::minmax_element(boost::begin(range),
boost::end(range),
lon_less);
lon_min = geometry::get<0>(*min_max_longitudes.first);
lon_max = geometry::get<0>(*min_max_longitudes.second);
// if the longitude span is "large" compute the true maximum gap
if (math::larger(lon_max - lon_min, Constants::half_period()))
{
std::sort(boost::begin(range), boost::end(range), lon_less);
CoordinateType max_gap_left = 0, max_gap_right = 0;
CoordinateType max_gap
= maximum_gap(range, max_gap_left, max_gap_right);
CoordinateType complement_gap
= Constants::period() + lon_min - lon_max;
if (math::larger(max_gap, complement_gap))
{
lon_min = max_gap_right;
lon_max = max_gap_left + Constants::period();
}
}
}
template
<
typename Constants,
typename Iterator,
typename LatitudeLess,
typename CoordinateType
>
static inline void get_min_max_latitudes(Iterator const first,
Iterator const last,
LatitudeLess const& lat_less,
bool has_south_pole,
bool has_north_pole,
CoordinateType& lat_min,
CoordinateType& lat_max)
{
if (has_south_pole && has_north_pole)
{
lat_min = Constants::min_latitude();
lat_max = Constants::max_latitude();
}
else if (has_south_pole)
{
lat_min = Constants::min_latitude();
lat_max
= geometry::get<1>(*std::max_element(first, last, lat_less));
}
else if (has_north_pole)
{
lat_min
= geometry::get<1>(*std::min_element(first, last, lat_less));
lat_max = Constants::max_latitude();
}
else
{
std::pair<Iterator, Iterator> min_max_latitudes
= boost::minmax_element(first, last, lat_less);
lat_min = geometry::get<1>(*min_max_latitudes.first);
lat_max = geometry::get<1>(*min_max_latitudes.second);
}
}
public:
template <typename MultiPoint, typename Box>
static inline void apply(MultiPoint const& multipoint, Box& mbr)
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef math::detail::constants_on_spheroid
<
coordinate_type,
typename geometry::detail::cs_angular_units<MultiPoint>::type
> constants;
if (boost::empty(multipoint))
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(mbr);
return;
}
geometry::detail::envelope::initialize<Box, 0, 2>::apply(mbr);
if (boost::size(multipoint) == 1)
{
return dispatch::envelope
<
typename boost::range_value<MultiPoint>::type
>::apply(range::front(multipoint), mbr, strategy::envelope::spherical_point());
}
// analyze the points and put the non-pole ones in the
// points vector
std::vector<point_type> points;
bool has_north_pole = false, has_south_pole = false;
analyze_point_coordinates<constants>(multipoint,
has_south_pole, has_north_pole,
std::back_inserter(points));
coordinate_type lon_min, lat_min, lon_max, lat_max;
if (points.size() == 1)
{
// we have one non-pole point and at least one pole point
lon_min = geometry::get<0>(range::front(points));
lon_max = geometry::get<0>(range::front(points));
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = has_north_pole
? constants::max_latitude()
: constants::min_latitude();
}
else if (points.empty())
{
// all points are pole points
BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
lon_min = coordinate_type(0);
lon_max = coordinate_type(0);
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = (has_north_pole)
? constants::max_latitude()
: constants::min_latitude();
}
else
{
get_min_max_longitudes<constants>(points,
coordinate_less<0>(),
lon_min,
lon_max);
get_min_max_latitudes<constants>(points.begin(),
points.end(),
coordinate_less<1>(),
has_south_pole,
has_north_pole,
lat_min,
lat_max);
}
typedef typename helper_geometry
<
Box,
coordinate_type,
typename geometry::detail::cs_angular_units<MultiPoint>::type
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set<min_corner, 0>(helper_mbr, lon_min);
geometry::set<min_corner, 1>(helper_mbr, lat_min);
geometry::set<max_corner, 0>(helper_mbr, lon_max);
geometry::set<max_corner, 1>(helper_mbr, lat_max);
// now transform to output MBR (per index)
geometry::detail::envelope::envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
geometry::detail::envelope::envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
geometry::detail::envelope::envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
for (++it; it != boost::end(multipoint); ++it)
{
strategy::expand::detail::point_loop
<
2, dimension<Box>::value
>::apply(mbr, *it);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<multi_point_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
template <typename CalculationType>
struct default_strategy<multi_point_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
template <typename CalculationType>
struct default_strategy<multi_point_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,111 @@
// 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, 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_SPHERICAL_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
struct spherical_point
{
template<typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
Point normalized_point;
strategy::normalize::spherical_point::apply(point, normalized_point);
typename point_type<Box>::type box_point;
// transform units of input point to units of a box point
geometry::detail::envelope::transform_units(normalized_point, box_point);
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
typedef geometry::detail::envelope::envelope_one_point
<
2, dimension<Point>::value
> per_corner;
per_corner::template apply<min_corner>(normalized_point, mbr);
per_corner::template apply<max_corner>(normalized_point, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_POINT_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
@@ -11,47 +11,406 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <cstddef>
#include <utility>
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/formulas/meridian_segment.hpp>
#include <boost/geometry/formulas/vertex_latitude.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/azimuth.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
namespace boost { namespace geometry
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace strategy { namespace envelope
{
namespace strategy { namespace envelope
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename CalculationType, typename CS_Tag>
struct envelope_segment_call_vertex_latitude
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& )
{
return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
::apply(lat1, alp1);
}
};
template <typename CalculationType>
struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& strategy)
{
return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
::apply(lat1, alp1, strategy.model());
}
};
template <typename Units, typename CS_Tag>
struct envelope_segment_convert_polar
{
template <typename T>
static inline void pre(T & , T & ) {}
template <typename T>
static inline void post(T & , T & ) {}
};
template <typename Units>
struct envelope_segment_convert_polar<Units, spherical_polar_tag>
{
template <typename T>
static inline void pre(T & lat1, T & lat2)
{
lat1 = math::latitude_convert_ep<Units>(lat1);
lat2 = math::latitude_convert_ep<Units>(lat2);
}
template <typename T>
static inline void post(T & lat1, T & lat2)
{
lat1 = math::latitude_convert_ep<Units>(lat1);
lat2 = math::latitude_convert_ep<Units>(lat2);
std::swap(lat1, lat2);
}
};
template <typename CS_Tag>
class envelope_segment_impl
{
private:
// degrees or radians
template <typename CalculationType>
static inline void swap(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
std::swap(lon1, lon2);
std::swap(lat1, lat2);
}
// radians
template <typename CalculationType>
static inline bool contains_pi_half(CalculationType const& a1,
CalculationType const& a2)
{
// azimuths a1 and a2 are assumed to be in radians
BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
static CalculationType const pi_half = math::half_pi<CalculationType>();
return (a1 < a2)
? (a1 < pi_half && pi_half < a2)
: (a1 > pi_half && pi_half > a2);
}
// radians or degrees
template <typename Units, typename CoordinateType>
static inline bool crosses_antimeridian(CoordinateType const& lon1,
CoordinateType const& lon2)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType, Units
> constants;
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
}
// degrees or radians
template <typename Units, typename CalculationType, typename Strategy>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
CalculationType a1,
CalculationType a2,
Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
boost::ignore_unused(lon1, lon2);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
if (math::equals(a1, a2))
{
// the segment must lie on the equator or is very short or is meridian
return;
}
if (lat1 > lat2)
{
std::swap(lat1, lat2);
std::swap(lat1_rad, lat2_rad);
std::swap(a1, a2);
}
if (contains_pi_half(a1, a2))
{
CalculationType p_max = envelope_segment_call_vertex_latitude
<CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
CalculationType const lat_min_rad = -p_max;
CalculationType const lat_min
= math::from_radian<Units>(lat_min_rad);
if (lat1 > lat_min)
{
lat1 = lat_min;
}
}
else
{
// update using max latitude
CalculationType const lat_max_rad = p_max;
CalculationType const lat_max
= math::from_radian<Units>(lat_max_rad);
if (lat2 < lat_max)
{
lat2 = lat_max;
}
}
}
}
template <typename Units, typename CalculationType>
static inline void special_cases(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
typedef math::detail::constants_on_spheroid
<
CalculationType, Units
> constants;
bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());
bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());
if (is_pole1 && is_pole2)
{
// both points are poles; nothing more to do:
// longitudes are already normalized to 0
// but just in case
lon1 = 0;
lon2 = 0;
}
else if (is_pole1 && !is_pole2)
{
// first point is a pole, second point is not:
// make the longitude of the first point the same as that
// of the second point
lon1 = lon2;
}
else if (!is_pole1 && is_pole2)
{
// second point is a pole, first point is not:
// make the longitude of the second point the same as that
// of the first point
lon2 = lon1;
}
if (lon1 == lon2)
{
// segment lies on a meridian
if (lat1 > lat2)
{
std::swap(lat1, lat2);
}
return;
}
BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
if (lon1 > lon2)
{
swap(lon1, lat1, lon2, lat2);
}
if (crosses_antimeridian<Units>(lon1, lon2))
{
lon1 += constants::period();
swap(lon1, lat1, lon2, lat2);
}
}
template
<
typename Units,
typename CalculationType,
typename Box
>
static inline void create_box(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
Box& mbr)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename helper_geometry
<
Box, box_coordinate_type, Units
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set
<
min_corner, 0
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
geometry::set
<
min_corner, 1
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
geometry::set
<
max_corner, 0
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
geometry::set
<
max_corner, 1
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
geometry::detail::envelope::transform_units(helper_mbr, mbr);
}
template <typename Units, typename CalculationType, typename Strategy>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
Strategy const& strategy)
{
special_cases<Units>(lon1, lat1, lon2, lat2);
CalculationType lon1_rad = math::as_radian<Units>(lon1);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
CalculationType alp1, alp2;
strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2);
compute_box_corners<Units>(lon1, lat1, lon2, lat2, alp1, alp2, strategy);
}
public:
template
<
typename Units,
typename CalculationType,
typename Box,
typename Strategy
>
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
Box& mbr,
Strategy const& strategy)
{
typedef envelope_segment_convert_polar<Units, typename cs_tag<Box>::type> convert_polar;
convert_polar::pre(lat1, lat2);
apply<Units>(lon1, lat1, lon2, lat2, strategy);
convert_polar::post(lat1, lat2);
create_box<Units>(lon1, lat1, lon2, lat2, mbr);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class spherical_segment
{
public :
inline spherical_segment()
{}
template <typename Point1, typename Point2, typename Box>
inline void
apply(Point1 const& point1, Point2 const& point2, Box& box) const
public:
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>
static inline void apply(Point const& point1, Point const& point2,
Box& box)
{
Point p1_normalized, p2_normalized;
strategy::normalize::spherical_point::apply(point1, p1_normalized);
strategy::normalize::spherical_point::apply(point2, p2_normalized);
geometry::strategy::azimuth::spherical<CalculationType> azimuth_spherical;
typedef typename coordinate_system<Point1>::type::units units_type;
typedef typename geometry::detail::cs_angular_units<Point>::type units_type;
geometry::detail::envelope::envelope_segment_impl<spherical_equatorial_tag>
::template apply<units_type>(geometry::get<0>(p1_normalized),
geometry::get<1>(p1_normalized),
geometry::get<0>(p2_normalized),
geometry::get<1>(p2_normalized),
box,
azimuth_spherical);
// first compute the envelope range for the first two coordinates
strategy::envelope::detail::envelope_segment_impl
<
spherical_equatorial_tag
>::template apply<units_type>(geometry::get<0>(p1_normalized),
geometry::get<1>(p1_normalized),
geometry::get<0>(p2_normalized),
geometry::get<1>(p2_normalized),
box,
azimuth_spherical);
// 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);
}
};
@@ -61,14 +420,14 @@ namespace services
{
template <typename CalculationType>
struct default_strategy<spherical_equatorial_tag, CalculationType>
struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_segment<CalculationType> type;
};
template <typename CalculationType>
struct default_strategy<spherical_polar_tag, CalculationType>
struct default_strategy<segment_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_segment<CalculationType> type;
};

View File

@@ -0,0 +1,98 @@
// 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_SPHERICAL_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP
#include <cstddef>
#include <algorithm>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/strategies/expand.hpp>
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct box_on_spheroid
{
template <typename BoxOut, typename BoxIn>
static inline void apply(BoxOut& box_out, BoxIn const& box_in)
{
// normalize both boxes and convert box-in to be of type of box-out
BoxOut mbrs[2];
strategy::envelope::spherical_box::apply(box_in, mbrs[0]);
strategy::envelope::spherical_box::apply(box_out, mbrs[1]);
// compute the envelope of the two boxes
geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct spherical_box
: detail::box_on_spheroid
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, geographic_tag, CalculationType>
{
typedef spherical_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP

View File

@@ -0,0 +1,233 @@
// 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-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
// 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_SPHERICAL_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_POINT_HPP
#include <cstddef>
#include <algorithm>
#include <functional>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/strategies/expand.hpp>
#include <boost/geometry/strategies/cartesian/expand_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// implementation for the spherical and geographic coordinate systems
template <std::size_t DimensionCount, bool IsEquatorial>
struct point_loop_on_spheroid
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& point)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename geometry::detail::cs_angular_units<Box>::type units_type;
typedef math::detail::constants_on_spheroid
<
box_coordinate_type,
units_type
> constants;
// normalize input point and input box
Point p_normalized;
strategy::normalize::spherical_point::apply(point, p_normalized);
// transform input point to be of the same type as the box point
box_point_type box_point;
geometry::detail::envelope::transform_units(p_normalized, box_point);
if (is_inverse_spheroidal_coordinates(box))
{
geometry::set_from_radian<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
geometry::set_from_radian<max_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
} else {
strategy::normalize::spherical_box::apply(box, box);
box_coordinate_type p_lon = geometry::get<0>(box_point);
box_coordinate_type p_lat = geometry::get<1>(box_point);
typename coordinate_type<Box>::type
b_lon_min = geometry::get<min_corner, 0>(box),
b_lat_min = geometry::get<min_corner, 1>(box),
b_lon_max = geometry::get<max_corner, 0>(box),
b_lat_max = geometry::get<max_corner, 1>(box);
if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
{
// the point of expansion is the either the north or the
// south pole; the only important coordinate here is the
// pole's latitude, as the longitude can be anything;
// we, thus, take into account the point's latitude only and return
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
if (math::equals(b_lat_min, b_lat_max)
&& math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
{
// the box degenerates to either the north or the south pole;
// the only important coordinate here is the pole's latitude,
// as the longitude can be anything;
// we thus take into account the box's latitude only and return
geometry::set<min_corner, 0>(box, p_lon);
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 0>(box, p_lon);
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
// update latitudes
b_lat_min = (std::min)(b_lat_min, p_lat);
b_lat_max = (std::max)(b_lat_max, p_lat);
// update longitudes
if (math::smaller(p_lon, b_lon_min))
{
box_coordinate_type p_lon_shifted = p_lon + constants::period();
if (math::larger(p_lon_shifted, b_lon_max))
{
// here we could check using: ! math::larger(.., ..)
if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
{
b_lon_min = p_lon;
}
else
{
b_lon_max = p_lon_shifted;
}
}
}
else if (math::larger(p_lon, b_lon_max))
{
// in this case, and since p_lon is normalized in the range
// (-180, 180], we must have that b_lon_max <= 180
if (b_lon_min < 0
&& math::larger(p_lon - b_lon_max,
constants::period() - p_lon + b_lon_min))
{
b_lon_min = p_lon;
b_lon_max += constants::period();
}
else
{
b_lon_max = p_lon;
}
}
geometry::set<min_corner, 0>(box, b_lon_min);
geometry::set<min_corner, 1>(box, b_lat_min);
geometry::set<max_corner, 0>(box, b_lon_max);
geometry::set<max_corner, 1>(box, b_lat_max);
}
point_loop
<
2, DimensionCount
>::apply(box, point);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct spherical_point
{
template <typename Box, typename Point>
static void apply(Box & box, Point const& point)
{
expand::detail::point_loop_on_spheroid
<
dimension<Point>::value,
! boost::is_same<typename cs_tag<Point>::type, spherical_polar_tag>::value
>::apply(box, point);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, geographic_tag, CalculationType>
{
typedef spherical_point type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_POINT_HPP

View File

@@ -0,0 +1,118 @@
// 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_SPHERICAL_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_SEGMENT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.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/strategies/expand.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct segment_on_spheroid
{
template <typename Box, typename Segment, typename EnvelopeStrategy>
static inline void apply(Box& box, Segment const& segment, EnvelopeStrategy const& strategy)
{
Box mbrs[2];
// compute the envelope of the segment
typename point_type<Segment>::type p[2];
geometry::detail::assign_point_from_index<0>(segment, p[0]);
geometry::detail::assign_point_from_index<1>(segment, p[1]);
geometry::detail::envelope::envelope_segment
<
dimension<Segment>::value
>::apply(p[0], p[1], mbrs[0], strategy);
// normalize the box
strategy::envelope::spherical_box::apply(box, mbrs[1]);
// compute the envelope of the two boxes
geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class spherical_segment
{
public:
template <typename Box, typename Segment>
static inline void apply(Box& box, Segment const& segment)
{
detail::segment_on_spheroid::apply(box, segment,
strategy::envelope::spherical_segment<CalculationType>());
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_segment<CalculationType> type;
};
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_segment<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_SEGMENT_HPP

View File

@@ -0,0 +1,81 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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
// 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_SPHERICAL_GET_RADIUS_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_GET_RADIUS_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace strategy_detail
{
template
<
typename RadiusTypeOrSphere,
typename Tag = typename tag<RadiusTypeOrSphere>::type
>
struct get_radius
{
typedef typename geometry::radius_type<RadiusTypeOrSphere>::type type;
static type apply(RadiusTypeOrSphere const& sphere)
{
return geometry::get_radius<0>(sphere);
}
};
template <typename RadiusTypeOrSphere>
struct get_radius<RadiusTypeOrSphere, void>
{
typedef RadiusTypeOrSphere type;
static type apply(RadiusTypeOrSphere const& radius)
{
return radius;
}
};
// For backward compatibility
template <typename Point>
struct get_radius<Point, point_tag>
{
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
double
>::type type;
template <typename RadiusOrSphere>
static typename get_radius<RadiusOrSphere>::type
apply(RadiusOrSphere const& radius_or_sphere)
{
return get_radius<RadiusOrSphere>::apply(radius_or_sphere);
}
};
} // namespace strategy_detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_GET_RADIUS_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,
@@ -33,14 +35,19 @@
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/envelope.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/within.hpp>
@@ -93,11 +100,10 @@ struct ecef_segments
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::winding
typedef strategy::within::spherical_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
side_strategy_type,
CalculationType
> type;
};
@@ -118,7 +124,7 @@ struct ecef_segments
{
typedef area::spherical
<
typename point_type<Geometry>::type,
typename coordinate_type<Geometry>::type,
CalculationType
> type;
};
@@ -147,44 +153,65 @@ struct ecef_segments
return strategy_type();
}
typedef envelope::spherical<CalculationType>
envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
{
return envelope_strategy_type();
}
typedef expand::spherical_segment<CalculationType>
expand_strategy_type;
static inline expand_strategy_type get_expand_strategy()
{
return expand_strategy_type();
}
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_spherical disjoint_segment_box_strategy_type;
static inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy()
{
return disjoint_segment_box_strategy_type();
}
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 };
// segment_intersection_info cannot outlive relate_ecef_segments
template <typename CoordinateType, typename SegmentRatio, typename Vector3d>
struct segment_intersection_info
{
typedef typename select_most_precise
<
CoordinateType, double
>::type promoted_type;
segment_intersection_info(CalcPolicy const& calc)
: calc_policy(calc)
{}
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)
{
@@ -268,7 +295,6 @@ struct ecef_segments
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
// 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);
@@ -293,36 +319,64 @@ struct ecef_segments
vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
bool degen_neq_coords = false;
side_info sides;
typename CalcPolicy::template plane<vec3d_t>
plane2 = calc_policy.get_plane(b1v, b2v);
// not normalized normals, the same as in side strategy
sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
if (sides.same<0>())
calc_t dist_b1_b2 = 0;
if (! b_is_point)
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
calculate_dist(b1v, b2v, plane2, dist_b1_b2);
if (math::equals(dist_b1_b2, c0))
{
degen_neq_coords = true;
b_is_point = true;
dist_b1_b2 = 0;
}
else
{
// not normalized normals, the same as in side strategy
sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
}
}
typename CalcPolicy::template plane<vec3d_t>
plane1 = calc_policy.get_plane(a1v, a2v);
// not normalized normals, the same as in side strategy
sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
if (sides.same<1>())
calc_t dist_a1_a2 = 0;
if (! a_is_point)
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
calculate_dist(a1v, a2v, plane1, dist_a1_a2);
if (math::equals(dist_a1_a2, c0))
{
degen_neq_coords = true;
a_is_point = true;
dist_a1_a2 = 0;
}
else
{
// not normalized normals, the same as in side strategy
sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
}
}
// NOTE: at this point the segments may still be disjoint
calc_t len1, len2;
calc_t len1 = 0;
// point or opposite sides of a sphere/spheroid, assume point
if (! detail::vec_normalize(plane1.normal, len1))
if (! a_is_point && ! detail::vec_normalize(plane1.normal, len1))
{
a_is_point = true;
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
@@ -331,7 +385,8 @@ struct ecef_segments
}
}
if (! detail::vec_normalize(plane2.normal, len2))
calc_t len2 = 0;
if (! b_is_point && ! detail::vec_normalize(plane2.normal, len2))
{
b_is_point = true;
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
@@ -395,30 +450,32 @@ struct ecef_segments
{
if (a_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v,
plane2, a1v, a2v, dist_b1_b2, degen_neq_coords);
}
else if (b_is_point)
{
// b2 used to be consistent with (degenerated) checks above (is it needed?)
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v,
plane1, b1v, b2v, dist_a1_a2, degen_neq_coords);
}
else
{
calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
calc_t dist_a1_b1, dist_a1_b2;
calc_t dist_b1_a1, dist_b1_a2;
// use shorter segment
if (len1 <= len2)
{
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2);
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, b2v, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b2, b1, a1v, a2v, plane1, b2v, b1v, 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, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2);
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, a2v, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a2, a1, b1v, b2v, plane2, a2v, a1v, 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;
@@ -478,10 +535,11 @@ struct ecef_segments
vec3d_t i1;
intersection_point_flag ip_flag;
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
calc_t dist_a1_i1, dist_b1_i1;
if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v,
plane1, plane2, calc_policy, sides,
i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))
plane1, plane2, calc_policy,
sides, dist_a1_a2, dist_b1_b2,
i1, dist_a1_i1, dist_b1_i1, ip_flag))
{
// intersects
segment_intersection_info
@@ -511,43 +569,68 @@ private:
collinear_one_degenerated(Segment const& segment, bool degenerated_a,
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
Vec3d const& v1, Vec3d const& v2,
Vec3d const& a1v, Vec3d const& a2v,
Plane const& plane,
Vec3d const& vother)
Vec3d const& b1v, Vec3d const& b2v,
CalcT const& dist_1_2,
bool degen_neq_coords)
{
CalcT dist_1_2, dist_1_o;
return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
CalcT dist_1_o;
return ! calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane, b1v, b2v, dist_1_2, dist_1_o, degen_neq_coords)
? Policy::disjoint()
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
template <typename Point1, typename Point2, typename Vec3d, typename Plane, 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
Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& b1v_or_b2v, // in
CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
Vec3d const& b1v, // in
Vec3d const& b2v, // in
CalcT const& dist_a1_a2, // in
CalcT& dist_a1_b1, // out
bool degen_neq_coords = false) // in
{
// calculate dist_a1_a2 and dist_a1_i1
calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
// calculate dist_a1_b1
calculate_dist(a1v, a2v, plane1, b1v, dist_a1_b1);
// if i1 is close to a1 and b1 or b2 is equal to a1
if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))
// if b1 is equal to a1
if (is_endpoint_equal(dist_a1_b1, a1, b1))
{
dist_a1_i1 = 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_i1, a2, b1, b2))
// or b1 is equal to a2
else if (is_endpoint_equal(dist_a1_a2 - dist_a1_b1, a2, b1))
{
dist_a1_i1 = 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;
CalcT dist_a1_b2 = 0;
calculate_dist(a1v, a2v, plane1, b2v, dist_a1_b2);
if (math::equals(dist_a1_b2, c0))
{
dist_a1_b1 = 0;
return true;
}
else if (math::equals(dist_a1_a2 - dist_a1_b2, c0))
{
dist_a1_b1 = dist_a1_a2;
return true;
}
}
// or i1 is on b
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
return segment_ratio<CalcT>(dist_a1_b1, dist_a1_a2).on_segment();
}
template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
@@ -559,15 +642,17 @@ private:
Plane const& plane2, // in
CalcPolicy const& calc_policy, // in
side_info const& sides, // in
Vec3d & ip, // out
CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
intersection_point_flag& ip_flag) // out
CalcT const& dist_a1_a2, // in
CalcT const& dist_b1_b2, // in
Vec3d & ip, // out
CalcT& dist_a1_ip, // out
CalcT& dist_b1_ip, // out
intersection_point_flag& ip_flag) // out
{
Vec3d ip1, ip2;
calc_policy.intersection_points(plane1, plane2, ip1, ip2);
calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
calculate_dist(a1v, a2v, plane1, ip1, dist_a1_ip);
ip = ip1;
// choose the opposite side of the globe if the distance is shorter
@@ -593,7 +678,7 @@ private:
return false;
}
calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip);
calculate_dist(b1v, b2v, plane2, ip, dist_b1_ip);
bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;
if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
@@ -602,7 +687,6 @@ private:
}
// reassign the IP if some endpoints overlap
using geometry::detail::equals::equals_point_point;
if (is_near_a1)
{
if (is_near_b1 && equals_point_point(a1, b1))
@@ -692,20 +776,26 @@ private:
}
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dists(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_i1) // out
static inline void calculate_dist(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
CalcT& dist_a1_a2) // out
{
//CalcT const c0 = 0;
CalcT const c1 = 1;
CalcT const c2 = 2;
CalcT const c4 = 4;
CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
static CalcT const c1 = 1;
CalcT const cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
}
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dist(Vec3d const& a1v, // in
Vec3d const& /*a2v*/, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_i1) // out
{
static CalcT const c1 = 1;
static CalcT const c2 = 2;
static CalcT const c4 = 4;
bool is_forward = true;
CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
@@ -719,7 +809,19 @@ private:
dist_a1_i1 += c4; // += 2pi
}
}
/*
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dists(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_i1) // out
{
calculate_dist(a1v, a2v, plane1, dist_a1_a2);
calculate_dist(a1v, a2v, plane1, i1, dist_a1_i1);
}
*/
// the dist of the ip on the other side of the sphere
template <typename CalcT>
static inline CalcT dist_of_i2(CalcT const& dist_a1_i1)
@@ -758,10 +860,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>
@@ -788,6 +890,13 @@ private:
: ca1 < cb2 ? 4
: 2 );
}
template <typename Point1, typename Point2>
static inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
{
return detail::equals::equals_point_point(point1, point2,
point_in_point_strategy_type());
}
};
struct spherical_segments_calc_policy
@@ -859,7 +968,7 @@ struct spherical_segments_calc_policy
multiply_value(ip2, coord_t(-1));
return true;
}
}
};

View File

@@ -0,0 +1,123 @@
// 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_SPHERICAL_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_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/formulas/interpolate_point_spherical.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/line_interpolate.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace line_interpolate
{
/*!
\brief Interpolate point on a spherical segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\tparam DistanceStrategy The underlying point-point distance strategy
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename DistanceStrategy = distance::haversine<double, CalculationType>
>
class spherical
{
public:
typedef typename DistanceStrategy::radius_type radius_type;
inline spherical()
{}
explicit inline spherical(typename DistanceStrategy::radius_type const& r)
: m_strategy(r)
{}
inline spherical(DistanceStrategy const& s)
: m_strategy(s)
{}
// point-point strategy getters
struct distance_pp_strategy
{
typedef DistanceStrategy type;
};
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
{
return m_strategy;
}
template <typename Point, typename Fraction, typename Distance>
inline void apply(Point const& p0,
Point const& p1,
Fraction const& fraction,
Point & p,
Distance const&) const
{
typedef typename select_calculation_type_alt
<
CalculationType,
Point
>::type calc_t;
formula::interpolate_point_spherical<calc_t> formula;
calc_t angle01;
formula.compute_angle(p0, p1, angle01);
formula.compute_axis(p0, angle01);
calc_t a = angle01 * fraction;
formula.compute_point(a, p);
}
private :
DistanceStrategy m_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef strategy::line_interpolate::spherical<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::line_interpolate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_LINE_INTERPOLATE_HPP

View File

@@ -0,0 +1,172 @@
// 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) 2013-2015 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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.
// 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_SPHERICAL_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within
{
class point_point_on_spheroid
{
private:
template <typename Point1, typename Point2, bool SameUnits>
struct are_same_points
{
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
typedef typename helper_geometry<Point1>::type helper_point_type1;
typedef typename helper_geometry<Point2>::type helper_point_type2;
helper_point_type1 point1_normalized;
strategy::normalize::spherical_point::apply(point1, point1_normalized);
helper_point_type2 point2_normalized;
strategy::normalize::spherical_point::apply(point2, point2_normalized);
return point_point_generic
<
0, dimension<Point1>::value
>::apply(point1_normalized, point2_normalized);
}
};
template <typename Point1, typename Point2>
struct are_same_points<Point1, Point2, false> // points have different units
{
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
typedef typename geometry::select_most_precise
<
typename fp_coordinate_type<Point1>::type,
typename fp_coordinate_type<Point2>::type
>::type calculation_type;
typename helper_geometry
<
Point1, calculation_type, radian
>::type helper_point1, helper_point2;
Point1 point1_normalized = return_normalized<Point1>(point1);
Point2 point2_normalized = return_normalized<Point2>(point2);
geometry::transform(point1_normalized, helper_point1);
geometry::transform(point2_normalized, helper_point2);
return point_point_generic
<
0, dimension<Point1>::value
>::apply(helper_point1, helper_point2);
}
};
public:
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
return are_same_points
<
Point1,
Point2,
boost::is_same
<
typename detail::cs_angular_units<Point1>::type,
typename detail::cs_angular_units<Point2>::type
>::value
>::apply(point1, point2);
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace within
{
struct spherical_point_point
: geometry::detail::within::point_point_on_spheroid
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::spherical_point_point type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::spherical_point_point type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POINT_HPP

View File

@@ -0,0 +1,596 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// 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.
// 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_SPHERICAL_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Point,
typename PointOfSegment = Point,
typename SideStrategy = typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type,
typename CalculationType = void
>
class spherical_winding_base
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
typedef math::detail::constants_on_spheroid<calculation_type, units_t> constants;
/*! subclass to keep state */
class counter
{
int m_count;
//int m_count_n;
int m_count_s;
int m_raw_count;
int m_raw_count_anti;
bool m_touches;
inline int code() const
{
if (m_touches)
{
return 0;
}
if (m_raw_count != 0 && m_raw_count_anti != 0)
{
if (m_raw_count > 0) // right, wrap around south pole
{
return (m_count + m_count_s) == 0 ? -1 : 1;
}
else // left, wrap around north pole
{
//return (m_count + m_count_n) == 0 ? -1 : 1;
// m_count_n is 0
return m_count == 0 ? -1 : 1;
}
}
return m_count == 0 ? -1 : 1;
}
public :
friend class spherical_winding_base;
inline counter()
: m_count(0)
//, m_count_n(0)
, m_count_s(0)
, m_raw_count(0)
, m_raw_count_anti(0)
, m_touches(false)
{}
};
struct count_info
{
explicit count_info(int c = 0, bool ia = false)
: count(c)
, is_anti(ia)
{}
int count;
bool is_anti;
};
public:
typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
{
return m_side_strategy.get_envelope_strategy();
}
typedef typename SideStrategy::disjoint_strategy_type disjoint_strategy_type;
inline disjoint_strategy_type get_disjoint_strategy() const
{
return m_side_strategy.get_disjoint_strategy();
}
typedef typename SideStrategy::equals_point_point_strategy_type equals_point_point_strategy_type;
inline equals_point_point_strategy_type get_equals_point_point_strategy() const
{
return m_side_strategy.get_equals_point_point_strategy();
}
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 covered_by::spherical_point_box disjoint_point_box_strategy_type;
spherical_winding_base()
{}
template <typename Model>
explicit spherical_winding_base(Model const& model)
: m_side_strategy(model)
{}
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state) const
{
bool eq1 = false;
bool eq2 = false;
bool s_antipodal = false;
count_info ci = check_segment(point, s1, s2, state, eq1, eq2, s_antipodal);
if (ci.count != 0)
{
if (! ci.is_anti)
{
int side = 0;
if (ci.count == 1 || ci.count == -1)
{
side = side_equal(point, eq1 ? s1 : s2, ci);
}
else // count == 2 || count == -2
{
if (! s_antipodal)
{
// 1 left, -1 right
side = m_side_strategy.apply(s1, s2, point);
}
else
{
calculation_type const pi = constants::half_period();
calculation_type const s1_lat = get<1>(s1);
calculation_type const s2_lat = get<1>(s2);
side = math::sign(ci.count)
* (pi - s1_lat - s2_lat <= pi // segment goes through north pole
? -1 // going right all points will be on right side
: 1); // going right all points will be on left side
}
}
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for left, 2 for right (or -1/1)
// Side positive thus means RIGHT and LEFTSIDE or LEFT and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * ci.count > 0)
{
state.m_count += ci.count;
}
state.m_raw_count += ci.count;
}
else
{
// Count negated because the segment is on the other side of the globe
// so it is reversed to match this side of the globe
// Assuming geometry wraps around north pole, for segments on the other side of the globe
// the point will always be RIGHT+RIGHTSIDE or LEFT+LEFTSIDE, so side*-count always < 0
//state.m_count_n -= 0;
// Assuming geometry wraps around south pole, for segments on the other side of the globe
// the point will always be RIGHT+LEFTSIDE or LEFT+RIGHTSIDE, so side*-count always > 0
state.m_count_s -= ci.count;
state.m_raw_count_anti -= ci.count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.code();
}
private:
static inline count_info check_segment(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2, bool& s_antipodal)
{
if (check_touch(point, seg1, seg2, state, eq1, eq2, s_antipodal))
{
return count_info(0, false);
}
return calculate_count(point, seg1, seg2, eq1, eq2, s_antipodal);
}
static inline int check_touch(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1,
bool& eq2,
bool& s_antipodal)
{
calculation_type const c0 = 0;
calculation_type const c2 = 2;
calculation_type const pi = constants::half_period();
calculation_type const half_pi = pi / c2;
calculation_type const p_lon = get<0>(point);
calculation_type const s1_lon = get<0>(seg1);
calculation_type const s2_lon = get<0>(seg2);
calculation_type const p_lat = get<1>(point);
calculation_type const s1_lat = get<1>(seg1);
calculation_type const s2_lat = get<1>(seg2);
// NOTE: lat in {-90, 90} and arbitrary lon
// it doesn't matter what lon it is if it's a pole
// so e.g. if one of the segment endpoints is a pole
// then only the other lon matters
bool eq1_strict = longitudes_equal(s1_lon, p_lon);
bool eq2_strict = longitudes_equal(s2_lon, p_lon);
bool eq1_anti = false;
bool eq2_anti = false;
calculation_type const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi);
eq1 = eq1_strict // lon strictly equal to s1
|| (eq1_anti = longitudes_equal(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1
|| math::equals(math::abs(s1_lat), half_pi); // s1 is pole
eq2 = eq2_strict // lon strictly equal to s2
|| (eq2_anti = longitudes_equal(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2
|| math::equals(math::abs(s2_lat), half_pi); // s2 is pole
// segment overlapping pole
calculation_type const s_lon_diff = math::longitude_distance_signed<units_t>(s1_lon, s2_lon);
s_antipodal = math::equals(s_lon_diff, pi);
if (s_antipodal)
{
eq1 = eq2 = eq1 || eq2;
// segment overlapping pole and point is pole
if (math::equals(math::abs(p_lat), half_pi))
{
eq1 = eq2 = true;
}
}
// Both equal p -> segment vertical
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
{
// segment endpoints on the same sides of the globe
if (! s_antipodal)
{
// p's lat between segment endpoints' lats
if ( (s1_lat <= p_lat && s2_lat >= p_lat) || (s2_lat <= p_lat && s1_lat >= p_lat) )
{
if (!eq1_anti || !eq2_anti)
{
state.m_touches = true;
}
}
}
else
{
// going through north or south pole?
if (pi - s1_lat - s2_lat <= pi)
{
if ( (eq1_strict && s1_lat <= p_lat) || (eq2_strict && s2_lat <= p_lat) // north
|| math::equals(p_lat, half_pi) ) // point on north pole
{
state.m_touches = true;
}
else if (! eq1_strict && ! eq2_strict && math::equals(p_lat, -half_pi) ) // point on south pole
{
return false;
}
}
else // south pole
{
if ( (eq1_strict && s1_lat >= p_lat) || (eq2_strict && s2_lat >= p_lat) // south
|| math::equals(p_lat, -half_pi) ) // point on south pole
{
state.m_touches = true;
}
else if (! eq1_strict && ! eq2_strict && math::equals(p_lat, half_pi) ) // point on north pole
{
return false;
}
}
}
return true;
}
return false;
}
// Called if point is not aligned with a vertical segment
static inline count_info calculate_count(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
bool eq1, bool eq2, bool s_antipodal)
{
// If both segment endpoints were poles below checks wouldn't be enough
// but this means that either both are the same or that they are N/S poles
// and therefore the segment is not valid.
// If needed (eq1 && eq2 ? 0) could be returned
calculation_type const c0 = 0;
calculation_type const pi = constants::half_period();
calculation_type const p = get<0>(point);
calculation_type const s1 = get<0>(seg1);
calculation_type const s2 = get<0>(seg2);
calculation_type const s1_p = math::longitude_distance_signed<units_t>(s1, p);
if (s_antipodal)
{
return count_info(s1_p < c0 ? -2 : 2, false); // choose W/E
}
calculation_type const s1_s2 = math::longitude_distance_signed<units_t>(s1, s2);
if (eq1 || eq2) // Point on level s1 or s2
{
return count_info(s1_s2 < c0 ? -1 : 1, // choose W/E
longitudes_equal(p + pi, (eq1 ? s1 : s2)));
}
// Point between s1 and s2
if ( math::sign(s1_p) == math::sign(s1_s2)
&& math::abs(s1_p) < math::abs(s1_s2) )
{
return count_info(s1_s2 < c0 ? -2 : 2, false); // choose W/E
}
calculation_type const s1_p_anti = math::longitude_distance_signed<units_t>(s1, p + pi);
// Anti-Point between s1 and s2
if ( math::sign(s1_p_anti) == math::sign(s1_s2)
&& math::abs(s1_p_anti) < math::abs(s1_s2) )
{
return count_info(s1_s2 < c0 ? -2 : 2, true); // choose W/E
}
return count_info(0, false);
}
// Fix for https://svn.boost.org/trac/boost/ticket/9628
// For floating point coordinates, the <D> coordinate of a point is compared
// with the segment's points using some EPS. If the coordinates are "equal"
// the sides are calculated. Therefore we can treat a segment as a long areal
// geometry having some width. There is a small ~triangular area somewhere
// between the segment's effective area and a segment's line used in sides
// calculation where the segment is on the one side of the line but on the
// other side of a segment (due to the width).
// Below picture assuming D = 1, if D = 0 horiz<->vert, E<->N, RIGHT<->UP.
// For the s1 of a segment going NE the real side is RIGHT but the point may
// be detected as LEFT, like this:
// RIGHT
// ___----->
// ^ O Pt __ __
// EPS __ __
// v__ __ BUT DETECTED AS LEFT OF THIS LINE
// _____7
// _____/
// _____/
// In the code below actually D = 0, so segments are nearly-vertical
// Called when the point is on the same level as one of the segment's points
// but the point is not aligned with a vertical segment
inline int side_equal(Point const& point,
PointOfSegment const& se,
count_info const& ci) const
{
typedef typename coordinate_type<PointOfSegment>::type scoord_t;
typedef typename geometry::detail::cs_angular_units<PointOfSegment>::type units_t;
if (math::equals(get<1>(point), get<1>(se)))
{
return 0;
}
// Create a horizontal segment intersecting the original segment's endpoint
// equal to the point, with the derived direction (E/W).
PointOfSegment ss1, ss2;
set<1>(ss1, get<1>(se));
set<0>(ss1, get<0>(se));
set<1>(ss2, get<1>(se));
scoord_t ss20 = get<0>(se);
if (ci.count > 0)
{
ss20 += small_angle();
}
else
{
ss20 -= small_angle();
}
math::normalize_longitude<units_t>(ss20);
set<0>(ss2, ss20);
// Check the side using this vertical segment
return m_side_strategy.apply(ss1, ss2, point);
}
// 1 deg or pi/180 rad
static inline calculation_type small_angle()
{
return constants::half_period() / calculation_type(180);
};
static inline bool longitudes_equal(calculation_type const& lon1, calculation_type const& lon2)
{
return math::equals(
math::longitude_distance_signed<units_t>(lon1, lon2),
calculation_type(0));
}
SideStrategy m_side_strategy;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Within detection using winding rule in spherical coordinate system.
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\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 CalculationType = void
>
class spherical_winding
: public within::detail::spherical_winding_base
<
Point,
PointOfSegment,
side::spherical_side_formula<CalculationType>,
CalculationType
>
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POLY_WINDING_HPP

Some files were not shown because too many files have changed in this diff Show More