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.
6 // Modifications copyright (c) 2013-2017 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/no_rescale_policy.hpp>
26 #include <boost/type_traits/is_base_of.hpp>
29 namespace boost { namespace geometry {
31 #ifndef DOXYGEN_NO_DETAIL
32 namespace detail { namespace relate { namespace turns {
34 template <bool IncludeDegenerate = false>
36 : overlay::assign_null_policy
38 static bool const include_degenerate = IncludeDegenerate;
47 typename GetTurnPolicy = detail::get_turns::get_turn_info_type
49 Geometry1, Geometry2, assign_policy<>
51 typename RobustPolicy = detail::no_rescale_policy
55 typedef typename geometry::point_type<Geometry1>::type point1_type;
57 typedef overlay::turn_info
60 typename segment_ratio_type<point1_type, RobustPolicy>::type,
61 typename detail::get_turns::turn_operation_type
64 typename segment_ratio_type
66 point1_type, RobustPolicy
71 template <typename Turns>
72 static inline void apply(Turns & turns,
73 Geometry1 const& geometry1,
74 Geometry2 const& geometry2)
76 detail::get_turns::no_interrupt_policy interrupt_policy;
78 typename strategy::intersection::services::default_strategy
80 typename cs_tag<Geometry1>::type
81 >::type intersection_strategy;
83 apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
86 template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
87 static inline void apply(Turns & turns,
88 Geometry1 const& geometry1,
89 Geometry2 const& geometry2,
90 InterruptPolicy & interrupt_policy,
91 IntersectionStrategy const& intersection_strategy)
93 RobustPolicy robust_policy = geometry::get_rescale_policy
96 >(geometry1, geometry2);
98 apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy);
101 template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
102 static inline void apply(Turns & turns,
103 Geometry1 const& geometry1,
104 Geometry2 const& geometry2,
105 InterruptPolicy & interrupt_policy,
106 IntersectionStrategy const& intersection_strategy,
107 RobustPolicy const& robust_policy)
109 static const bool reverse1 = detail::overlay::do_reverse
111 geometry::point_order<Geometry1>::value
114 static const bool reverse2 = detail::overlay::do_reverse
116 geometry::point_order<Geometry2>::value
121 typename geometry::tag<Geometry1>::type,
122 typename geometry::tag<Geometry2>::type,
128 >::apply(0, geometry1, 1, geometry2,
129 intersection_strategy, robust_policy,
130 turns, interrupt_policy);
134 // TURNS SORTING AND SEARCHING
136 template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
139 template <typename Operation>
140 inline int operator()(Operation const& op) const
144 case detail::overlay::operation_none : return N;
145 case detail::overlay::operation_union : return U;
146 case detail::overlay::operation_intersection : return I;
147 case detail::overlay::operation_blocked : return B;
148 case detail::overlay::operation_continue : return C;
149 case detail::overlay::operation_opposite : return O;
155 template <std::size_t OpId, typename OpToInt>
156 struct less_op_xxx_linear
158 template <typename Turn>
159 inline bool operator()(Turn const& left, Turn const& right) const
161 static OpToInt op_to_int;
162 return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);
166 template <std::size_t OpId>
167 struct less_op_linear_linear
168 : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
171 template <std::size_t OpId>
172 struct less_op_linear_areal_single
174 template <typename Turn>
175 inline bool operator()(Turn const& left, Turn const& right) const
177 static const std::size_t other_op_id = (OpId + 1) % 2;
178 static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
179 static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
181 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
182 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
184 typedef typename Turn::turn_operation_type operation_type;
185 operation_type const& left_operation = left.operations[OpId];
186 operation_type const& right_operation = right.operations[OpId];
188 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
190 return op_to_int_xuic(left_operation)
191 < op_to_int_xuic(right_operation);
195 return op_to_int_xiuc(left_operation)
196 < op_to_int_xiuc(right_operation);
201 template <std::size_t OpId>
202 struct less_op_areal_linear
203 : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >
206 template <std::size_t OpId>
207 struct less_op_areal_areal
209 template <typename Turn>
210 inline bool operator()(Turn const& left, Turn const& right) const
212 static const std::size_t other_op_id = (OpId + 1) % 2;
213 static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;
214 static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;
216 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
217 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
219 typedef typename Turn::turn_operation_type operation_type;
220 operation_type const& left_operation = left.operations[OpId];
221 operation_type const& right_operation = right.operations[OpId];
223 if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
225 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
227 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
231 if ( left_other_seg_id.ring_index == -1 )
233 if ( left_operation.operation == overlay::operation_union )
235 else if ( left_operation.operation == overlay::operation_intersection )
238 else if ( right_other_seg_id.ring_index == -1 )
240 if ( right_operation.operation == overlay::operation_union )
242 else if ( right_operation.operation == overlay::operation_intersection )
246 return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
251 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
256 template <std::size_t OpId>
257 struct less_other_multi_index
259 static const std::size_t other_op_id = (OpId + 1) % 2;
261 template <typename Turn>
262 inline bool operator()(Turn const& left, Turn const& right) const
264 return left.operations[other_op_id].seg_id.multi_index
265 < right.operations[other_op_id].seg_id.multi_index;
269 // sort turns by G1 - source_index == 0 by:
270 // seg_id -> distance -> operation
271 template <std::size_t OpId = 0,
272 typename LessOp = less_op_xxx_linear< OpId, op_to_int<> > >
275 BOOST_STATIC_ASSERT(OpId < 2);
277 template <typename Turn>
278 static inline bool use_fraction(Turn const& left, Turn const& right)
280 static LessOp less_op;
283 geometry::math::equals(left.operations[OpId].fraction,
284 right.operations[OpId].fraction)
288 (left.operations[OpId].fraction < right.operations[OpId].fraction)
292 template <typename Turn>
293 inline bool operator()(Turn const& left, Turn const& right) const
295 segment_identifier const& sl = left.operations[OpId].seg_id;
296 segment_identifier const& sr = right.operations[OpId].seg_id;
298 return sl < sr || ( sl == sr && use_fraction(left, right) );
302 }}} // namespace detail::relate::turns
303 #endif // DOXYGEN_NO_DETAIL
305 }} // namespace boost::geometry
307 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP