Chris@102: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@102: Chris@102: // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@102: Chris@102: // This file was modified by Oracle on 2013, 2014, 2015. Chris@102: // Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. Chris@102: Chris@102: // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle Chris@102: Chris@102: // Use, modification and distribution is subject to the Boost Software License, Chris@102: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@102: // http://www.boost.org/LICENSE_1_0.txt) Chris@102: Chris@102: #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP Chris@102: #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP Chris@102: Chris@102: #include Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: #include Chris@102: Chris@102: // TEMP - move this header to geometry/detail Chris@102: #include Chris@102: Chris@102: namespace boost { namespace geometry { Chris@102: Chris@102: #ifndef DOXYGEN_NO_DETAIL Chris@102: namespace detail { namespace relate { Chris@102: Chris@102: enum field { interior = 0, boundary = 1, exterior = 2 }; Chris@102: Chris@102: // TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES Chris@102: // THE VALUE ALREADY STORED MUSN'T BE CHECKED Chris@102: // update() calls chould be replaced with set() in those cases Chris@102: // but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that Chris@102: // so some additional function could be added, e.g. set_dim() Chris@102: Chris@102: // matrix Chris@102: Chris@102: // TODO add height? Chris@102: Chris@102: template Chris@102: class matrix Chris@102: { Chris@102: BOOST_STATIC_ASSERT(Width == 2 || Width == 3); Chris@102: Chris@102: public: Chris@102: Chris@102: static const std::size_t size = Width * Width; Chris@102: Chris@102: inline matrix() Chris@102: { Chris@102: ::memset(m_array, 'F', size); Chris@102: } Chris@102: Chris@102: template Chris@102: inline char get() const Chris@102: { Chris@102: static const bool in_bounds = F1 * Width + F2 < size; Chris@102: return get_dispatch(integral_constant()); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void set() Chris@102: { Chris@102: static const bool in_bounds = F1 * Width + F2 < size; Chris@102: set_dispatch(integral_constant()); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void update() Chris@102: { Chris@102: static const bool in_bounds = F1 * Width + F2 < size; Chris@102: update_dispatch(integral_constant()); Chris@102: } Chris@102: Chris@102: inline const char * data() const Chris@102: { Chris@102: return m_array; Chris@102: } Chris@102: Chris@102: private: Chris@102: template Chris@102: inline char get_dispatch(integral_constant) const Chris@102: { Chris@102: return m_array[F1 * Width + F2]; Chris@102: } Chris@102: template Chris@102: inline char get_dispatch(integral_constant) const Chris@102: { Chris@102: return 'F'; Chris@102: } Chris@102: Chris@102: template Chris@102: inline void set_dispatch(integral_constant) Chris@102: { Chris@102: BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F'); Chris@102: m_array[F1 * Width + F2] = V; Chris@102: } Chris@102: template Chris@102: inline void set_dispatch(integral_constant) Chris@102: {} Chris@102: Chris@102: template Chris@102: inline void update_dispatch(integral_constant) Chris@102: { Chris@102: BOOST_STATIC_ASSERT('0' <= D && D <= '9'); Chris@102: char c = m_array[F1 * Width + F2]; Chris@102: if ( D > c || c > '9') Chris@102: m_array[F1 * Width + F2] = D; Chris@102: } Chris@102: template Chris@102: inline void update_dispatch(integral_constant) Chris@102: {} Chris@102: Chris@102: char m_array[size]; Chris@102: }; Chris@102: Chris@102: // TODO add EnableDimensions parameter? Chris@102: Chris@102: struct matrix9 {}; Chris@102: //struct matrix4 {}; Chris@102: Chris@102: // matrix_width Chris@102: Chris@102: template Chris@102: struct matrix_width Chris@102: : not_implemented Chris@102: {}; Chris@102: Chris@102: template <> Chris@102: struct matrix_width Chris@102: { Chris@102: static const std::size_t value = 3; Chris@102: }; Chris@102: Chris@102: // matrix_handler Chris@102: Chris@102: template Chris@102: class matrix_handler Chris@102: : private matrix::value> Chris@102: { Chris@102: typedef matrix::value> base_t; Chris@102: Chris@102: public: Chris@102: typedef std::string result_type; Chris@102: Chris@102: static const bool interrupt = false; Chris@102: Chris@102: matrix_handler(Matrix const&) Chris@102: {} Chris@102: Chris@102: result_type result() const Chris@102: { Chris@102: return std::string(this->data(), Chris@102: this->data() + base_t::size); Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool may_update() const Chris@102: { Chris@102: BOOST_STATIC_ASSERT('0' <= D && D <= '9'); Chris@102: Chris@102: char const c = static_cast(*this).template get(); Chris@102: return D > c || c > '9'; Chris@102: } Chris@102: Chris@102: //template Chris@102: //inline char get() const Chris@102: //{ Chris@102: // return static_cast(*this).template get(); Chris@102: //} Chris@102: Chris@102: template Chris@102: inline void set() Chris@102: { Chris@102: static_cast(*this).template set(); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void update() Chris@102: { Chris@102: static_cast(*this).template update(); Chris@102: } Chris@102: }; Chris@102: Chris@102: // RUN-TIME MASKS Chris@102: Chris@102: // mask9 Chris@102: Chris@102: class mask9 Chris@102: { Chris@102: public: Chris@102: static const std::size_t width = 3; // TEMP Chris@102: Chris@102: inline mask9(std::string const& de9im_mask) Chris@102: { Chris@102: // TODO: throw an exception here? Chris@102: BOOST_ASSERT(de9im_mask.size() == 9); Chris@102: ::memcpy(m_mask, de9im_mask.c_str(), 9); Chris@102: } Chris@102: Chris@102: template Chris@102: inline char get() const Chris@102: { Chris@102: return m_mask[F1 * 3 + F2]; Chris@102: } Chris@102: Chris@102: private: Chris@102: char m_mask[9]; Chris@102: }; Chris@102: Chris@102: // interrupt() Chris@102: Chris@102: template Chris@102: struct interrupt_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Mask const&) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct interrupt_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Mask const& mask) Chris@102: { Chris@102: char m = mask.template get(); Chris@102: return check_element(m); Chris@102: } Chris@102: Chris@102: template Chris@102: static inline bool check_element(char m) Chris@102: { Chris@102: if ( BOOST_GEOMETRY_CONDITION(V >= '0' && V <= '9') ) Chris@102: { Chris@102: return m == 'F' || ( m < V && m >= '0' && m <= '9' ); Chris@102: } Chris@102: else if ( BOOST_GEOMETRY_CONDITION(V == 'T') ) Chris@102: { Chris@102: return m == 'F'; Chris@102: } Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template ::value> Chris@102: struct interrupt_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const& masks) Chris@102: { Chris@102: typedef typename boost::tuples::element::type mask_type; Chris@102: mask_type const& mask = boost::get(masks); Chris@102: return interrupt_dispatch::template apply(mask) Chris@102: && interrupt_dispatch_tuple::template apply(masks); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct interrupt_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const& ) Chris@102: { Chris@102: return true; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct interrupt_dispatch, true> Chris@102: { Chris@102: typedef boost::tuple mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask) Chris@102: { Chris@102: return interrupt_dispatch_tuple::template apply(mask); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct interrupt_dispatch, true> Chris@102: { Chris@102: typedef boost::tuples::cons mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask) Chris@102: { Chris@102: return interrupt_dispatch_tuple::template apply(mask); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline bool interrupt(Mask const& mask) Chris@102: { Chris@102: return interrupt_dispatch Chris@102: ::template apply(mask); Chris@102: } Chris@102: Chris@102: // may_update() Chris@102: Chris@102: template Chris@102: struct may_update_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Mask const& mask, Matrix const& matrix) Chris@102: { Chris@102: BOOST_STATIC_ASSERT('0' <= D && D <= '9'); Chris@102: Chris@102: char const m = mask.template get(); Chris@102: Chris@102: if ( m == 'F' ) Chris@102: { Chris@102: return true; Chris@102: } Chris@102: else if ( m == 'T' ) Chris@102: { Chris@102: char const c = matrix.template get(); Chris@102: return c == 'F'; // if it's T or between 0 and 9, the result will be the same Chris@102: } Chris@102: else if ( m >= '0' && m <= '9' ) Chris@102: { Chris@102: char const c = matrix.template get(); Chris@102: return D > c || c > '9'; Chris@102: } Chris@102: Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template ::value> Chris@102: struct may_update_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const& masks, Matrix const& matrix) Chris@102: { Chris@102: typedef typename boost::tuples::element::type mask_type; Chris@102: mask_type const& mask = boost::get(masks); Chris@102: return may_update_dispatch::template apply(mask, matrix) Chris@102: || may_update_dispatch_tuple::template apply(masks, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct may_update_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const& , Matrix const& ) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct may_update_dispatch< boost::tuple > Chris@102: { Chris@102: typedef boost::tuple mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask, Matrix const& matrix) Chris@102: { Chris@102: return may_update_dispatch_tuple::template apply(mask, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct may_update_dispatch< boost::tuples::cons > Chris@102: { Chris@102: typedef boost::tuples::cons mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask, Matrix const& matrix) Chris@102: { Chris@102: return may_update_dispatch_tuple::template apply(mask, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline bool may_update(Mask const& mask, Matrix const& matrix) Chris@102: { Chris@102: return may_update_dispatch Chris@102: ::template apply(mask, matrix); Chris@102: } Chris@102: Chris@102: // check_matrix() Chris@102: Chris@102: template Chris@102: struct check_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Mask const& mask, Matrix const& matrix) Chris@102: { Chris@102: return per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix) Chris@102: && per_one(mask, matrix); Chris@102: } Chris@102: Chris@102: template Chris@102: static inline bool per_one(Mask const& mask, Matrix const& matrix) Chris@102: { Chris@102: const char mask_el = mask.template get(); Chris@102: const char el = matrix.template get(); Chris@102: Chris@102: if ( mask_el == 'F' ) Chris@102: { Chris@102: return el == 'F'; Chris@102: } Chris@102: else if ( mask_el == 'T' ) Chris@102: { Chris@102: return el == 'T' || ( el >= '0' && el <= '9' ); Chris@102: } Chris@102: else if ( mask_el >= '0' && mask_el <= '9' ) Chris@102: { Chris@102: return el == mask_el; Chris@102: } Chris@102: Chris@102: return true; Chris@102: } Chris@102: }; Chris@102: Chris@102: template ::value> Chris@102: struct check_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const& masks, Matrix const& matrix) Chris@102: { Chris@102: typedef typename boost::tuples::element::type mask_type; Chris@102: mask_type const& mask = boost::get(masks); Chris@102: return check_dispatch::apply(mask, matrix) Chris@102: || check_dispatch_tuple::apply(masks, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct check_dispatch_tuple Chris@102: { Chris@102: template Chris@102: static inline bool apply(Masks const&, Matrix const&) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct check_dispatch< boost::tuple > Chris@102: { Chris@102: typedef boost::tuple mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask, Matrix const& matrix) Chris@102: { Chris@102: return check_dispatch_tuple::apply(mask, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct check_dispatch< boost::tuples::cons > Chris@102: { Chris@102: typedef boost::tuples::cons mask_type; Chris@102: Chris@102: template Chris@102: static inline bool apply(mask_type const& mask, Matrix const& matrix) Chris@102: { Chris@102: return check_dispatch_tuple::apply(mask, matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline bool check_matrix(Mask const& mask, Matrix const& matrix) Chris@102: { Chris@102: return check_dispatch::apply(mask, matrix); Chris@102: } Chris@102: Chris@102: // matrix_width Chris@102: Chris@102: template <> Chris@102: struct matrix_width Chris@102: { Chris@102: static const std::size_t value = 3; Chris@102: }; Chris@102: Chris@102: template ::value> Chris@102: struct matrix_width_tuple Chris@102: { Chris@102: static const std::size_t Chris@102: current = matrix_width::type>::value; Chris@102: static const std::size_t Chris@102: next = matrix_width_tuple::value; Chris@102: Chris@102: static const std::size_t Chris@102: value = current > next ? current : next; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct matrix_width_tuple Chris@102: { Chris@102: static const std::size_t value = 0; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct matrix_width< boost::tuples::cons > Chris@102: { Chris@102: static const std::size_t Chris@102: value = matrix_width_tuple< boost::tuples::cons >::value; Chris@102: }; Chris@102: Chris@102: // matrix_handler Chris@102: Chris@102: template Chris@102: class mask_handler Chris@102: : private matrix::value> Chris@102: { Chris@102: typedef matrix::value> base_t; Chris@102: Chris@102: public: Chris@102: typedef bool result_type; Chris@102: Chris@102: bool interrupt; Chris@102: Chris@102: inline mask_handler(Mask const& m) Chris@102: : interrupt(false) Chris@102: , m_mask(m) Chris@102: {} Chris@102: Chris@102: result_type result() const Chris@102: { Chris@102: return !interrupt Chris@102: && check_matrix(m_mask, static_cast(*this)); Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool may_update() const Chris@102: { Chris@102: return detail::relate::may_update( Chris@102: m_mask, static_cast(*this) Chris@102: ); Chris@102: } Chris@102: Chris@102: //template Chris@102: //inline char get() const Chris@102: //{ Chris@102: // return static_cast(*this).template get(); Chris@102: //} Chris@102: Chris@102: template Chris@102: inline void set() Chris@102: { Chris@102: if ( relate::interrupt(m_mask) ) Chris@102: { Chris@102: interrupt = true; Chris@102: } Chris@102: else Chris@102: { Chris@102: base_t::template set(); Chris@102: } Chris@102: } Chris@102: Chris@102: template Chris@102: inline void update() Chris@102: { Chris@102: if ( relate::interrupt(m_mask) ) Chris@102: { Chris@102: interrupt = true; Chris@102: } Chris@102: else Chris@102: { Chris@102: base_t::template update(); Chris@102: } Chris@102: } Chris@102: Chris@102: private: Chris@102: Mask const& m_mask; Chris@102: }; Chris@102: Chris@102: // STATIC MASKS Chris@102: Chris@102: // static_mask Chris@102: Chris@102: template Chris@102: class static_mask Chris@102: { Chris@102: typedef boost::mpl::vector_c Chris@102: < Chris@102: char, II, IB, IE, BI, BB, BE, EI, EB, EE Chris@102: > vector_type; Chris@102: Chris@102: public: Chris@102: template Chris@102: struct get Chris@102: { Chris@102: BOOST_STATIC_ASSERT(F1 * 3 + F2 < boost::mpl::size::value); Chris@102: Chris@102: static const char value Chris@102: = boost::mpl::at_c::type::value; Chris@102: }; Chris@102: }; Chris@102: Chris@102: // static_should_handle_element Chris@102: Chris@102: template Chris@102: struct static_should_handle_element_dispatch Chris@102: { Chris@102: static const char mask_el = StaticMask::template get::value; Chris@102: static const bool value = mask_el == 'F' Chris@102: || mask_el == 'T' Chris@102: || ( mask_el >= '0' && mask_el <= '9' ); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_should_handle_element_sequence Chris@102: { Chris@102: typedef typename boost::mpl::deref::type StaticMask; Chris@102: Chris@102: static const bool value Chris@102: = static_should_handle_element_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: F1, F2, Chris@102: boost::mpl::is_sequence::value Chris@102: >::value Chris@102: || static_should_handle_element_sequence Chris@102: < Chris@102: typename boost::mpl::next::type, Chris@102: Last, Chris@102: F1, F2 Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_should_handle_element_sequence Chris@102: { Chris@102: static const bool value = false; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_should_handle_element_dispatch Chris@102: { Chris@102: static const bool value Chris@102: = static_should_handle_element_sequence Chris@102: < Chris@102: typename boost::mpl::begin::type, Chris@102: typename boost::mpl::end::type, Chris@102: F1, F2 Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_should_handle_element Chris@102: { Chris@102: static const bool value Chris@102: = static_should_handle_element_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: F1, F2, Chris@102: boost::mpl::is_sequence::value Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: // static_interrupt Chris@102: Chris@102: template Chris@102: struct static_interrupt_dispatch Chris@102: { Chris@102: static const bool value = false; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_interrupt_dispatch Chris@102: { Chris@102: static const char mask_el = StaticMask::template get::value; Chris@102: Chris@102: static const bool value Chris@102: = ( V >= '0' && V <= '9' ) ? Chris@102: ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) : Chris@102: ( ( V == 'T' ) ? mask_el == 'F' : false ); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_interrupt_sequence Chris@102: { Chris@102: typedef typename boost::mpl::deref::type StaticMask; Chris@102: Chris@102: static const bool value Chris@102: = static_interrupt_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: V, F1, F2, Chris@102: true, Chris@102: boost::mpl::is_sequence::value Chris@102: >::value Chris@102: && static_interrupt_sequence Chris@102: < Chris@102: typename boost::mpl::next::type, Chris@102: Last, Chris@102: V, F1, F2 Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_interrupt_sequence Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_interrupt_dispatch Chris@102: { Chris@102: static const bool value Chris@102: = static_interrupt_sequence Chris@102: < Chris@102: typename boost::mpl::begin::type, Chris@102: typename boost::mpl::end::type, Chris@102: V, F1, F2 Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_interrupt Chris@102: { Chris@102: static const bool value Chris@102: = static_interrupt_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: V, F1, F2, Chris@102: EnableInterrupt, Chris@102: boost::mpl::is_sequence::value Chris@102: >::value; Chris@102: }; Chris@102: Chris@102: // static_may_update Chris@102: Chris@102: template Chris@102: struct static_may_update_dispatch Chris@102: { Chris@102: static const char mask_el = StaticMask::template get::value; Chris@102: static const int version Chris@102: = mask_el == 'F' ? 0 Chris@102: : mask_el == 'T' ? 1 Chris@102: : mask_el >= '0' && mask_el <= '9' ? 2 Chris@102: : 3; Chris@102: Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return apply_dispatch(matrix, integral_constant()); Chris@102: } Chris@102: Chris@102: // mask_el == 'F' Chris@102: template Chris@102: static inline bool apply_dispatch(Matrix const& , integral_constant) Chris@102: { Chris@102: return true; Chris@102: } Chris@102: // mask_el == 'T' Chris@102: template Chris@102: static inline bool apply_dispatch(Matrix const& matrix, integral_constant) Chris@102: { Chris@102: char const c = matrix.template get(); Chris@102: return c == 'F'; // if it's T or between 0 and 9, the result will be the same Chris@102: } Chris@102: // mask_el >= '0' && mask_el <= '9' Chris@102: template Chris@102: static inline bool apply_dispatch(Matrix const& matrix, integral_constant) Chris@102: { Chris@102: char const c = matrix.template get(); Chris@102: return D > c || c > '9'; Chris@102: } Chris@102: // else Chris@102: template Chris@102: static inline bool apply_dispatch(Matrix const&, integral_constant) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_may_update_sequence Chris@102: { Chris@102: typedef typename boost::mpl::deref::type StaticMask; Chris@102: Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_may_update_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: D, F1, F2, Chris@102: boost::mpl::is_sequence::value Chris@102: >::apply(matrix) Chris@102: || static_may_update_sequence Chris@102: < Chris@102: typename boost::mpl::next::type, Chris@102: Last, Chris@102: D, F1, F2 Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_may_update_sequence Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& /*matrix*/) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_may_update_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_may_update_sequence Chris@102: < Chris@102: typename boost::mpl::begin::type, Chris@102: typename boost::mpl::end::type, Chris@102: D, F1, F2 Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_may_update Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_may_update_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: D, F1, F2, Chris@102: boost::mpl::is_sequence::value Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: // static_check Chris@102: Chris@102: template Chris@102: struct static_check_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix) Chris@102: && per_one::apply(matrix); Chris@102: } Chris@102: Chris@102: template Chris@102: struct per_one Chris@102: { Chris@102: static const char mask_el = StaticMask::template get::value; Chris@102: static const int version Chris@102: = mask_el == 'F' ? 0 Chris@102: : mask_el == 'T' ? 1 Chris@102: : mask_el >= '0' && mask_el <= '9' ? 2 Chris@102: : 3; Chris@102: Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: const char el = matrix.template get(); Chris@102: return apply_dispatch(el, integral_constant()); Chris@102: } Chris@102: Chris@102: // mask_el == 'F' Chris@102: static inline bool apply_dispatch(char el, integral_constant) Chris@102: { Chris@102: return el == 'F'; Chris@102: } Chris@102: // mask_el == 'T' Chris@102: static inline bool apply_dispatch(char el, integral_constant) Chris@102: { Chris@102: return el == 'T' || ( el >= '0' && el <= '9' ); Chris@102: } Chris@102: // mask_el >= '0' && mask_el <= '9' Chris@102: static inline bool apply_dispatch(char el, integral_constant) Chris@102: { Chris@102: return el == mask_el; Chris@102: } Chris@102: // else Chris@102: static inline bool apply_dispatch(char /*el*/, integral_constant) Chris@102: { Chris@102: return true; Chris@102: } Chris@102: }; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_check_sequence Chris@102: { Chris@102: typedef typename boost::mpl::deref::type StaticMask; Chris@102: Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_check_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: boost::mpl::is_sequence::value Chris@102: >::apply(matrix) Chris@102: || static_check_sequence Chris@102: < Chris@102: typename boost::mpl::next::type, Chris@102: Last Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_check_sequence Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& /*matrix*/) Chris@102: { Chris@102: return false; Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_check_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_check_sequence Chris@102: < Chris@102: typename boost::mpl::begin::type, Chris@102: typename boost::mpl::end::type Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_check_matrix Chris@102: { Chris@102: template Chris@102: static inline bool apply(Matrix const& matrix) Chris@102: { Chris@102: return static_check_dispatch Chris@102: < Chris@102: StaticMask, Chris@102: boost::mpl::is_sequence::value Chris@102: >::apply(matrix); Chris@102: } Chris@102: }; Chris@102: Chris@102: // static_mask_handler Chris@102: Chris@102: template Chris@102: class static_mask_handler Chris@102: : private matrix<3> Chris@102: { Chris@102: typedef matrix<3> base_t; Chris@102: Chris@102: public: Chris@102: typedef bool result_type; Chris@102: Chris@102: bool interrupt; Chris@102: Chris@102: inline static_mask_handler(StaticMask const& /*dummy*/) Chris@102: : interrupt(false) Chris@102: {} Chris@102: Chris@102: result_type result() const Chris@102: { Chris@102: return (!Interrupt || !interrupt) Chris@102: && static_check_matrix:: Chris@102: apply(static_cast(*this)); Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool may_update() const Chris@102: { Chris@102: return static_may_update:: Chris@102: apply(static_cast(*this)); Chris@102: } Chris@102: Chris@102: template Chris@102: static inline bool expects() Chris@102: { Chris@102: return static_should_handle_element::value; Chris@102: } Chris@102: Chris@102: //template Chris@102: //inline char get() const Chris@102: //{ Chris@102: // return base_t::template get(); Chris@102: //} Chris@102: Chris@102: template Chris@102: inline void set() Chris@102: { Chris@102: static const bool interrupt_c = static_interrupt::value; Chris@102: static const bool should_handle = static_should_handle_element::value; Chris@102: static const int version = interrupt_c ? 0 Chris@102: : should_handle ? 1 Chris@102: : 2; Chris@102: Chris@102: set_dispatch(integral_constant()); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void update() Chris@102: { Chris@102: static const bool interrupt_c = static_interrupt::value; Chris@102: static const bool should_handle = static_should_handle_element::value; Chris@102: static const int version = interrupt_c ? 0 Chris@102: : should_handle ? 1 Chris@102: : 2; Chris@102: Chris@102: update_dispatch(integral_constant()); Chris@102: } Chris@102: Chris@102: private: Chris@102: // Interrupt && interrupt Chris@102: template Chris@102: inline void set_dispatch(integral_constant) Chris@102: { Chris@102: interrupt = true; Chris@102: } Chris@102: // else should_handle Chris@102: template Chris@102: inline void set_dispatch(integral_constant) Chris@102: { Chris@102: base_t::template set(); Chris@102: } Chris@102: // else Chris@102: template Chris@102: inline void set_dispatch(integral_constant) Chris@102: {} Chris@102: Chris@102: // Interrupt && interrupt Chris@102: template Chris@102: inline void update_dispatch(integral_constant) Chris@102: { Chris@102: interrupt = true; Chris@102: } Chris@102: // else should_handle Chris@102: template Chris@102: inline void update_dispatch(integral_constant) Chris@102: { Chris@102: base_t::template update(); Chris@102: } Chris@102: // else Chris@102: template Chris@102: inline void update_dispatch(integral_constant) Chris@102: {} Chris@102: }; Chris@102: Chris@102: // OPERATORS Chris@102: Chris@102: template inline Chris@102: boost::tuples::cons< Chris@102: Mask1, Chris@102: boost::tuples::cons Chris@102: > Chris@102: operator||(Mask1 const& m1, Mask2 const& m2) Chris@102: { Chris@102: namespace bt = boost::tuples; Chris@102: Chris@102: return Chris@102: bt::cons< Mask1, bt::cons > Chris@102: ( m1, bt::cons(m2, bt::null_type()) ); Chris@102: } Chris@102: Chris@102: template inline Chris@102: typename index::detail::tuples::push_back< Chris@102: boost::tuples::cons, Mask Chris@102: >::type Chris@102: operator||(boost::tuples::cons const& t, Mask const& m) Chris@102: { Chris@102: namespace bt = boost::tuples; Chris@102: Chris@102: return Chris@102: index::detail::tuples::push_back< Chris@102: bt::cons, Mask Chris@102: >::apply(t, m); Chris@102: } Chris@102: Chris@102: // PREDEFINED MASKS Chris@102: Chris@102: // TODO: Chris@102: // 1. specialize for simplified masks if available Chris@102: // e.g. for TOUCHES use 1 mask for A/A Chris@102: // 2. Think about dimensions > 2 e.g. should TOUCHES be true Chris@102: // if the interior of the Areal overlaps the boundary of the Volumetric Chris@102: // like it's true for Linear/Areal Chris@102: Chris@102: // EQUALS Chris@102: template Chris@102: struct static_mask_equals_type Chris@102: { Chris@102: typedef static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia Chris@102: //typedef static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC Chris@102: }; Chris@102: Chris@102: // DISJOINT Chris@102: typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_disjoint; Chris@102: Chris@102: // TOUCHES - NOT P/P Chris@102: template ::value, Chris@102: std::size_t Dim2 = topological_dimension::value> Chris@102: struct static_mask_touches_impl Chris@102: { Chris@102: typedef boost::mpl::vector< Chris@102: static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>, Chris@102: static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>, Chris@102: static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'> Chris@102: > type; Chris@102: }; Chris@102: // According to OGC, doesn't apply to P/P Chris@102: // Using the above mask the result would be always false Chris@102: template Chris@102: struct static_mask_touches_impl Chris@102: : not_implemented::type, Chris@102: typename geometry::tag::type> Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct static_mask_touches_type Chris@102: : static_mask_touches_impl Chris@102: {}; Chris@102: Chris@102: // WITHIN Chris@102: typedef static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> static_mask_within; Chris@102: Chris@102: // COVERED_BY (non OGC) Chris@102: typedef boost::mpl::vector< Chris@102: static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>, Chris@102: static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>, Chris@102: static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>, Chris@102: static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'> Chris@102: > static_mask_covered_by; Chris@102: Chris@102: // CROSSES Chris@102: // dim(G1) < dim(G2) - P/L P/A L/A Chris@102: template ::value, Chris@102: std::size_t Dim2 = topological_dimension::value, Chris@102: bool D1LessD2 = (Dim1 < Dim2) Chris@102: > Chris@102: struct static_mask_crosses_impl Chris@102: { Chris@102: typedef static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type; Chris@102: }; Chris@102: // TODO: I'm not sure if this one below should be available! Chris@102: // dim(G1) > dim(G2) - L/P A/P A/L Chris@102: template Chris@102: struct static_mask_crosses_impl Chris@102: { Chris@102: typedef static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type; Chris@102: }; Chris@102: // dim(G1) == dim(G2) - P/P A/A Chris@102: template Chris@102: struct static_mask_crosses_impl Chris@102: : not_implemented::type, Chris@102: typename geometry::tag::type> Chris@102: {}; Chris@102: // dim(G1) == 1 && dim(G2) == 1 - L/L Chris@102: template Chris@102: struct static_mask_crosses_impl Chris@102: { Chris@102: typedef static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_mask_crosses_type Chris@102: : static_mask_crosses_impl Chris@102: {}; Chris@102: Chris@102: // OVERLAPS Chris@102: Chris@102: // dim(G1) != dim(G2) - NOT P/P, L/L, A/A Chris@102: template ::value, Chris@102: std::size_t Dim2 = topological_dimension::value Chris@102: > Chris@102: struct static_mask_overlaps_impl Chris@102: : not_implemented::type, Chris@102: typename geometry::tag::type> Chris@102: {}; Chris@102: // dim(G1) == D && dim(G2) == D - P/P A/A Chris@102: template Chris@102: struct static_mask_overlaps_impl Chris@102: { Chris@102: typedef static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; Chris@102: }; Chris@102: // dim(G1) == 1 && dim(G2) == 1 - L/L Chris@102: template Chris@102: struct static_mask_overlaps_impl Chris@102: { Chris@102: typedef static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; Chris@102: }; Chris@102: Chris@102: template Chris@102: struct static_mask_overlaps_type Chris@102: : static_mask_overlaps_impl Chris@102: {}; Chris@102: Chris@102: // RESULTS/HANDLERS UTILS Chris@102: Chris@102: template Chris@102: inline void set(Result & res) Chris@102: { Chris@102: res.template set(); Chris@102: } Chris@102: Chris@102: template Chris@102: struct set_dispatch Chris@102: { Chris@102: template Chris@102: static inline void apply(Result & res) Chris@102: { Chris@102: res.template set(); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct set_dispatch Chris@102: { Chris@102: template Chris@102: static inline void apply(Result & res) Chris@102: { Chris@102: res.template set(); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline void set(Result & res) Chris@102: { Chris@102: set_dispatch::apply(res); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void set(Result & res) Chris@102: { Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void set(Result & res) Chris@102: { Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: res.template set(); Chris@102: } Chris@102: Chris@102: template Chris@102: inline void update(Result & res) Chris@102: { Chris@102: res.template update(); Chris@102: } Chris@102: Chris@102: template Chris@102: struct update_result_dispatch Chris@102: { Chris@102: template Chris@102: static inline void apply(Result & res) Chris@102: { Chris@102: update(res); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct update_result_dispatch Chris@102: { Chris@102: template Chris@102: static inline void apply(Result & res) Chris@102: { Chris@102: update(res); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline void update(Result & res) Chris@102: { Chris@102: update_result_dispatch::apply(res); Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool may_update(Result const& res) Chris@102: { Chris@102: return res.template may_update(); Chris@102: } Chris@102: Chris@102: template Chris@102: struct may_update_result_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Result const& res) Chris@102: { Chris@102: return may_update(res); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: struct may_update_result_dispatch Chris@102: { Chris@102: template Chris@102: static inline bool apply(Result const& res) Chris@102: { Chris@102: return may_update(res); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: inline bool may_update(Result const& res) Chris@102: { Chris@102: return may_update_result_dispatch::apply(res); Chris@102: } Chris@102: Chris@102: template Chris@102: inline Result return_result() Chris@102: { Chris@102: Result res; Chris@102: set(res); Chris@102: return res; Chris@102: } Chris@102: Chris@102: template Chris@102: struct result_dimension Chris@102: { Chris@102: BOOST_STATIC_ASSERT(geometry::dimension::value >= 0); Chris@102: static const char value Chris@102: = ( geometry::dimension::value <= 9 ) ? Chris@102: ( '0' + geometry::dimension::value ) : Chris@102: 'T'; Chris@102: }; Chris@102: Chris@102: }} // namespace detail::relate Chris@102: #endif // DOXYGEN_NO_DETAIL Chris@102: Chris@102: }} // namespace boost::geometry Chris@102: Chris@102: #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP