// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2014, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace is_simple { template struct is_simple_linestring { static inline bool apply(Linestring const& linestring) { return !detail::is_valid::has_duplicates < Linestring, closed >::apply(linestring) && !detail::is_valid::has_spikes < Linestring, closed >::apply(linestring) && !(CheckSelfIntersections && geometry::intersects(linestring)); } }; template class is_simple_multilinestring { private: class is_acceptable_turn { private: template static inline bool is_boundary_point_of(Point const& point, Linestring const& linestring) { BOOST_ASSERT( boost::size(linestring) > 1 ); return !geometry::equals(range::front(linestring), range::back(linestring)) && ( geometry::equals(point, range::front(linestring)) || geometry::equals(point, range::back(linestring)) ); } template static inline bool have_same_boundary_points(Linestring1 const& ls1, Linestring2 const& ls2) { return geometry::equals(range::front(ls1), range::front(ls2)) ? geometry::equals(range::back(ls1), range::back(ls2)) : (geometry::equals(range::front(ls1), range::back(ls2)) && geometry::equals(range::back(ls1), range::front(ls2)) ) ; } public: is_acceptable_turn(MultiLinestring const& multilinestring) : m_multilinestring(multilinestring) {} template inline bool apply(Turn const& turn) const { typedef typename boost::range_value < MultiLinestring >::type linestring; linestring const& ls1 = range::at(m_multilinestring, turn.operations[0].seg_id.multi_index); linestring const& ls2 = range::at(m_multilinestring, turn.operations[1].seg_id.multi_index); return is_boundary_point_of(turn.point, ls1) && is_boundary_point_of(turn.point, ls2) && ( boost::size(ls1) != 2 || boost::size(ls2) != 2 || !have_same_boundary_points(ls1, ls2) ); } private: MultiLinestring const& m_multilinestring; }; public: static inline bool apply(MultiLinestring const& multilinestring) { typedef typename boost::range_value::type linestring; typedef typename point_type::type point_type; typedef point_type point; // check each of the linestrings for simplicity if ( !detail::check_iterator_range < is_simple_linestring, false // do not allow empty multilinestring >::apply(boost::begin(multilinestring), boost::end(multilinestring)) ) { return false; } // compute self turns typedef detail::overlay::turn_info < point_type, geometry::segment_ratio < typename geometry::coordinate_type::type > > turn_info; std::deque turns; typedef detail::overlay::get_turn_info < detail::disjoint::assign_disjoint_policy > turn_policy; is_acceptable_turn predicate(multilinestring); detail::overlay::predicate_based_interrupt_policy < is_acceptable_turn > interrupt_policy(predicate); detail::self_get_turn_points::get_turns < turn_policy >::apply(multilinestring, detail::no_rescale_policy(), turns, interrupt_policy); detail::is_valid::debug_print_turns(turns.begin(), turns.end()); debug_print_boundary_points(multilinestring); return !interrupt_policy.has_intersections; } }; }} // namespace detail::is_simple #endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { // A linestring is a curve. // A curve is simple if it does not pass through the same point twice, // with the possible exception of its two endpoints // // Reference: OGC 06-103r4 (6.1.6.1) template struct is_simple : detail::is_simple::is_simple_linestring {}; // A MultiLinestring is a MultiCurve // A MultiCurve is simple if all of its elements are simple and the // only intersections between any two elements occur at Points that // are on the boundaries of both elements. // // Reference: OGC 06-103r4 (6.1.8.1; Fig. 9) template struct is_simple : detail::is_simple::is_simple_multilinestring {}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP