diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp new file mode 100644 index 000000000..c6144f4d1 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -0,0 +1,121 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 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_HAS_SELF_INTERSECTIONS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP + +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS +# include +# include +#endif + + +namespace boost { namespace geometry +{ + + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + +/*! +\brief Overlay Invalid Input Exception +\ingroup overlay +\details The overlay_invalid_input_exception is thrown at invalid input + */ +class overlay_invalid_input_exception : public geometry::exception +{ +public: + + inline overlay_invalid_input_exception() {} + + virtual char const* what() const throw() + { + return "Boost.Geometry Overlay invald input exception"; + } +}; + +#endif + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +inline bool has_self_intersections(Geometry const& geometry) +{ + using namespace boost::geometry; + typedef typename point_type::type point_type; + typedef detail::overlay::turn_info turn_info; + std::deque turns; + detail::get_turns::no_interrupt_policy policy; + geometry::self_turns(geometry, turns, policy); + +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS + bool first = true; +#endif + for(typename std::deque::const_iterator it = boost::begin(turns); + it != boost::end(turns); ++it) + { + turn_info const& info = *it; + bool const both_union_turn = + info.operations[0].operation == detail::overlay::operation_union + && info.operations[1].operation == detail::overlay::operation_union; + bool const both_intersection_turn = + info.operations[0].operation == detail::overlay::operation_intersection + && info.operations[1].operation == detail::overlay::operation_intersection; + + bool const valid = (both_union_turn || both_intersection_turn) + && (info.method == detail::overlay::method_touch + || info.method == detail::overlay::method_touch_interior); + + if (! valid) + { +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS + if (first) + { + std::cout << "turn points: " << std::endl; + first = false; + } + std::cout << method_char(info.method); + for (int i = 0; i < 2; i++) + { + std::cout << " " << operation_char(info.operations[i].operation); + } + std::cout << " " << geometry::dsv(info.point) << std::endl; +#endif + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw overlay_invalid_input_exception(); +#endif + } + + } + return false; +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP + diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index a469dd93a..459ccb1bd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include @@ -168,6 +170,9 @@ struct overlay GeometryOut, Direction, ReverseOut >(geometry1, geometry2, out); } + + has_self_intersections(geometry1); + has_self_intersections(geometry2); container_type turn_points; diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 3efe5c7d7..f996b60ea 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -136,6 +136,31 @@ struct self_get_turn_points {}; +template +< + typename Box, + typename Turns, + typename TurnPolicy, + typename InterruptPolicy +> +struct self_get_turn_points + < + box_tag, Box, + Turns, + TurnPolicy, + InterruptPolicy + > +{ + static inline bool apply( + Box const& , + Turns& , + InterruptPolicy& ) + { + return true; + } +}; + + template < typename Polygon, @@ -182,7 +207,7 @@ template typename Turns, typename InterruptPolicy > -inline void get_turns(Geometry const& geometry, +inline void self_turns(Geometry const& geometry, Turns& turns, InterruptPolicy& interrupt_policy) { concept::check();