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, 2018.
7 // Modifications copyright (c) 2017-2018 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;
83 inline self_section_visitor(Geometry const& g,
84 IntersectionStrategy const& is,
85 RobustPolicy const& rp,
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,
104 m_intersection_strategy.get_disjoint_box_box_strategy())
108 // false if interrupted
109 return detail::get_turns::get_turns_in_sections
115 >::apply(m_source_index, m_geometry, sec1,
116 m_source_index, m_geometry, sec2,
117 false, m_skip_adjacent,
118 m_intersection_strategy,
120 m_turns, m_interrupt_policy);
130 template <bool Reverse, typename TurnPolicy>
133 template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
134 static inline bool apply(
135 Geometry const& geometry,
136 IntersectionStrategy const& intersection_strategy,
137 RobustPolicy const& robust_policy,
139 InterruptPolicy& interrupt_policy,
140 int source_index, bool skip_adjacent)
144 typename geometry::robust_point_type
146 typename geometry::point_type<Geometry>::type,
151 // sectionalize in two dimensions to detect
152 // all potential spikes correctly
153 typedef geometry::sections<box_type, 2> sections_type;
155 typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
158 geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec,
159 intersection_strategy.get_envelope_strategy(),
160 intersection_strategy.get_expand_strategy());
165 Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
166 > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent);
168 typedef detail::section::get_section_box
170 typename IntersectionStrategy::expand_box_strategy_type
171 > get_section_box_type;
172 typedef detail::section::overlaps_section_box
174 typename IntersectionStrategy::disjoint_box_box_strategy_type
175 > overlaps_section_box_type;
177 // false if interrupted
181 >::apply(sec, visitor,
182 get_section_box_type(),
183 overlaps_section_box_type());
185 return ! interrupt_policy.has_intersections;
190 }} // namespace detail::self_get_turn_points
191 #endif // DOXYGEN_NO_DETAIL
194 #ifndef DOXYGEN_NO_DISPATCH
201 typename GeometryTag,
205 struct self_get_turn_points
216 struct self_get_turn_points
218 Reverse, ring_tag, Ring,
221 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
231 struct self_get_turn_points
233 Reverse, box_tag, Box,
237 template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
238 static inline bool apply(
241 RobustPolicy const& ,
244 int /*source_index*/,
245 bool /*skip_adjacent*/)
258 struct self_get_turn_points
260 Reverse, polygon_tag, Polygon,
263 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
270 typename MultiPolygon,
273 struct self_get_turn_points
275 Reverse, multi_polygon_tag, MultiPolygon,
278 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
282 } // namespace dispatch
283 #endif // DOXYGEN_NO_DISPATCH
286 #ifndef DOXYGEN_NO_DETAIL
287 namespace detail { namespace self_get_turn_points
290 // Version where Reverse can be specified manually. TODO:
291 // can most probably be merged with self_get_turn_points::get_turn
295 typename AssignPolicy,
297 typename IntersectionStrategy,
298 typename RobustPolicy,
300 typename InterruptPolicy
302 inline void self_turns(Geometry const& geometry,
303 IntersectionStrategy const& strategy,
304 RobustPolicy const& robust_policy,
306 InterruptPolicy& interrupt_policy,
307 int source_index = 0,
308 bool skip_adjacent = false)
310 concepts::check<Geometry const>();
312 typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
314 dispatch::self_get_turn_points
317 typename tag<Geometry>::type,
320 >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
321 source_index, skip_adjacent);
324 }} // namespace detail::self_get_turn_points
325 #endif // DOXYGEN_NO_DETAIL
328 \brief Calculate self intersections of a geometry
330 \tparam Geometry geometry type
331 \tparam Turns type of intersection container
332 (e.g. vector of "intersection/turn point"'s)
333 \param geometry geometry
334 \param strategy strategy to be used
335 \param robust_policy policy to handle robustness issues
336 \param turns container which will contain intersection points
337 \param interrupt_policy policy determining if process is stopped
338 when intersection is found
339 \param source_index source index for generated turns
340 \param skip_adjacent indicates if adjacent turns should be skipped
344 typename AssignPolicy,
346 typename IntersectionStrategy,
347 typename RobustPolicy,
349 typename InterruptPolicy
351 inline void self_turns(Geometry const& geometry,
352 IntersectionStrategy const& strategy,
353 RobustPolicy const& robust_policy,
355 InterruptPolicy& interrupt_policy,
356 int source_index = 0,
357 bool skip_adjacent = false)
359 concepts::check<Geometry const>();
361 static bool const reverse = detail::overlay::do_reverse
363 geometry::point_order<Geometry>::value
366 detail::self_get_turn_points::self_turns
370 >(geometry, strategy, robust_policy, turns, interrupt_policy,
371 source_index, skip_adjacent);
376 }} // namespace boost::geometry
378 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP