1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2013, 2014, 2015, 2017, 2019.
6 // Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 // Contributed and/or modified by Menelaos Karavelas, 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_RELATE_TURNS_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
18 #include <boost/geometry/strategies/distance.hpp>
19 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
20 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
21 #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
23 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
24 #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
26 #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
27 #include <boost/geometry/strategies/spherical/point_in_point.hpp>
29 #include <boost/type_traits/is_base_of.hpp>
32 namespace boost { namespace geometry {
34 #ifndef DOXYGEN_NO_DETAIL
35 namespace detail { namespace relate { namespace turns {
37 template <bool IncludeDegenerate = false>
39 : overlay::assign_null_policy
41 static bool const include_degenerate = IncludeDegenerate;
50 typename GetTurnPolicy = detail::get_turns::get_turn_info_type
52 Geometry1, Geometry2, assign_policy<>
57 typedef typename geometry::point_type<Geometry1>::type point1_type;
59 template <typename Strategy>
60 struct robust_policy_type
61 : geometry::rescale_overlay_policy_type
65 typename Strategy::cs_tag
72 typename RobustPolicy = typename robust_policy_type<Strategy>::type
76 typedef typename segment_ratio_type<point1_type, RobustPolicy>::type ratio_type;
77 typedef overlay::turn_info
81 typename detail::get_turns::turn_operation_type
83 Geometry1, Geometry2, ratio_type
88 template <typename Turns>
89 static inline void apply(Turns & turns,
90 Geometry1 const& geometry1,
91 Geometry2 const& geometry2)
93 detail::get_turns::no_interrupt_policy interrupt_policy;
95 typename strategy::intersection::services::default_strategy
97 typename cs_tag<Geometry1>::type
98 >::type intersection_strategy;
100 apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
103 template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
104 static inline void apply(Turns & turns,
105 Geometry1 const& geometry1,
106 Geometry2 const& geometry2,
107 InterruptPolicy & interrupt_policy,
108 IntersectionStrategy const& intersection_strategy)
110 typedef typename robust_policy_type<IntersectionStrategy>::type robust_policy_t;
112 robust_policy_t robust_policy
113 = geometry::get_rescale_policy<robust_policy_t>(
114 geometry1, geometry2, intersection_strategy);
116 apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy);
119 template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy, typename RobustPolicy>
120 static inline void apply(Turns & turns,
121 Geometry1 const& geometry1,
122 Geometry2 const& geometry2,
123 InterruptPolicy & interrupt_policy,
124 IntersectionStrategy const& intersection_strategy,
125 RobustPolicy const& robust_policy)
127 static const bool reverse1 = detail::overlay::do_reverse
129 geometry::point_order<Geometry1>::value
132 static const bool reverse2 = detail::overlay::do_reverse
134 geometry::point_order<Geometry2>::value
139 typename geometry::tag<Geometry1>::type,
140 typename geometry::tag<Geometry2>::type,
146 >::apply(0, geometry1, 1, geometry2,
147 intersection_strategy, robust_policy,
148 turns, interrupt_policy);
152 // TURNS SORTING AND SEARCHING
154 template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
157 template <typename Operation>
158 inline int operator()(Operation const& op) const
162 case detail::overlay::operation_none : return N;
163 case detail::overlay::operation_union : return U;
164 case detail::overlay::operation_intersection : return I;
165 case detail::overlay::operation_blocked : return B;
166 case detail::overlay::operation_continue : return C;
167 case detail::overlay::operation_opposite : return O;
173 template <std::size_t OpId, typename OpToInt>
174 struct less_op_xxx_linear
176 template <typename Turn>
177 inline bool operator()(Turn const& left, Turn const& right) const
179 static OpToInt op_to_int;
180 return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);
184 template <std::size_t OpId>
185 struct less_op_linear_linear
186 : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
189 template <std::size_t OpId>
190 struct less_op_linear_areal_single
192 template <typename Turn>
193 inline bool operator()(Turn const& left, Turn const& right) const
195 static const std::size_t other_op_id = (OpId + 1) % 2;
196 static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
197 static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
199 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
200 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
202 typedef typename Turn::turn_operation_type operation_type;
203 operation_type const& left_operation = left.operations[OpId];
204 operation_type const& right_operation = right.operations[OpId];
206 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
208 return op_to_int_xuic(left_operation)
209 < op_to_int_xuic(right_operation);
213 return op_to_int_xiuc(left_operation)
214 < op_to_int_xiuc(right_operation);
219 template <std::size_t OpId>
220 struct less_op_areal_linear
221 : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >
224 template <std::size_t OpId>
225 struct less_op_areal_areal
227 template <typename Turn>
228 inline bool operator()(Turn const& left, Turn const& right) const
230 static const std::size_t other_op_id = (OpId + 1) % 2;
231 static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;
232 static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;
234 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
235 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
237 typedef typename Turn::turn_operation_type operation_type;
238 operation_type const& left_operation = left.operations[OpId];
239 operation_type const& right_operation = right.operations[OpId];
241 if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
243 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
245 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
249 if ( left_other_seg_id.ring_index == -1 )
251 if ( left_operation.operation == overlay::operation_union )
253 else if ( left_operation.operation == overlay::operation_intersection )
256 else if ( right_other_seg_id.ring_index == -1 )
258 if ( right_operation.operation == overlay::operation_union )
260 else if ( right_operation.operation == overlay::operation_intersection )
264 return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
269 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
274 template <std::size_t OpId>
275 struct less_other_multi_index
277 static const std::size_t other_op_id = (OpId + 1) % 2;
279 template <typename Turn>
280 inline bool operator()(Turn const& left, Turn const& right) const
282 return left.operations[other_op_id].seg_id.multi_index
283 < right.operations[other_op_id].seg_id.multi_index;
287 // sort turns by G1 - source_index == 0 by:
288 // seg_id -> distance and coordinates -> operation
289 template <std::size_t OpId, typename LessOp, typename CSTag>
292 BOOST_STATIC_ASSERT(OpId < 2);
294 template <typename Turn>
295 static inline bool use_fraction(Turn const& left, Turn const& right)
297 typedef typename geometry::strategy::within::services::default_strategy
299 typename Turn::point_type, typename Turn::point_type,
300 point_tag, point_tag,
301 pointlike_tag, pointlike_tag,
302 typename tag_cast<CSTag, spherical_tag>::type,
303 typename tag_cast<CSTag, spherical_tag>::type
304 >::type eq_pp_strategy_type;
306 static LessOp less_op;
308 // NOTE: Assuming fraction is more permissive and faster than
309 // comparison of points with strategy.
310 return geometry::math::equals(left.operations[OpId].fraction,
311 right.operations[OpId].fraction)
312 && eq_pp_strategy_type::apply(left.point, right.point)
316 (left.operations[OpId].fraction < right.operations[OpId].fraction)
320 template <typename Turn>
321 inline bool operator()(Turn const& left, Turn const& right) const
323 segment_identifier const& sl = left.operations[OpId].seg_id;
324 segment_identifier const& sr = right.operations[OpId].seg_id;
326 return sl < sr || ( sl == sr && use_fraction(left, right) );
330 }}} // namespace detail::relate::turns
331 #endif // DOXYGEN_NO_DETAIL
333 }} // namespace boost::geometry
335 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP