// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020 Oracle and/or its affiliates.
+// Copyright (c) 2014-2021 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
#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/assert.hpp>
-#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/core/tags.hpp>
-
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
-#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/calculation_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
-
namespace boost { namespace geometry
{
{
-// TODO: Take strategy
-template <typename Segment, typename Box>
-inline bool intersects_segment_box(Segment const& segment, Box const& box)
+template <typename Segment, typename Box, typename Strategy>
+inline bool intersects_segment_box(Segment const& segment, Box const& box,
+ Strategy const& strategy)
{
- typedef typename strategy::disjoint::services::default_strategy
- <
- Segment, Box
- >::type strategy_type;
-
- return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
- strategy_type());
+ return ! detail::disjoint::disjoint_segment_box::apply(segment, box, strategy);
}
+// TODO: segment_to_box_2D_generic is not used anymore. Remove?
+
+// TODO: Furthermore this utility can potentially use different strategy than
+// the one that was passed into bg::distance() but it seems this is by design.
template
<
typename Segment,
typename Box,
- typename Strategy,
- bool UsePointBoxStrategy = false
+ typename Strategies,
+ bool UsePointBoxStrategy = false // use only PointSegment strategy
>
class segment_to_box_2D_generic
{
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::type box_point;
- typedef typename strategy::distance::services::comparable_type
- <
- typename Strategy::distance_ps_strategy::type
- >::type comparable_strategy;
+ typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
typedef detail::closest_feature::point_to_point_range
<
segment_point,
std::vector<box_point>,
- open,
- comparable_strategy
+ open
> point_to_point_range;
-
- typedef typename strategy::distance::services::return_type
- <
- comparable_strategy, segment_point, box_point
- >::type comparable_return_type;
public:
- typedef typename strategy::distance::services::return_type
- <
- Strategy, segment_point, box_point
- >::type return_type;
+ // TODO: Or should the return type be defined by sb_strategy_type?
+ typedef distance::return_t<box_point, Segment, Strategies> return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
- Strategy const& strategy,
+ Strategies const& strategies,
bool check_intersection = true)
{
- if (check_intersection && intersects_segment_box(segment, box))
+ if (check_intersection && intersects_segment_box(segment, box, strategies))
{
- return 0;
+ return return_type(0);
}
- comparable_strategy cstrategy =
- strategy::distance::services::get_comparable
- <
- typename Strategy::distance_ps_strategy::type
- >::apply(strategy.get_distance_ps_strategy());
-
// get segment points
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
- comparable_return_type cd[6];
+ ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
+
+ auto const cstrategy = strategy::distance::services::get_comparable
+ <
+ ps_strategy_type
+ >::apply(strategy);
+
+ distance::creturn_t<box_point, Segment, Strategies> cd[6];
for (unsigned int i = 0; i < 4; ++i)
{
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
}
}
- if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<ps_strategy_type>::value))
{
return cd[imin];
}
if (imin < 4)
{
- return strategy.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]);
+ return strategy.apply(box_points[imin], p[0], p[1]);
}
else
{
unsigned int bimin = imin - 4;
- return strategy.get_distance_ps_strategy().apply(p[bimin],
+ return strategy.apply(p[bimin],
*bit_min[bimin].first,
*bit_min[bimin].second);
}
<
typename Segment,
typename Box,
- typename Strategy
+ typename Strategies
>
-class segment_to_box_2D_generic<Segment, Box, Strategy, true>
+class segment_to_box_2D_generic<Segment, Box, Strategies, true> // Use both PointSegment and PointBox strategies
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::type box_point;
- typedef typename strategy::distance::services::comparable_type
- <
- Strategy
- >::type comparable_strategy;
-
- typedef typename strategy::distance::services::return_type
- <
- comparable_strategy, segment_point, box_point
- >::type comparable_return_type;
-
- typedef typename detail::distance::default_strategy
- <
- segment_point, Box
- >::type point_box_strategy;
-
- typedef typename strategy::distance::services::comparable_type
- <
- point_box_strategy
- >::type point_box_comparable_strategy;
+ typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
+ typedef distance::strategy_t<segment_point, Box, Strategies> pb_strategy_type;
public:
- typedef typename strategy::distance::services::return_type
- <
- Strategy, segment_point, box_point
- >::type return_type;
-
+ // TODO: Or should the return type be defined by sb_strategy_type?
+ typedef distance::return_t<box_point, Segment, Strategies> return_type;
+
static inline return_type apply(Segment const& segment,
Box const& box,
- Strategy const& strategy,
+ Strategies const& strategies,
bool check_intersection = true)
{
- if (check_intersection && intersects_segment_box(segment, box))
+ if (check_intersection && intersects_segment_box(segment, box, strategies))
{
- return 0;
+ return return_type(0);
}
- comparable_strategy cstrategy =
- strategy::distance::services::get_comparable
- <
- Strategy
- >::apply(strategy);
- boost::ignore_unused(cstrategy);
-
// get segment points
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
// get box points
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
-
- comparable_return_type cd[6];
+
+ distance::creturn_t<box_point, Segment, Strategies> cd[6];
+
+ ps_strategy_type ps_strategy = strategies.distance(dummy_point(), dummy_segment());
+ auto const ps_cstrategy = strategy::distance::services::get_comparable
+ <
+ ps_strategy_type
+ >::apply(ps_strategy);
+ boost::ignore_unused(ps_strategy, ps_cstrategy);
+
for (unsigned int i = 0; i < 4; ++i)
{
- cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
+ cd[i] = ps_cstrategy.apply(box_points[i], p[0], p[1]);
}
- point_box_comparable_strategy pb_cstrategy;
- boost::ignore_unused(pb_cstrategy);
+ pb_strategy_type const pb_strategy = strategies.distance(dummy_point(), dummy_box());
+ auto const pb_cstrategy = strategy::distance::services::get_comparable
+ <
+ pb_strategy_type
+ >::apply(pb_strategy);
+ boost::ignore_unused(pb_strategy, pb_cstrategy);
+
cd[4] = pb_cstrategy.apply(p[0], box);
cd[5] = pb_cstrategy.apply(p[1], box);
}
}
- if (is_comparable<Strategy>::value)
- {
- return cd[imin];
- }
-
if (imin < 4)
{
- strategy.apply(box_points[imin], p[0], p[1]);
+ if (is_comparable<ps_strategy_type>::value)
+ {
+ return cd[imin];
+ }
+
+ return ps_strategy.apply(box_points[imin], p[0], p[1]);
}
else
{
- return point_box_strategy().apply(p[imin - 4], box);
+ if (is_comparable<pb_strategy_type>::value)
+ {
+ return cd[imin];
+ }
+
+ return pb_strategy.apply(p[imin - 4], box);
}
}
};
typename ReturnType,
typename SegmentPoint,
typename BoxPoint,
- typename SBStrategy
+ typename Strategies
>
class segment_to_box_2D
{
SegmentPoint const& p1,
BoxPoint const& bottom_right,
BoxPoint const& top_right,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- boost::ignore_unused(sb_strategy);
-
// the implementation below is written for non-negative slope
// segments
//
LessEqual less_equal;
- typename SBStrategy::distance_ps_strategy::type ps_strategy =
- sb_strategy.get_distance_ps_strategy();
+ auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
{
static inline ReturnType apply(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const& top_left,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- boost::ignore_unused(sb_strategy);
- return apply(p0, p1, p0, top_left, sb_strategy);
+ return apply(p0, p1, p0, top_left, strategies);
}
static inline ReturnType apply(SegmentPoint const& p0,
SegmentPoint const& p1,
SegmentPoint const& p_max,
BoxPoint const& top_left,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- boost::ignore_unused(sb_strategy);
+ auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
+
typedef cast_to_result<ReturnType> cast;
LessEqual less_equal;
// then compute the vertical (i.e. meridian for spherical) distance
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
{
- ReturnType diff =
- sb_strategy.get_distance_ps_strategy().vertical_or_meridian(
+ ReturnType diff = ps_strategy.vertical_or_meridian(
geometry::get_as_radian<1>(p_max),
geometry::get_as_radian<1>(top_left));
return strategy::distance::services::result_from_distance
<
- SBStrategy, SegmentPoint, BoxPoint
- >::apply(sb_strategy, math::abs(diff));
+ std::remove_const_t<decltype(ps_strategy)>,
+ SegmentPoint, BoxPoint
+ >::apply(ps_strategy, math::abs(diff));
}
// p0 is to the left of the box, but p1 is above the box
// in this case the distance is realized between the
// top-left corner of the box and the segment
- return cast::apply(sb_strategy.get_distance_ps_strategy().
- apply(top_left, p0, p1));
+ return cast::apply(ps_strategy.apply(top_left, p0, p1));
}
};
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
- SBStrategy const& sb_strategy,
+ Strategies const& strategies,
ReturnType& result)
{
// p0 lies to the right of the box
<
LessEqual
>::apply(p0, p1, bottom_right, top_right,
- sb_strategy);
+ strategies);
return true;
}
<
typename other_compare<LessEqual>::type
>::apply(p1, p0, top_left, bottom_left,
- sb_strategy);
+ strategies);
return true;
}
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
- SBStrategy const& sb_strategy,
+ Strategies const& strategies,
ReturnType& result)
{
typedef compare_less_equal<ReturnType, false> GreaterEqual;
// the segment lies below the box
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
{
+ auto const sb_strategy = strategies.distance(dummy_segment(), dummy_box());
+
+ // TODO: this strategy calls this algorithm's again, specifically:
+ // geometry::detail::distance::segment_to_box_2D<>::call_above_of_box
+ // If possible rewrite them to avoid this.
+ // For now just pass umbrella strategy.
result = sb_strategy.template segment_below_of_box
<
LessEqual,
ReturnType
>(p0, p1,
top_left, top_right,
- bottom_left, bottom_right);
+ bottom_left, bottom_right,
+ strategies);
return true;
}
result = (std::min)(above_of_box
<
LessEqual
- >::apply(p0, p1, top_left, sb_strategy),
+ >::apply(p0, p1, top_left, strategies),
above_of_box
<
GreaterEqual
- >::apply(p1, p0, top_right, sb_strategy));
+ >::apply(p1, p0, top_right, strategies));
return true;
}
return false;
SegmentPoint const& p1,
BoxPoint const& corner1,
BoxPoint const& corner2,
- SBStrategy const& sb_strategy,
+ Strategies const& strategies,
ReturnType& result)
{
- typename SBStrategy::side_strategy_type
- side_strategy = sb_strategy.get_side_strategy();
+ auto const side_strategy = strategies.side();
+ auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
typedef cast_to_result<ReturnType> cast;
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
- cast::apply(geometry::get<1>(p0));
- typename SBStrategy::distance_ps_strategy::type ps_strategy =
- sb_strategy.get_distance_ps_strategy();
-
int sign = diff1 < 0 ? -1 : 1;
if (side_strategy.apply(p0, p1, corner1) * sign < 0)
{
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
typedef compare_less_equal<ReturnType, true> less_equal;
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
if (check_generic_position::apply(p0, p1,
top_left, bottom_right,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
typedef compare_less_equal<ReturnType, false> greater_equal;
greater_equal
>::apply(p0, p1,
bottom_left, bottom_right, top_left, top_right,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
greater_equal
>::apply(p1, p0,
top_right, top_left, bottom_right, bottom_left,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
if (check_generic_position::apply(p0, p1,
bottom_left, top_right,
- sb_strategy, result))
+ strategies, result))
{
return result;
}
BoxPoint const& top_right,
BoxPoint const& bottom_left,
BoxPoint const& bottom_right,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename SBStrategy::cs_tag>()(p0, p1))
+ BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename Strategies::cs_tag>()(p0, p1))
|| geometry::has_nan_coordinate(p0)
|| geometry::has_nan_coordinate(p1) );
return negative_slope_segment(p0, p1,
top_left, top_right,
bottom_left, bottom_right,
- sb_strategy);
+ strategies);
}
return non_negative_slope_segment(p0, p1,
top_left, top_right,
bottom_left, bottom_right,
- sb_strategy);
+ strategies);
}
template <typename LessEqual>
SegmentPoint const& p1,
SegmentPoint const& p_max,
BoxPoint const& top_left,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, sb_strategy);
+ return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, strategies);
}
template <typename LessEqual>
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const& top_left,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
- return above_of_box<LessEqual>::apply(p0, p1, top_left, sb_strategy);
+ return above_of_box<LessEqual>::apply(p0, p1, top_left, strategies);
}
};
typename Segment,
typename Box,
typename std::size_t Dimension,
- typename SBStrategy
+ typename Strategies
>
class segment_to_box
: not_implemented<Segment, Box>
<
typename Segment,
typename Box,
- typename SBStrategy
+ typename Strategies
>
-class segment_to_box<Segment, Box, 2, SBStrategy>
+class segment_to_box<Segment, Box, 2, Strategies>
{
-private:
- typedef typename point_type<Segment>::type segment_point;
- typedef typename point_type<Box>::type box_point;
-
- typedef typename strategy::distance::services::comparable_type
- <
- SBStrategy
- >::type ps_comparable_strategy;
+ typedef distance::strategy_t<Segment, Box, Strategies> strategy_type;
- typedef typename strategy::distance::services::return_type
- <
- ps_comparable_strategy, segment_point, box_point
- >::type comparable_return_type;
public:
- typedef typename strategy::distance::services::return_type
- <
- SBStrategy, segment_point, box_point
- >::type return_type;
+ typedef distance::return_t<Segment, Box, Strategies> return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
- SBStrategy const& sb_strategy)
+ Strategies const& strategies)
{
+ typedef typename point_type<Segment>::type segment_point;
+ typedef typename point_type<Box>::type box_point;
+
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
- if (detail::equals::equals_point_point(p[0], p[1],
- sb_strategy.get_equals_point_point_strategy()))
+ if (detail::equals::equals_point_point(p[0], p[1], strategies))
{
- typedef std::conditional_t
- <
- std::is_same
- <
- ps_comparable_strategy,
- SBStrategy
- >::value,
- typename strategy::distance::services::comparable_type
- <
- typename SBStrategy::distance_pb_strategy::type
- >::type,
- typename SBStrategy::distance_pb_strategy::type
- > point_box_strategy_type;
-
return dispatch::distance
<
segment_point,
Box,
- point_box_strategy_type
- >::apply(p[0], box, point_box_strategy_type());
+ Strategies
+ >::apply(p[0], box, strategies);
}
box_point top_left, top_right, bottom_left, bottom_right;
detail::assign_box_corners(box, bottom_left, bottom_right,
top_left, top_right);
- SBStrategy::mirror(p[0], p[1],
- bottom_left, bottom_right,
- top_left, top_right);
+ strategy_type::mirror(p[0], p[1],
+ bottom_left, bottom_right,
+ top_left, top_right);
- typedef geometry::less<segment_point, -1, typename SBStrategy::cs_tag> less_type;
+ typedef geometry::less<segment_point, -1, typename Strategies::cs_tag> less_type;
if (less_type()(p[0], p[1]))
{
return segment_to_box_2D
return_type,
segment_point,
box_point,
- SBStrategy
+ Strategies
>::apply(p[0], p[1],
top_left, top_right, bottom_left, bottom_right,
- sb_strategy);
+ strategies);
}
else
{
return_type,
segment_point,
box_point,
- SBStrategy
+ Strategies
>::apply(p[1], p[0],
top_left, top_right, bottom_left, bottom_right,
- sb_strategy);
+ strategies);
}
}
};
{
-template <typename Segment, typename Box, typename Strategy>
+template <typename Segment, typename Box, typename Strategies>
struct distance
<
- Segment, Box, Strategy, segment_tag, box_tag,
+ Segment, Box, Strategies, segment_tag, box_tag,
strategy_tag_distance_segment_box, false
>
{
- typedef typename strategy::distance::services::return_type
- <
- Strategy,
- typename point_type<Segment>::type,
- typename point_type<Box>::type
- >::type return_type;
-
-
- static inline return_type apply(Segment const& segment,
- Box const& box,
- Strategy const& strategy)
+ static inline auto apply(Segment const& segment, Box const& box,
+ Strategies const& strategies)
{
assert_dimension_equal<Segment, Box>();
Segment,
Box,
dimension<Segment>::value,
- Strategy
- >::apply(segment, box, strategy);
+ Strategies
+ >::apply(segment, box, strategies);
}
};