diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 423e051f9..a105907e5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -46,15 +46,15 @@ static inline bool within_selected_input(Item const& item2, ring_identifier cons switch (ring_id.source_index) { case 0 : - code = point_in_ring(item2.point, + code = within_code(item2.point, get_ring::apply(ring_id, geometry1)); break; case 1 : - code = point_in_ring(item2.point, + code = within_code(item2.point, get_ring::apply(ring_id, geometry2)); break; case 2 : - code = point_in_ring(item2.point, + code = within_code(item2.point, get_ring::apply(ring_id, collection)); break; } diff --git a/include/boost/geometry/algorithms/detail/overlay/within_util.hpp b/include/boost/geometry/algorithms/detail/overlay/within_util.hpp deleted file mode 100644 index 8618b81fe..000000000 --- a/include/boost/geometry/algorithms/detail/overlay/within_util.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2011 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_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP - - - -#include -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -struct within_code -{}; - -template -struct within_code -{ - static inline int apply(Point const& point, Box const& box) - { - // 1. Check outside - if (get<0>(point) < get(box) - || get<0>(point) > get(box) - || get<1>(point) < get(box) - || get<1>(point) > get(box)) - { - return -1; - } - // 2. Check border - if (geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<0>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box)) - || geometry::math::equals(get<1>(point), get(box))) - { - return 0; - } - return 1; - } -}; -template -struct within_code -{ - static inline int apply(Point const& point, Ring const& ring) - { - // Same as point_in_ring but here ALWAYS with winding. - typedef strategy::within::winding strategy_type; - - return detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - strategy_type - >::apply(point, ring, strategy_type()); - } -}; - - -template -inline int point_in_ring(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry); -} - -template -inline bool within_or_touch(Point const& point, Geometry const& geometry) -{ - return within_code::type, Point, Geometry> - ::apply(point, geometry) >= 0; -} - - - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_WITHIN_UTIL_HPP diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 912ba4bab..9a5fb0592 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,28 @@ namespace detail { namespace within { +struct within_state +{ + bool outside, inside, on_border; + inline within_state() + : outside(false) + , on_border(false) + {} + + inline int code() const + { + // Note the order: 1) outside 2) on_border 3) inside + // If one dim. is outside, it IS outside, else + // if one dim is on border, it IS on border, + // if it only inside if inside=true and the rest is false + return outside ? -1 + : on_border ? 0 + : 1 + ; + } + +}; + /*! \brief Implementation for boxes \ingroup boolean_relations @@ -61,26 +84,36 @@ template std::size_t Dimension, std::size_t DimensionCount > -struct point_in_box +struct point_in_box_helper { - static inline int apply(Point const& p, Box const& b, Strategy const& s) + static inline void apply(Point const& p, Box const& b, Strategy const& s, within_state& state) { - assert_dimension_equal(); - - if (get(p) <= get(b) - || get(p) >= get(b)) + typename geometry::coordinate_type::type const v + = get(p); + typename geometry::coordinate_type::type const b_min + = get(b); + typename geometry::coordinate_type::type const b_max + = get(b); + + if (geometry::math::equals(v, b_min) + || geometry::math::equals(v, b_max)) { - return -1; + state.on_border = true; } - - return point_in_box + else if (v < b_min || v > b_max) + { + state.outside = true; + return; + } + + point_in_box_helper < Point, Box, Strategy, Dimension + 1, DimensionCount - >::apply(p, b, s); + >::apply(p, b, s, state); } }; @@ -91,11 +124,31 @@ template typename Strategy, std::size_t DimensionCount > -struct point_in_box +struct point_in_box_helper { - static inline int apply(Point const& , Box const& , Strategy const& ) + static inline void apply(Point const& , Box const& , Strategy const&, within_state& ) { - return 1; + } +}; + +template +< + typename Point, + typename Box, + typename Strategy +> +struct point_in_box +{ + static inline int apply(Point const& point, Box const& box, Strategy const& strategy) + { + assert_dimension_equal(); + within_state state; + point_in_box_helper + < + Point, Box, Strategy, + 0, dimension::type::value + >::apply(point, box, strategy, state); + return state.code(); } }; @@ -108,26 +161,50 @@ template std::size_t Dimension, std::size_t DimensionCount > -struct box_in_box +struct box_in_box_helper { - static inline int apply(Box1 const& b1, Box2 const& b2, Strategy const& s) + static inline void apply(Box1 const& b_contained, Box2 const& b_containing, + Strategy const& strategy, within_state& state) { assert_dimension_equal(); - if (get(b1) <= get(b2) - || get(b1) >= get(b2)) + typename geometry::coordinate_type::type const ced_min + = get(b_contained); + typename geometry::coordinate_type::type const ced_max + = get(b_contained); + typename geometry::coordinate_type::type const cing_min + = get(b_containing); + typename geometry::coordinate_type::type const cing_max + = get(b_containing); + + if (geometry::math::equals(ced_min, cing_min)) { - return -1; + state.on_border = true; + } + else if (ced_min < cing_min) + { + state.outside = true; + return; } - return box_in_box + if (geometry::math::equals(ced_max, cing_max)) + { + state.on_border = true; + } + else if (ced_max > cing_max) + { + state.outside = true; + return; + } + + box_in_box_helper < Box1, Box2, Strategy, Dimension + 1, DimensionCount - >::apply(b1, b2, s); + >::apply(b_contained, b_containing, strategy, state); } }; @@ -138,11 +215,31 @@ template typename Strategy, std::size_t DimensionCount > -struct box_in_box +struct box_in_box_helper { - static inline int apply(Box1 const& , Box2 const& , Strategy const&) + static inline void apply(Box1 const& , Box2 const& , Strategy const&, within_state&) { - return 1; + } +}; + +template +< + typename Box1, + typename Box2, + typename Strategy +> +struct box_in_box +{ + static inline int apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) + { + assert_dimension_equal(); + within_state state; + box_in_box_helper + < + Box1, Box1, Strategy, + 0, dimension::type::value + >::apply(box1, box2, strategy, state); + return state.code(); } }; @@ -181,13 +278,14 @@ struct point_in_ring iterator_type it = boost::begin(view); iterator_type end = boost::end(view); + bool stop = false; for (iterator_type previous = it++; - it != end; + it != end && ! stop; ++previous, ++it) { if (! strategy.apply(point, *previous, *it, state)) { - return false; + stop = true; } } @@ -284,9 +382,7 @@ struct within < Point, Box, - Strategy, - 0, - dimension::type::value + Strategy > {}; @@ -296,9 +392,7 @@ struct within < Box1, Box2, - Strategy, - 0, - dimension::type::value + Strategy > {}; @@ -359,6 +453,63 @@ struct default_strategy +inline int within_code(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + concept::check(); + concept::check(); + + typedef typename point_type::type point_type1; + typedef typename point_type::type point_type2; + + typedef typename strategy::within::services::default_strategy + < + typename tag::type, + typename tag_cast::type, areal_tag>::type, + typename cs_tag::type, + typename cs_tag::type, + point_type1, + point_type2 + >::type strategy_type; + + return dispatch::within + < + typename tag::type, + typename tag::type, + Geometry1, + Geometry2, + strategy_type + >::apply(geometry1, geometry2, strategy_type()); +} + + +template +inline int within_code(Geometry1 const& geometry1, Geometry2 const& geometry2, + Strategy const& strategy) +{ + // Always assume a point-in-polygon strategy here. + // Because for point-in-box, it makes no sense to specify one. + BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy) ); + + concept::check(); + concept::check(); + + return dispatch::within + < + typename tag::type, + typename tag::type, + Geometry1, + Geometry2, + Strategy + >::apply(geometry1, geometry2, strategy); +} + +} + /*! \brief \brief_check12{is completely inside} \ingroup within @@ -387,28 +538,7 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2) { concept::check(); concept::check(); - - typedef typename point_type::type point_type1; - typedef typename point_type::type point_type2; - - typedef typename strategy::within::services::default_strategy - < - typename tag::type, - typename tag_cast::type, areal_tag>::type, - typename cs_tag::type, - typename cs_tag::type, - point_type1, - point_type2 - >::type strategy_type; - - return dispatch::within - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - strategy_type - >::apply(geometry1, geometry2, strategy_type()) == 1; + return detail::within_code(geometry1, geometry2) == 1; } /*! @@ -449,15 +579,7 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2, concept::check(); concept::check(); - - return dispatch::within - < - typename tag::type, - typename tag::type, - Geometry1, - Geometry2, - Strategy - >::apply(geometry1, geometry2, strategy) == 1; + return detail::within_code(geometry1, geometry2, strategy) == 1; } }} // namespace boost::geometry