feat():initial version

This commit is contained in:
2026-06-09 20:16:47 +08:00
commit 85fbb3188c
14809 changed files with 3044607 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer for linestrings be asymmetric
\ingroup strategies
\tparam NumericType \tparam_numeric
\details This strategy can be used as DistanceStrategy for the buffer algorithm.
It can be applied for (multi)linestrings. It uses a (potentially) different
distances for left and for right. This means the (multi)linestrings are
interpreted having a direction.
\qbk{
[heading Example]
[buffer_distance_asymmetric]
[heading Output]
[$img/strategies/buffer_distance_asymmetric.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_distance_symmetric distance_symmetric]
}
*/
template<typename NumericType>
class distance_asymmetric
{
public :
//! \brief Constructs the strategy, two distances must be specified
//! \param left The distance (or radius) of the buffer on the left side
//! \param right The distance on the right side
distance_asymmetric(NumericType const& left,
NumericType const& right)
: m_left(left)
, m_right(right)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Returns the distance-value for the specified side
template <typename Point>
inline NumericType apply(Point const& , Point const& ,
buffer_side_selector side) const
{
NumericType result = side == buffer_side_left ? m_left : m_right;
return negative() ? math::abs(result) : result;
}
//! Used internally, returns -1 for deflate, 1 for inflate
inline int factor() const
{
return negative() ? -1 : 1;
}
//! Returns true if both distances are negative
inline bool negative() const
{
return m_left < 0 && m_right < 0;
}
//! Returns the max distance distance up to the buffer will reach
template <typename JoinStrategy, typename EndStrategy>
inline NumericType max_distance(JoinStrategy const& join_strategy,
EndStrategy const& end_strategy) const
{
boost::ignore_unused(join_strategy, end_strategy);
NumericType const left = geometry::math::abs(m_left);
NumericType const right = geometry::math::abs(m_right);
NumericType const dist = (std::max)(left, right);
return (std::max)(join_strategy.max_distance(dist),
end_strategy.max_distance(dist));
}
//! Returns the distance at which the input is simplified before the buffer process
inline NumericType simplify_distance() const
{
NumericType const left = geometry::math::abs(m_left);
NumericType const right = geometry::math::abs(m_right);
return (std::min)(left, right) / 1000.0;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
NumericType m_left;
NumericType m_right;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP

View File

@@ -0,0 +1,107 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer algorithm create buffers with same distances
\ingroup strategies
\tparam NumericType \tparam_numeric
\details This strategy can be used as DistanceStrategy for the buffer algorithm.
It can be applied for all geometries. It uses one distance for left and
for right.
If the distance is negative and used with a (multi)polygon or ring, the
geometry will shrink (deflate) instead of expand (inflate).
\qbk{
[heading Example]
[buffer_distance_symmetric]
[heading Output]
[$img/strategies/buffer_distance_symmetric.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_distance_asymmetric distance_asymmetric]
}
*/
template<typename NumericType>
class distance_symmetric
{
public :
//! \brief Constructs the strategy, a distance must be specified
//! \param distance The distance (or radius) of the buffer
explicit inline distance_symmetric(NumericType const& distance)
: m_distance(distance)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Returns the distance-value
template <typename Point>
inline NumericType apply(Point const& , Point const& ,
buffer_side_selector ) const
{
return negative() ? geometry::math::abs(m_distance) : m_distance;
}
//! Used internally, returns -1 for deflate, 1 for inflate
inline int factor() const
{
return negative() ? -1 : 1;
}
//! Returns true if distance is negative (aka deflate)
inline bool negative() const
{
return m_distance < 0;
}
//! Returns the max distance distance up to the buffer will reach
template <typename JoinStrategy, typename EndStrategy>
inline NumericType max_distance(JoinStrategy const& join_strategy,
EndStrategy const& end_strategy) const
{
boost::ignore_unused(join_strategy, end_strategy);
NumericType const dist = geometry::math::abs(m_distance);
return (std::max)(join_strategy.max_distance(dist),
end_strategy.max_distance(dist));
}
//! Returns the distance at which the input is simplified before the buffer process
inline NumericType simplify_distance() const
{
return geometry::math::abs(m_distance) / 1000.0;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
NumericType m_distance;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP

View File

@@ -0,0 +1,344 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 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_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
#include <cstddef>
#include <algorithm>
#include <vector>
#include <boost/range/begin.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.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/policies/compare.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace convex_hull
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Geometry, typename Point, typename Less>
inline void get_extremes(Geometry const& geometry,
Point& left, Point& right,
Less const& less)
{
bool first = true;
geometry::detail::for_each_range(geometry, [&](auto const& range)
{
if (boost::empty(range))
{
return;
}
// First iterate through this range
// (this two-stage approach avoids many point copies,
// because iterators are kept in memory. Because iterators are
// not persistent (in MSVC) this approach is not applicable
// for more ranges together)
auto left_it = boost::begin(range);
auto right_it = boost::begin(range);
for (auto it = ++boost::begin(range); it != boost::end(range); ++it)
{
if (less(*it, *left_it))
{
left_it = it;
}
if (less(*right_it, *it))
{
right_it = it;
}
}
// Then compare with earlier
if (first)
{
// First time, assign left/right
left = *left_it;
right = *right_it;
first = false;
}
else
{
// Next time, check if this range was left/right from
// the extremes already collected
if (less(*left_it, left))
{
left = *left_it;
}
if (less(right, *right_it))
{
right = *right_it;
}
}
});
}
template
<
typename Geometry,
typename Point,
typename Container,
typename SideStrategy
>
inline void assign_ranges(Geometry const& geometry,
Point const& most_left, Point const& most_right,
Container& lower_points, Container& upper_points,
SideStrategy const& side)
{
geometry::detail::for_each_range(geometry, [&](auto const& range)
{
// Put points in one of the two output sequences
for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
// check if it is lying most_left or most_right from the line
int dir = side.apply(most_left, most_right, *it);
switch(dir)
{
case 1 : // left side
upper_points.push_back(*it);
break;
case -1 : // right side
lower_points.push_back(*it);
break;
// 0: on line most_left-most_right,
// or most_left, or most_right,
// -> all never part of hull
}
}
});
}
template <typename Range, typename Less>
inline void sort(Range& range, Less const& less)
{
std::sort(boost::begin(range), boost::end(range), less);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Graham scan strategy to calculate convex hull
\ingroup strategies
*/
template <typename InputGeometry, typename OutputPoint>
class graham_andrew
{
public :
typedef OutputPoint point_type;
typedef InputGeometry geometry_type;
private:
typedef typename cs_tag<point_type>::type cs_tag;
typedef typename std::vector<point_type> container_type;
typedef typename std::vector<point_type>::const_iterator iterator;
typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
class partitions
{
friend class graham_andrew;
container_type m_lower_hull;
container_type m_upper_hull;
container_type m_copied_input;
};
public:
typedef partitions state_type;
inline void apply(InputGeometry const& geometry, partitions& state) const
{
// First pass.
// Get min/max (in most cases left / right) points
// This makes use of the geometry::less/greater predicates
// For the left boundary it is important that multiple points
// are sorted from bottom to top. Therefore the less predicate
// does not take the x-only template parameter (this fixes ticket #6019.
// For the right boundary it is not necessary (though also not harmful),
// because points are sorted from bottom to top in a later stage.
// For symmetry and to get often more balanced lower/upper halves
// we keep it.
typedef typename geometry::point_type<InputGeometry>::type point_type;
point_type most_left, most_right;
// TODO: User-defined CS-specific less-compare
geometry::less<point_type> less;
detail::get_extremes(geometry, most_left, most_right, less);
container_type lower_points, upper_points;
// TODO: User-defiend CS-specific side strategy
typename strategy::side::services::default_strategy<cs_tag>::type side;
// Bounding left/right points
// Second pass, now that extremes are found, assign all points
// in either lower, either upper
detail::assign_ranges(geometry, most_left, most_right,
lower_points, upper_points,
side);
// Sort both collections, first on x(, then on y)
detail::sort(lower_points, less);
detail::sort(upper_points, less);
// And decide which point should be in the final hull
build_half_hull<-1>(lower_points, state.m_lower_hull,
most_left, most_right,
side);
build_half_hull<1>(upper_points, state.m_upper_hull,
most_left, most_right,
side);
}
template <typename OutputIterator>
inline void result(partitions const& state,
OutputIterator out,
bool clockwise,
bool closed) const
{
if (clockwise)
{
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
}
else
{
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
}
}
private:
template <int Factor, typename SideStrategy>
static inline void build_half_hull(container_type const& input,
container_type& output,
point_type const& left, point_type const& right,
SideStrategy const& side)
{
output.push_back(left);
for(iterator it = input.begin(); it != input.end(); ++it)
{
add_to_hull<Factor>(*it, output, side);
}
add_to_hull<Factor>(right, output, side);
}
template <int Factor, typename SideStrategy>
static inline void add_to_hull(point_type const& p, container_type& output,
SideStrategy const& side)
{
output.push_back(p);
std::size_t output_size = output.size();
while (output_size >= 3)
{
rev_iterator rit = output.rbegin();
point_type const last = *rit++;
point_type const& last2 = *rit++;
if (Factor * side.apply(*rit, last, last2) <= 0)
{
// Remove last two points from stack, and add last again
// This is much faster then erasing the one but last.
output.pop_back();
output.pop_back();
output.push_back(last);
output_size--;
}
else
{
return;
}
}
}
template <typename OutputIterator>
static inline void output_ranges(container_type const& first, container_type const& second,
OutputIterator out, bool closed)
{
std::copy(boost::begin(first), boost::end(first), out);
BOOST_GEOMETRY_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);
std::copy(++boost::rbegin(second), // skip the first Point
closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open
out);
typedef typename boost::range_size<container_type>::type size_type;
size_type const count = boost::size(first) + boost::size(second) - 1;
// count describes a closed case but comparison with min size of closed
// gives the result compatible also with open
// here core_detail::closure::minimum_ring_size<closed> could be used
if (count < 4)
{
// there should be only one missing
*out++ = *boost::begin(first);
}
}
};
}} // namespace strategy::convex_hull
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
template <typename InputGeometry, typename OutputPoint>
struct strategy_convex_hull<InputGeometry, OutputPoint, cartesian_tag>
{
typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;
};
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP

View File

@@ -0,0 +1,110 @@
// 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.
// 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.
// 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_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
#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>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
struct decide_within
{
static inline bool apply(int side, bool& result)
{
if (side != 1)
{
result = false;
return false;
}
return true; // continue
}
};
struct decide_covered_by
{
static inline bool apply(int side, bool& result)
{
if (side != 1)
{
result = side >= 0;
return false;
}
return true; // continue
}
};
// WARNING
// 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 Decide = decide_within>
struct point_in_box_by_side
{
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
boost::array<typename point_type<Box>::type, 5> bp;
geometry::detail::assign_box_corners_oriented<true>(box, bp);
bp[4] = bp[0];
bool result = true;
side_strategy_type strategy;
boost::ignore_unused(strategy);
for (int i = 1; i < 5; i++)
{
int const side = strategy.apply(point, bp[i - 1], bp[i]);
if (! Decide::apply(side, result))
{
return result;
}
}
return result;
}
};
} // namespace within
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP

View File

@@ -0,0 +1,60 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-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_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_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
{
namespace strategy { namespace within
{
template
<
typename Point1, typename Point2,
typename CSTag = typename cs_tag<Point1>::type
>
struct point_in_point
: strategy::within::cartesian_point_point
{};
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, spherical_equatorial_tag>
: strategy::within::spherical_point_point
{};
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, spherical_polar_tag>
: strategy::within::spherical_point_point
{};
template <typename Point1, typename Point2>
struct point_in_point<Point1, Point2, geographic_tag>
: strategy::within::spherical_point_point
{};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP

View File

@@ -0,0 +1,206 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using winding rule, but checking if enclosing ring is
counter clockwise and, if so, reverses the result
\ingroup strategies
\tparam Point \tparam_point
\tparam Reverse True if parameter should be reversed
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
bool Reverse,
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class oriented_winding
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type strategy_side_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
calculation_type m_sum_area;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
inline int clockwise_oriented_code() const
{
return (m_sum_area > 0) ? code() : -code();
}
inline int oriented_code() const
{
return Reverse
? -clockwise_oriented_code()
: clockwise_oriented_code();
}
public :
friend class oriented_winding;
inline counter()
: m_count(0)
, m_touches(false)
, m_sum_area(0)
{}
inline void add_to_area(calculation_type triangle)
{
m_sum_area += triangle;
}
};
template <size_t D>
static inline int check_touch(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
{
state.m_touches = true;
}
return 0;
}
template <size_t D>
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
// Check if one of segment endpoints is at same level of point
bool eq1 = math::equals(s1, p);
bool eq2 = math::equals(s2, p);
if (eq1 && eq2)
{
// Both equal p -> segment is horizontal (or vertical for D=0)
// The only thing which has to be done is check if point is ON segment
return check_touch<1 - D>(point, seg1, seg2, state);
}
return
eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
: 0;
}
public :
// 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)
{
state.add_to_area(get<0>(s2) * get<1>(s1) - get<0>(s1) * get<1>(s2));
int count = check_segment<1>(point, s1, s2, state);
if (count != 0)
{
int side = strategy_side_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 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.oriented_code();
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP

View File

@@ -0,0 +1,131 @@
// 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-2020.
// Modifications copyright (c) 2013-2020 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_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.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/spherical/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
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_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this coordinate system.",
Point, PointOfSegment, CSTag);
};
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, cartesian_tag>
{
typedef within::cartesian_winding<void, void, CalculationType> type;
};
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type,
CalculationType
> type;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\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 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 winding
: public within::detail::winding_base_type
<
Point, PointOfSegment, CalculationType
>::type
{
typedef typename within::detail::winding_base_type
<
Point, PointOfSegment, CalculationType
>::type base_t;
public:
winding() {}
template <typename Model>
explicit winding(Model const& model)
: base_t(model)
{}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP

View File

@@ -0,0 +1,322 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 1995, 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 1995 Maarten Hilferink, Amsterdam, the Netherlands
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, 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.
// 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_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
#include <cstddef>
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <iostream>
#endif
#include <vector>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/distance.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/io/dsv/write.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace simplify
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/*!
\brief Small wrapper around a point, with an extra member "included"
\details
It has a const-reference to the original point (so no copy here)
\tparam the enclosed point type
*/
template<typename Point>
struct douglas_peucker_point
{
Point const& p;
bool included;
inline douglas_peucker_point(Point const& ap)
: p(ap)
, included(false)
{}
// Necessary for proper compilation
inline douglas_peucker_point<Point> operator=(douglas_peucker_point<Point> const& )
{
return douglas_peucker_point<Point>(*this);
}
};
template
<
typename Point,
typename PointDistanceStrategy,
typename LessCompare
= std::less
<
typename strategy::distance::services::return_type
<
PointDistanceStrategy,
Point, Point
>::type
>
>
class douglas_peucker
: LessCompare // for empty base optimization
{
public :
// See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954
// Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more.
// For now we have to take the real distance.
typedef PointDistanceStrategy distance_strategy_type;
// typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;
typedef typename strategy::distance::services::return_type
<
distance_strategy_type,
Point, Point
>::type distance_type;
douglas_peucker()
{}
douglas_peucker(LessCompare const& less_compare)
: LessCompare(less_compare)
{}
private :
typedef detail::douglas_peucker_point<Point> dp_point_type;
typedef typename std::vector<dp_point_type>::iterator iterator_type;
LessCompare const& less() const
{
return *this;
}
inline void consider(iterator_type begin,
iterator_type end,
distance_type const& max_dist,
int& n,
distance_strategy_type const& ps_distance_strategy) const
{
std::size_t size = end - begin;
// size must be at least 3
// because we want to consider a candidate point in between
if (size <= 2)
{
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
if (begin != end)
{
std::cout << "ignore between " << dsv(begin->p)
<< " and " << dsv((end - 1)->p)
<< " size=" << size << std::endl;
}
std::cout << "return because size=" << size << std::endl;
#endif
return;
}
iterator_type last = end - 1;
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "find between " << dsv(begin->p)
<< " and " << dsv(last->p)
<< " size=" << size << std::endl;
#endif
// Find most far point, compare to the current segment
//geometry::segment<Point const> s(begin->p, last->p);
distance_type md(-1.0); // any value < 0
iterator_type candidate;
for(iterator_type it = begin + 1; it != last; ++it)
{
distance_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "consider " << dsv(it->p)
<< " at " << double(dist)
<< ((dist > max_dist) ? " maybe" : " no")
<< std::endl;
#endif
if ( less()(md, dist) )
{
md = dist;
candidate = it;
}
}
// If a point is found, set the include flag
// and handle segments in between recursively
if ( less()(max_dist, md) )
{
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "use " << dsv(candidate->p) << std::endl;
#endif
candidate->included = true;
n++;
consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
consider(candidate, end, max_dist, n, ps_distance_strategy);
}
}
public :
template <typename Range, typename OutputIterator>
inline OutputIterator apply(Range const& range,
OutputIterator out,
distance_type max_distance) const
{
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "max distance: " << max_distance
<< std::endl << std::endl;
#endif
distance_strategy_type strategy;
// Copy coordinates, a vector of references to all points
std::vector<dp_point_type> ref_candidates(boost::begin(range),
boost::end(range));
// Include first and last point of line,
// they are always part of the line
int n = 2;
ref_candidates.front().included = true;
ref_candidates.back().included = true;
// Get points, recursively, including them if they are further away
// than the specified distance
consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
// Copy included elements to the output
for(typename std::vector<dp_point_type>::const_iterator it
= boost::begin(ref_candidates);
it != boost::end(ref_candidates);
++it)
{
if (it->included)
{
// copy-coordinates does not work because OutputIterator
// does not model Point (??)
//geometry::convert(it->p, *out);
*out = it->p;
out++;
}
}
return out;
}
};
}
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Implements the simplify algorithm.
\ingroup strategies
\details The douglas_peucker strategy simplifies a linestring, ring or
vector of points using the well-known Douglas-Peucker algorithm.
\tparam Point the point type
\tparam PointDistanceStrategy point-segment distance strategy to be used
\note This strategy uses itself a point-segment-distance strategy which
can be specified
\author Barend and Maarten, 1995/1996
\author Barend, revised for Generic Geometry Library, 2008
*/
/*
For the algorithm, see for example:
- http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
*/
template
<
typename Point,
typename PointDistanceStrategy
>
class douglas_peucker
{
public :
typedef PointDistanceStrategy distance_strategy_type;
typedef typename detail::douglas_peucker
<
Point,
PointDistanceStrategy
>::distance_type distance_type;
template <typename Range, typename OutputIterator>
static inline OutputIterator apply(Range const& range,
OutputIterator out,
distance_type const& max_distance)
{
namespace services = strategy::distance::services;
typedef typename services::comparable_type
<
PointDistanceStrategy
>::type comparable_distance_strategy_type;
return detail::douglas_peucker
<
Point, comparable_distance_strategy_type
>().apply(range, out,
services::result_from_distance
<
comparable_distance_strategy_type, Point, Point
>::apply(comparable_distance_strategy_type(),
max_distance)
);
}
};
}} // namespace strategy::simplify
namespace traits {
template <typename P>
struct point_type<geometry::strategy::simplify::detail::douglas_peucker_point<P> >
{
typedef P type;
};
} // namespace traits
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/area.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_HPP

View File

@@ -0,0 +1,63 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_CARTESIAN_HPP
#include <boost/geometry/strategy/cartesian/area.hpp>
#include <boost/geometry/strategies/area/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace area
{
template <typename CalculationType = void>
struct cartesian : strategies::detail::cartesian_base
{
template <typename Geometry>
static auto area(Geometry const&)
{
return strategy::area::cartesian<CalculationType>();
}
};
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, cartesian_tag>
{
using type = strategies::area::cartesian<>;
};
template <typename CT>
struct strategy_converter<strategy::area::cartesian<CT> >
{
static auto get(strategy::area::cartesian<CT> const&)
{
return strategies::area::cartesian<CT>();
}
};
} // namespace services
}} // namespace strategies::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_CARTESIAN_HPP

View File

@@ -0,0 +1,82 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_GEOGRAPHIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_GEOGRAPHIC_HPP
#include <boost/geometry/strategy/geographic/area.hpp>
#include <boost/geometry/strategies/area/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace area
{
template
<
typename FormulaPolicy = strategy::andoyer,
std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic : strategies::detail::geographic_base<Spheroid>
{
using base_t = strategies::detail::geographic_base<Spheroid>;
public:
geographic()
: base_t()
{}
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
template <typename Geometry>
auto area(Geometry const&) const
{
return strategy::area::geographic
<
FormulaPolicy, SeriesOrder, Spheroid, CalculationType
>(base_t::m_spheroid);
}
};
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, geographic_tag>
{
using type = strategies::area::geographic<>;
};
template <typename FP, std::size_t SO, typename S, typename CT>
struct strategy_converter<strategy::area::geographic<FP, SO, S, CT> >
{
static auto get(strategy::area::geographic<FP, SO, S, CT> const& strategy)
{
return strategies::area::geographic<FP, SO, S, CT>(strategy.model());
}
};
} // namespace services
}} // namespace strategies::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_GEOGRAPHIC_HPP

View File

@@ -0,0 +1,55 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_SERVICES_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_SERVICES_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace area {
namespace services
{
template
<
typename Geometry,
typename CSTag = typename geometry::cs_tag<Geometry>::type
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Geometry's coordinate system.",
Geometry, CSTag);
};
template <typename Strategy>
struct strategy_converter
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy);
};
} // namespace services
}} // namespace strategies::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_SERVICES_HPP

View File

@@ -0,0 +1,94 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_SPHERICAL_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_SPHERICAL_HPP
#include <boost/geometry/strategy/spherical/area.hpp>
#include <boost/geometry/strategies/area/services.hpp>
#include <boost/geometry/strategies/detail.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace area
{
template
<
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical : strategies::detail::spherical_base<RadiusTypeOrSphere>
{
using base_t = strategies::detail::spherical_base<RadiusTypeOrSphere>;
public:
spherical()
: base_t()
{}
template <typename RadiusOrSphere>
explicit spherical(RadiusOrSphere const& radius_or_sphere)
: base_t(radius_or_sphere)
{}
template <typename Geometry>
auto area(Geometry const&) const
{
return strategy::area::spherical
<
typename base_t::radius_type, CalculationType
>(base_t::m_radius);
}
};
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, spherical_tag>
{
using type = strategies::area::spherical<>;
};
template <typename Geometry>
struct default_strategy<Geometry, spherical_equatorial_tag>
{
using type = strategies::area::spherical<>;
};
template <typename Geometry>
struct default_strategy<Geometry, spherical_polar_tag>
{
using type = strategies::area::spherical<>;
};
template <typename R, typename CT>
struct strategy_converter<strategy::area::spherical<R, CT> >
{
static auto get(strategy::area::spherical<R, CT> const& strategy)
{
return strategies::area::spherical<R, CT>(strategy.model());
}
};
} // namespace services
}} // namespace strategies::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_SPHERICAL_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/algorithms/area_result.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP

View File

@@ -0,0 +1,42 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2020 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_AZIMUTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace azimuth { namespace services
{
/*!
\brief Traits class binding a default azimuth strategy to a coordinate system
\ingroup util
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
template <typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this type.",
CSTag);
};
}}} // namespace strategy::azimuth::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP

View File

@@ -0,0 +1,103 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_CARTESIAN_BUFFER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*
A Buffer-join strategy gets 4 input points.
On the two consecutive segments s1 and s2 (joining at vertex v):
The lines from parallel at s1, s2 (at buffer-distance) end/start
in two points perpendicular to the segments: p1 and p2.
These parallel lines interesct in point ip
(s2)
|
|
^
|
(p2) |(v)
* +----<--- (s1)
x(ip) *(p1)
So, in clockwise order:
v : vertex point
p1: perpendicular on left side of segment1<1> (perp1)
ip: intersection point
p2: perpendicular on left side of segment2<0> (perp2)
*/
/*!
\brief Enumerates options for side of buffer (left/right w.r.t. directed
segment)
\ingroup enum
\details Around a linestring, a buffer can be defined left or right.
Around a polygon, assumed clockwise internally,
a buffer is either on the left side (inflates the polygon), or on the
right side (deflates the polygon)
*/
enum buffer_side_selector { buffer_side_left, buffer_side_right };
/*!
\brief Enumerates types of pieces (parts of buffer) around geometries
\ingroup enum
*/
enum piece_type
{
buffered_segment,
buffered_join,
buffered_round_end,
buffered_flat_end,
buffered_point,
buffered_concave, // always on the inside
piece_type_unknown
};
/*!
\brief Enumerates types of joins
\ingroup enum
*/
enum join_selector
{
join_convex,
join_concave,
join_continue, // collinear, next segment touches previous segment
join_spike // collinear, with overlap, next segment goes back
};
/*!
\brief Enumerates types of result codes from buffer strategies
\ingroup enum
*/
enum result_code
{
result_normal,
result_error_numerical,
result_no_output
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP

View File

@@ -0,0 +1,106 @@
// Boost.Geometry
// Copyright (c) 2020, 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_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_HPP
#include <boost/geometry/strategies/area/cartesian.hpp>
#include <boost/geometry/strategies/envelope/cartesian.hpp>
#include <boost/geometry/strategies/expand/cartesian.hpp>
namespace boost { namespace geometry
{
namespace strategies
{
template <typename CalculationType = void>
struct cartesian : strategies::detail::cartesian_base
{
// area
template <typename Geometry>
static auto area(Geometry const&)
{
return strategy::area::cartesian<CalculationType>();
}
// envelope
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_box();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_segment<CalculationType>();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_polysegmental_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian<CalculationType>();
}
// expand
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_point();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_box();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_segment();
}
};
} // namespace strategies
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/area.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_SURVEYOR_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/area.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP

View File

@@ -0,0 +1,51 @@
// 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_CARTESIAN_AZIMUTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace azimuth
{
template
<
typename CalculationType = void
>
class cartesian
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef strategy::azimuth::cartesian<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::azimuth
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP

View File

@@ -0,0 +1,395 @@
// 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 2015, 2016, 2017, 2019.
// Modifications copyright (c) 2016-2019, 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_BOX_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct box_within_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
return bing_min <= bed_min && bed_max <= bing_max // contained in containing
&& bed_min < bed_max; // interiors overlap
}
};
struct box_covered_by_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
return bed_min >= bing_min && bed_max <= bing_max;
}
};
struct box_within_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_ed)
{
return diff_ed > CalcT(0);
}
};
struct box_covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const&)
{
return true;
}
};
template <typename Geometry,
typename CoordCheck,
typename InteriorCheck>
struct box_longitude_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
typedef typename select_most_precise
<
BoxContainedValue,
BoxContainingValue
>::type calc_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(bed_min, bed_max, bing_min, bing_max))
{
return true;
}
// min <= max <=> diff >= 0
calc_t const diff_ed = bed_max - bed_min;
calc_t const diff_ing = bing_max - bing_min;
// if containing covers the whole globe it contains all
if (diff_ing >= constants::period())
{
return true;
}
// if containing is smaller it cannot contain
// and check interior (within vs covered_by)
if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
{
return false;
}
// calculate positive longitude translation with bing_min as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
// max of contained translated into the containing origin must be lesser than max of containing
return bing_min + diff_min + diff_ed <= bing_max
/*|| bing_max - diff_min - diff_ed >= bing_min*/;
}
};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename CSTag,
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_box_box_loop
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
{
assert_dimension_equal<Box1, Box2>();
if (! SubStrategy<Box1, Dimension, CSTag>::apply(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
get<min_corner, Dimension>(b_containing),
get<max_corner, Dimension>(b_containing)
)
)
{
return false;
}
return within::detail::relate_box_box_loop
<
SubStrategy, CSTag,
Dimension + 1, DimensionCount
>::apply(b_contained, b_containing);
}
};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename CSTag,
std::size_t DimensionCount
>
struct relate_box_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& , Box2 const& )
{
return true;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
// for backward compatibility
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct box_within_range
: within::detail::box_within_coord
{};
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct box_covered_by_range
: within::detail::box_covered_by_coord
{};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Geometry>
struct box_within_range<Geometry, 0, spherical_tag>
: within::detail::box_longitude_range
<
Geometry,
within::detail::box_within_coord,
within::detail::box_within_longitude_diff
>
{};
template <typename Geometry>
struct box_covered_by_range<Geometry, 0, spherical_tag>
: within::detail::box_longitude_range
<
Geometry,
within::detail::box_covered_by_coord,
within::detail::box_covered_by_longitude_diff
>
{};
// for backward compatibility
template
<
typename B1,
typename B2,
template <typename, std::size_t, typename> class SubStrategy = box_within_range
>
struct box_in_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
typedef typename tag_cast
<
typename geometry::cs_tag<Box1>::type,
spherical_tag
>::type cs_tag;
return within::detail::relate_box_box_loop
<
SubStrategy, cs_tag,
0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
struct cartesian_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return within::detail::relate_box_box_loop
<
box_within_range,
cartesian_tag,
0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
struct spherical_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return within::detail::relate_box_box_loop
<
box_within_range,
spherical_tag,
0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
} // namespace within
namespace covered_by
{
struct cartesian_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return within::detail::relate_box_box_loop
<
strategy::within::box_covered_by_range,
cartesian_tag,
0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
struct spherical_box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return within::detail::relate_box_box_loop
<
strategy::within::box_covered_by_range,
spherical_tag,
0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
}
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace within { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef cartesian_box_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef spherical_box_box type;
};
}} // namespace within::services
namespace covered_by { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef cartesian_box_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef spherical_box_box type;
};
}} // namespace covered_by::services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP

View File

@@ -0,0 +1,114 @@
// 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)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_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>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create flat ends
\ingroup strategies
\details This strategy can be used as EndStrategy for the buffer algorithm.
It creates a flat end for each linestring-end. It can be applied
for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_end_flat]
[heading Output]
[$img/strategies/buffer_end_flat.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_end_round end_round]
}
*/
class end_flat
{
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a flat end
template <typename Point, typename RangeOut, typename DistanceStrategy>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
Point const& perp_right_point,
buffer_side_selector side,
DistanceStrategy const& distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
bool reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
|| (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right)
;
if (reversed)
{
range_out.push_back(perp_right_point);
range_out.push_back(perp_left_point);
}
else
{
range_out.push_back(perp_left_point);
range_out.push_back(perp_right_point);
}
// Don't add the ultimate_point (endpoint of the linestring).
// The buffer might be generated completely at one side.
// In other cases it does no harm but is further useless
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
//! Returns the piece_type (flat end)
static inline piece_type get_piece_type()
{
return buffered_flat_end;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP

View File

@@ -0,0 +1,182 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Menelaos Karavelas, 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_BUFFER_END_ROUND_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create rounded ends
\ingroup strategies
\details This strategy can be used as EndStrategy for the buffer algorithm.
It creates a rounded end for each linestring-end. It can be applied
for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_end_round]
[heading Output]
[$img/strategies/buffer_end_round.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_end_flat end_flat]
}
*/
class end_round
{
private :
std::size_t m_points_per_circle;
template
<
typename Point,
typename PromotedType,
typename DistanceType,
typename RangeOut
>
inline void generate_points(Point const& point,
PromotedType alpha, // by value
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
std::size_t point_buffer_count = m_points_per_circle;
PromotedType const diff = two_pi / PromotedType(point_buffer_count);
// For half circle:
point_buffer_count /= 2;
point_buffer_count++;
for (std::size_t i = 0; i < point_buffer_count; i++, alpha -= diff)
{
typename boost::range_value<RangeOut>::type p;
set<0>(p, get<0>(point) + buffer_distance * cos(alpha));
set<1>(p, get<1>(point) + buffer_distance * sin(alpha));
range_out.push_back(p);
}
}
template <typename T, typename P1, typename P2>
static inline T calculate_angle(P1 const& from_point, P2 const& to_point)
{
typedef P1 vector_type;
vector_type v = from_point;
geometry::subtract_point(v, to_point);
return atan2(geometry::get<1>(v), geometry::get<0>(v));
}
public :
//! \brief Constructs the strategy
//! \param points_per_circle points which would be used for a full circle
//! (if points_per_circle is smaller than 4, it is internally set to 4)
explicit inline end_round(std::size_t points_per_circle = 90)
: m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a flat end
template <typename Point, typename RangeOut, typename DistanceStrategy>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
Point const& perp_right_point,
buffer_side_selector side,
DistanceStrategy const& distance,
RangeOut& range_out) const
{
boost::ignore_unused(perp_left_point);
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
promoted_type const alpha
= calculate_angle<promoted_type>(penultimate_point, ultimate_point)
- geometry::math::half_pi<promoted_type>();
if (geometry::math::equals(dist_left, dist_right))
{
generate_points(ultimate_point, alpha, dist_left, range_out);
}
else
{
static promoted_type const two = 2.0;
promoted_type const dist_average = (dist_left + dist_right) / two;
promoted_type const dist_half
= (side == buffer_side_right
? (dist_right - dist_left)
: (dist_left - dist_right)) / two;
Point shifted_point;
set<0>(shifted_point, get<0>(ultimate_point) + dist_half * cos(alpha));
set<1>(shifted_point, get<1>(ultimate_point) + dist_half * sin(alpha));
generate_points(shifted_point, alpha, dist_average, range_out);
}
if (m_points_per_circle % 2 == 1)
{
// For a half circle, if the number of points is not even,
// we should insert the end point too, to generate a full cap
range_out.push_back(perp_right_point);
}
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
//! Returns the piece_type (flat end)
static inline piece_type get_piece_type()
{
return buffered_round_end;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP

View File

@@ -0,0 +1,142 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_CARTESIAN_BUFFER_JOIN_MITER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.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
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create sharp corners
\ingroup strategies
\details This strategy can be used as JoinStrategy for the buffer algorithm.
It creates a sharp corners around each convex vertex. It can be applied
for (multi)linestrings and (multi)polygons.
If corners are sharp by themselves, the miters might become very long. Therefore
there is a limit (miter_limit), in terms of the used distance, which limits
their length. The miter is not changed to a bevel form (as done in some
other software), it is just adapted to the specified miter_limit but keeps
its miter form.
If the buffer distance is 5.0, and the miter limit is 2.0, generated points
will be located at a distance of at most 10.0 (2*5) units.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_join_miter]
[heading Output]
[$img/strategies/buffer_join_miter.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
}
*/
class join_miter
{
public:
//! \brief Constructs the strategy
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
explicit inline join_miter(double miter_limit = 5.0)
: m_miter_limit(valid_limit(miter_limit))
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a sharp shape around a vertex
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
geometry::equal_to<Point> equals;
if (equals(ip, vertex))
{
return false;
}
if (equals(perp1, perp2))
{
return false;
}
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
Point p = ip;
// Check the distance ip-vertex (= miter distance)
// (We calculate it manually (not using Pythagoras strategy) to reuse
// dx and dy)
coordinate_type const dx = get<0>(p) - get<0>(vertex);
coordinate_type const dy = get<1>(p) - get<1>(vertex);
promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
promoted_type const max_distance
= m_miter_limit * geometry::math::abs(buffer_distance);
if (distance > max_distance)
{
BOOST_GEOMETRY_ASSERT(distance != 0.0);
promoted_type const proportion = max_distance / distance;
set<0>(p, get<0>(vertex) + dx * proportion);
set<1>(p, get<1>(vertex) + dy * proportion);
}
range_out.push_back(perp1);
range_out.push_back(p);
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
inline NumericType max_distance(NumericType const& distance) const
{
return distance * m_miter_limit;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
double valid_limit(double miter_limit) const
{
if (miter_limit < 1.0)
{
// It should always exceed the buffer distance
miter_limit = 1.0;
}
return miter_limit;
}
double m_miter_limit;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP

View File

@@ -0,0 +1,187 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Menelaos Karavelas, 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_BUFFER_JOIN_ROUND_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
#include <algorithm>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
#include <iostream>
#include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create rounded corners
\ingroup strategies
\details This strategy can be used as JoinStrategy for the buffer algorithm.
It creates a rounded corners around each convex vertex. It can be applied
for (multi)linestrings and (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_join_round]
[heading Output]
[$img/strategies/buffer_join_round.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]
}
*/
class join_round
{
public :
//! \brief Constructs the strategy
//! \param points_per_circle points which would be used for a full circle
explicit inline join_round(std::size_t points_per_circle = 90)
: m_points_per_circle(points_per_circle)
{}
private :
template
<
typename PromotedType,
typename Point,
typename DistanceType,
typename RangeOut
>
inline void generate_points(Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
PromotedType const angle1 = atan2(dy1, dx1);
PromotedType angle2 = atan2(dy2, dx2);
while (angle2 > angle1)
{
angle2 -= two_pi;
}
PromotedType const angle_diff = angle1 - angle2;
// Divide the angle into an integer amount of steps to make it
// visually correct also for a low number of points / circle
// If a full circle is divided into 3 parts (e.g. angle is 125),
// the one point in between must still be generated
// The calculation below:
// - generates 1 point in between for an angle of 125 based on 3 points
// - generates 0 points in between for an angle of 90 based on 4 points
std::size_t const n = (std::max)(static_cast<std::size_t>(
ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
PromotedType a = angle1 - diff;
// Walk to n - 1 to avoid generating the last point
for (std::size_t i = 0; i < n - 1; i++, a -= diff)
{
Point p;
set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
range_out.push_back(p);
}
}
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a rounded shape around a vertex
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename boost::range_value<RangeOut>::type output_point_type;
typedef typename geometry::select_most_precise
<
typename geometry::select_most_precise
<
coordinate_type,
typename geometry::coordinate_type<output_point_type>::type
>::type,
double
>::type promoted_type;
geometry::equal_to<Point> equals;
if (equals(perp1, perp2))
{
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
#endif
return false;
}
// Generate 'vectors'
coordinate_type vix = (get<0>(ip) - get<0>(vertex));
coordinate_type viy = (get<1>(ip) - get<1>(vertex));
promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);
DistanceType const bd = geometry::math::abs(buffer_distance);
promoted_type prop = bd / length_i;
Point bp;
set<0>(bp, get<0>(vertex) + vix * prop);
set<1>(bp, get<1>(vertex) + viy * prop);
range_out.push_back(perp1);
generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
std::size_t m_points_per_circle;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP

View File

@@ -0,0 +1,154 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
#include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
class join_round_by_divide
{
public :
inline join_round_by_divide(std::size_t max_level = 4)
: m_max_level(max_level)
{}
template
<
typename PromotedType,
typename Point,
typename DistanceType,
typename RangeOut
>
inline void mid_points(Point const& vertex,
Point const& p1, Point const& p2,
DistanceType const& buffer_distance,
RangeOut& range_out,
std::size_t level = 1) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
// Generate 'vectors'
coordinate_type const vp1_x = get<0>(p1) - get<0>(vertex);
coordinate_type const vp1_y = get<1>(p1) - get<1>(vertex);
coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex));
coordinate_type const vp2_y = (get<1>(p2) - get<1>(vertex));
// Average them to generate vector in between
coordinate_type const two = 2;
coordinate_type const v_x = (vp1_x + vp2_x) / two;
coordinate_type const v_y = (vp1_y + vp2_y) / two;
PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);
PromotedType prop = buffer_distance / length2;
Point mid_point;
set<0>(mid_point, get<0>(vertex) + v_x * prop);
set<1>(mid_point, get<1>(vertex) + v_y * prop);
if (level < m_max_level)
{
mid_points<PromotedType>(vertex, p1, mid_point, buffer_distance, range_out, level + 1);
}
range_out.push_back(mid_point);
if (level < m_max_level)
{
mid_points<PromotedType>(vertex, mid_point, p2, buffer_distance, range_out, level + 1);
}
}
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
geometry::equal_to<Point> equals;
if (equals(perp1, perp2))
{
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
#endif
return false;
}
// Generate 'vectors'
coordinate_type const vix = (get<0>(ip) - get<0>(vertex));
coordinate_type const viy = (get<1>(ip) - get<1>(vertex));
promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy);
promoted_type const bd = geometry::math::abs(buffer_distance);
promoted_type prop = bd / length_i;
Point bp;
set<0>(bp, get<0>(vertex) + vix * prop);
set<1>(bp, get<1>(vertex) + viy * prop);
range_out.push_back(perp1);
if (m_max_level > 1)
{
mid_points<promoted_type>(vertex, perp1, bp, bd, range_out);
range_out.push_back(bp);
mid_points<promoted_type>(vertex, bp, perp2, bd, range_out);
}
else if (m_max_level == 1)
{
range_out.push_back(bp);
}
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
private :
std::size_t m_max_level;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP

View File

@@ -0,0 +1,120 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
// 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
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP
#include <cstddef>
#include <boost/range/value_type.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
{
namespace strategy { namespace buffer
{
/*!
\brief Create a circular buffer around a point
\ingroup strategies
\details This strategy can be used as PointStrategy for the buffer algorithm.
It creates a circular buffer around a point. It can be applied
for points and multi_points, but also for a linestring (if it is degenerate,
so consisting of only one point) and for polygons (if it is degenerate).
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_point_circle]
[heading Output]
[$img/strategies/buffer_point_circle.png]
[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
{
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 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 geometry::select_most_precise
<
typename geometry::select_most_precise
<
typename geometry::coordinate_type<Point>::type,
typename geometry::coordinate_type<output_point_type>::type
>::type,
double
>::type promoted_type;
promoted_type const buffer_distance = distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left);
promoted_type const two_pi = geometry::math::two_pi<promoted_type>();
promoted_type const diff = two_pi / promoted_type(m_count);
promoted_type a = 0;
for (std::size_t i = 0; i < m_count; i++, a -= diff)
{
output_point_type p;
set<0>(p, get<0>(point) + buffer_distance * cos(a));
set<1>(p, get<1>(point) + buffer_distance * sin(a));
output_range.push_back(p);
}
// Close it:
output_range.push_back(output_range.front());
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
std::size_t m_count;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP

View File

@@ -0,0 +1,117 @@
// 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)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP
#include <cstddef>
#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
{
namespace strategy { namespace buffer
{
/*!
\brief Create a squared form buffer around a point
\ingroup strategies
\details This strategy can be used as PointStrategy for the buffer algorithm.
It creates a square from each point, where the point lies in the center.
It can be applied for points and multi_points, but also for a linestring (if it is degenerate,
so consisting of only one point) and for polygons (if it is degenerate).
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_point_square]
[heading Output]
[$img/strategies/buffer_point_square.png]
[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
{
template
<
typename Point,
typename DistanceType,
typename MultiplierType,
typename OutputRange
>
inline void add_point(Point const& point,
DistanceType const& distance,
MultiplierType const& x,
MultiplierType const& y,
OutputRange& output_range) const
{
typename boost::range_value<OutputRange>::type p;
set<0>(p, get<0>(point) + x * distance);
set<1>(p, get<1>(point) + y * distance);
output_range.push_back(p);
}
template
<
typename Point,
typename DistanceType,
typename OutputRange
>
inline void add_points(Point const& point,
DistanceType const& distance,
OutputRange& output_range) const
{
add_point(point, distance, -1.0, -1.0, output_range);
add_point(point, distance, -1.0, +1.0, output_range);
add_point(point, distance, +1.0, +1.0, output_range);
add_point(point, distance, +1.0, -1.0, output_range);
// Close it:
output_range.push_back(output_range.front());
}
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a square around point using distance_strategy
template
<
typename Point,
typename DistanceStrategy,
typename OutputRange
>
inline void apply(Point const& point,
DistanceStrategy const& distance_strategy,
OutputRange& output_range) const
{
add_points(point, distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left), output_range);
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP

View File

@@ -0,0 +1,136 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 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_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP
#include <cstddef>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer use straight sides along segments (the default)
\ingroup strategies
\details This strategy can be used as SideStrategy for the buffer algorithm.
It is currently the only provided strategy for this purpose
\qbk{
[heading Example]
See the examples for other buffer strategies\, for example
[link geometry.reference.strategies.strategy_buffer_join_round join_round]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
}
*/
class side_straight
{
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
<
typename Point,
typename OutputRange,
typename DistanceStrategy
>
static inline result_code apply(
Point const& input_p1, Point const& input_p2,
buffer_side_selector side,
DistanceStrategy const& distance,
OutputRange& output_range)
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
// Generate a block along (left or right of) the segment
// Simulate a vector d (dx,dy)
coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);
coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
if (! boost::math::isfinite(length))
{
// In case of coordinates differences of e.g. 1e300, length
// will overflow and we should not generate output
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Error in length calculation for points "
<< geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
<< " length: " << length << std::endl;
#endif
return result_error_numerical;
}
if (geometry::math::equals(length, 0))
{
// Coordinates are simplified and therefore most often not equal.
// But if simplify is skipped, or for lines with two
// equal points, length is 0 and we cannot generate output.
return result_no_output;
}
promoted_type const d = distance.apply(input_p1, input_p2, side);
// Generate the normalized perpendicular p, to the left (ccw)
promoted_type const px = -dy / length;
promoted_type const py = dx / length;
if (geometry::math::equals(px, 0)
&& geometry::math::equals(py, 0))
{
// This basically should not occur - because of the checks above.
// There are no unit tests triggering this condition
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Error in perpendicular calculation for points "
<< geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
<< " length: " << length
<< " distance: " << d
<< std::endl;
#endif
return result_no_output;
}
output_range.resize(2);
set<0>(output_range.front(), get<0>(input_p1) + px * d);
set<1>(output_range.front(), get<1>(input_p1) + py * d);
set<0>(output_range.back(), get<0>(input_p2) + px * d);
set<1>(output_range.back(), get<1>(input_p2) + py * d);
return result_normal;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP

View File

@@ -0,0 +1,128 @@
// 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 2015.
// Modifications copyright (c) 2015 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_CENTROID_AVERAGE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
#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>
#include <boost/geometry/strategies/centroid.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
/*!
\brief Centroid calculation taking average of points
\ingroup strategies
*/
template
<
typename PointCentroid,
typename Point = PointCentroid
>
class average
{
private :
/*! subclass to keep state */
class sum
{
friend class average;
signed_size_type count;
PointCentroid centroid;
public :
inline sum()
: count(0)
{
assign_zero(centroid);
}
};
public :
typedef sum state_type;
typedef PointCentroid centroid_point_type;
typedef Point point_type;
static inline void apply(Point const& p, sum& state)
{
add_point(state.centroid, p);
state.count++;
}
static inline bool result(sum const& state, PointCentroid& centroid)
{
centroid = state.centroid;
if ( state.count > 0 )
{
divide_value(centroid, state.count);
return true;
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, std::size_t DimensionCount, typename Geometry>
struct default_strategy
<
cartesian_tag,
pointlike_tag,
DimensionCount,
Point,
Geometry
>
{
typedef average
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP

View File

@@ -0,0 +1,252 @@
// 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-2020.
// Modifications copyright (c) 2015-2020, 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_CENTROID_BASHEIN_DETMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
#include <cstddef>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#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_most_precise.hpp>
namespace boost { namespace geometry
{
// Note: when calling the namespace "centroid", it sometimes,
// somehow, in gcc, gives compilation problems (confusion with function centroid).
namespace strategy { namespace centroid
{
/*!
\brief Centroid calculation using algorithm Bashein / Detmer
\ingroup strategies
\details Calculates centroid using triangulation method published by
Bashein / Detmer
\tparam Point point type of centroid to calculate
\tparam PointOfSegment point type of segments, defaults to Point
\tparam CalculationType \tparam_calculation
\author Adapted from "Centroid of a Polygon" by
Gerard Bashein and Paul R. Detmer<em>,
in "Graphics Gems IV", Academic Press, 1994</em>
\qbk{
[heading See also]
[link geometry.reference.algorithms.centroid.centroid_3_with_strategy centroid (with strategy)]
}
*/
/*
\par Research notes
The algorithm gives the same results as Oracle and PostGIS but
differs from MySQL
(tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
Without holes:
- this: POINT(4.06923363095238 1.65055803571429)
- geolib: POINT(4.07254 1.66819)
- MySQL: POINT(3.6636363636364 1.6272727272727)'
- PostGIS: POINT(4.06923363095238 1.65055803571429)
- Oracle: 4.06923363095238 1.65055803571429
- SQL Server: POINT(4.06923362245959 1.65055804168294)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,
sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(
2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6
,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
- \b SQL Server 2008: select geometry::STGeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))',0)
.STCentroid()
.STAsText()
With holes:
- this: POINT(4.04663 1.6349)
- geolib: POINT(4.04675 1.65735)
- MySQL: POINT(3.6090580503834 1.607573932092)
- PostGIS: POINT(4.0466265060241 1.63489959839357)
- Oracle: 4.0466265060241 1.63489959839357
- SQL Server: POINT(4.0466264962959677 1.6348996057331333)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)
,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null
, sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)
, sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,
2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4,
4.8,1.9, 4.4,2.2, 4,2))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class bashein_detmer
{
private :
// If user specified a calculation type, use that type,
// whatever it is and whatever the point-type(s) are.
// Else, use the most appropriate coordinate type
// of the two points, but at least double
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<PointOfSegment>::type,
double
>::type,
CalculationType
> calculation_type;
/*! subclass to keep state */
class sums
{
friend class bashein_detmer;
std::size_t count;
calculation_type sum_a2;
calculation_type sum_x;
calculation_type sum_y;
public :
inline sums()
: count(0)
, sum_a2(calculation_type())
, sum_x(calculation_type())
, sum_y(calculation_type())
{}
};
public :
typedef sums state_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2, sums& state)
{
/* Algorithm:
For each segment:
begin
ai = x1 * y2 - x2 * y1;
sum_a2 += ai;
sum_x += ai * (x1 + x2);
sum_y += ai * (y1 + y2);
end
return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
*/
// Get coordinates and promote them to calculation_type
calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));
calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));
calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));
calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));
calculation_type const ai = geometry::detail::determinant<calculation_type>(p1, p2);
state.count++;
state.sum_a2 += ai;
state.sum_x += ai * (x1 + x2);
state.sum_y += ai * (y1 + y2);
}
static inline bool result(sums const& state, Point& centroid)
{
calculation_type const zero = calculation_type();
if (state.count > 0 && ! math::equals(state.sum_a2, zero))
{
calculation_type const v3 = 3;
calculation_type const a3 = v3 * state.sum_a2;
typedef typename geometry::coordinate_type
<
Point
>::type coordinate_type;
// Prevent NaN centroid coordinates
if (boost::math::isfinite(a3))
{
// NOTE: above calculation_type is checked, not the centroid coordinate_type
// which means that the centroid can still be filled with INF
// if e.g. calculation_type is double and centroid contains floats
set<0>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_x / a3));
set<1>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_y / a3));
return true;
}
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register this strategy for rings and (multi)polygons, in two dimensions
template <typename Point, typename Geometry>
struct default_strategy<cartesian_tag, areal_tag, 2, Point, Geometry>
{
typedef bashein_detmer
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP

View File

@@ -0,0 +1,174 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, 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_CENTROID_WEIGHTED_LENGTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
// Helper geometry
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
namespace detail
{
template <typename Type, std::size_t DimensionCount>
struct weighted_length_sums
{
typedef typename geometry::model::point
<
Type, DimensionCount,
cs::cartesian
> work_point;
Type length;
work_point average_sum;
inline weighted_length_sums()
: length(Type())
{
geometry::assign_zero(average_sum);
}
};
}
template
<
typename Point,
typename PointOfSegment = Point
>
class weighted_length
{
private :
typedef typename select_most_precise
<
typename default_distance_result<Point>::type,
typename default_distance_result<PointOfSegment>::type
>::type distance_type;
public :
typedef detail::weighted_length_sums
<
distance_type,
geometry::dimension<Point>::type::value
> state_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2, state_type& state)
{
distance_type const d = geometry::distance(p1, p2);
state.length += d;
typename state_type::work_point weighted_median;
geometry::assign_zero(weighted_median);
geometry::add_point(weighted_median, p1);
geometry::add_point(weighted_median, p2);
geometry::multiply_value(weighted_median, d/2);
geometry::add_point(state.average_sum, weighted_median);
}
static inline bool result(state_type const& state, Point& centroid)
{
distance_type const zero = distance_type();
if (! geometry::math::equals(state.length, zero)
&& boost::math::isfinite(state.length)) // Prevent NaN centroid coordinates
{
// NOTE: above distance_type is checked, not the centroid coordinate_type
// which means that the centroid can still be filled with INF
// if e.g. distance_type is double and centroid contains floats
geometry::for_each_coordinate(centroid, set_sum_div_length(state));
return true;
}
return false;
}
struct set_sum_div_length
{
state_type const& m_state;
set_sum_div_length(state_type const& state)
: m_state(state)
{}
template <typename Pt, std::size_t Dimension>
void apply(Pt & centroid) const
{
typedef typename geometry::coordinate_type<Pt>::type coordinate_type;
geometry::set<Dimension>(
centroid,
boost::numeric_cast<coordinate_type>(
geometry::get<Dimension>(m_state.average_sum) / m_state.length
)
);
}
};
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register this strategy for linear geometries, in all dimensions
template <std::size_t N, typename Point, typename Geometry>
struct default_strategy
<
cartesian_tag,
linear_tag,
N,
Point,
Geometry
>
{
typedef weighted_length
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_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

@@ -0,0 +1,309 @@
// Boost.Geometry
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2019.
// Modifications copyright (c) 2013-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
// 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_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_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/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
namespace detail
{
template <std::size_t I>
struct compute_tmin_tmax_per_dim
{
template <typename SegmentPoint, typename Box, typename RelativeDistance>
static inline void apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box,
RelativeDistance& ti_min,
RelativeDistance& ti_max,
RelativeDistance& diff)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename coordinate_type
<
SegmentPoint
>::type point_coordinate_type;
RelativeDistance c_p0 = boost::numeric_cast
<
point_coordinate_type
>( geometry::get<I>(p0) );
RelativeDistance c_p1 = boost::numeric_cast
<
point_coordinate_type
>( geometry::get<I>(p1) );
RelativeDistance c_b_min = boost::numeric_cast
<
box_coordinate_type
>( geometry::get<geometry::min_corner, I>(box) );
RelativeDistance c_b_max = boost::numeric_cast
<
box_coordinate_type
>( geometry::get<geometry::max_corner, I>(box) );
if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
{
diff = c_p1 - c_p0;
ti_min = c_b_min - c_p0;
ti_max = c_b_max - c_p0;
}
else
{
diff = c_p0 - c_p1;
ti_min = c_p0 - c_b_max;
ti_max = c_p0 - c_b_min;
}
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t I,
std::size_t Dimension
>
struct disjoint_segment_box_impl
{
template <typename RelativeDistancePair>
static inline bool apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box,
RelativeDistancePair& t_min,
RelativeDistancePair& t_max)
{
RelativeDistance ti_min, ti_max, diff;
compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
if ( geometry::math::equals(diff, 0) )
{
if ( (geometry::math::equals(t_min.second, 0)
&& t_min.first > ti_max)
||
(geometry::math::equals(t_max.second, 0)
&& t_max.first < ti_min)
||
(math::sign(ti_min) * math::sign(ti_max) > 0) )
{
return true;
}
}
RelativeDistance t_min_x_diff = t_min.first * diff;
RelativeDistance t_max_x_diff = t_max.first * diff;
if ( t_min_x_diff > ti_max * t_min.second
|| t_max_x_diff < ti_min * t_max.second )
{
return true;
}
if ( ti_min * t_min.second > t_min_x_diff )
{
t_min.first = ti_min;
t_min.second = diff;
}
if ( ti_max * t_max.second < t_max_x_diff )
{
t_max.first = ti_max;
t_max.second = diff;
}
if ( t_min.first > t_min.second || t_max.first < 0 )
{
return true;
}
return disjoint_segment_box_impl
<
RelativeDistance,
SegmentPoint,
Box,
I + 1,
Dimension
>::apply(p0, p1, box, t_min, t_max);
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t Dimension
>
struct disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, 0, Dimension
>
{
static inline bool apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box)
{
std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
RelativeDistance diff;
compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
t_min.first, t_max.first, diff);
if ( geometry::math::equals(diff, 0) )
{
if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
{
return true;
}
}
if ( t_min.first > diff || t_max.first < 0 )
{
return true;
}
t_min.second = t_max.second = diff;
return disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, 1, Dimension
>::apply(p0, p1, box, t_min, t_max);
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t Dimension
>
struct disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, Dimension, Dimension
>
{
template <typename RelativeDistancePair>
static inline bool apply(SegmentPoint const&, SegmentPoint const&,
Box const&,
RelativeDistancePair&, RelativeDistancePair&)
{
return false;
}
};
} // namespace detail
// 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
{
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
return disjoint_point_box_strategy_type();
}
template <typename Segment, typename Box>
static inline bool apply(Segment const& segment, Box const& box)
{
assert_dimension_equal<Segment, Box>();
typedef typename util::calculation_type::geometric::binary
<
Segment, Box, void
>::type relative_distance_type;
typedef typename point_type<Segment>::type segment_point_type;
segment_point_type p0, p1;
geometry::detail::assign_point_from_index<0>(segment, p0);
geometry::detail::assign_point_from_index<1>(segment, p1);
return detail::disjoint_segment_box_impl
<
relative_distance_type, segment_point_type, Box,
0, dimension<Box>::value
>::apply(p0, p1, 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, 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, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP

View File

@@ -0,0 +1,306 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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-2020.
// Modifications copyright (c) 2014-2020, 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.
// 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_PROJECTED_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
#include <type_traits>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/strategies/tags.hpp>
#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/strategies/cartesian/intersection.hpp>
// Helper geometry (projected point on line)
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy for distance point to segment
\ingroup strategies
\details Calculates distance using projected-point method, and (optionally) Pythagoras
\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-point distance strategy
\par Concepts for Strategy:
- cartesian_distance operator(Point,Point)
\note If the Strategy is a "comparable::pythagoras", this strategy
automatically is a comparable projected_point strategy (so without sqrt)
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
class projected_point
{
public :
typedef within::cartesian_point_point equals_point_point_strategy_type;
typedef intersection::cartesian_segments
<
CalculationType
> relate_segment_segment_strategy_type;
static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
{
return relate_segment_segment_strategy_type();
}
typedef within::cartesian_winding
<
void, void, CalculationType
> point_in_geometry_strategy_type;
static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
{
return point_in_geometry_strategy_type();
}
// The three typedefs below are necessary to calculate distances
// from segments defined in integer coordinates.
// Integer coordinates can still result in FP distances.
// There is a division, which must be represented in FP.
// So promote.
template <typename Point, typename PointOfSegment>
struct calculation_type
: promote_floating_point
<
typename strategy::distance::services::return_type
<
Strategy,
Point,
PointOfSegment
>::type
>
{};
template <typename Point, typename PointOfSegment>
inline typename calculation_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
{
assert_dimension_equal<Point, PointOfSegment>();
typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
// A projected point of points in Integer coordinates must be able to be
// represented in FP.
typedef model::point
<
calculation_type,
dimension<PointOfSegment>::value,
typename coordinate_system<PointOfSegment>::type
> fp_point_type;
// For convenience
typedef fp_point_type fp_vector_type;
/*
Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
VECTOR v(x2 - x1, y2 - y1)
VECTOR w(px - x1, py - y1)
c1 = w . v
c2 = v . v
b = c1 / c2
RETURN POINT(x1 + b * vx, y1 + b * vy)
*/
// v is multiplied below with a (possibly) FP-value, so should be in FP
// For consistency we define w also in FP
fp_vector_type v, w, projected;
geometry::convert(p2, v);
geometry::convert(p, w);
geometry::convert(p1, projected);
subtract_point(v, projected);
subtract_point(w, projected);
Strategy strategy;
boost::ignore_unused(strategy);
calculation_type const zero = calculation_type();
calculation_type const c1 = dot_product(w, v);
if (c1 <= zero)
{
return strategy.apply(p, p1);
}
calculation_type const c2 = dot_product(v, v);
if (c2 <= c1)
{
return strategy.apply(p, p2);
}
// See above, c1 > 0 AND c2 > c1 so: c2 != 0
calculation_type const b = c1 / c2;
multiply_value(v, b);
add_point(projected, v);
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
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<projected_point<CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<projected_point<CalculationType, Strategy>, P, PS>
: projected_point<CalculationType, Strategy>::template calculation_type<P, PS>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<projected_point<CalculationType, Strategy> >
{
// Define a projected_point strategy with its underlying point-point-strategy
// being comparable
typedef projected_point
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<projected_point<CalculationType, Strategy> >
{
typedef typename comparable_type
<
projected_point<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>
{
private :
typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;
public :
template <typename T>
static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)
{
Strategy s;
return result_from_distance<Strategy, P, PS>::apply(s, value);
}
};
// Get default-strategy for point-segment distance calculation
// while still have the possibility to specify point-point distance strategy (PPS)
// It is used in algorithms/distance.hpp where users specify PPS for distance
// of point-to-segment or point-to-linestring.
// Convenient for geographic coordinate systems especially.
template <typename Point, typename PointOfSegment, typename Strategy>
struct default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag, Strategy
>
{
typedef strategy::distance::projected_point
<
void,
std::conditional_t
<
std::is_void<Strategy>::value,
typename default_strategy
<
point_tag, point_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag
>::type,
Strategy
>
> type;
};
template <typename PointOfSegment, typename Point, typename Strategy>
struct default_strategy
<
segment_tag, point_tag, PointOfSegment, Point,
cartesian_tag, cartesian_tag, Strategy
>
{
typedef typename default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag, Strategy
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP

View File

@@ -0,0 +1,315 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// 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.
// 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_PROJECTED_POINT_AX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP
#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>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/strategies/tags.hpp>
#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/distance_projected_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
// Helper geometry (projected point on line)
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename T>
struct projected_point_ax_result
{
typedef T value_type;
projected_point_ax_result(T const& c = T(0))
: atd(c), xtd(c)
{}
projected_point_ax_result(T const& a, T const& x)
: atd(a), xtd(x)
{}
friend inline bool operator<(projected_point_ax_result const& left,
projected_point_ax_result const& right)
{
return left.xtd < right.xtd || left.atd < right.atd;
}
T atd, xtd;
};
// This less-comparator may be used as a parameter of detail::douglas_peucker.
// In this simplify strategy distances are compared in 2 places
// 1. to choose the furthest candidate (md < dist)
// 2. to check if the candidate is further than max_distance (max_distance < md)
template <typename Distance>
class projected_point_ax_less
{
public:
projected_point_ax_less(Distance const& max_distance)
: m_max_distance(max_distance)
{}
inline bool operator()(Distance const& left, Distance const& right) const
{
//return left.xtd < right.xtd && right.atd < m_max_distance.atd;
typedef typename Distance::value_type value_type;
value_type const lx = left.xtd > m_max_distance.xtd ? left.xtd - m_max_distance.xtd : 0;
value_type const rx = right.xtd > m_max_distance.xtd ? right.xtd - m_max_distance.xtd : 0;
value_type const la = left.atd > m_max_distance.atd ? left.atd - m_max_distance.atd : 0;
value_type const ra = right.atd > m_max_distance.atd ? right.atd - m_max_distance.atd : 0;
value_type const l = (std::max)(lx, la);
value_type const r = (std::max)(rx, ra);
return l < r;
}
private:
Distance const& m_max_distance;
};
// This strategy returns 2-component Point/Segment distance.
// The ATD (along track distance) is parallel to the Segment
// and is a distance between Point projected into a line defined by a Segment and the nearest Segment's endpoint.
// If the projected Point intersects the Segment the ATD is equal to 0.
// The XTD (cross track distance) is perpendicular to the Segment
// and is a distance between input Point and its projection.
// If the Segment has length equal to 0, ATD and XTD has value equal
// to the distance between the input Point and one of the Segment's endpoints.
//
// p3 p4
// ^ 7
// | /
// p1<-----e========e----->p2
//
// p1: atd=D, xtd=0
// p2: atd=D, xtd=0
// p3: atd=0, xtd=D
// p4: atd=D/2, xtd=D
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
class projected_point_ax
{
public :
template <typename Point, typename PointOfSegment>
struct calculation_type
: public projected_point<CalculationType, Strategy>
::template calculation_type<Point, PointOfSegment>
{};
template <typename Point, typename PointOfSegment>
struct result_type
{
typedef projected_point_ax_result
<
typename calculation_type<Point, PointOfSegment>::type
> type;
};
public :
template <typename Point, typename PointOfSegment>
inline typename result_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
{
assert_dimension_equal<Point, PointOfSegment>();
typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
// A projected point of points in Integer coordinates must be able to be
// represented in FP.
typedef model::point
<
calculation_type,
dimension<PointOfSegment>::value,
typename coordinate_system<PointOfSegment>::type
> fp_point_type;
// For convenience
typedef fp_point_type fp_vector_type;
/*
Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
VECTOR v(x2 - x1, y2 - y1)
VECTOR w(px - x1, py - y1)
c1 = w . v
c2 = v . v
b = c1 / c2
RETURN POINT(x1 + b * vx, y1 + b * vy)
*/
// v is multiplied below with a (possibly) FP-value, so should be in FP
// For consistency we define w also in FP
fp_vector_type v, w, projected;
geometry::convert(p2, v);
geometry::convert(p, w);
geometry::convert(p1, projected);
subtract_point(v, projected);
subtract_point(w, projected);
Strategy strategy;
boost::ignore_unused(strategy);
typename result_type<Point, PointOfSegment>::type result;
calculation_type const zero = calculation_type();
calculation_type const c2 = dot_product(v, v);
if ( math::equals(c2, zero) )
{
result.xtd = strategy.apply(p, projected);
// assume that the 0-length segment is perpendicular to the Pt->ProjPt vector
result.atd = 0;
return result;
}
calculation_type const c1 = dot_product(w, v);
calculation_type const b = c1 / c2;
multiply_value(v, b);
add_point(projected, v);
result.xtd = strategy.apply(p, projected);
if (c1 <= zero)
{
result.atd = strategy.apply(p1, projected);
}
else if (c2 <= c1)
{
result.atd = strategy.apply(p2, projected);
}
else
{
result.atd = 0;
}
return result;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<detail::projected_point_ax<CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>
{
typedef typename detail::projected_point_ax<CalculationType, Strategy>
::template result_type<P, PS>::type type;
};
template <typename CalculationType, typename Strategy>
struct comparable_type<detail::projected_point_ax<CalculationType, Strategy> >
{
// Define a projected_point strategy with its underlying point-point-strategy
// being comparable
typedef detail::projected_point_ax
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<detail::projected_point_ax<CalculationType, Strategy> >
{
typedef typename comparable_type
<
detail::projected_point_ax<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(detail::projected_point_ax<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct result_from_distance<detail::projected_point_ax<CalculationType, Strategy>, P, PS>
{
private :
typedef typename return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>::type return_type;
public :
template <typename T>
static inline return_type apply(detail::projected_point_ax<CalculationType, Strategy> const& , T const& value)
{
Strategy s;
return_type ret;
ret.atd = result_from_distance<Strategy, P, PS>::apply(s, value.atd);
ret.xtd = result_from_distance<Strategy, P, PS>::apply(s, value.xtd);
return ret;
}
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP

View File

@@ -0,0 +1,295 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// 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.
// 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_PYTHAGORAS_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
#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>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <size_t I, typename T>
struct compute_pythagoras
{
template <typename Point1, typename Point2>
static inline T apply(Point1 const& p1, Point2 const& p2)
{
T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
T const d = c1 - c2;
return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
}
};
template <typename T>
struct compute_pythagoras<0, T>
{
template <typename Point1, typename Point2>
static inline T apply(Point1 const&, Point2 const&)
{
return boost::numeric_cast<T>(0);
}
};
}
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between two points
\ingroup strategies
\tparam Point1 \tparam_first_point
\tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras
{
public :
template <typename Point1, typename Point2>
struct calculation_type
: util::calculation_type::geometric::binary
<
Point1,
Point2,
CalculationType,
double,
double
>
{};
template <typename Point1, typename Point2>
static inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& p1, Point2 const& p2)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Point1, Point2>();
return detail::compute_pythagoras
<
dimension<Point1>::value,
typename calculation_type<Point1, Point2>::type
>::apply(p1, p2);
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between two points
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for points with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras
{
public :
template <typename P1, typename P2>
struct calculation_type
: util::calculation_type::geometric::binary
<
P1,
P2,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras
\return the calculated distance (including taking the square root)
\param p1 first point
\param p2 second point
*/
template <typename P1, typename P2>
static inline typename calculation_type<P1, P2>::type
apply(P1 const& p1, P2 const& p2)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type<P1, P2>::type>
(
comparable::pythagoras<CalculationType>::apply(p1, p2)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras<CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename CalculationType, typename P1, typename P2>
struct return_type<distance::pythagoras<CalculationType>, P1, P2>
: pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> comparable_type;
public :
static inline comparable_type apply(pythagoras<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
{
private :
typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
public :
template <typename T>
static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras
template <typename CalculationType>
struct tag<comparable::pythagoras<CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename CalculationType, typename P1, typename P2>
struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
: comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
{
private :
typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
public :
template <typename T>
static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename Point1, typename Point2>
struct default_strategy
<
point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag
>
{
typedef pythagoras<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP

View File

@@ -0,0 +1,341 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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, 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.
// 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_PYTHAGORAS_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP
#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>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t I>
struct compute_pythagoras_box_box
{
template <typename Box1, typename Box2, typename T>
static inline void apply(Box1 const& box1, Box2 const& box2, T& result)
{
T const b1_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box1));
T const b1_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box1));
T const b2_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box2));
T const b2_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box2));
if ( b1_max_coord < b2_min_coord )
{
T diff = b2_min_coord - b1_max_coord;
result += diff * diff;
}
if ( b1_min_coord > b2_max_coord )
{
T diff = b1_min_coord - b2_max_coord;
result += diff * diff;
}
compute_pythagoras_box_box<I-1>::apply(box1, box2, result);
}
};
template <>
struct compute_pythagoras_box_box<0>
{
template <typename Box1, typename Box2, typename T>
static inline void apply(Box1 const&, Box2 const&, T&)
{
}
};
}
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between two boxes
\ingroup strategies
\tparam Box1 \tparam_first_box
\tparam Box2 \tparam_second_box
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras_box_box
{
public :
template <typename Box1, typename Box2>
struct calculation_type
{
typedef typename util::calculation_type::geometric::binary
<
Box1,
Box2,
CalculationType
>::type type;
};
template <typename Box1, typename Box2>
static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const& box1, Box2 const& box2)
{
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box1>::type>) );
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box2>::type>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Box1, Box2>();
typename calculation_type<Box1, Box2>::type result(0);
detail::compute_pythagoras_box_box
<
dimension<Box1>::value
>::apply(box1, box2, result);
return result;
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between two boxes
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for boxes with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras_box_box
{
public :
template <typename Box1, typename Box2>
struct calculation_type
: util::calculation_type::geometric::binary
<
Box1,
Box2,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras_box_box
\return the calculated distance (including taking the square root)
\param box1 first box
\param box2 second box
*/
template <typename Box1, typename Box2>
static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const& box1, Box2 const& box2)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type
<
Box1, Box2
>::type>
(
comparable::pythagoras_box_box
<
CalculationType
>::apply(box1, box2)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras_box_box<CalculationType> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename CalculationType, typename Box1, typename Box2>
struct return_type<distance::pythagoras_box_box<CalculationType>, Box1, Box2>
: pythagoras_box_box<CalculationType>::template calculation_type<Box1, Box2>
{};
template <typename CalculationType>
struct comparable_type<pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> comparable_type;
public :
static inline comparable_type
apply(pythagoras_box_box<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Box1, typename Box2>
struct result_from_distance<pythagoras_box_box<CalculationType>, Box1, Box2>
{
private:
typedef typename return_type
<
pythagoras_box_box<CalculationType>, Box1, Box2
>::type return_type;
public:
template <typename T>
static inline return_type
apply(pythagoras_box_box<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras_box_box
template <typename CalculationType>
struct tag<comparable::pythagoras_box_box<CalculationType> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename CalculationType, typename Box1, typename Box2>
struct return_type<comparable::pythagoras_box_box<CalculationType>, Box1, Box2>
: comparable::pythagoras_box_box
<
CalculationType
>::template calculation_type<Box1, Box2>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable_type const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Box1, typename Box2>
struct result_from_distance
<
comparable::pythagoras_box_box<CalculationType>, Box1, Box2
>
{
private :
typedef typename return_type
<
comparable::pythagoras_box_box<CalculationType>, Box1, Box2
>::type return_type;
public :
template <typename T>
static inline return_type
apply(comparable::pythagoras_box_box<CalculationType> const&,
T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename BoxPoint1, typename BoxPoint2>
struct default_strategy
<
box_tag, box_tag, BoxPoint1, BoxPoint2, cartesian_tag, cartesian_tag
>
{
typedef pythagoras_box_box<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP

View File

@@ -0,0 +1,353 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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, 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.
// 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_PYTHAGORAS_POINT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP
#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>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <size_t I>
struct compute_pythagoras_point_box
{
template <typename Point, typename Box, typename T>
static inline void apply(Point const& point, Box const& box, T& result)
{
T const p_coord = boost::numeric_cast<T>(geometry::get<I-1>(point));
T const b_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box));
T const b_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box));
if ( p_coord < b_min_coord )
{
T diff = b_min_coord - p_coord;
result += diff * diff;
}
if ( p_coord > b_max_coord )
{
T diff = p_coord - b_max_coord;
result += diff * diff;
}
compute_pythagoras_point_box<I-1>::apply(point, box, result);
}
};
template <>
struct compute_pythagoras_point_box<0>
{
template <typename Point, typename Box, typename T>
static inline void apply(Point const&, Box const&, T&)
{
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between a point
and a box
\ingroup strategies
\tparam Point \tparam_first_point
\tparam Box \tparam_second_box
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras_point_box
{
public :
template <typename Point, typename Box>
struct calculation_type
{
typedef typename util::calculation_type::geometric::binary
<
Point, Box, CalculationType
>::type type;
};
template <typename Point, typename Box>
static inline typename calculation_type<Point, Box>::type
apply(Point const& point, Box const& box)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box>::type>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Point, Box>();
typename calculation_type<Point, Box>::type result(0);
detail::compute_pythagoras_point_box
<
dimension<Point>::value
>::apply(point, box, result);
return result;
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between a point and a box
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for points and boxes with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras_point_box
{
public :
template <typename Point, typename Box>
struct calculation_type
: util::calculation_type::geometric::binary
<
Point,
Box,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras
\return the calculated distance (including taking the square root)
\param point point
\param box box
*/
template <typename Point, typename Box>
static inline typename calculation_type<Point, Box>::type
apply(Point const& point, Box const& box)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type
<
Point, Box
>::type>
(
comparable::pythagoras_point_box
<
CalculationType
>::apply(point, box)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras_point_box<CalculationType> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename CalculationType, typename Point, typename Box>
struct return_type<distance::pythagoras_point_box<CalculationType>, Point, Box>
: pythagoras_point_box
<
CalculationType
>::template calculation_type<Point, Box>
{};
template <typename CalculationType>
struct comparable_type<pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> comparable_type;
public :
static inline comparable_type
apply(pythagoras_point_box<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point, typename Box>
struct result_from_distance<pythagoras_point_box<CalculationType>, Point, Box>
{
private :
typedef typename return_type
<
pythagoras_point_box<CalculationType>, Point, Box
>::type return_type;
public :
template <typename T>
static inline return_type
apply(pythagoras_point_box<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras_point_box
template <typename CalculationType>
struct tag<comparable::pythagoras_point_box<CalculationType> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename CalculationType, typename Point, typename Box>
struct return_type
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
> : comparable::pythagoras_point_box
<
CalculationType
>::template calculation_type<Point, Box>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable_type const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point, typename Box>
struct result_from_distance
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
>
{
private :
typedef typename return_type
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
>::type return_type;
public :
template <typename T>
static inline return_type
apply(comparable::pythagoras_point_box<CalculationType> const& ,
T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename Point, typename BoxPoint>
struct default_strategy
<
point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag
>
{
typedef pythagoras_point_box<> type;
};
template <typename BoxPoint, typename Point>
struct default_strategy
<
box_tag, point_tag, BoxPoint, Point, cartesian_tag, cartesian_tag
>
{
typedef typename default_strategy
<
point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP

View File

@@ -0,0 +1,225 @@
// 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/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.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
>
{};
typedef cartesian_tag cs_tag;
// 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();
}
struct distance_pb_strategy
{
typedef pythagoras_point_box<CalculationType> type;
};
inline typename distance_pb_strategy::type get_distance_pb_strategy() const
{
return typename distance_pb_strategy::type();
}
typedef side::side_by_triangle<CalculationType> side_strategy_type;
static inline side_strategy_type get_side_strategy()
{
return side_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,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/envelope_multipoint.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP

View File

@@ -0,0 +1,198 @@
// Boost.Geometry Index
//
// R-tree strategies
//
// Copyright (c) 2019-2020, 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_CARTESIAN_INDEX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.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_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/index.hpp>
namespace boost { namespace geometry { namespace strategy { namespace index
{
template
<
typename CalculationType = void
>
struct cartesian
{
typedef cartesian_tag cs_tag;
typedef geometry::strategy::envelope::cartesian_point envelope_point_strategy_type;
typedef geometry::strategy::envelope::cartesian_box envelope_box_strategy_type;
typedef geometry::strategy::envelope::cartesian_segment
<
CalculationType
> envelope_segment_strategy_type;
static inline envelope_segment_strategy_type get_envelope_segment_strategy()
{
return envelope_segment_strategy_type();
}
typedef geometry::strategy::expand::cartesian_point expand_point_strategy_type;
typedef geometry::strategy::expand::cartesian_box expand_box_strategy_type;
typedef geometry::strategy::expand::cartesian_segment expand_segment_strategy_type;
static inline expand_segment_strategy_type get_expand_segment_strategy()
{
return expand_segment_strategy_type();
}
typedef geometry::strategy::covered_by::cartesian_point_box covered_by_point_box_strategy_type;
typedef geometry::strategy::covered_by::cartesian_box_box covered_by_box_box_strategy_type;
typedef geometry::strategy::within::cartesian_point_point within_point_point_strategy_type;
/*
typedef geometry::strategy::within::cartesian_point_box within_point_box_strategy_type;
typedef geometry::strategy::within::cartesian_box_box within_box_box_strategy_type;
typedef geometry::strategy::within::cartesian_winding
<
void, void, CalculationType
> within_point_segment_strategy_type;
static inline within_point_segment_strategy_type get_within_point_segment_strategy()
{
return within_point_segment_strategy_type();
}
*/
// used in equals(Seg, Seg) but only to get_point_in_point_strategy()
typedef geometry::strategy::intersection::cartesian_segments
<
CalculationType
> relate_segment_segment_strategy_type;
static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
{
return relate_segment_segment_strategy_type();
}
// used in intersection_content
typedef geometry::strategy::disjoint::cartesian_box_box disjoint_box_box_strategy_type;
typedef geometry::strategy::distance::comparable::pythagoras
<
CalculationType
> comparable_distance_point_point_strategy_type;
static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy()
{
return comparable_distance_point_point_strategy_type();
}
typedef geometry::strategy::distance::comparable::pythagoras_point_box
<
CalculationType
> comparable_distance_point_box_strategy_type;
static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy()
{
return comparable_distance_point_box_strategy_type();
}
// TODO: comparable version should be possible
typedef geometry::strategy::distance::projected_point
<
CalculationType,
geometry::strategy::distance::pythagoras<CalculationType>
> comparable_distance_point_segment_strategy_type;
static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy()
{
return comparable_distance_point_segment_strategy_type();
}
typedef geometry::strategy::distance::cartesian_segment_box
<
CalculationType,
geometry::strategy::distance::pythagoras<CalculationType>
> comparable_distance_segment_box_strategy_type;
static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy()
{
return comparable_distance_segment_box_strategy_type();
}
};
namespace services
{
template <typename Geometry>
struct default_strategy<Geometry, cartesian_tag>
{
typedef cartesian<> type;
};
// within and relate (MPt, Mls/MPoly)
template <typename Point1, typename Point2, typename CalculationType>
struct from_strategy<within::cartesian_winding<Point1, Point2, CalculationType> >
{
typedef strategy::index::cartesian<CalculationType> type;
static inline type get(within::cartesian_winding<Point1, Point2, CalculationType> const&)
{
return type();
}
};
// distance (MPt, MPt)
template <typename CalculationType>
struct from_strategy<distance::comparable::pythagoras<CalculationType> >
{
typedef strategy::index::cartesian<CalculationType> type;
static inline type get(distance::comparable::pythagoras<CalculationType> const&)
{
return type();
}
};
// distance (MPt, Linear/Areal)
template <typename CalculationType, typename PPStrategy>
struct from_strategy<distance::projected_point<CalculationType, PPStrategy> >
{
typedef strategy::index::cartesian<CalculationType> type;
static inline type get(distance::projected_point<CalculationType, PPStrategy> const&)
{
return type();
}
};
} // namespace services
}}}} // namespace boost::geometry::strategy::index
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP

View File

@@ -0,0 +1,860 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, 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
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#include <algorithm>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategy/cartesian/area.hpp>
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.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/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>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
# include <boost/geometry/io/wkt/write.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace intersection
{
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
*/
template
<
typename CalculationType = void
>
struct cartesian_segments
{
typedef cartesian_tag cs_tag;
typedef side::side_by_triangle<CalculationType> side_strategy_type;
static inline side_strategy_type get_side_strategy()
{
return side_strategy_type();
}
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::cartesian_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
CalculationType
> type;
};
template <typename Geometry1, typename Geometry2>
static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
get_point_in_geometry_strategy()
{
typedef typename point_in_geometry_strategy
<
Geometry1, Geometry2
>::type strategy_type;
return strategy_type();
}
template <typename Geometry>
struct area_strategy
{
typedef area::cartesian
<
CalculationType
> type;
};
template <typename Geometry>
static inline typename area_strategy<Geometry>::type get_area_strategy()
{
typedef typename area_strategy<Geometry>::type strategy_type;
return strategy_type();
}
template <typename Geometry>
struct distance_strategy
{
typedef distance::pythagoras
<
CalculationType
> type;
};
template <typename Geometry>
static inline typename distance_strategy<Geometry>::type get_distance_strategy()
{
typedef typename distance_strategy<Geometry>::type strategy_type;
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 covered_by::cartesian_point_box covered_by_point_box_strategy_type;
typedef within::cartesian_point_box within_point_box_strategy_type;
typedef envelope::cartesian_box envelope_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
>::type promoted_type;
promoted_type comparable_length_a() const
{
return dx_a * dx_a + dy_a * dy_a;
}
promoted_type comparable_length_b() const
{
return dx_b * dx_b + dy_b * dy_b;
}
template <typename Point, typename Segment1, typename Segment2>
void assign_a(Point& point, Segment1 const& a, Segment2 const& ) const
{
assign(point, a, dx_a, dy_a, robust_ra);
}
template <typename Point, typename Segment1, typename Segment2>
void assign_b(Point& point, Segment1 const& , Segment2 const& b) const
{
assign(point, b, dx_b, dy_b, robust_rb);
}
template <typename Point, typename Segment>
void assign(Point& point, Segment const& segment, CoordinateType const& dx, CoordinateType const& dy, SegmentRatio const& ratio) const
{
// Calculate the intersection point based on segment_ratio
// Up to now, division was postponed. Here we divide using numerator/
// denominator. In case of integer this results in an integer
// division.
BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
typedef typename promote_integral<CoordinateType>::type calc_type;
calc_type const numerator
= boost::numeric_cast<calc_type>(ratio.numerator());
calc_type const denominator
= boost::numeric_cast<calc_type>(ratio.denominator());
calc_type const dx_calc = boost::numeric_cast<calc_type>(dx);
calc_type const dy_calc = boost::numeric_cast<calc_type>(dy);
set<0>(point, get<0, 0>(segment)
+ boost::numeric_cast<CoordinateType>(numerator * dx_calc
/ denominator));
set<1>(point, get<0, 1>(segment)
+ boost::numeric_cast<CoordinateType>(numerator * dy_calc
/ 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;
SegmentRatio robust_rb;
};
template <typename D, typename W, typename ResultType>
static inline void cramers_rule(D const& dx_a, D const& dy_a,
D const& dx_b, D const& dy_b, W const& wx, W const& wy,
// out:
ResultType& nominator, ResultType& denominator)
{
// Cramers rule
nominator = geometry::detail::determinant<ResultType>(dx_b, dy_b, wx, wy);
denominator = geometry::detail::determinant<ResultType>(dx_a, dy_a, dx_b, dy_b);
// Ratio r = nominator/denominator
// Collinear if denominator == 0, intersecting if 0 <= r <= 1
// IntersectionPoint = (x1 + r * dx_a, y1 + r * dy_a)
}
// Version for non-rescaled policies
template
<
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy
>
static inline typename Policy::return_type
apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
Policy const& policy)
{
// Pass the same ranges both as normal ranges and as modelled ranges
return apply(range_p, range_q, policy, range_p, range_q);
}
// Version for non rescaled versions.
// The "modelled" parameter might be rescaled (will be removed later)
template
<
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy,
typename ModelledUniqueSubRange1,
typename ModelledUniqueSubRange2
>
static inline typename Policy::return_type
apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
Policy const& policy,
ModelledUniqueSubRange1 const& modelled_range_p,
ModelledUniqueSubRange2 const& modelled_range_q)
{
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
point1_type const& p1 = range_p.at(0);
point1_type const& p2 = range_p.at(1);
point2_type const& q1 = range_q.at(0);
point2_type const& q2 = range_q.at(1);
// Declare segments, currently necessary for the policies
// (segment_crosses, segment_colinear, degenerate, one_degenerate, etc)
model::referring_segment<point1_type const> const p(p1, p2);
model::referring_segment<point2_type const> const q(q1, q2);
typedef typename select_most_precise
<
typename geometry::coordinate_type<typename ModelledUniqueSubRange1::point_type>::type,
typename geometry::coordinate_type<typename ModelledUniqueSubRange1::point_type>::type
>::type modelled_coordinate_type;
typedef segment_ratio<modelled_coordinate_type> ratio_type;
segment_intersection_info
<
typename select_calculation_type<point1_type, point2_type, CalculationType>::type,
ratio_type
> sinfo;
sinfo.dx_a = get<0>(p2) - get<0>(p1); // distance in x-dir
sinfo.dx_b = get<0>(q2) - get<0>(q1);
sinfo.dy_a = get<1>(p2) - get<1>(p1); // distance in y-dir
sinfo.dy_b = get<1>(q2) - get<1>(q1);
return unified<ratio_type>(sinfo, p, q, policy, modelled_range_p, modelled_range_q);
}
//! Returns true if two segments do not overlap.
//! If not, then no further calculations need to be done.
template
<
std::size_t Dimension,
typename CoordinateType,
typename PointP,
typename PointQ
>
static inline bool disjoint_by_range(PointP const& p1, PointP const& p2,
PointQ const& q1, PointQ const& q2)
{
CoordinateType minp = get<Dimension>(p1);
CoordinateType maxp = get<Dimension>(p2);
CoordinateType minq = get<Dimension>(q1);
CoordinateType maxq = get<Dimension>(q2);
if (minp > maxp)
{
std::swap(minp, maxp);
}
if (minq > maxq)
{
std::swap(minq, maxq);
}
// In this case, max(p) < min(q)
// P Q
// <-------> <------->
// (and the space in between is not extremely small)
return math::smaller(maxp, minq) || math::smaller(maxq, minp);
}
// Implementation for either rescaled or non rescaled versions.
template
<
typename RatioType,
typename SegmentInfo,
typename Segment1,
typename Segment2,
typename Policy,
typename UniqueSubRange1,
typename UniqueSubRange2
>
static inline typename Policy::return_type
unified(SegmentInfo& sinfo,
Segment1 const& p, Segment2 const& q, Policy const&,
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q)
{
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
typedef typename select_most_precise
<
typename geometry::coordinate_type<point1_type>::type,
typename geometry::coordinate_type<point2_type>::type
>::type coordinate_type;
point1_type const& p1 = range_p.at(0);
point1_type const& p2 = range_p.at(1);
point2_type const& q1 = range_q.at(0);
point2_type const& q2 = range_q.at(1);
using geometry::detail::equals::equals_point_point;
bool const p_is_point = equals_point_point(p1, p2, point_in_point_strategy_type());
bool const q_is_point = equals_point_point(q1, q2, point_in_point_strategy_type());
if (p_is_point && q_is_point)
{
return equals_point_point(p1, q2, point_in_point_strategy_type())
? Policy::degenerate(p, true)
: Policy::disjoint()
;
}
if (disjoint_by_range<0, coordinate_type>(p1, p2, q1, q2)
|| disjoint_by_range<1, coordinate_type>(p1, p2, q1, q2))
{
return Policy::disjoint();
}
side_info sides;
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
side_strategy_type::apply(q1, q2, p2));
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
sides.set<1>(side_strategy_type::apply(p1, p2, q1),
side_strategy_type::apply(p1, p2, q2));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
bool collinear = sides.collinear();
// Calculate the differences again
// (for rescaled version, this is different from dx_p etc)
coordinate_type const dx_p = get<0>(p2) - get<0>(p1);
coordinate_type const dx_q = get<0>(q2) - get<0>(q1);
coordinate_type const dy_p = get<1>(p2) - get<1>(p1);
coordinate_type const dy_q = get<1>(q2) - get<1>(q1);
// r: ratio 0-1 where intersection divides A/B
// (only calculated for non-collinear segments)
if (! collinear)
{
coordinate_type denominator_a, nominator_a;
coordinate_type denominator_b, nominator_b;
cramers_rule(dx_p, dy_p, dx_q, dy_q,
get<0>(p1) - get<0>(q1),
get<1>(p1) - get<1>(q1),
nominator_a, denominator_a);
cramers_rule(dx_q, dy_q, dx_p, dy_p,
get<0>(q1) - get<0>(p1),
get<1>(q1) - get<1>(p1),
nominator_b, denominator_b);
math::detail::equals_factor_policy<coordinate_type>
policy(dx_p, dy_p, dx_q, dy_q);
coordinate_type const zero = 0;
if (math::detail::equals_by_policy(denominator_a, zero, policy)
|| math::detail::equals_by_policy(denominator_b, zero, policy))
{
// If this is the case, no rescaling is done for FP precision.
// We set it to collinear, but it indicates a robustness issue.
sides.set<0>(0, 0);
sides.set<1>(0, 0);
collinear = true;
}
else
{
sinfo.robust_ra.assign(nominator_a, denominator_a);
sinfo.robust_rb.assign(nominator_b, denominator_b);
}
}
if (collinear)
{
std::pair<bool, bool> const collinear_use_first
= is_x_more_significant(geometry::math::abs(dx_p),
geometry::math::abs(dy_p),
geometry::math::abs(dx_q),
geometry::math::abs(dy_q),
p_is_point, q_is_point);
if (collinear_use_first.second)
{
// Degenerate cases: segments of single point, lying on other segment, are not disjoint
// This situation is collinear too
if (collinear_use_first.first)
{
return relate_collinear<0, Policy, RatioType>(p, q,
p1, p2, q1, q2,
p_is_point, q_is_point);
}
else
{
// Y direction contains larger segments (maybe dx is zero)
return relate_collinear<1, Policy, RatioType>(p, q,
p1, p2, q1, q2,
p_is_point, q_is_point);
}
}
}
return Policy::segments_crosses(sides, sinfo, p, q);
}
private:
// first is true if x is more significant
// second is true if the more significant difference is not 0
template <typename CoordinateType>
static inline std::pair<bool, bool>
is_x_more_significant(CoordinateType const& abs_dx_a,
CoordinateType const& abs_dy_a,
CoordinateType const& abs_dx_b,
CoordinateType const& abs_dy_b,
bool const a_is_point,
bool const b_is_point)
{
//BOOST_GEOMETRY_ASSERT_MSG(!(a_is_point && b_is_point), "both segments shouldn't be degenerated");
// for degenerated segments the second is always true because this function
// shouldn't be called if both segments were degenerated
if (a_is_point)
{
return std::make_pair(abs_dx_b >= abs_dy_b, true);
}
else if (b_is_point)
{
return std::make_pair(abs_dx_a >= abs_dy_a, true);
}
else
{
CoordinateType const min_dx = (std::min)(abs_dx_a, abs_dx_b);
CoordinateType const min_dy = (std::min)(abs_dy_a, abs_dy_b);
return min_dx == min_dy ?
std::make_pair(true, min_dx > CoordinateType(0)) :
std::make_pair(min_dx > min_dy, true);
}
}
template
<
std::size_t Dimension,
typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustPoint1,
typename RobustPoint2
>
static inline typename Policy::return_type
relate_collinear(Segment1 const& a,
Segment2 const& b,
RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
bool a_is_point, bool b_is_point)
{
if (a_is_point)
{
return relate_one_degenerate<Policy, RatioType>(a,
get<Dimension>(robust_a1),
get<Dimension>(robust_b1), get<Dimension>(robust_b2),
true);
}
if (b_is_point)
{
return relate_one_degenerate<Policy, RatioType>(b,
get<Dimension>(robust_b1),
get<Dimension>(robust_a1), get<Dimension>(robust_a2),
false);
}
return relate_collinear<Policy, RatioType>(a, b,
get<Dimension>(robust_a1),
get<Dimension>(robust_a2),
get<Dimension>(robust_b1),
get<Dimension>(robust_b2));
}
/// Relate segments known collinear
template
<
typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename Type1,
typename Type2
>
static inline typename Policy::return_type
relate_collinear(Segment1 const& a, Segment2 const& b,
Type1 oa_1, Type1 oa_2,
Type2 ob_1, Type2 ob_2)
{
// Calculate the ratios where a starts in b, b starts in a
// a1--------->a2 (2..7)
// b1----->b2 (5..8)
// length_a: 7-2=5
// length_b: 8-5=3
// b1 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)
// b2 is located w.r.t. a at ratio: (8-2)/5=6/5 (right of a)
// a1 is located w.r.t. b at ratio: (2-5)/3=-3/3 (left of b)
// a2 is located w.r.t. b at ratio: (7-5)/3=2/3 (on b)
// A arrives (a2 on b), B departs (b1 on a)
// If both are reversed:
// a2<---------a1 (7..2)
// b2<-----b1 (8..5)
// length_a: 2-7=-5
// length_b: 5-8=-3
// b1 is located w.r.t. a at ratio: (8-7)/-5=-1/5 (before a starts)
// b2 is located w.r.t. a at ratio: (5-7)/-5=2/5 (on a)
// a1 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)
// a2 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)
// If both one is reversed:
// a1--------->a2 (2..7)
// b2<-----b1 (8..5)
// length_a: 7-2=+5
// length_b: 5-8=-3
// b1 is located w.r.t. a at ratio: (8-2)/5=6/5 (after a ends)
// b2 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)
// a1 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)
// a2 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)
Type1 const length_a = oa_2 - oa_1; // no abs, see above
Type2 const length_b = ob_2 - ob_1;
RatioType ra_from(oa_1 - ob_1, length_b);
RatioType ra_to(oa_2 - ob_1, length_b);
RatioType rb_from(ob_1 - oa_1, length_a);
RatioType rb_to(ob_2 - oa_1, length_a);
// use absolute measure to detect endpoints intersection
// NOTE: it'd be possible to calculate bx_wrt_a using ax_wrt_b values
int const a1_wrt_b = position_value(oa_1, ob_1, ob_2);
int const a2_wrt_b = position_value(oa_2, ob_1, ob_2);
int const b1_wrt_a = position_value(ob_1, oa_1, oa_2);
int const b2_wrt_a = position_value(ob_2, oa_1, oa_2);
// fix the ratios if necessary
// CONSIDER: fixing ratios also in other cases, if they're inconsistent
// e.g. if ratio == 1 or 0 (so IP at the endpoint)
// but position value indicates that the IP is in the middle of the segment
// because one of the segments is very long
// In such case the ratios could be moved into the middle direction
// by some small value (e.g. EPS+1ULP)
if (a1_wrt_b == 1)
{
ra_from.assign(0, 1);
rb_from.assign(0, 1);
}
else if (a1_wrt_b == 3)
{
ra_from.assign(1, 1);
rb_to.assign(0, 1);
}
if (a2_wrt_b == 1)
{
ra_to.assign(0, 1);
rb_from.assign(1, 1);
}
else if (a2_wrt_b == 3)
{
ra_to.assign(1, 1);
rb_to.assign(1, 1);
}
if ((a1_wrt_b < 1 && a2_wrt_b < 1) || (a1_wrt_b > 3 && a2_wrt_b > 3))
//if ((ra_from.left() && ra_to.left()) || (ra_from.right() && ra_to.right()))
{
return Policy::disjoint();
}
bool const opposite = math::sign(length_a) != math::sign(length_b);
return Policy::segments_collinear(a, b, opposite,
a1_wrt_b, a2_wrt_b, b1_wrt_a, b2_wrt_a,
ra_from, ra_to, rb_from, rb_to);
}
/// Relate segments where one is degenerate
template
<
typename Policy,
typename RatioType,
typename DegenerateSegment,
typename Type1,
typename Type2
>
static inline typename Policy::return_type
relate_one_degenerate(DegenerateSegment const& degenerate_segment,
Type1 d, Type2 s1, Type2 s2,
bool a_degenerate)
{
// Calculate the ratios where ds starts in s
// a1--------->a2 (2..6)
// b1/b2 (4..4)
// Ratio: (4-2)/(6-2)
RatioType const ratio(d - s1, s2 - s1);
if (!ratio.on_segment())
{
return Policy::disjoint();
}
return Policy::one_degenerate(degenerate_segment, ratio, a_degenerate);
}
template <typename ProjCoord1, typename ProjCoord2>
static inline int position_value(ProjCoord1 const& ca1,
ProjCoord2 const& cb1,
ProjCoord2 const& cb2)
{
// S1x 0 1 2 3 4
// S2 |---------->
return math::equals(ca1, cb1) ? 1
: math::equals(ca1, cb2) ? 3
: cb1 < cb2 ?
( ca1 < cb1 ? 0
: ca1 > cb2 ? 4
: 2 )
: ( ca1 > cb1 ? 0
: ca1 < cb2 ? 4
: 2 );
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef cartesian_segments<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::intersection
namespace strategy
{
namespace within { namespace services
{
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
}} // within::services
namespace covered_by { namespace services
{
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
}} // within::services
} // strategy
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP

View File

@@ -0,0 +1,74 @@
// Boost.Geometry
// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP
#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP
#include <boost/geometry/strategies/io.hpp>
#include <boost/geometry/strategies/cartesian/point_order.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace io
{
template <typename CalculationType = void>
struct cartesian
{
typedef strategy::point_order::cartesian<CalculationType> point_order_strategy_type;
static inline point_order_strategy_type get_point_order_strategy()
{
return point_order_strategy_type();
}
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::cartesian_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
CalculationType
> type;
};
template <typename Geometry1, typename Geometry2>
static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
get_point_in_geometry_strategy()
{
typedef typename point_in_geometry_strategy
<
Geometry1, Geometry2
>::type strategy_type;
return strategy_type();
}
};
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef cartesian<> type;
};
} // namespace services
}} // namespace strategy::io
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_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_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

@@ -0,0 +1,332 @@
// 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 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_POINT_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
#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>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct within_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value > min_value && value < max_value;
}
};
struct covered_by_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value >= min_value && value <= max_value;
}
};
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct within_range
: within_coord
{};
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct covered_by_range
: covered_by_coord
{};
// NOTE: the result would be the same if instead of structs defined below
// the above xxx_range were used with the following arguments:
// (min_value + diff_min, min_value, max_value)
struct within_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
CalcT const c0 = 0;
return diff_min > c0
&& (min_value + diff_min < max_value
/*|| max_value - diff_min > min_value*/);
}
};
struct covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
return min_value + diff_min <= max_value
/*|| max_value - diff_min >= min_value*/;
}
};
template <typename Geometry,
typename CoordCheck,
typename DiffCheck>
struct longitude_range
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
typedef typename select_most_precise
<
Value1, Value2
>::type calc_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))
{
return true;
}
// min <= max <=> diff >= 0
calc_t const diff_ing = max_value - min_value;
// if containing covers the whole globe it contains all
if (diff_ing >= constants::period())
{
return true;
}
// calculate positive longitude translation with min_value as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);
return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value);
}
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Geometry>
struct within_range<Geometry, 0, spherical_tag>
: longitude_range<Geometry, within_coord, within_longitude_diff>
{};
template <typename Geometry>
struct covered_by_range<Geometry, 0, spherical_tag>
: longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff>
{};
template
<
template <typename, std::size_t, typename> class SubStrategy,
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)
{
if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point),
get<min_corner, Dimension>(box),
get<max_corner, Dimension>(box))
)
{
return false;
}
return relate_point_box_loop
<
SubStrategy,
CSTag,
Dimension + 1, DimensionCount
>::apply(point, box);
}
};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename CSTag,
std::size_t 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
struct cartesian_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,
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 services
{
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef covered_by::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 covered_by::spherical_point_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace covered_by
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP

View File

@@ -0,0 +1,126 @@
// 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, 2019.
// Modifications copyright (c) 2013-2019, 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
{
typedef cartesian_tag cs_tag;
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

@@ -0,0 +1,134 @@
// 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.
// This file was modified by Oracle on 2018, 2019.
// Modifications copyright (c) 2018, 2019, 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_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#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>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting,
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c
\note Does NOT work correctly for point ON border
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point_, // for backward compatibility
typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class crossings_multiply
{
template <typename Point, typename PointOfSegment>
struct calculation_type
: select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>
{};
class flags
{
bool inside_flag;
bool first;
bool yflag0;
public :
friend class crossings_multiply;
inline flags()
: inside_flag(false)
, first(true)
, yflag0(false)
{}
};
public :
typedef flags state_type;
template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
flags& state)
{
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
calc_t const tx = get<0>(point);
calc_t const ty = get<1>(point);
calc_t const x0 = get<0>(seg1);
calc_t const y0 = get<1>(seg1);
calc_t const x1 = get<0>(seg2);
calc_t const y1 = get<1>(seg2);
if (state.first)
{
state.first = false;
state.yflag0 = y0 >= ty;
}
bool yflag1 = y1 >= ty;
if (state.yflag0 != yflag1)
{
if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )
{
state.inside_flag = ! state.inside_flag;
}
}
state.yflag0 = yflag1;
return true;
}
static inline int result(flags const& state)
{
return state.inside_flag ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP

View File

@@ -0,0 +1,128 @@
// 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.
// This file was modified by Oracle on 2018, 2019.
// Modifications copyright (c) 2018, 2019, 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_POINT_IN_POLY_FRANKLIN_HPP
#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>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author adapted from Randolph Franklin algorithm
\author Barend and Maarten, 1995
\author Revised for templatized library, Barend Gehrels, 2007
\return true if point is in ring, works for closed rings in both directions
\note Does NOT work correctly for point ON border
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point_, // for backward compatibility
typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class franklin
{
template <typename Point, typename PointOfSegment>
struct calculation_type
: select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>
{};
/*! subclass to keep state */
class crossings
{
bool crosses;
public :
friend class franklin;
inline crossings()
: crosses(false)
{}
};
public :
typedef crossings state_type;
template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
crossings& state)
{
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
calc_t const& px = get<0>(point);
calc_t const& py = get<1>(point);
calc_t const& x1 = get<0>(seg1);
calc_t const& y1 = get<1>(seg1);
calc_t const& x2 = get<0>(seg2);
calc_t const& y2 = get<1>(seg2);
if (
( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
&& (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)
)
{
state.crosses = ! state.crosses;
}
return true;
}
static inline int result(crossings const& state)
{
return state.crosses ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP

View File

@@ -0,0 +1,315 @@
// 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-2020.
// Modifications copyright (c) 2013-2020 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/strategy/cartesian/expand_point.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_ = void, // for backward compatibility
typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class cartesian_winding
{
template <typename Point, typename PointOfSegment>
struct calculation_type
: select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>
{};
/*! 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 cartesian_tag cs_tag;
typedef side::side_by_triangle<CalculationType> side_strategy_type;
static inline side_strategy_type get_side_strategy()
{
return side_strategy_type();
}
typedef expand::cartesian_point expand_point_strategy_type;
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 counter state_type;
template <typename Point, typename PointOfSegment>
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:
template <typename Point, typename PointOfSegment>
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);
}
template <typename Point, typename PointOfSegment>
static inline bool check_touch(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2)
{
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
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;
}
template <typename Point, typename PointOfSegment>
static inline int calculate_count(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
bool eq1, bool eq2)
{
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
calc_t const p = get<0>(point);
calc_t const s1 = get<0>(seg1);
calc_t 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;
}
template <typename Point, typename PointOfSegment>
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<> 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<> 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<> 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<> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP

View File

@@ -0,0 +1,54 @@
// Boost.Geometry
// Copyright (c) 2019-2020, 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_POINT_ORDER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategy/cartesian/area.hpp>
#include <boost/geometry/strategies/point_order.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace point_order
{
template <typename CalculationType = void>
struct cartesian
: strategy::area::cartesian<CalculationType>
{
typedef area_tag version_tag;
// TEMP
static strategy::area::cartesian<CalculationType> get_area_strategy()
{
return strategy::area::cartesian<CalculationType>();
}
};
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef cartesian<> type;
};
} // namespace services
}} // namespace strategy::point_order
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP

View File

@@ -0,0 +1,296 @@
// 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-2020.
// Modifications copyright (c) 2015-2020, 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.
// 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_SIDE_BY_TRIANGLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#include <type_traits>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.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/equals/point_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
/*!
\brief Check at which side of a segment a point lies:
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class side_by_triangle
{
template <typename Policy>
struct eps_policy
{
eps_policy() {}
template <typename Type>
eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
: policy(a, b, c, d)
{}
Policy policy;
};
struct eps_empty
{
eps_empty() {}
template <typename Type>
eps_empty(Type const&, Type const&, Type const&, Type const&) {}
};
public :
typedef cartesian_tag cs_tag;
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
// strategy-struct itself.
// Types can be all three different. Therefore it is
// not implemented (anymore) as "segment"
template
<
typename CoordinateType,
typename PromotedType,
typename P1,
typename P2,
typename P,
typename EpsPolicy
>
static inline
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
{
CoordinateType const x = get<0>(p);
CoordinateType const y = get<1>(p);
CoordinateType const sx1 = get<0>(p1);
CoordinateType const sy1 = get<1>(p1);
CoordinateType const sx2 = get<0>(p2);
CoordinateType const sy2 = get<1>(p2);
PromotedType const dx = sx2 - sx1;
PromotedType const dy = sy2 - sy1;
PromotedType const dpx = x - sx1;
PromotedType const dpy = y - sy1;
eps_policy = EpsPolicy(dx, dy, dpx, dpy);
return geometry::detail::determinant<PromotedType>
(
dx, dy,
dpx, dpy
);
}
template
<
typename CoordinateType,
typename PromotedType,
typename P1,
typename P2,
typename P
>
static inline
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
{
eps_empty dummy;
return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
}
template
<
typename CoordinateType,
typename PromotedType,
bool AreAllIntegralCoordinates
>
struct compute_side_value
{
template <typename P1, typename P2, typename P, typename EpsPolicy>
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
{
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
}
};
template <typename CoordinateType, typename PromotedType>
struct compute_side_value<CoordinateType, PromotedType, false>
{
template <typename P1, typename P2, typename P, typename EpsPolicy>
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
{
// For robustness purposes, first check if any two points are
// the same; in this case simply return that the points are
// collinear
if (equals_point_point(p1, p2)
|| equals_point_point(p1, p)
|| equals_point_point(p2, p))
{
return PromotedType(0);
}
// The side_by_triangle strategy computes the signed area of
// the point triplet (p1, p2, p); as such it is (in theory)
// invariant under cyclic permutations of its three arguments.
//
// In the context of numerical errors that arise in
// floating-point computations, and in order to make the strategy
// consistent with respect to cyclic permutations of its three
// arguments, we cyclically permute them so that the first
// argument is always the lexicographically smallest point.
typedef compare::cartesian<compare::less> less;
if (less::apply(p, p1))
{
if (less::apply(p, p2))
{
// p is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
}
else
{
// p2 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
}
}
if (less::apply(p1, p2))
{
// p1 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
}
else
{
// p2 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
}
}
};
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
typedef typename coordinate_type<P1>::type coordinate_type1;
typedef typename coordinate_type<P2>::type coordinate_type2;
typedef typename coordinate_type<P>::type coordinate_type3;
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_most_precise
<
coordinate_type1,
coordinate_type2,
coordinate_type3
>::type,
CalculationType
> coordinate_type;
// Promote float->double, small int->int
typedef typename select_most_precise
<
coordinate_type,
double
>::type promoted_type;
bool const are_all_integral_coordinates =
std::is_integral<coordinate_type1>::value
&& std::is_integral<coordinate_type2>::value
&& std::is_integral<coordinate_type3>::value;
eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
promoted_type s = compute_side_value
<
coordinate_type, promoted_type, are_all_integral_coordinates
>::apply(p1, p2, p, epsp);
promoted_type const zero = promoted_type();
return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
: s > zero ? 1
: -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());
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef side_by_triangle<CalculationType> type;
};
}
#endif
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP

View File

@@ -0,0 +1,213 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2020 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_CARTESIAN_TURN_IN_RING_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
#ifndef DOXYGEN_NO_DETAIL
enum place_on_ring_type
{
// +----offsetted----> (offsetted is considered as outside)
// | |
// | |
// left right (first point outside, rest inside)
// | |
// | |
// <-----original----+ (original is considered as inside)
place_on_ring_offsetted,
place_on_ring_original,
place_on_ring_to_offsetted,
place_on_ring_from_offsetted,
};
template <typename CalculationType>
class turn_in_ring_winding
{
// Implements the winding rule.
// Basic calculations (on a clockwise ring of 5 segments)
// (as everywhere in BG, -1 = right, 0 = on segment, +1 = left)
// +--------2--------+ // P : For 1/3, nothing happens, it returns
// | | // For 2, side is right (-1), multiplier=2, -2
// | P | // For 4, side is right (-1), multiplier=1, -1
// 1 3 // For 5, side is right (-1), multiplier=1, -1, total -4
// | Q | // Q : For 2: -2, for 4: -2, total -4
// | | // R : For 2: -2, for 5: +2, total 0
// +----5---*----4---+ // S : For 2: -1, 3: nothing, 4: +1, total 0
//
// R S
//
public:
struct counter
{
inline counter()
: m_count(0)
, m_min_distance(0)
, m_close_to_offset(false)
{}
//! Returns -1 for outside, 1 for inside
inline int code() const
{
return m_count == 0 ? -1 : 1;
}
//! Counter, is increased if point is left of a segment (outside),
//! and decreased if point is right of a segment (inside)
int m_count;
//! Indicate an indication of distance. It is always set, unless
//! the point is located on the border-part of the original.
//! It is not guaranteed to be the minimum distance, because it is only
//! calculated for a selection of the offsetted ring.
CalculationType m_min_distance;
bool m_close_to_offset;
};
typedef counter state_type;
template <typename Point, typename PointOfSegment>
static inline bool in_vertical_range(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2)
{
CalculationType const py = get<1>(point);
CalculationType const s1y = get<1>(s1);
CalculationType const s2y = get<1>(s2);
return (s1y >= py && s2y <= py)
|| (s2y >= py && s1y <= py);
}
template <typename Dm, typename Point, typename PointOfSegment>
static inline void apply_on_boundary(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2,
place_on_ring_type place_on_ring,
counter& the_state)
{
if (place_on_ring == place_on_ring_offsetted)
{
// Consider the point as "outside"
the_state.m_count = 0;
the_state.m_close_to_offset = true;
the_state.m_min_distance = 0;
}
else if (place_on_ring == place_on_ring_to_offsetted
|| place_on_ring == place_on_ring_from_offsetted)
{
// Check distance from "point" to either s1 or s2
// on a line perpendicular to s1-s2
typedef model::infinite_line<CalculationType> line_type;
line_type const line
= detail::make::make_perpendicular_line<CalculationType>(s1, s2,
place_on_ring == place_on_ring_to_offsetted ? s2 : s1);
Dm perp;
perp.measure = arithmetic::side_value(line, point);
// If it is to the utmost point s1 or s2, it is "outside"
the_state.m_count = perp.is_zero() ? 0 : 1;
the_state.m_close_to_offset = true;
the_state.m_min_distance = geometry::math::abs(perp.measure);
}
else
{
// It is on the border, the part of the original
// Consider it as "inside".
the_state.m_count = 1;
}
}
template <typename Dm, typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2,
Dm const& dm,
place_on_ring_type place_on_ring,
counter& the_state)
{
CalculationType const px = get<0>(point);
CalculationType const s1x = get<0>(s1);
CalculationType const s2x = get<0>(s2);
bool const in_horizontal_range
= (s1x >= px && s2x <= px)
|| (s2x >= px && s1x <= px);
bool const vertical = s1x == s2x;
bool const measured_on_boundary = dm.is_zero();
if (measured_on_boundary
&& (in_horizontal_range
|| (vertical && in_vertical_range(point, s1, s2))))
{
apply_on_boundary<Dm>(point, s1, s2, place_on_ring, the_state);
// Indicate that no further processing is necessary.
return false;
}
bool const is_on_right_side = dm.is_negative();
if (place_on_ring == place_on_ring_offsetted
&& is_on_right_side
&& (! the_state.m_close_to_offset
|| -dm.measure < the_state.m_min_distance))
{
// This part of the ring was the offsetted part,
// keep track of the distance WITHIN the ring
// with respect to the offsetted part
// NOTE: this is also done if it is NOT in the horizontal range.
the_state.m_min_distance = -dm.measure;
the_state.m_close_to_offset = true;
}
if (in_horizontal_range)
{
// Use only absolute comparisons, because the ring is continuous -
// what was missed is there earlier or later, and turns should
// not be counted twice (which can happen if an epsilon is used).
bool const eq1 = s1x == px;
bool const eq2 = s2x == px;
// Account for 1 or 2 for left side (outside)
// and for -1 or -2 for right side (inside)
int const side = is_on_right_side ? -1 : 1;
int const multiplier = eq1 || eq2 ? 1 : 2;
the_state.m_count += side * multiplier;
}
return true;
}
};
#endif // DOXYGEN_NO_DETAIL
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP

View File

@@ -0,0 +1,74 @@
// 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.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, 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_CENTROID_HPP
#define BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
#include <cstddef>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
struct not_applicable_strategy
{
};
namespace services
{
/*!
\brief Traits class binding a centroid calculation strategy to a coordinate system
\ingroup centroid
\tparam CsTag tag of coordinate system, for specialization
\tparam GeometryTag tag of geometry, for specialization
\tparam Dimension dimension of geometry, for specialization
\tparam Point point-type
\tparam Geometry
*/
template
<
typename CsTag,
typename GeometryTag,
std::size_t Dimension,
typename Point,
typename Geometry
>
struct default_strategy
{
typedef not_applicable_strategy type;
};
} // namespace services
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP

View File

@@ -0,0 +1,254 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, 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_COMPARABLE_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
template
<
typename Geometry1, typename Geometry2, typename Strategy,
bool AreGeometries = (util::is_geometry<Geometry1>::value
&& util::is_geometry<Geometry2>::value)
>
struct comparable_distance_result
: strategy::distance::services::return_type
<
typename strategy::distance::services::comparable_type
<
Strategy
>::type,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>
{};
template <typename Geometry1, typename Geometry2, bool AreGeometries>
struct comparable_distance_result<Geometry1, Geometry2, default_strategy, AreGeometries>
: comparable_distance_result
<
Geometry1,
Geometry2,
typename detail::distance::default_strategy
<
Geometry1, Geometry2
>::type
>
{};
// Workaround for VS2015
#if defined(_MSC_VER) && (_MSC_VER < 1910)
template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_result<Geometry1, Geometry2, Strategy, false>
{
typedef int type;
};
template <typename Geometry1, typename Geometry2>
struct comparable_distance_result<Geometry1, Geometry2, default_strategy, false>
{
typedef int type;
};
#endif
} // namespace resolve_strategy
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Strategy = geometry::default_strategy>
struct more_precise_comparable_distance_result
{
template <typename Curr, typename Next>
struct predicate
: std::is_same
<
typename resolve_strategy::comparable_distance_result
<
typename util::sequence_element<0, Curr>::type,
typename util::sequence_element<1, Curr>::type,
Strategy
>::type,
typename geometry::select_most_precise
<
typename resolve_strategy::comparable_distance_result
<
typename util::sequence_element<0, Curr>::type,
typename util::sequence_element<1, Curr>::type,
Strategy
>::type,
typename resolve_strategy::comparable_distance_result
<
typename util::sequence_element<0, Next>::type,
typename util::sequence_element<1, Next>::type,
Strategy
>::type
>::type
>
{};
};
}} // namespace detail::distance
#endif //DOXYGEN_NO_DETAIL
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_result
: resolve_strategy::comparable_distance_result
<
Geometry1,
Geometry2,
Strategy
>
{};
template
<
typename Geometry1,
BOOST_VARIANT_ENUM_PARAMS(typename T),
typename Strategy
>
struct comparable_distance_result
<
Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
>
{
// Select the most precise distance strategy result type
// for all variant type combinations.
// TODO: We should ignore the combinations that are not valid
// but is_implemented is not ready for prime time.
typedef typename util::select_combination_element
<
util::type_sequence<Geometry1>,
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(T)>,
detail::distance::more_precise_comparable_distance_result
<
Strategy
>::template predicate
>::type elements;
typedef typename resolve_strategy::comparable_distance_result
<
typename util::sequence_element<0, elements>::type,
typename util::sequence_element<1, elements>::type,
Strategy
>::type type;
};
// Distance arguments are commutative
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T),
typename Geometry2,
typename Strategy
>
struct comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2, Strategy
>
: public comparable_distance_result
<
Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
>
{};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T),
BOOST_VARIANT_ENUM_PARAMS(typename U),
typename Strategy
>
struct comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>,
Strategy
>
{
// Select the most precise distance strategy result type
// for all variant type combinations.
// TODO: We should ignore the combinations that are not valid
// but is_implemented is not ready for prime time.
typedef typename util::select_combination_element
<
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(T)>,
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(U)>,
detail::distance::more_precise_comparable_distance_result
<
Strategy
>::template predicate
>::type elements;
typedef typename resolve_strategy::comparable_distance_result
<
typename util::sequence_element<0, elements>::type,
typename util::sequence_element<1, elements>::type,
Strategy
>::type type;
};
} // namespace resolve_variant
/*!
\brief Meta-function defining return type of comparable_distance function
\ingroup distance
*/
template
<
typename Geometry1,
typename Geometry2 = Geometry1,
typename Strategy = void
>
struct comparable_distance_result
: resolve_variant::comparable_distance_result
<
Geometry1, Geometry2, Strategy
>
{};
template <typename Geometry1, typename Geometry2>
struct comparable_distance_result<Geometry1, Geometry2, void>
: comparable_distance_result<Geometry1, Geometry2, default_strategy>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP

View File

@@ -0,0 +1,218 @@
// 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.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, 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_COMPARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
#include <algorithm>
#include <cstddef>
#include <functional>
#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/core/static_assert.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace compare
{
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 ComparePolicy,
std::size_t Dimension,
std::size_t DimensionCount
>
struct compare_loop
{
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
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,
((std::min)(geometry::dimension<Point1>::value,
geometry::dimension<Point2>::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_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for these 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
#endif // BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP

View File

@@ -0,0 +1,79 @@
// 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 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.
// 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_CONCEPTS_AREA_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for area
\ingroup area
*/
template <typename Geometry, typename Strategy>
class AreaStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state template,
typedef typename Strategy::template state<Geometry> state_type;
// 2) must define result_type template,
typedef typename Strategy::template result_type<Geometry>::type return_type;
struct check_methods
{
static void apply()
{
Strategy const* str = 0;
state_type *st = 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);
// 4) must implement a static method result with the following signature
return_type r = str->result(*st);
boost::ignore_unused(r, str);
}
};
public :
BOOST_CONCEPT_USAGE(AreaStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP

View File

@@ -0,0 +1,77 @@
// 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.
// 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_CONCEPTS_CENTROID_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for centroid
\ingroup centroid
*/
template <typename Strategy>
class CentroidStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type,
typedef typename Strategy::state_type state_type;
// 2) must define point_type,
typedef typename Strategy::point_type point_type;
// 3) must define point_type, of polygon (segments)
typedef typename Strategy::segment_point_type spoint_type;
struct check_methods
{
static void apply()
{
Strategy *str = 0;
state_type *st = 0;
// 4) must implement a static method apply,
// getting two segment-points
spoint_type const* sp = 0;
str->apply(*sp, *sp, *st);
// 5) must implement a static method result
// getting the centroid
point_type *c = 0;
bool r = str->result(*st, *c);
boost::ignore_unused(str, r);
}
};
public :
BOOST_CONCEPT_USAGE(CentroidStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP

View File

@@ -0,0 +1,80 @@
// 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.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 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_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
#include <vector>
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for convex_hull
\ingroup convex_hull
*/
template <typename Strategy>
class ConvexHullStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type
typedef typename Strategy::state_type state_type;
// 2) must define point_type
typedef typename Strategy::point_type point_type;
// 3) must define geometry_type
typedef typename Strategy::geometry_type geometry_type;
struct check_methods
{
static void apply()
{
Strategy const* str = 0;
state_type* st = 0;
geometry_type* sp = 0;
std::vector<point_type> *v = 0;
// 4) must implement a method apply, iterating over a range
str->apply(*sp, *st);
// 5) must implement a method result, with an output iterator
str->result(*st, std::back_inserter(*v), true, true);
}
};
public :
BOOST_CONCEPT_USAGE(ConvexHullStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP

View File

@@ -0,0 +1,215 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, 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.
// 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_CONCEPTS_DISTANCE_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
#include <iterator>
#include <type_traits>
#include <vector>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/parameter_type_of.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for point-point or point-box or box-box distance
\ingroup distance
*/
template <typename Strategy, typename Point1, typename Point2>
struct PointDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod)
{
// 1: inspect and define both arguments of apply
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type ptype1;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type ptype2;
// 2) must define meta-function "return_type"
typedef typename strategy::distance::services::return_type
<
Strategy, ptype1, ptype2
>::type rtype;
// 3) must define meta-function "comparable_type"
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type ctype;
// 4) must define meta-function "tag"
typedef typename strategy::distance::services::tag
<
Strategy
>::type tag;
static const bool is_correct_strategy_tag =
std::is_same<tag, strategy_tag_distance_point_point>::value
|| std::is_same<tag, strategy_tag_distance_point_box>::value
|| std::is_same<tag, strategy_tag_distance_box_box>::value;
BOOST_GEOMETRY_STATIC_ASSERT(
is_correct_strategy_tag,
"Incorrect Strategy tag.",
Strategy, tag);
// 5) must implement apply with arguments
Strategy* str = 0;
ptype1 *p1 = 0;
ptype2 *p2 = 0;
rtype r = str->apply(*p1, *p2);
// 6) must define (meta)struct "get_comparable" with apply
ctype c = strategy::distance::services::get_comparable
<
Strategy
>::apply(*str);
// 7) must define (meta)struct "result_from_distance" with apply
r = strategy::distance::services::result_from_distance
<
Strategy,
ptype1, ptype2
>::apply(*str, 1.0);
boost::ignore_unused<tag>();
boost::ignore_unused(str, c, r);
}
};
public :
BOOST_CONCEPT_USAGE(PointDistanceStrategy)
{
checker::apply(&Strategy::template apply<Point1, Point2>);
}
#endif
};
/*!
\brief Checks strategy for point-segment distance
\ingroup strategy_concepts
*/
template <typename Strategy, typename Point, typename PointOfSegment>
struct PointSegmentDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod)
{
// 1) inspect and define both arguments of apply
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type ptype;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type sptype;
namespace services = strategy::distance::services;
// 2) must define meta-function "tag"
typedef typename services::tag<Strategy>::type tag;
BOOST_GEOMETRY_STATIC_ASSERT(
(std::is_same
<
tag, strategy_tag_distance_point_segment
>::value),
"Incorrect Strategy tag.",
Strategy, tag);
// 3) must define meta-function "return_type"
typedef typename services::return_type
<
Strategy, ptype, sptype
>::type rtype;
// 4) must define meta-function "comparable_type"
typedef typename services::comparable_type<Strategy>::type ctype;
// 5) must implement apply with arguments
Strategy *str = 0;
ptype *p = 0;
sptype *sp1 = 0;
sptype *sp2 = 0;
rtype r = str->apply(*p, *sp1, *sp2);
// 6) must define (meta-)struct "get_comparable" with apply
ctype cstrategy = services::get_comparable<Strategy>::apply(*str);
// 7) must define (meta-)struct "result_from_distance" with apply
r = services::result_from_distance
<
Strategy, ptype, sptype
>::apply(*str, rtype(1.0));
boost::ignore_unused(str, r, cstrategy);
}
};
public :
BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
{
checker::apply(&Strategy::template apply<Point, PointOfSegment>);
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP

View File

@@ -0,0 +1,78 @@
// 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.
// 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_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
//NOT FINISHED!
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for segment intersection
\ingroup segment_intersection
*/
template <typename Strategy>
class SegmentIntersectStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define return_type
typedef typename Strategy::return_type return_type;
// 2) must define point_type (of segment points)
//typedef typename Strategy::point_type point_type;
// 3) must define segment_type 1 and 2 (of segment points)
typedef typename Strategy::segment_type1 segment_type1;
typedef typename Strategy::segment_type2 segment_type2;
struct check_methods
{
static void apply()
{
Strategy const* str;
return_type* rt;
//point_type const* p;
segment_type1 const* s1;
segment_type2 const* s2;
// 4) must implement a method apply
// having two segments
*rt = str->apply(*s1, *s2);
}
};
public :
BOOST_CONCEPT_USAGE(SegmentIntersectStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP

View File

@@ -0,0 +1,101 @@
// 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.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, 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_CONCEPTS_SIMPLIFY_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
#include <iterator>
#include <type_traits>
#include <vector>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for simplify
\ingroup simplify
*/
template <typename Strategy, typename Point>
struct SimplifyStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
// 1) must define distance_strategy_type,
// defining point-segment distance strategy (to be checked)
typedef typename Strategy::distance_strategy_type ds_type;
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod)
{
namespace ft = boost::function_types;
typedef typename ft::parameter_types
<
ApplyMethod
>::type parameter_types;
typedef std::conditional_t
<
ft::is_member_function_pointer<ApplyMethod>::value,
std::integral_constant<int, 1>,
std::integral_constant<int, 0>
> base_index;
BOOST_CONCEPT_ASSERT
(
(concepts::PointSegmentDistanceStrategy<ds_type, Point, Point>)
);
Strategy *str = 0;
std::vector<Point> const* v1 = 0;
std::vector<Point> * v2 = 0;
// 2) must implement method apply with arguments
// - Range
// - OutputIterator
// - floating point value
str->apply(*v1, std::back_inserter(*v2), 1.0);
boost::ignore_unused<parameter_types, base_index>();
boost::ignore_unused(str);
}
};
public :
BOOST_CONCEPT_USAGE(SimplifyStrategy)
{
checker::apply(&ds_type::template apply<Point, Point>);
}
#endif
};
}}} // namespace boost::geometry::concepts
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP

View File

@@ -0,0 +1,322 @@
// 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.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020 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_CONCEPTS_WITHIN_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
#include <type_traits>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/geometry/core/static_assert.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>
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks strategy for within (point-in-polygon)
\ingroup within
*/
template <typename Point, typename Polygonal, typename Strategy>
class WithinStrategyPolygonal
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
typedef typename geometry::point_type<Polygonal>::type point_of_segment;
// 1) must define state_type
typedef typename Strategy::state_type state_type;
struct checker
{
template <typename ApplyMethod, typename ResultMethod>
static void apply(ApplyMethod, ResultMethod)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type point_type;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type segment_point_type;
// CHECK: apply-arguments should both fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concepts::ConstPoint<point_type>)
);
BOOST_CONCEPT_ASSERT
(
(concepts::ConstPoint<segment_point_type>)
);
// CHECK: return types (result: int, apply: bool)
BOOST_GEOMETRY_STATIC_ASSERT
(
(std::is_same
<
bool, typename boost::function_types::result_type<ApplyMethod>::type
>::value),
"Wrong return type of apply().",
bool, ApplyMethod
);
BOOST_GEOMETRY_STATIC_ASSERT
(
(std::is_same
<
int, typename boost::function_types::result_type<ResultMethod>::type
>::value),
"Wrong return type of result().",
int, ResultMethod
);
// CHECK: calling method apply and result
Strategy const* str = 0;
state_type* st = 0;
point_type const* p = 0;
segment_point_type const* sp = 0;
bool b = str->apply(*p, *sp, *sp, *st);
int r = str->result(*st);
boost::ignore_unused(r, b, str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
{
checker::apply(&Strategy::template apply<Point, point_of_segment>,
&Strategy::result);
}
#endif
};
template <typename Point, typename Box, typename Strategy>
class WithinStrategyPointBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type point_type;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type box_type;
// CHECK: apply-arguments should fulfill point/box concept
BOOST_CONCEPT_ASSERT
(
(concepts::ConstPoint<point_type>)
);
BOOST_CONCEPT_ASSERT
(
(concepts::ConstBox<box_type>)
);
// CHECK: return types (apply: bool)
BOOST_GEOMETRY_STATIC_ASSERT
(
(std::is_same
<
bool,
typename boost::function_types::result_type<ApplyMethod>::type
>::value),
"Wrong return type of apply().",
bool, ApplyMethod
);
// CHECK: calling method apply
Strategy const* str = 0;
point_type const* p = 0;
box_type const* bx = 0;
bool b = str->apply(*p, *bx);
boost::ignore_unused(b, str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
{
checker::apply(&Strategy::template apply<Point, Box>);
}
#endif
};
template <typename Box1, typename Box2, typename Strategy>
class WithinStrategyBoxBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type box_type1;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type box_type2;
// CHECK: apply-arguments should both fulfill box concept
BOOST_CONCEPT_ASSERT
(
(concepts::ConstBox<box_type1>)
);
BOOST_CONCEPT_ASSERT
(
(concepts::ConstBox<box_type2>)
);
// CHECK: return types (apply: bool)
BOOST_GEOMETRY_STATIC_ASSERT
(
(std::is_same
<
bool,
typename boost::function_types::result_type<ApplyMethod>::type
>::value),
"Wrong return type of apply().",
bool, ApplyMethod
);
// CHECK: calling method apply
Strategy const* str = 0;
box_type1 const* b1 = 0;
box_type2 const* b2 = 0;
bool b = str->apply(*b1, *b2);
boost::ignore_unused(b, str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
{
checker::apply(&Strategy::template apply<Box1, Box2>);
}
#endif
};
// So now: boost::geometry::concepts::within
namespace within
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1, typename Geometry2,
typename FirstTag, typename SecondTag, typename CastedTag,
typename Strategy
>
struct check_within
{};
template
<
typename Geometry1, typename Geometry2,
typename AnyTag,
typename Strategy
>
struct check_within<Geometry1, Geometry2, point_tag, AnyTag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Geometry1, Geometry2, Strategy>) );
};
template <typename Geometry1, typename Geometry2, typename Strategy>
struct check_within<Geometry1, Geometry2, point_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Geometry1, Geometry2, Strategy>) );
};
template <typename Geometry1, typename Geometry2, typename Strategy>
struct check_within<Geometry1, Geometry2, box_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Geometry1, Geometry2, Strategy>) );
};
} // namespace dispatch
#endif
/*!
\brief Checks, in compile-time, the concept of any within-strategy
\ingroup concepts
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline void check()
{
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);
}
}}}} // namespace boost::geometry::concepts::within
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP

View File

@@ -0,0 +1,53 @@
// 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.
// 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.
// 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_CONVEX_HULL_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
/*!
\brief Traits class binding a convex hull calculation strategy to a coordinate system
\ingroup convex_hull
\tparam Tag tag of coordinate system
\tparam Geometry the geometry type (hull operates internally per hull over geometry)
\tparam Point point-type of output points
*/
template
<
typename Geometry1,
typename Point,
typename CsTag = typename cs_tag<Point>::type
>
struct strategy_convex_hull
{
typedef strategy::not_implemented type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP

View File

@@ -0,0 +1,96 @@
// 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.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, 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_COVERED_BY_HPP
#define BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/tag_cast.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace covered_by
{
namespace services
{
/*!
\brief Traits class binding a covered_by determination strategy to a coordinate system
\ingroup covered_by
\tparam GeometryContained geometry-type of input (possibly) contained type
\tparam GeometryContaining geometry-type of input (possibly) containing type
\tparam TagContained casted tag of (possibly) contained type
\tparam TagContaining casted tag of (possibly) containing type
\tparam CsTagContained tag of coordinate system of (possibly) contained type
\tparam CsTagContaining tag of coordinate system of (possibly) containing type
*/
template
<
typename GeometryContained,
typename GeometryContaining,
typename TagContained = typename tag<GeometryContained>::type,
typename TagContaining = typename tag<GeometryContaining>::type,
typename CastedTagContained = typename tag_cast
<
typename tag<GeometryContained>::type,
pointlike_tag, linear_tag, polygonal_tag, areal_tag
>::type,
typename CastedTagContaining = typename tag_cast
<
typename tag<GeometryContaining>::type,
pointlike_tag, linear_tag, polygonal_tag, areal_tag
>::type,
typename CsTagContained = typename tag_cast
<
typename cs_tag<typename point_type<GeometryContained>::type>::type,
spherical_tag
>::type,
typename CsTagContaining = typename tag_cast
<
typename cs_tag<typename point_type<GeometryContaining>::type>::type,
spherical_tag
>::type
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for these types.",
GeometryContained, GeometryContaining);
};
} // namespace services
}} // namespace strategy::covered_by
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_DEFAULT_AREA_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/algorithms/default_area_result.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP

View File

@@ -0,0 +1,43 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// 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.
// 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_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP
#include <boost/geometry/strategies/comparable_distance_result.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of comparable_distance function
\ingroup distance
\note The strategy defines the return-type (so this situation is different
from length, where distance is sqr/sqrt, but length always squared)
*/
template <typename Geometry1, typename Geometry2 = Geometry1>
struct default_comparable_distance_result
: comparable_distance_result<Geometry1, Geometry2, void>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP

View File

@@ -0,0 +1,43 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// 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.
// 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_DEFAULT_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP
#include <boost/geometry/strategies/distance_result.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of distance function
\ingroup distance
\note The strategy defines the return-type (so this situation is different
from length, where distance is sqr/sqrt, but length always squared)
*/
template <typename Geometry1, typename Geometry2 = Geometry1>
struct default_distance_result
: distance_result<Geometry1, Geometry2, void>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP

View File

@@ -0,0 +1,106 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
// 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_DEFAULT_LENGTH_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
// NOTE: The implementation was simplified greately preserving the old
// behavior. In general case the result types of Strategies should be
// taken into account.
// It would probably be enough to use distance_result and
// default_distance_result here.
// Workaround for VS2015
#if defined(_MSC_VER) && (_MSC_VER < 1910)
template
<
typename Geometry,
bool IsGeometry = util::is_geometry<Geometry>::value
>
struct coordinate_type
: geometry::coordinate_type<Geometry>
{};
template <typename Geometry>
struct coordinate_type<Geometry, false>
{
typedef long double type;
};
#endif
template <typename ...Geometries>
struct default_length_result
{
typedef typename select_most_precise
<
typename coordinate_type<Geometries>::type...,
long double
>::type type;
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry>
struct default_length_result
: resolve_strategy::default_length_result<Geometry>
{};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct default_length_result<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
: resolve_strategy::default_length_result<BOOST_VARIANT_ENUM_PARAMS(T)>
{};
} // namespace resolve_variant
/*!
\brief Meta-function defining return type of length function
\ingroup length
\note Length of a line of integer coordinates can be double.
So we take at least a double. If Big Number types are used,
we take that type.
*/
template <typename Geometry>
struct default_length_result
: resolve_variant::default_length_result<Geometry>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP

View File

@@ -0,0 +1,34 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.
// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// 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_DEFAULT_STRATEGY_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_STRATEGY_HPP
namespace boost { namespace geometry
{
// This is a strategy placeholder type, which is passed by the algorithm free
// functions to the multi-stage resolving process. It's resolved into an actual
// strategy type during the resolve_strategy stage, possibly depending on the
// input geometry type(s). This typically happens after the resolve_variant
// stage, as it needs to be based on concrete geometry types - as opposed to
// variant geometry types.
struct default_strategy {};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_STRATEGY_HPP

View File

@@ -0,0 +1,39 @@
// Boost.Geometry
// Copyright (c) 2017-2020, 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/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this coordinate system.",
CSTag);
};
} // namespace services
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP

View File

@@ -0,0 +1,131 @@
// Boost.Geometry
// Copyright (c) 2020, 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_DETAIL_HPP
#define BOOST_GEOMETRY_STRATEGIES_DETAIL_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
namespace strategies
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct umbrella_strategy {};
template <typename Strategy>
struct is_umbrella_strategy
{
static const bool value = std::is_base_of<umbrella_strategy, Strategy>::value;
};
struct cartesian_base : umbrella_strategy
{
typedef cartesian_tag tag;
};
template
<
typename RadiusTypeOrSphere
>
class spherical_base : umbrella_strategy
{
protected:
typedef typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type radius_type;
public:
typedef spherical_tag tag;
spherical_base()
: m_radius(1.0)
{}
template <typename RadiusOrSphere>
explicit spherical_base(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
srs::sphere<radius_type> model() const
{
return srs::sphere<radius_type>(m_radius);
}
protected:
radius_type m_radius;
};
template <>
class spherical_base<void> : umbrella_strategy
{
public:
typedef spherical_tag tag;
srs::sphere<double> model() const
{
return srs::sphere<double>(1.0);
}
};
template <typename Spheroid>
class geographic_base : umbrella_strategy
{
public:
typedef geographic_tag tag;
geographic_base()
: m_spheroid()
{}
explicit geographic_base(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
Spheroid model() const
{
return m_spheroid;
}
protected:
Spheroid m_spheroid;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
} // namespace strategies
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DETAIL_HPP

View File

@@ -0,0 +1,83 @@
// Boost.Geometry
// Copyright (c) 2017-2020, 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_DISJOINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename Geometry1,
typename Geometry2,
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,
typename CsTag1 = typename cs_tag<Geometry1>::type,
typename CsTag2 = typename cs_tag<Geometry2>::type
>
struct default_strategy
: relate::services::default_strategy
<
Geometry1, Geometry2
>
{};
template <typename Point, typename Box>
struct default_strategy<Point, Box, point_tag, box_tag, 0, 2>
: strategy::covered_by::services::default_strategy<Point, Box>
{};
template <typename Box, typename Point>
struct default_strategy<Box, Point, box_tag, point_tag, 2, 0>
: strategy::covered_by::services::default_strategy<Point, Box>
{};
template <typename MultiPoint, typename Box>
struct default_strategy<MultiPoint, Box, multi_point_tag, box_tag, 0, 2>
: strategy::covered_by::services::default_strategy
<
typename point_type<MultiPoint>::type,
Box
>
{};
template <typename Box, typename MultiPoint>
struct default_strategy<Box, MultiPoint, box_tag, multi_point_tag, 2, 0>
: strategy::covered_by::services::default_strategy
<
typename point_type<MultiPoint>::type,
Box
>
{};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP

View File

@@ -0,0 +1,109 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, 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.
// 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_DISTANCE_HPP
#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance { namespace services
{
template <typename Strategy> struct tag {};
template <typename Strategy, typename P1, typename P2>
struct return_type
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy, P1, P2);
};
template <typename Strategy> struct comparable_type
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy);
};
template <typename Strategy> struct get_comparable
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy);
};
template <typename Strategy, typename P1, typename P2>
struct result_from_distance
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy, P1, P2);
};
// Default strategy
/*!
\brief Traits class binding a default strategy for distance
to one (or possibly two) coordinate system(s)
\ingroup distance
\tparam GeometryTag1 tag (point/segment/box) for which this strategy is the default
\tparam GeometryTag2 tag (point/segment/box) for which this strategy is the default
\tparam Point1 first point-type
\tparam Point2 second point-type
\tparam CsTag1 tag of coordinate system of first point type
\tparam CsTag2 tag of coordinate system of second point type
*/
template
<
typename GeometryTag1,
typename GeometryTag2,
typename Point1,
typename Point2 = Point1,
typename CsTag1 = typename cs_tag<Point1>::type,
typename CsTag2 = typename cs_tag<Point2>::type,
typename UnderlyingStrategy = void
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Point type combination.",
Point1, Point2, CsTag1, CsTag2);
};
}}} // namespace strategy::distance::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP

View File

@@ -0,0 +1,253 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, 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.
// 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_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
template
<
typename Geometry1, typename Geometry2, typename Strategy,
bool AreGeometries = (util::is_geometry<Geometry1>::value
&& util::is_geometry<Geometry2>::value)
>
struct distance_result
: strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>
{};
template <typename Geometry1, typename Geometry2, bool AreGeometries>
struct distance_result<Geometry1, Geometry2, default_strategy, AreGeometries>
: distance_result
<
Geometry1,
Geometry2,
typename detail::distance::default_strategy
<
Geometry1, Geometry2
>::type
>
{};
// Workaround for VS2015
#if defined(_MSC_VER) && (_MSC_VER < 1910)
template <typename Geometry1, typename Geometry2, typename Strategy>
struct distance_result<Geometry1, Geometry2, Strategy, false>
{
typedef int type;
};
template <typename Geometry1, typename Geometry2>
struct distance_result<Geometry1, Geometry2, default_strategy, false>
{
typedef int type;
};
#endif
} // namespace resolve_strategy
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Strategy = geometry::default_strategy>
struct more_precise_distance_result
{
template <typename Curr, typename Next>
struct predicate
: std::is_same
<
typename resolve_strategy::distance_result
<
typename util::sequence_element<0, Curr>::type,
typename util::sequence_element<1, Curr>::type,
Strategy
>::type,
typename geometry::select_most_precise
<
typename resolve_strategy::distance_result
<
typename util::sequence_element<0, Curr>::type,
typename util::sequence_element<1, Curr>::type,
Strategy
>::type,
typename resolve_strategy::distance_result
<
typename util::sequence_element<0, Next>::type,
typename util::sequence_element<1, Next>::type,
Strategy
>::type
>::type
>
{};
};
}} // namespace detail::distance
#endif //DOXYGEN_NO_DETAIL
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2, typename Strategy>
struct distance_result
: resolve_strategy::distance_result
<
Geometry1,
Geometry2,
Strategy
>
{};
template
<
typename Geometry1,
BOOST_VARIANT_ENUM_PARAMS(typename T),
typename Strategy
>
struct distance_result
<
Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
>
{
// Select the most precise distance strategy result type
// for all variant type combinations.
// TODO: We should ignore the combinations that are not valid
// but is_implemented is not ready for prime time.
typedef typename util::select_combination_element
<
util::type_sequence<Geometry1>,
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(T)>,
detail::distance::more_precise_distance_result<Strategy>::template predicate
>::type elements;
typedef typename resolve_strategy::distance_result
<
typename util::sequence_element<0, elements>::type,
typename util::sequence_element<1, elements>::type,
Strategy
>::type type;
};
// Distance arguments are commutative
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T),
typename Geometry2,
typename Strategy
>
struct distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2, Strategy
>
: public distance_result
<
Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
>
{};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T),
BOOST_VARIANT_ENUM_PARAMS(typename U),
typename Strategy
>
struct distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>,
Strategy
>
{
// Select the most precise distance strategy result type
// for all variant type combinations.
// TODO: We should ignore the combinations that are not valid
// but is_implemented is not ready for prime time.
typedef typename util::select_combination_element
<
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(T)>,
util::type_sequence<BOOST_VARIANT_ENUM_PARAMS(U)>,
detail::distance::more_precise_distance_result<Strategy>::template predicate
>::type elements;
typedef typename resolve_strategy::distance_result
<
typename util::sequence_element<0, elements>::type,
typename util::sequence_element<1, elements>::type,
Strategy
>::type type;
};
} // namespace resolve_variant
/*!
\brief Meta-function defining return type of distance function
\ingroup distance
\note The strategy defines the return-type (so this situation is different
from length, where distance is sqr/sqrt, but length always squared)
*/
template
<
typename Geometry1,
typename Geometry2 = Geometry1,
typename Strategy = void
>
struct distance_result
: resolve_variant::distance_result<Geometry1, Geometry2, Strategy>
{};
template <typename Geometry1, typename Geometry2>
struct distance_result<Geometry1, Geometry2, void>
: distance_result<Geometry1, Geometry2, default_strategy>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/envelope.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES2_ENVELOPE_HPP

View File

@@ -0,0 +1,160 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_CARTESIAN_HPP
#include <type_traits>
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategy/cartesian/envelope_multipoint.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp> // TEMP
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp> // TEMP
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/envelope/services.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace envelope
{
template <typename CalculationType = void>
struct cartesian : strategies::detail::cartesian_base
{
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_box();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_segment<CalculationType>();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_polysegmental_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian<CalculationType>();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_point();
}
// TEMP
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_box();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_segment();
}
};
namespace services
{
template <typename Geometry, typename Box>
struct default_strategy<Geometry, Box, cartesian_tag>
{
using type = strategies::envelope::cartesian<>;
};
template <>
struct strategy_converter<strategy::envelope::cartesian_point>
{
static auto get(strategy::envelope::cartesian_point const& )
{
return strategies::envelope::cartesian<>();
}
};
template <>
struct strategy_converter<strategy::envelope::cartesian_multipoint>
{
static auto get(strategy::envelope::cartesian_multipoint const&)
{
return strategies::envelope::cartesian<>();
}
};
template <>
struct strategy_converter<strategy::envelope::cartesian_box>
{
static auto get(strategy::envelope::cartesian_box const& )
{
return strategies::envelope::cartesian<>();
}
};
template <typename CT>
struct strategy_converter<strategy::envelope::cartesian_segment<CT> >
{
static auto get(strategy::envelope::cartesian_segment<CT> const&)
{
return strategies::envelope::cartesian<CT>();
}
};
template <typename CT>
struct strategy_converter<strategy::envelope::cartesian<CT> >
{
static auto get(strategy::envelope::cartesian<CT> const&)
{
return strategies::envelope::cartesian<CT>();
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_CARTESIAN_HPP

View File

@@ -0,0 +1,151 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_GEOGRAPHIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_GEOGRAPHIC_HPP
#include <type_traits>
#include <boost/geometry/strategy/geographic/envelope.hpp>
#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
#include <boost/geometry/strategy/geographic/expand_segment.hpp> // TEMP
#include <boost/geometry/strategies/envelope/spherical.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace envelope
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic : strategies::detail::geographic_base<Spheroid>
{
using base_t = strategies::detail::geographic_base<Spheroid>;
public:
geographic()
: base_t()
{}
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_box();
}
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
typename util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
typename util::enable_if_polysegmental_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_point();
}
// TEMP
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_box();
}
template <typename Box, typename Geometry>
auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
};
namespace services
{
template <typename Geometry, typename Box>
struct default_strategy<Geometry, Box, geographic_tag>
{
using type = strategies::envelope::geographic<>;
};
template <typename FP, typename S, typename CT>
struct strategy_converter<strategy::envelope::geographic_segment<FP, S, CT> >
{
static auto get(strategy::envelope::geographic_segment<FP, S, CT> const& s)
{
return strategies::envelope::geographic<FP, S, CT>(s.model());
}
};
template <typename FP, typename S, typename CT>
struct strategy_converter<strategy::envelope::geographic<FP, S, CT> >
{
static auto get(strategy::envelope::geographic<FP, S, CT> const& s)
{
return strategies::envelope::geographic<FP, S, CT>(s.model());
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_GEOGRAPHIC_HPP

View File

@@ -0,0 +1,52 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_SERVICES_HPP
#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_SERVICES_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace envelope { namespace services
{
template
<
typename Geometry,
typename Box,
typename CSTag = typename geometry::cs_tag<Geometry>::type
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this coordinate system.",
Geometry, Box, CSTag);
};
template <typename Strategy>
struct strategy_converter
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy);
};
}}} // namespace strategies::envelope::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_SERVICES_HPP

View File

@@ -0,0 +1,178 @@
// Boost.Geometry
// Copyright (c) 2020, 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_ENVELOPE_SPHERICAL_HPP
#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_SPHERICAL_HPP
#include <type_traits>
#include <boost/geometry/strategy/spherical/envelope.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
#include <boost/geometry/strategy/spherical/envelope_point.hpp>
#include <boost/geometry/strategy/spherical/envelope_multipoint.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
#include <boost/geometry/strategy/spherical/expand_box.hpp> // TEMP
#include <boost/geometry/strategy/spherical/expand_point.hpp>
#include <boost/geometry/strategy/spherical/expand_segment.hpp> // TEMP
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/envelope/services.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace envelope
{
template
<
typename CalculationType = void
>
class spherical : strategies::detail::spherical_base<void>
{
using base_t = strategies::detail::spherical_base<void>;
public:
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_box();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_segment<CalculationType>();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_polysegmental_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical<CalculationType>();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_point();
}
// TEMP
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_box();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_segment<CalculationType>();
}
};
namespace services
{
template <typename Geometry, typename Box>
struct default_strategy<Geometry, Box, spherical_tag>
{
using type = strategies::envelope::spherical<>;
};
template <typename Geometry, typename Box>
struct default_strategy<Geometry, Box, spherical_equatorial_tag>
{
using type = strategies::envelope::spherical<>;
};
template <typename Geometry, typename Box>
struct default_strategy<Geometry, Box, spherical_polar_tag>
{
using type = strategies::envelope::spherical<>;
};
template <>
struct strategy_converter<strategy::envelope::spherical_point>
{
static auto get(strategy::envelope::spherical_point const& )
{
return strategies::envelope::spherical<>();
}
};
template <>
struct strategy_converter<strategy::envelope::spherical_multipoint>
{
static auto get(strategy::envelope::spherical_multipoint const&)
{
return strategies::envelope::spherical<>();
}
};
template <>
struct strategy_converter<strategy::envelope::spherical_box>
{
static auto get(strategy::envelope::spherical_box const& )
{
return strategies::envelope::spherical<>();
}
};
template <typename CT>
struct strategy_converter<strategy::envelope::spherical_segment<CT> >
{
static auto get(strategy::envelope::spherical_segment<CT> const&)
{
return strategies::envelope::spherical<CT>();
}
};
template <typename CT>
struct strategy_converter<strategy::envelope::spherical<CT> >
{
static auto get(strategy::envelope::spherical<CT> const&)
{
return strategies::envelope::spherical<CT>();
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_SPHERICAL_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/expand.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP

View File

@@ -0,0 +1,102 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_CARTESIAN_HPP
#include <type_traits>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace expand
{
template <typename CalculationType = void>
struct cartesian : strategies::detail::cartesian_base
{
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_point();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_box();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::expand::cartesian_segment();
}
};
namespace services
{
template <typename Box, typename Geometry>
struct default_strategy<Box, Geometry, cartesian_tag>
{
using type = strategies::expand::cartesian<>;
};
template <>
struct strategy_converter<strategy::expand::cartesian_point>
{
static auto get(strategy::expand::cartesian_point const& )
{
return strategies::expand::cartesian<>();
}
};
template <>
struct strategy_converter<strategy::expand::cartesian_box>
{
static auto get(strategy::expand::cartesian_box const& )
{
return strategies::expand::cartesian<>();
}
};
template <>
struct strategy_converter<strategy::expand::cartesian_segment>
{
static auto get(strategy::expand::cartesian_segment const&)
{
return strategies::expand::cartesian<>();
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_CARTESIAN_HPP

View File

@@ -0,0 +1,99 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_GEOGRAPHIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_GEOGRAPHIC_HPP
#include <type_traits>
#include <boost/geometry/strategy/geographic/expand_segment.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/spherical.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace expand
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic : strategies::detail::geographic_base<Spheroid>
{
using base_t = strategies::detail::geographic_base<Spheroid>;
public:
geographic()
: base_t()
{}
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_point();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_box();
}
template <typename Box, typename Geometry>
auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
};
namespace services
{
template <typename Box, typename Geometry>
struct default_strategy<Box, Geometry, geographic_tag>
{
using type = strategies::expand::geographic<>;
};
template <typename FP, typename S, typename CT>
struct strategy_converter<strategy::expand::geographic_segment<FP, S, CT> >
{
static auto get(strategy::expand::geographic_segment<FP, S, CT> const& s)
{
return strategies::expand::geographic<FP, S, CT>(s.model());
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_GEOGRAPHIC_HPP

View File

@@ -0,0 +1,52 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_SERVICES_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_SERVICES_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace expand { namespace services
{
template
<
typename Box,
typename Geometry,
typename CSTag = typename geometry::cs_tag<Geometry>::type
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this coordinate system.",
Geometry, Box, CSTag);
};
template <typename Strategy>
struct strategy_converter
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this Strategy.",
Strategy);
};
}}} // namespace strategies::expand::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_SERVICES_HPP

View File

@@ -0,0 +1,119 @@
// Boost.Geometry
// Copyright (c) 2020, 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_EXPAND_SPHERICAL_HPP
#define BOOST_GEOMETRY_STRATEGIES_EXPAND_SPHERICAL_HPP
#include <type_traits>
#include <boost/geometry/strategy/spherical/expand_box.hpp>
#include <boost/geometry/strategy/spherical/expand_point.hpp>
#include <boost/geometry/strategy/spherical/expand_segment.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp>
namespace boost { namespace geometry
{
namespace strategies { namespace expand
{
template
<
typename CalculationType = void
>
class spherical : strategies::detail::spherical_base<void>
{
using base_t = strategies::detail::spherical_base<void>;
public:
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_point();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_box();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_segment<CalculationType>();
}
};
namespace services
{
template <typename Box, typename Geometry>
struct default_strategy<Box, Geometry, spherical_tag>
{
using type = strategies::expand::spherical<>;
};
template <typename Box, typename Geometry>
struct default_strategy<Box, Geometry, spherical_equatorial_tag>
{
using type = strategies::expand::spherical<>;
};
template <typename Box, typename Geometry>
struct default_strategy<Box, Geometry, spherical_polar_tag>
{
using type = strategies::expand::spherical<>;
};
template <>
struct strategy_converter<strategy::expand::spherical_point>
{
static auto get(strategy::expand::spherical_point const& )
{
return strategies::expand::spherical<>();
}
};
template <>
struct strategy_converter<strategy::expand::spherical_box>
{
static auto get(strategy::expand::spherical_box const& )
{
return strategies::expand::spherical<>();
}
};
template <typename CT>
struct strategy_converter<strategy::expand::spherical_segment<CT> >
{
static auto get(strategy::expand::spherical_segment<CT> const&)
{
return strategies::expand::spherical<CT>();
}
};
} // namespace services
}} // namespace strategies::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_SPHERICAL_HPP

View File

@@ -0,0 +1,135 @@
// Boost.Geometry
// Copyright (c) 2020, 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_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_HPP
#include <boost/geometry/strategies/area/geographic.hpp>
#include <boost/geometry/strategies/envelope/geographic.hpp>
#include <boost/geometry/strategies/expand/geographic.hpp>
namespace boost { namespace geometry
{
namespace strategies
{
template
<
typename FormulaPolicy = strategy::andoyer,
std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic : strategies::detail::geographic_base<Spheroid>
{
using base_t = strategies::detail::geographic_base<Spheroid>;
public:
geographic()
: base_t()
{}
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
// area
template <typename Geometry>
auto area(Geometry const&) const
{
return strategy::area::geographic
<
FormulaPolicy, SeriesOrder, Spheroid, CalculationType
>(base_t::m_spheroid);
}
// envelope
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_box();
}
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
typename util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
typename util::enable_if_polysegmental_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
// expand
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_point();
}
template <typename Box, typename Geometry>
static auto expand(Box const&, Geometry const&,
typename util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::expand::spherical_box();
}
template <typename Box, typename Geometry>
auto expand(Box const&, Geometry const&,
typename util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
};
} // namespace strategies
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_HPP

View File

@@ -0,0 +1,21 @@
// Boost.Geometry
// Copyright (c) 2020, 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_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#include <boost/geometry/strategy/geographic/area.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP

View File

@@ -0,0 +1,150 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2020 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_AZIMUTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
#include <type_traits>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace azimuth
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
public :
typedef Spheroid model_type;
inline geographic()
: m_spheroid()
{}
explicit inline geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
inline model_type const& model() const
{
return m_spheroid;
}
template <typename T>
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 std::conditional_t
<
std::is_void<CalculationType>::value, T, CalculationType
> calc_t;
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);
if (EnableAzimuth)
{
a1 = i_res.azimuth;
}
if (EnableReverseAzimuth)
{
a2 = i_res.reverse_azimuth;
}
}
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<geographic_tag, CalculationType>
{
typedef strategy::azimuth::geographic
<
strategy::andoyer,
srs::spheroid<double>,
CalculationType
> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::azimuth
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP

View File

@@ -0,0 +1,137 @@
// Boost.Geometry
// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 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_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP
#include <cstddef>
#include <boost/range/value_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.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_calculation_type
<
Point, output_point_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 pi = geometry::math::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)
{
if (angle > pi)
{
angle -= two_pi;
}
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,131 @@
// 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
// 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>
// 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/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/normalize.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)
{}
typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
return disjoint_point_box_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

@@ -0,0 +1,237 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
// 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,
// 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_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/radius.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
{
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,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
public :
template <typename Point1, typename Point2>
struct calculation_type
: promote_floating_point
<
typename select_calculation_type
<
Point1,
Point2,
CalculationType
>::type
>
{};
typedef Spheroid model_type;
inline geographic()
: m_spheroid()
{}
explicit inline geographic(Spheroid const& spheroid)
: 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
{
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
{
return m_spheroid;
}
private :
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct tag<geographic<FormulaPolicy, Spheroid, CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType,
typename P1,
typename P2
>
struct return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
: geographic<FormulaPolicy, Spheroid, CalculationType>::template calculation_type<P1, P2>
{};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct comparable_type<geographic<FormulaPolicy, Spheroid, CalculationType> >
{
typedef geographic<FormulaPolicy, Spheroid, CalculationType> type;
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType
>
struct get_comparable<geographic<FormulaPolicy, Spheroid, CalculationType> >
{
static inline geographic<FormulaPolicy, Spheroid, CalculationType>
apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& input)
{
return input;
}
};
template
<
typename FormulaPolicy,
typename Spheroid,
typename CalculationType,
typename P1,
typename P2
>
struct result_from_distance<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
{
template <typename T>
static inline typename return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>::type
apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& , T const& value)
{
return value;
}
};
template <typename Point1, typename Point2>
struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
{
typedef strategy::distance::geographic
<
strategy::andoyer,
srs::spheroid
<
typename select_coordinate_type<Point1, Point2>::type
>
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP

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