Chris@102
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@102
|
2
|
Chris@102
|
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@102
|
4
|
Chris@102
|
5 // This file was modified by Oracle on 2013, 2014, 2015.
|
Chris@102
|
6 // Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
|
Chris@102
|
7
|
Chris@102
|
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
Chris@102
|
9 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@102
|
10
|
Chris@102
|
11 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@102
|
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
13 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
14
|
Chris@102
|
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
|
Chris@102
|
16 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
|
Chris@102
|
17
|
Chris@102
|
18 #include <boost/geometry/strategies/distance.hpp>
|
Chris@102
|
19 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
Chris@102
|
20 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
Chris@102
|
21 #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
Chris@102
|
22
|
Chris@102
|
23 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
Chris@102
|
24 #include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
Chris@102
|
25
|
Chris@102
|
26 #include <boost/type_traits/is_base_of.hpp>
|
Chris@102
|
27
|
Chris@102
|
28
|
Chris@102
|
29 namespace boost { namespace geometry {
|
Chris@102
|
30
|
Chris@102
|
31 #ifndef DOXYGEN_NO_DETAIL
|
Chris@102
|
32 namespace detail { namespace relate { namespace turns {
|
Chris@102
|
33
|
Chris@102
|
34 template <bool IncludeDegenerate = false>
|
Chris@102
|
35 struct assign_policy
|
Chris@102
|
36 : overlay::assign_null_policy
|
Chris@102
|
37 {
|
Chris@102
|
38 static bool const include_degenerate = IncludeDegenerate;
|
Chris@102
|
39 };
|
Chris@102
|
40
|
Chris@102
|
41 // GET_TURNS
|
Chris@102
|
42
|
Chris@102
|
43 template
|
Chris@102
|
44 <
|
Chris@102
|
45 typename Geometry1,
|
Chris@102
|
46 typename Geometry2,
|
Chris@102
|
47 typename GetTurnPolicy = detail::get_turns::get_turn_info_type
|
Chris@102
|
48 <
|
Chris@102
|
49 Geometry1, Geometry2, assign_policy<>
|
Chris@102
|
50 >,
|
Chris@102
|
51 typename RobustPolicy = detail::no_rescale_policy
|
Chris@102
|
52 >
|
Chris@102
|
53 struct get_turns
|
Chris@102
|
54 {
|
Chris@102
|
55 typedef typename geometry::point_type<Geometry1>::type point1_type;
|
Chris@102
|
56
|
Chris@102
|
57 typedef overlay::turn_info
|
Chris@102
|
58 <
|
Chris@102
|
59 point1_type,
|
Chris@102
|
60 typename segment_ratio_type<point1_type, RobustPolicy>::type,
|
Chris@102
|
61 typename detail::get_turns::turn_operation_type
|
Chris@102
|
62 <
|
Chris@102
|
63 Geometry1, Geometry2,
|
Chris@102
|
64 typename segment_ratio_type
|
Chris@102
|
65 <
|
Chris@102
|
66 point1_type, RobustPolicy
|
Chris@102
|
67 >::type
|
Chris@102
|
68 >::type
|
Chris@102
|
69 > turn_info;
|
Chris@102
|
70
|
Chris@102
|
71 template <typename Turns>
|
Chris@102
|
72 static inline void apply(Turns & turns,
|
Chris@102
|
73 Geometry1 const& geometry1,
|
Chris@102
|
74 Geometry2 const& geometry2)
|
Chris@102
|
75 {
|
Chris@102
|
76 detail::get_turns::no_interrupt_policy interrupt_policy;
|
Chris@102
|
77
|
Chris@102
|
78 apply(turns, geometry1, geometry2, interrupt_policy);
|
Chris@102
|
79 }
|
Chris@102
|
80
|
Chris@102
|
81 template <typename Turns, typename InterruptPolicy>
|
Chris@102
|
82 static inline void apply(Turns & turns,
|
Chris@102
|
83 Geometry1 const& geometry1,
|
Chris@102
|
84 Geometry2 const& geometry2,
|
Chris@102
|
85 InterruptPolicy & interrupt_policy)
|
Chris@102
|
86 {
|
Chris@102
|
87 static const bool reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value;
|
Chris@102
|
88 static const bool reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value;
|
Chris@102
|
89
|
Chris@102
|
90 RobustPolicy robust_policy = geometry::get_rescale_policy
|
Chris@102
|
91 <
|
Chris@102
|
92 RobustPolicy
|
Chris@102
|
93 >(geometry1, geometry2);
|
Chris@102
|
94
|
Chris@102
|
95
|
Chris@102
|
96 dispatch::get_turns
|
Chris@102
|
97 <
|
Chris@102
|
98 typename geometry::tag<Geometry1>::type,
|
Chris@102
|
99 typename geometry::tag<Geometry2>::type,
|
Chris@102
|
100 Geometry1,
|
Chris@102
|
101 Geometry2,
|
Chris@102
|
102 reverse1,
|
Chris@102
|
103 reverse2,
|
Chris@102
|
104 GetTurnPolicy
|
Chris@102
|
105 >::apply(0, geometry1, 1, geometry2,
|
Chris@102
|
106 robust_policy, turns, interrupt_policy);
|
Chris@102
|
107 }
|
Chris@102
|
108 };
|
Chris@102
|
109
|
Chris@102
|
110 // TURNS SORTING AND SEARCHING
|
Chris@102
|
111
|
Chris@102
|
112 template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
|
Chris@102
|
113 struct op_to_int
|
Chris@102
|
114 {
|
Chris@102
|
115 template <typename SegmentRatio>
|
Chris@102
|
116 inline int operator()(detail::overlay::turn_operation<SegmentRatio> const& op) const
|
Chris@102
|
117 {
|
Chris@102
|
118 switch(op.operation)
|
Chris@102
|
119 {
|
Chris@102
|
120 case detail::overlay::operation_none : return N;
|
Chris@102
|
121 case detail::overlay::operation_union : return U;
|
Chris@102
|
122 case detail::overlay::operation_intersection : return I;
|
Chris@102
|
123 case detail::overlay::operation_blocked : return B;
|
Chris@102
|
124 case detail::overlay::operation_continue : return C;
|
Chris@102
|
125 case detail::overlay::operation_opposite : return O;
|
Chris@102
|
126 }
|
Chris@102
|
127 return -1;
|
Chris@102
|
128 }
|
Chris@102
|
129 };
|
Chris@102
|
130
|
Chris@102
|
131 template <std::size_t OpId, typename OpToInt>
|
Chris@102
|
132 struct less_op_xxx_linear
|
Chris@102
|
133 {
|
Chris@102
|
134 template <typename Turn>
|
Chris@102
|
135 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@102
|
136 {
|
Chris@102
|
137 static OpToInt op_to_int;
|
Chris@102
|
138 return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);
|
Chris@102
|
139 }
|
Chris@102
|
140 };
|
Chris@102
|
141
|
Chris@102
|
142 template <std::size_t OpId>
|
Chris@102
|
143 struct less_op_linear_linear
|
Chris@102
|
144 : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
|
Chris@102
|
145 {};
|
Chris@102
|
146
|
Chris@102
|
147 template <std::size_t OpId>
|
Chris@102
|
148 struct less_op_linear_areal_single
|
Chris@102
|
149 {
|
Chris@102
|
150 template <typename Turn>
|
Chris@102
|
151 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@102
|
152 {
|
Chris@102
|
153 static const std::size_t other_op_id = (OpId + 1) % 2;
|
Chris@102
|
154 static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
|
Chris@102
|
155 static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
|
Chris@102
|
156
|
Chris@102
|
157 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
|
Chris@102
|
158 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
|
Chris@102
|
159
|
Chris@102
|
160 typedef typename Turn::turn_operation_type operation_type;
|
Chris@102
|
161 operation_type const& left_operation = left.operations[OpId];
|
Chris@102
|
162 operation_type const& right_operation = right.operations[OpId];
|
Chris@102
|
163
|
Chris@102
|
164 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
|
Chris@102
|
165 {
|
Chris@102
|
166 return op_to_int_xuic(left_operation)
|
Chris@102
|
167 < op_to_int_xuic(right_operation);
|
Chris@102
|
168 }
|
Chris@102
|
169 else
|
Chris@102
|
170 {
|
Chris@102
|
171 return op_to_int_xiuc(left_operation)
|
Chris@102
|
172 < op_to_int_xiuc(right_operation);
|
Chris@102
|
173 }
|
Chris@102
|
174 }
|
Chris@102
|
175 };
|
Chris@102
|
176
|
Chris@102
|
177 template <std::size_t OpId>
|
Chris@102
|
178 struct less_op_areal_linear
|
Chris@102
|
179 : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >
|
Chris@102
|
180 {};
|
Chris@102
|
181
|
Chris@102
|
182 template <std::size_t OpId>
|
Chris@102
|
183 struct less_op_areal_areal
|
Chris@102
|
184 {
|
Chris@102
|
185 template <typename Turn>
|
Chris@102
|
186 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@102
|
187 {
|
Chris@102
|
188 static const std::size_t other_op_id = (OpId + 1) % 2;
|
Chris@102
|
189 static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;
|
Chris@102
|
190 static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;
|
Chris@102
|
191
|
Chris@102
|
192 segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
|
Chris@102
|
193 segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
|
Chris@102
|
194
|
Chris@102
|
195 typedef typename Turn::turn_operation_type operation_type;
|
Chris@102
|
196 operation_type const& left_operation = left.operations[OpId];
|
Chris@102
|
197 operation_type const& right_operation = right.operations[OpId];
|
Chris@102
|
198
|
Chris@102
|
199 if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
|
Chris@102
|
200 {
|
Chris@102
|
201 if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
|
Chris@102
|
202 {
|
Chris@102
|
203 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
|
Chris@102
|
204 }
|
Chris@102
|
205 else
|
Chris@102
|
206 {
|
Chris@102
|
207 if ( left_other_seg_id.ring_index == -1 )
|
Chris@102
|
208 {
|
Chris@102
|
209 if ( left_operation.operation == overlay::operation_union )
|
Chris@102
|
210 return false;
|
Chris@102
|
211 else if ( left_operation.operation == overlay::operation_intersection )
|
Chris@102
|
212 return true;
|
Chris@102
|
213 }
|
Chris@102
|
214 else if ( right_other_seg_id.ring_index == -1 )
|
Chris@102
|
215 {
|
Chris@102
|
216 if ( right_operation.operation == overlay::operation_union )
|
Chris@102
|
217 return true;
|
Chris@102
|
218 else if ( right_operation.operation == overlay::operation_intersection )
|
Chris@102
|
219 return false;
|
Chris@102
|
220 }
|
Chris@102
|
221
|
Chris@102
|
222 return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
|
Chris@102
|
223 }
|
Chris@102
|
224 }
|
Chris@102
|
225 else
|
Chris@102
|
226 {
|
Chris@102
|
227 return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
|
Chris@102
|
228 }
|
Chris@102
|
229 }
|
Chris@102
|
230 };
|
Chris@102
|
231
|
Chris@102
|
232 template <std::size_t OpId>
|
Chris@102
|
233 struct less_other_multi_index
|
Chris@102
|
234 {
|
Chris@102
|
235 static const std::size_t other_op_id = (OpId + 1) % 2;
|
Chris@102
|
236
|
Chris@102
|
237 template <typename Turn>
|
Chris@102
|
238 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@102
|
239 {
|
Chris@102
|
240 return left.operations[other_op_id].seg_id.multi_index
|
Chris@102
|
241 < right.operations[other_op_id].seg_id.multi_index;
|
Chris@102
|
242 }
|
Chris@102
|
243 };
|
Chris@102
|
244
|
Chris@102
|
245 // sort turns by G1 - source_index == 0 by:
|
Chris@102
|
246 // seg_id -> distance -> operation
|
Chris@102
|
247 template <std::size_t OpId = 0,
|
Chris@102
|
248 typename LessOp = less_op_xxx_linear< OpId, op_to_int<> > >
|
Chris@102
|
249 struct less
|
Chris@102
|
250 {
|
Chris@102
|
251 BOOST_STATIC_ASSERT(OpId < 2);
|
Chris@102
|
252
|
Chris@102
|
253 template <typename Turn>
|
Chris@102
|
254 static inline bool use_fraction(Turn const& left, Turn const& right)
|
Chris@102
|
255 {
|
Chris@102
|
256 static LessOp less_op;
|
Chris@102
|
257
|
Chris@102
|
258 return left.operations[OpId].fraction < right.operations[OpId].fraction
|
Chris@102
|
259 || ( left.operations[OpId].fraction == right.operations[OpId].fraction
|
Chris@102
|
260 && less_op(left, right) );
|
Chris@102
|
261 }
|
Chris@102
|
262
|
Chris@102
|
263 template <typename Turn>
|
Chris@102
|
264 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@102
|
265 {
|
Chris@102
|
266 segment_identifier const& sl = left.operations[OpId].seg_id;
|
Chris@102
|
267 segment_identifier const& sr = right.operations[OpId].seg_id;
|
Chris@102
|
268
|
Chris@102
|
269 return sl < sr || ( sl == sr && use_fraction(left, right) );
|
Chris@102
|
270 }
|
Chris@102
|
271 };
|
Chris@102
|
272
|
Chris@102
|
273 }}} // namespace detail::relate::turns
|
Chris@102
|
274 #endif // DOXYGEN_NO_DETAIL
|
Chris@102
|
275
|
Chris@102
|
276 }} // namespace boost::geometry
|
Chris@102
|
277
|
Chris@102
|
278 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
|