Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@16: // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. Chris@16: // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Chris@16: // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. Chris@16: Chris@16: // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library Chris@16: // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP Chris@16: #define BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: namespace detail { namespace disjoint Chris@16: { Chris@16: Chris@16: template Chris@16: struct check_each_ring_for_within Chris@16: { Chris@16: bool has_within; Chris@16: Geometry const& m_geometry; Chris@16: Chris@16: inline check_each_ring_for_within(Geometry const& g) Chris@16: : has_within(false) Chris@16: , m_geometry(g) Chris@16: {} Chris@16: Chris@16: template Chris@16: inline void apply(Range const& range) Chris@16: { Chris@16: typename geometry::point_type::type p; Chris@16: geometry::point_on_border(p, range); Chris@16: if (geometry::within(p, m_geometry)) Chris@16: { Chris@16: has_within = true; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline bool rings_containing(FirstGeometry const& geometry1, Chris@16: SecondGeometry const& geometry2) Chris@16: { Chris@16: check_each_ring_for_within checker(geometry1); Chris@16: geometry::detail::for_each_range(geometry2, checker); Chris@16: return checker.has_within; Chris@16: } Chris@16: Chris@16: Chris@16: struct assign_disjoint_policy Chris@16: { Chris@16: // We want to include all points: Chris@16: static bool const include_no_turn = true; Chris@16: static bool const include_degenerate = true; Chris@16: static bool const include_opposite = true; Chris@16: Chris@16: // We don't assign extra info: Chris@16: template Chris@16: < Chris@16: typename Info, Chris@16: typename Point1, Chris@16: typename Point2, Chris@16: typename IntersectionInfo, Chris@16: typename DirInfo Chris@16: > Chris@16: static inline void apply(Info& , Point1 const& , Point2 const&, Chris@16: IntersectionInfo const&, DirInfo const&) Chris@16: {} Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct disjoint_linear Chris@16: { Chris@16: static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) Chris@16: { Chris@16: typedef typename geometry::point_type::type point_type; Chris@16: Chris@16: typedef overlay::turn_info turn_info; Chris@16: std::deque turns; Chris@16: Chris@16: // Specify two policies: Chris@16: // 1) Stop at any intersection Chris@16: // 2) In assignment, include also degenerate points (which are normally skipped) Chris@16: disjoint_interrupt_policy policy; Chris@16: geometry::get_turns Chris@16: < Chris@16: false, false, Chris@16: assign_disjoint_policy Chris@16: >(geometry1, geometry2, turns, policy); Chris@16: if (policy.has_intersections) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: return true; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct disjoint_segment Chris@16: { Chris@16: static inline bool apply(Segment1 const& segment1, Segment2 const& segment2) Chris@16: { Chris@16: typedef typename point_type::type point_type; Chris@16: Chris@16: segment_intersection_points is Chris@16: = strategy::intersection::relate_cartesian_segments Chris@16: < Chris@16: policies::relate::segments_intersection_points Chris@16: < Chris@16: Segment1, Chris@16: Segment2, Chris@16: segment_intersection_points Chris@16: > Chris@16: >::apply(segment1, segment2); Chris@16: Chris@16: return is.count == 0; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct general_areal Chris@16: { Chris@16: static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) Chris@16: { Chris@16: if (! disjoint_linear::apply(geometry1, geometry2)) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: // If there is no intersection of segments, they might located Chris@16: // inside each other Chris@16: if (rings_containing(geometry1, geometry2) Chris@16: || rings_containing(geometry2, geometry1)) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: return true; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct disjoint_segment_box Chris@16: { Chris@16: static inline bool apply(Segment const& segment, Box const& box) Chris@16: { Chris@16: typedef typename point_type::type point_type; Chris@16: point_type p0, p1; Chris@16: geometry::detail::assign_point_from_index<0>(segment, p0); Chris@16: geometry::detail::assign_point_from_index<1>(segment, p1); Chris@16: Chris@16: return ! detail::disjoint::segment_box_intersection::apply(p0, p1, box); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct disjoint_linestring_box Chris@16: { Chris@16: static inline bool apply(Linestring const& linestring, Box const& box) Chris@16: { Chris@16: typedef typename ::boost::range_value::type point_type; Chris@16: typedef typename ::boost::range_const_iterator::type const_iterator; Chris@16: typedef typename ::boost::range_size::type size_type; Chris@16: Chris@16: const size_type count = ::boost::size(linestring); Chris@16: Chris@16: if ( count == 0 ) Chris@16: return false; Chris@16: else if ( count == 1 ) Chris@16: return detail::disjoint::point_box::value> Chris@16: ::apply(*::boost::begin(linestring), box); Chris@16: else Chris@16: { Chris@16: const_iterator it0 = ::boost::begin(linestring); Chris@16: const_iterator it1 = ::boost::begin(linestring) + 1; Chris@16: const_iterator last = ::boost::end(linestring); Chris@16: Chris@16: for ( ; it1 != last ; ++it0, ++it1 ) Chris@16: { Chris@16: if ( detail::disjoint::segment_box_intersection::apply(*it0, *it1, box) ) Chris@16: return false; Chris@16: } Chris@16: return true; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: }} // namespace detail::disjoint Chris@16: #endif // DOXYGEN_NO_DETAIL Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DISPATCH Chris@16: namespace dispatch Chris@16: { Chris@16: Chris@16: Chris@16: template Chris@16: < Chris@16: typename Geometry1, typename Geometry2, Chris@16: std::size_t DimensionCount = dimension::type::value, Chris@16: typename Tag1 = typename tag::type, Chris@16: typename Tag2 = typename tag::type, Chris@16: bool Reverse = reverse_dispatch::type::value Chris@16: > Chris@16: struct disjoint Chris@16: : detail::disjoint::general_areal Chris@16: {}; Chris@16: Chris@16: Chris@16: // If reversal is needed, perform it Chris@16: template Chris@16: < Chris@16: typename Geometry1, typename Geometry2, Chris@16: std::size_t DimensionCount, Chris@16: typename Tag1, typename Tag2 Chris@16: > Chris@16: struct disjoint Chris@16: : disjoint Chris@16: { Chris@16: static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) Chris@16: { Chris@16: return disjoint Chris@16: < Chris@16: Geometry2, Geometry1, Chris@16: DimensionCount, Chris@16: Tag2, Tag1 Chris@16: >::apply(g2, g1); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::point_point Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::box_box Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::point_box Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::reverse_covered_by Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::reverse_covered_by Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::disjoint_linear Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::disjoint_segment Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::disjoint_linear Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::disjoint_segment_box Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct disjoint Chris@16: : detail::disjoint::disjoint_linestring_box Chris@16: {}; Chris@16: Chris@16: } // namespace dispatch Chris@16: #endif // DOXYGEN_NO_DISPATCH Chris@16: Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief \brief_check2{are disjoint} Chris@16: \ingroup disjoint Chris@16: \tparam Geometry1 \tparam_geometry Chris@16: \tparam Geometry2 \tparam_geometry Chris@16: \param geometry1 \param_geometry Chris@16: \param geometry2 \param_geometry Chris@16: \return \return_check2{are disjoint} Chris@16: Chris@16: \qbk{[include reference/algorithms/disjoint.qbk]} Chris@16: */ Chris@16: template Chris@16: inline bool disjoint(Geometry1 const& geometry1, Chris@16: Geometry2 const& geometry2) Chris@16: { Chris@16: concept::check_concepts_and_equal_dimensions Chris@16: < Chris@16: Geometry1 const, Chris@16: Geometry2 const Chris@16: >(); Chris@16: Chris@16: return dispatch::disjoint::apply(geometry1, geometry2); Chris@16: } Chris@16: Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: Chris@16: #endif // BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP