mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
[strategies] Support non-cartesian CSes in box_in_box strategy.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#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
|
||||
@@ -34,6 +35,8 @@ namespace boost { namespace geometry { namespace strategy
|
||||
namespace within
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_within_range
|
||||
{
|
||||
template <typename BoxContainedValue, typename BoxContainingValue>
|
||||
@@ -48,6 +51,7 @@ struct box_within_range
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_covered_by_range
|
||||
{
|
||||
template <typename BoxContainedValue, typename BoxContainingValue>
|
||||
@@ -61,9 +65,103 @@ struct box_covered_by_range
|
||||
};
|
||||
|
||||
|
||||
// spherical_equatorial_tag and spherical_polar_tag is casted to spherical_tag
|
||||
template <typename Geometry>
|
||||
struct box_within_range<Geometry, 0, spherical_tag>
|
||||
{
|
||||
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 coordinate_system<Geometry>::type::units units_t;
|
||||
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
|
||||
|
||||
// min <= max <=> diff >= 0
|
||||
calc_t diff_ed = bed_max - bed_min;
|
||||
calc_t diff_ing = bing_max - bing_min;
|
||||
// if containing is smaller it cannot contain
|
||||
// or interiors doesn't overlap (no interior in contained)
|
||||
if (diff_ing < diff_ed || diff_ed == 0)
|
||||
return false;
|
||||
|
||||
// if containing covers the whole globe it contains all
|
||||
if (!math::smaller(diff_ing, constants::period())) // >= period
|
||||
return true;
|
||||
|
||||
// calculate positive longitude translation with bing_min as origin
|
||||
calc_t const c0 = 0;
|
||||
calc_t diff_min = bed_min - bing_min;
|
||||
math::normalize_longitude<units_t, calc_t>(diff_min);
|
||||
if (diff_min < c0) // [-180, 180] -> [0, 360]
|
||||
diff_min += constants::period();
|
||||
|
||||
return bing_min + diff_min + diff_ed <= bing_max;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct box_covered_by_range<Geometry, 0, spherical_tag>
|
||||
{
|
||||
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 coordinate_system<Geometry>::type::units units_t;
|
||||
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
|
||||
|
||||
// min <= max <=> diff >= 0
|
||||
calc_t diff_ed = bed_max - bed_min;
|
||||
calc_t diff_ing = bing_max - bing_min;
|
||||
// if containing is smaller it cannot contain
|
||||
if (diff_ing < diff_ed)
|
||||
return false;
|
||||
|
||||
// if containing covers the whole globe it contains all
|
||||
if (!math::smaller(diff_ing, constants::period())) // >= period
|
||||
return true;
|
||||
|
||||
// calculate positive longitude translation with bing_min as origin
|
||||
calc_t const c0 = 0;
|
||||
calc_t diff_min = bed_min - bing_min;
|
||||
math::normalize_longitude<units_t, calc_t>(diff_min);
|
||||
if (diff_min < c0) // [-180, 180] -> [0, 360]
|
||||
diff_min += constants::period();
|
||||
|
||||
return bing_min + diff_min + diff_ed <= bing_max;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct box_within_range<Geometry, 0, geographic_tag>
|
||||
: box_within_range<Geometry, 0, spherical_tag>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct box_covered_by_range<Geometry, 0, geographic_tag>
|
||||
: box_covered_by_range<Geometry, 0, spherical_tag>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename SubStrategy,
|
||||
template <typename, std::size_t, typename> class SubStrategy,
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
std::size_t Dimension,
|
||||
@@ -74,8 +172,9 @@ struct relate_box_box_loop
|
||||
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;
|
||||
|
||||
if (! SubStrategy::apply(
|
||||
if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
|
||||
get<min_corner, Dimension>(b_contained),
|
||||
get<max_corner, Dimension>(b_contained),
|
||||
get<min_corner, Dimension>(b_containing),
|
||||
@@ -97,7 +196,7 @@ struct relate_box_box_loop
|
||||
|
||||
template
|
||||
<
|
||||
typename SubStrategy,
|
||||
template <typename, std::size_t, typename> class SubStrategy,
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
std::size_t DimensionCount
|
||||
@@ -114,7 +213,7 @@ template
|
||||
<
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
typename SubStrategy = box_within_range
|
||||
template <typename, std::size_t, typename> class SubStrategy = box_within_range
|
||||
>
|
||||
struct box_in_box
|
||||
{
|
||||
@@ -150,6 +249,30 @@ struct default_strategy
|
||||
typedef within::box_in_box<BoxContained, BoxContaining> type;
|
||||
};
|
||||
|
||||
template <typename BoxContained, typename BoxContaining>
|
||||
struct default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
box_tag, areal_tag,
|
||||
spherical_tag, spherical_tag,
|
||||
BoxContained, BoxContaining
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box<BoxContained, BoxContaining> type;
|
||||
};
|
||||
|
||||
template <typename BoxContained, typename BoxContaining>
|
||||
struct default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
box_tag, areal_tag,
|
||||
geographic_tag, geographic_tag,
|
||||
BoxContained, BoxContaining
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box<BoxContained, BoxContaining> type;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace within::services
|
||||
|
||||
@@ -172,6 +295,38 @@ struct default_strategy
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename BoxContained, typename BoxContaining>
|
||||
struct default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
box_tag, areal_tag,
|
||||
spherical_tag, spherical_tag,
|
||||
BoxContained, BoxContaining
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box
|
||||
<
|
||||
BoxContained, BoxContaining,
|
||||
within::box_covered_by_range
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename BoxContained, typename BoxContaining>
|
||||
struct default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
box_tag, areal_tag,
|
||||
geographic_tag, geographic_tag,
|
||||
BoxContained, BoxContaining
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box
|
||||
<
|
||||
BoxContained, BoxContaining,
|
||||
within::box_covered_by_range
|
||||
> type;
|
||||
};
|
||||
|
||||
}} // namespace covered_by::services
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user