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-2020.
7 // Modifications copyright (c) 2017-2020 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
22 #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
23 #include <boost/geometry/algorithms/detail/partition.hpp>
24 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
25 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
26 #include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
28 #include <boost/geometry/core/access.hpp>
29 #include <boost/geometry/core/coordinate_dimension.hpp>
30 #include <boost/geometry/core/point_order.hpp>
31 #include <boost/geometry/core/tags.hpp>
33 #include <boost/geometry/geometries/box.hpp>
34 #include <boost/geometry/geometries/concepts/check.hpp>
36 #include <boost/geometry/util/condition.hpp>
39 namespace boost { namespace geometry
42 #ifndef DOXYGEN_NO_DETAIL
43 namespace detail { namespace self_get_turn_points
46 struct no_interrupt_policy
48 static bool const enabled = false;
49 static bool const has_intersections = false;
52 template <typename Range>
53 static inline bool apply(Range const&)
66 typename IntersectionStrategy,
67 typename RobustPolicy,
68 typename InterruptPolicy
70 struct self_section_visitor
72 Geometry const& m_geometry;
73 IntersectionStrategy const& m_intersection_strategy;
74 RobustPolicy const& m_rescale_policy;
76 InterruptPolicy& m_interrupt_policy;
80 inline self_section_visitor(Geometry const& g,
81 IntersectionStrategy const& is,
82 RobustPolicy const& rp,
88 , m_intersection_strategy(is)
89 , m_rescale_policy(rp)
91 , m_interrupt_policy(ip)
92 , m_source_index(source_index)
93 , m_skip_adjacent(skip_adjacent)
96 template <typename Section>
97 inline bool apply(Section const& sec1, Section const& sec2)
99 if (! detail::disjoint::disjoint_box_box(sec1.bounding_box,
101 m_intersection_strategy.get_disjoint_box_box_strategy())
105 // false if interrupted
106 return detail::get_turns::get_turns_in_sections
112 >::apply(m_source_index, m_geometry, sec1,
113 m_source_index, m_geometry, sec2,
114 false, m_skip_adjacent,
115 m_intersection_strategy,
117 m_turns, m_interrupt_policy);
127 template <bool Reverse, typename TurnPolicy>
130 template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
131 static inline bool apply(
132 Geometry const& geometry,
133 IntersectionStrategy const& intersection_strategy,
134 RobustPolicy const& robust_policy,
136 InterruptPolicy& interrupt_policy,
137 int source_index, bool skip_adjacent)
141 typename geometry::robust_point_type
143 typename geometry::point_type<Geometry>::type,
148 // sectionalize in two dimensions to detect
149 // all potential spikes correctly
150 typedef geometry::sections<box_type, 2> sections_type;
152 typedef std::integer_sequence<std::size_t, 0, 1> dimensions;
155 geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec,
156 intersection_strategy.get_envelope_strategy(),
157 intersection_strategy.get_expand_strategy());
162 Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
163 > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent);
165 typedef detail::section::get_section_box
167 typename IntersectionStrategy::expand_box_strategy_type
168 > get_section_box_type;
169 typedef detail::section::overlaps_section_box
171 typename IntersectionStrategy::disjoint_box_box_strategy_type
172 > overlaps_section_box_type;
174 // false if interrupted
178 >::apply(sec, visitor,
179 get_section_box_type(),
180 overlaps_section_box_type());
182 return ! interrupt_policy.has_intersections;
187 }} // namespace detail::self_get_turn_points
188 #endif // DOXYGEN_NO_DETAIL
191 #ifndef DOXYGEN_NO_DISPATCH
198 typename GeometryTag,
202 struct self_get_turn_points
213 struct self_get_turn_points
215 Reverse, ring_tag, Ring,
218 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
228 struct self_get_turn_points
230 Reverse, box_tag, Box,
234 template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
235 static inline bool apply(
238 RobustPolicy const& ,
241 int /*source_index*/,
242 bool /*skip_adjacent*/)
255 struct self_get_turn_points
257 Reverse, polygon_tag, Polygon,
260 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
267 typename MultiPolygon,
270 struct self_get_turn_points
272 Reverse, multi_polygon_tag, MultiPolygon,
275 : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
279 } // namespace dispatch
280 #endif // DOXYGEN_NO_DISPATCH
283 #ifndef DOXYGEN_NO_DETAIL
284 namespace detail { namespace self_get_turn_points
287 // Version where Reverse can be specified manually. TODO:
288 // can most probably be merged with self_get_turn_points::get_turn
292 typename AssignPolicy,
294 typename IntersectionStrategy,
295 typename RobustPolicy,
297 typename InterruptPolicy
299 inline void self_turns(Geometry const& geometry,
300 IntersectionStrategy const& strategy,
301 RobustPolicy const& robust_policy,
303 InterruptPolicy& interrupt_policy,
304 int source_index = 0,
305 bool skip_adjacent = false)
307 concepts::check<Geometry const>();
309 typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
311 dispatch::self_get_turn_points
314 typename tag<Geometry>::type,
317 >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
318 source_index, skip_adjacent);
321 }} // namespace detail::self_get_turn_points
322 #endif // DOXYGEN_NO_DETAIL
325 \brief Calculate self intersections of a geometry
327 \tparam Geometry geometry type
328 \tparam Turns type of intersection container
329 (e.g. vector of "intersection/turn point"'s)
330 \param geometry geometry
331 \param strategy strategy to be used
332 \param robust_policy policy to handle robustness issues
333 \param turns container which will contain intersection points
334 \param interrupt_policy policy determining if process is stopped
335 when intersection is found
336 \param source_index source index for generated turns
337 \param skip_adjacent indicates if adjacent turns should be skipped
341 typename AssignPolicy,
343 typename IntersectionStrategy,
344 typename RobustPolicy,
346 typename InterruptPolicy
348 inline void self_turns(Geometry const& geometry,
349 IntersectionStrategy const& strategy,
350 RobustPolicy const& robust_policy,
352 InterruptPolicy& interrupt_policy,
353 int source_index = 0,
354 bool skip_adjacent = false)
356 concepts::check<Geometry const>();
358 static bool const reverse = detail::overlay::do_reverse
360 geometry::point_order<Geometry>::value
363 detail::self_get_turn_points::self_turns
367 >(geometry, strategy, robust_policy, turns, interrupt_policy,
368 source_index, skip_adjacent);
373 }} // namespace boost::geometry
375 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP