1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
6 // This file was modified by Oracle on 2017.
7 // Modifications copyright (c) 2017 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
21 #include <boost/mpl/vector_c.hpp>
22 #include <boost/range.hpp>
24 #include <boost/geometry/core/access.hpp>
25 #include <boost/geometry/core/coordinate_dimension.hpp>
26 #include <boost/geometry/core/point_order.hpp>
27 #include <boost/geometry/core/tags.hpp>
29 #include <boost/geometry/geometries/concepts/check.hpp>
31 #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
32 #include <boost/geometry/algorithms/detail/partition.hpp>
33 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
34 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
35 #include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
37 #include <boost/geometry/geometries/box.hpp>
39 #include <boost/geometry/util/condition.hpp>
42 namespace boost { namespace geometry
45 #ifndef DOXYGEN_NO_DETAIL
46 namespace detail { namespace self_get_turn_points
49 struct no_interrupt_policy
51 static bool const enabled = false;
52 static bool const has_intersections = false;
55 template <typename Range>
56 static inline bool apply(Range const&)
69 typename IntersectionStrategy,
70 typename RobustPolicy,
71 typename InterruptPolicy
73 struct self_section_visitor
75 Geometry const& m_geometry;
76 IntersectionStrategy const& m_intersection_strategy;
77 RobustPolicy const& m_rescale_policy;
79 InterruptPolicy& m_interrupt_policy;
80 std::size_t m_source_index;
83 inline self_section_visitor(Geometry const& g,
84 IntersectionStrategy const& is,
85 RobustPolicy const& rp,
88 std::size_t source_index,
91 , m_intersection_strategy(is)
92 , m_rescale_policy(rp)
94 , m_interrupt_policy(ip)
95 , m_source_index(source_index)
96 , m_skip_adjacent(skip_adjacent)
99 template <typename Section>
100 inline bool apply(Section const& sec1, Section const& sec2)
102 if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box)
106 // false if interrupted
107 return detail::get_turns::get_turns_in_sections
113 >::apply(m_source_index, m_geometry, sec1,
114 m_source_index, m_geometry, sec2,
115 false, m_skip_adjacent,
116 m_intersection_strategy,
118 m_turns, m_interrupt_policy);
128 template <bool Reverse, typename TurnPolicy>
131 template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
132 static inline bool apply(
133 Geometry const& geometry,
134 IntersectionStrategy const& intersection_strategy,
135 RobustPolicy const& robust_policy,
137 InterruptPolicy& interrupt_policy,
138 std::size_t source_index, bool skip_adjacent)
142 typename geometry::robust_point_type
144 typename geometry::point_type<Geometry>::type,
149 // sectionalize in two dimensions to detect
150 // all potential spikes correctly
151 typedef geometry::sections<box_type, 2> sections_type;
153 typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
156 geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec,
157 intersection_strategy.get_envelope_strategy());
162 Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
163 > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent);
165 // false if interrupted
169 >::apply(sec, visitor,
170 detail::section::get_section_box(),
171 detail::section::overlaps_section_box());
173 return ! interrupt_policy.has_intersections;
178 }} // namespace detail::self_get_turn_points
179 #endif // DOXYGEN_NO_DETAIL
182 #ifndef DOXYGEN_NO_DISPATCH
189 typename GeometryTag,
193 struct self_get_turn_points
204 struct self_get_turn_points
206 Reverse, ring_tag, Ring,
209 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
219 struct self_get_turn_points
221 Reverse, box_tag, Box,
225 template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
226 static inline bool apply(
229 RobustPolicy const& ,
232 std::size_t /*source_index*/,
233 bool /*skip_adjacent*/)
246 struct self_get_turn_points
248 Reverse, polygon_tag, Polygon,
251 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
258 typename MultiPolygon,
261 struct self_get_turn_points
263 Reverse, multi_polygon_tag, MultiPolygon,
266 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
270 } // namespace dispatch
271 #endif // DOXYGEN_NO_DISPATCH
274 #ifndef DOXYGEN_NO_DETAIL
275 namespace detail { namespace self_get_turn_points
278 // Version where Reverse can be specified manually. TODO:
279 // can most probably be merged with self_get_turn_points::get_turn
283 typename AssignPolicy,
285 typename IntersectionStrategy,
286 typename RobustPolicy,
288 typename InterruptPolicy
290 inline void self_turns(Geometry const& geometry,
291 IntersectionStrategy const& strategy,
292 RobustPolicy const& robust_policy,
294 InterruptPolicy& interrupt_policy,
295 std::size_t source_index = 0,
296 bool skip_adjacent = false)
298 concepts::check<Geometry const>();
300 typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
302 dispatch::self_get_turn_points
305 typename tag<Geometry>::type,
308 >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
309 source_index, skip_adjacent);
312 }} // namespace detail::self_get_turn_points
313 #endif // DOXYGEN_NO_DETAIL
316 \brief Calculate self intersections of a geometry
318 \tparam Geometry geometry type
319 \tparam Turns type of intersection container
320 (e.g. vector of "intersection/turn point"'s)
321 \param geometry geometry
322 \param strategy strategy to be used
323 \param robust_policy policy to handle robustness issues
324 \param turns container which will contain intersection points
325 \param interrupt_policy policy determining if process is stopped
326 when intersection is found
330 typename AssignPolicy,
332 typename IntersectionStrategy,
333 typename RobustPolicy,
335 typename InterruptPolicy
337 inline void self_turns(Geometry const& geometry,
338 IntersectionStrategy const& strategy,
339 RobustPolicy const& robust_policy,
341 InterruptPolicy& interrupt_policy,
342 std::size_t source_index = 0,
343 bool skip_adjacent = false)
345 concepts::check<Geometry const>();
347 static bool const reverse = detail::overlay::do_reverse
349 geometry::point_order<Geometry>::value
352 detail::self_get_turn_points::self_turns
356 >(geometry, strategy, robust_policy, turns, interrupt_policy,
357 source_index, skip_adjacent);
362 }} // namespace boost::geometry
364 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP