]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
92f5a8d4 TL |
5 | // This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019. |
6 | // Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. | |
b32b8144 FG |
7 | |
8 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
7c673cae FG |
9 | |
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
7c673cae FG |
14 | #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP |
15 | #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP | |
16 | ||
92f5a8d4 TL |
17 | #include <boost/geometry/algorithms/detail/direction_code.hpp> |
18 | #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> | |
19 | #include <boost/geometry/algorithms/detail/recalculate.hpp> | |
20 | #include <boost/geometry/core/assert.hpp> | |
21 | #include <boost/geometry/geometries/segment.hpp> // referring_segment | |
22 | #include <boost/geometry/policies/relate/direction.hpp> | |
23 | #include <boost/geometry/policies/relate/intersection_points.hpp> | |
24 | #include <boost/geometry/policies/relate/tupled.hpp> | |
25 | #include <boost/geometry/policies/robustness/rescale_policy_tags.hpp> | |
26 | #include <boost/geometry/strategies/intersection_result.hpp> | |
7c673cae FG |
27 | |
28 | namespace boost { namespace geometry { | |
29 | ||
30 | #ifndef DOXYGEN_NO_DETAIL | |
31 | namespace detail { namespace overlay { | |
32 | ||
33 | enum turn_position { position_middle, position_front, position_back }; | |
34 | ||
35 | template <typename Point, typename SegmentRatio> | |
36 | struct turn_operation_linear | |
37 | : public turn_operation<Point, SegmentRatio> | |
38 | { | |
39 | turn_operation_linear() | |
40 | : position(position_middle) | |
41 | , is_collinear(false) | |
42 | {} | |
43 | ||
44 | turn_position position; | |
45 | bool is_collinear; // valid only for Linear geometry | |
46 | }; | |
47 | ||
92f5a8d4 TL |
48 | template |
49 | < | |
50 | typename TurnPointCSTag, | |
51 | typename UniqueSubRange1, | |
52 | typename UniqueSubRange2, | |
53 | typename SideStrategy | |
7c673cae FG |
54 | > |
55 | struct side_calculator | |
56 | { | |
92f5a8d4 TL |
57 | typedef typename UniqueSubRange1::point_type point1_type; |
58 | typedef typename UniqueSubRange2::point_type point2_type; | |
59 | ||
60 | inline side_calculator(UniqueSubRange1 const& range_p, | |
61 | UniqueSubRange2 const& range_q, | |
b32b8144 | 62 | SideStrategy const& side_strategy) |
92f5a8d4 TL |
63 | : m_side_strategy(side_strategy) |
64 | , m_range_p(range_p) | |
65 | , m_range_q(range_q) | |
7c673cae FG |
66 | {} |
67 | ||
92f5a8d4 TL |
68 | inline int pk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_pk()); } |
69 | inline int pk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pk()); } | |
70 | inline int qk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qk()); } | |
71 | inline int qk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_qk()); } | |
72 | ||
73 | inline int pk_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pk()); } | |
74 | inline int qk_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qk()); } | |
75 | ||
76 | // Necessary when rescaling turns off: | |
77 | inline int qj_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qj()); } | |
78 | inline int qj_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qj()); } | |
79 | inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); } | |
80 | inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); } | |
7c673cae | 81 | |
92f5a8d4 TL |
82 | inline point1_type const& get_pi() const { return m_range_p.at(0); } |
83 | inline point1_type const& get_pj() const { return m_range_p.at(1); } | |
84 | inline point1_type const& get_pk() const { return m_range_p.at(2); } | |
7c673cae | 85 | |
92f5a8d4 TL |
86 | inline point2_type const& get_qi() const { return m_range_q.at(0); } |
87 | inline point2_type const& get_qj() const { return m_range_q.at(1); } | |
88 | inline point2_type const& get_qk() const { return m_range_q.at(2); } | |
b32b8144 | 89 | |
92f5a8d4 TL |
90 | // Used side-strategy, owned by the calculator, |
91 | // created from .get_side_strategy() | |
b32b8144 | 92 | SideStrategy m_side_strategy; |
92f5a8d4 TL |
93 | |
94 | // Used ranges - owned by get_turns or (for robust points) by intersection_info_base | |
95 | UniqueSubRange1 const& m_range_p; | |
96 | UniqueSubRange2 const& m_range_q; | |
7c673cae FG |
97 | }; |
98 | ||
92f5a8d4 TL |
99 | template<typename Point, typename UniqueSubRange, typename RobustPolicy> |
100 | struct robust_subrange_adapter | |
101 | { | |
102 | typedef Point point_type; | |
103 | ||
104 | robust_subrange_adapter(UniqueSubRange const& unique_sub_range, | |
105 | Point const& robust_point_i, Point const& robust_point_j, | |
106 | RobustPolicy const& robust_policy) | |
107 | ||
108 | : m_unique_sub_range(unique_sub_range) | |
109 | , m_robust_policy(robust_policy) | |
110 | , m_robust_point_i(robust_point_i) | |
111 | , m_robust_point_j(robust_point_j) | |
112 | , m_k_retrieved(false) | |
113 | {} | |
114 | ||
115 | std::size_t size() const { return m_unique_sub_range.size(); } | |
116 | ||
117 | //! Get precalculated point | |
118 | Point const& at(std::size_t index) const | |
119 | { | |
120 | BOOST_GEOMETRY_ASSERT(index < size()); | |
121 | switch (index) | |
122 | { | |
123 | case 0 : return m_robust_point_i; | |
124 | case 1 : return m_robust_point_j; | |
125 | case 2 : return get_point_k(); | |
126 | default : return m_robust_point_i; | |
127 | } | |
128 | } | |
129 | ||
130 | private : | |
131 | Point const& get_point_k() const | |
132 | { | |
133 | if (! m_k_retrieved) | |
134 | { | |
135 | geometry::recalculate(m_robust_point_k, m_unique_sub_range.at(2), m_robust_policy); | |
136 | m_k_retrieved = true; | |
137 | } | |
138 | return m_robust_point_k; | |
139 | } | |
140 | ||
141 | UniqueSubRange const& m_unique_sub_range; | |
142 | RobustPolicy const& m_robust_policy; | |
143 | ||
144 | Point const& m_robust_point_i; | |
145 | Point const& m_robust_point_j; | |
146 | mutable Point m_robust_point_k; | |
147 | ||
148 | mutable bool m_k_retrieved; | |
149 | }; | |
150 | ||
151 | template | |
152 | < | |
153 | typename UniqueSubRange1, typename UniqueSubRange2, | |
154 | typename RobustPolicy | |
155 | > | |
156 | struct robust_point_calculator | |
7c673cae FG |
157 | { |
158 | typedef typename geometry::robust_point_type | |
159 | < | |
92f5a8d4 | 160 | typename UniqueSubRange1::point_type, RobustPolicy |
7c673cae | 161 | >::type robust_point1_type; |
92f5a8d4 TL |
162 | typedef typename geometry::robust_point_type |
163 | < | |
164 | typename UniqueSubRange2::point_type, RobustPolicy | |
165 | >::type robust_point2_type; | |
166 | ||
167 | inline robust_point_calculator(UniqueSubRange1 const& range_p, | |
168 | UniqueSubRange2 const& range_q, | |
169 | RobustPolicy const& robust_policy) | |
170 | : m_robust_policy(robust_policy) | |
171 | , m_range_p(range_p) | |
172 | , m_range_q(range_q) | |
173 | , m_pk_retrieved(false) | |
174 | , m_qk_retrieved(false) | |
175 | { | |
176 | // Calculate pi,pj and qi,qj which are almost always necessary | |
177 | // But don't calculate pk/qk yet, which is retrieved (taking | |
178 | // more time) and not always necessary. | |
179 | geometry::recalculate(m_rpi, range_p.at(0), robust_policy); | |
180 | geometry::recalculate(m_rpj, range_p.at(1), robust_policy); | |
181 | geometry::recalculate(m_rqi, range_q.at(0), robust_policy); | |
182 | geometry::recalculate(m_rqj, range_q.at(1), robust_policy); | |
183 | } | |
7c673cae | 184 | |
92f5a8d4 | 185 | inline robust_point1_type const& get_rpk() const |
7c673cae | 186 | { |
92f5a8d4 TL |
187 | if (! m_pk_retrieved) |
188 | { | |
189 | geometry::recalculate(m_rpk, m_range_p.at(2), m_robust_policy); | |
190 | m_pk_retrieved = true; | |
191 | } | |
192 | return m_rpk; | |
7c673cae | 193 | } |
92f5a8d4 TL |
194 | inline robust_point2_type const& get_rqk() const |
195 | { | |
196 | if (! m_qk_retrieved) | |
197 | { | |
198 | geometry::recalculate(m_rqk, m_range_q.at(2), m_robust_policy); | |
199 | m_qk_retrieved = true; | |
200 | } | |
201 | return m_rqk; | |
202 | } | |
203 | ||
204 | robust_point1_type m_rpi, m_rpj; | |
205 | robust_point2_type m_rqi, m_rqj; | |
7c673cae | 206 | |
92f5a8d4 TL |
207 | private : |
208 | RobustPolicy const& m_robust_policy; | |
209 | UniqueSubRange1 const& m_range_p; | |
210 | UniqueSubRange2 const& m_range_q; | |
211 | ||
212 | // On retrieval | |
213 | mutable robust_point1_type m_rpk; | |
214 | mutable robust_point2_type m_rqk; | |
215 | mutable bool m_pk_retrieved; | |
216 | mutable bool m_qk_retrieved; | |
7c673cae FG |
217 | }; |
218 | ||
92f5a8d4 TL |
219 | // Default version (empty - specialized below) |
220 | template | |
221 | < | |
222 | typename UniqueSubRange1, typename UniqueSubRange2, | |
223 | typename TurnPoint, typename UmbrellaStrategy, | |
224 | typename RobustPolicy, | |
225 | typename Tag = typename rescale_policy_type<RobustPolicy>::type | |
226 | > | |
227 | class intersection_info_base {}; | |
228 | ||
229 | // Version with rescaling, having robust points | |
230 | template | |
231 | < | |
232 | typename UniqueSubRange1, typename UniqueSubRange2, | |
233 | typename TurnPoint, typename UmbrellaStrategy, | |
234 | typename RobustPolicy | |
235 | > | |
236 | class intersection_info_base<UniqueSubRange1, UniqueSubRange2, | |
237 | TurnPoint, UmbrellaStrategy, RobustPolicy, rescale_policy_tag> | |
7c673cae | 238 | { |
92f5a8d4 TL |
239 | typedef robust_point_calculator |
240 | < | |
241 | UniqueSubRange1, UniqueSubRange2, | |
242 | RobustPolicy | |
243 | > | |
244 | robust_calc_type; | |
7c673cae FG |
245 | |
246 | public: | |
92f5a8d4 TL |
247 | typedef segment_intersection_points |
248 | < | |
249 | TurnPoint, | |
250 | geometry::segment_ratio<boost::long_long_type> | |
251 | > intersection_point_type; | |
252 | typedef policies::relate::segments_tupled | |
253 | < | |
254 | policies::relate::segments_intersection_points | |
255 | < | |
256 | intersection_point_type | |
257 | >, | |
258 | policies::relate::segments_direction | |
259 | > intersection_policy_type; | |
260 | ||
261 | typedef typename intersection_policy_type::return_type result_type; | |
262 | ||
263 | typedef typename robust_calc_type::robust_point1_type robust_point1_type; | |
264 | typedef typename robust_calc_type::robust_point2_type robust_point2_type; | |
7c673cae | 265 | |
92f5a8d4 TL |
266 | typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1; |
267 | typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2; | |
7c673cae FG |
268 | |
269 | typedef typename cs_tag<TurnPoint>::type cs_tag; | |
270 | ||
92f5a8d4 TL |
271 | typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; |
272 | typedef side_calculator<cs_tag, robust_subrange1, robust_subrange2, | |
273 | side_strategy_type> side_calculator_type; | |
274 | ||
275 | typedef side_calculator | |
276 | < | |
277 | cs_tag, robust_subrange2, robust_subrange1, | |
278 | side_strategy_type | |
279 | > robust_swapped_side_calculator_type; | |
280 | ||
281 | intersection_info_base(UniqueSubRange1 const& range_p, | |
282 | UniqueSubRange2 const& range_q, | |
283 | UmbrellaStrategy const& umbrella_strategy, | |
7c673cae | 284 | RobustPolicy const& robust_policy) |
92f5a8d4 TL |
285 | : m_range_p(range_p) |
286 | , m_range_q(range_q) | |
287 | , m_robust_calc(range_p, range_q, robust_policy) | |
288 | , m_robust_range_p(range_p, m_robust_calc.m_rpi, m_robust_calc.m_rpj, robust_policy) | |
289 | , m_robust_range_q(range_q, m_robust_calc.m_rqi, m_robust_calc.m_rqj, robust_policy) | |
290 | , m_side_calc(m_robust_range_p, m_robust_range_q, | |
291 | umbrella_strategy.get_side_strategy()) | |
292 | , m_result(umbrella_strategy.apply(range_p, range_q, | |
293 | intersection_policy_type(), | |
294 | m_robust_range_p, m_robust_range_q)) | |
7c673cae FG |
295 | {} |
296 | ||
92f5a8d4 TL |
297 | inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); } |
298 | inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); } | |
7c673cae | 299 | |
92f5a8d4 TL |
300 | inline robust_point1_type const& rpi() const { return m_robust_calc.m_rpi; } |
301 | inline robust_point1_type const& rpj() const { return m_robust_calc.m_rpj; } | |
302 | inline robust_point1_type const& rpk() const { return m_robust_calc.get_rpk(); } | |
7c673cae | 303 | |
92f5a8d4 TL |
304 | inline robust_point2_type const& rqi() const { return m_robust_calc.m_rqi; } |
305 | inline robust_point2_type const& rqj() const { return m_robust_calc.m_rqj; } | |
306 | inline robust_point2_type const& rqk() const { return m_robust_calc.get_rqk(); } | |
7c673cae FG |
307 | |
308 | inline side_calculator_type const& sides() const { return m_side_calc; } | |
92f5a8d4 TL |
309 | |
310 | robust_swapped_side_calculator_type get_swapped_sides() const | |
311 | { | |
312 | robust_swapped_side_calculator_type result( | |
313 | m_robust_range_q, m_robust_range_p, | |
314 | m_side_calc.m_side_strategy); | |
315 | return result; | |
316 | } | |
317 | ||
318 | private : | |
319 | ||
320 | // Owned by get_turns | |
321 | UniqueSubRange1 const& m_range_p; | |
322 | UniqueSubRange2 const& m_range_q; | |
323 | ||
324 | // Owned by this class | |
325 | robust_calc_type m_robust_calc; | |
326 | robust_subrange1 m_robust_range_p; | |
327 | robust_subrange2 m_robust_range_q; | |
7c673cae FG |
328 | side_calculator_type m_side_calc; |
329 | ||
92f5a8d4 TL |
330 | protected : |
331 | result_type m_result; | |
7c673cae FG |
332 | }; |
333 | ||
92f5a8d4 TL |
334 | // Version without rescaling |
335 | template | |
336 | < | |
337 | typename UniqueSubRange1, typename UniqueSubRange2, | |
338 | typename TurnPoint, typename UmbrellaStrategy, | |
339 | typename RobustPolicy | |
340 | > | |
341 | class intersection_info_base<UniqueSubRange1, UniqueSubRange2, | |
342 | TurnPoint, UmbrellaStrategy, RobustPolicy, no_rescale_policy_tag> | |
7c673cae FG |
343 | { |
344 | public: | |
7c673cae | 345 | |
92f5a8d4 TL |
346 | typedef segment_intersection_points<TurnPoint> intersection_point_type; |
347 | typedef policies::relate::segments_tupled | |
348 | < | |
349 | policies::relate::segments_intersection_points | |
350 | < | |
351 | intersection_point_type | |
352 | >, | |
353 | policies::relate::segments_direction | |
354 | > intersection_policy_type; | |
7c673cae | 355 | |
92f5a8d4 | 356 | typedef typename intersection_policy_type::return_type result_type; |
7c673cae | 357 | |
92f5a8d4 TL |
358 | typedef typename UniqueSubRange1::point_type point1_type; |
359 | typedef typename UniqueSubRange2::point_type point2_type; | |
360 | ||
361 | typedef typename UmbrellaStrategy::cs_tag cs_tag; | |
362 | ||
363 | typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; | |
364 | typedef side_calculator<cs_tag, UniqueSubRange1, UniqueSubRange2, side_strategy_type> side_calculator_type; | |
365 | ||
366 | typedef side_calculator | |
367 | < | |
368 | cs_tag, UniqueSubRange2, UniqueSubRange1, | |
369 | side_strategy_type | |
370 | > swapped_side_calculator_type; | |
7c673cae | 371 | |
92f5a8d4 TL |
372 | intersection_info_base(UniqueSubRange1 const& range_p, |
373 | UniqueSubRange2 const& range_q, | |
374 | UmbrellaStrategy const& umbrella_strategy, | |
375 | no_rescale_policy const& ) | |
376 | : m_range_p(range_p) | |
377 | , m_range_q(range_q) | |
378 | , m_side_calc(range_p, range_q, | |
379 | umbrella_strategy.get_side_strategy()) | |
380 | , m_result(umbrella_strategy.apply(range_p, range_q, intersection_policy_type())) | |
7c673cae FG |
381 | {} |
382 | ||
92f5a8d4 TL |
383 | inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); } |
384 | inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); } | |
7c673cae | 385 | |
92f5a8d4 TL |
386 | inline point1_type const& rpi() const { return m_side_calc.get_pi(); } |
387 | inline point1_type const& rpj() const { return m_side_calc.get_pj(); } | |
388 | inline point1_type const& rpk() const { return m_side_calc.get_pk(); } | |
7c673cae | 389 | |
92f5a8d4 TL |
390 | inline point2_type const& rqi() const { return m_side_calc.get_qi(); } |
391 | inline point2_type const& rqj() const { return m_side_calc.get_qj(); } | |
392 | inline point2_type const& rqk() const { return m_side_calc.get_qk(); } | |
7c673cae FG |
393 | |
394 | inline side_calculator_type const& sides() const { return m_side_calc; } | |
92f5a8d4 TL |
395 | |
396 | swapped_side_calculator_type get_swapped_sides() const | |
397 | { | |
398 | swapped_side_calculator_type result( | |
399 | m_range_q, m_range_p, | |
400 | m_side_calc.m_side_strategy); | |
401 | return result; | |
402 | } | |
403 | ||
404 | private : | |
405 | // Owned by get_turns | |
406 | UniqueSubRange1 const& m_range_p; | |
407 | UniqueSubRange2 const& m_range_q; | |
408 | ||
409 | // Owned by this class | |
7c673cae | 410 | side_calculator_type m_side_calc; |
92f5a8d4 TL |
411 | |
412 | protected : | |
413 | result_type m_result; | |
7c673cae FG |
414 | }; |
415 | ||
416 | ||
417 | template | |
418 | < | |
92f5a8d4 | 419 | typename UniqueSubRange1, typename UniqueSubRange2, |
7c673cae | 420 | typename TurnPoint, |
92f5a8d4 | 421 | typename UmbrellaStrategy, |
7c673cae FG |
422 | typename RobustPolicy |
423 | > | |
424 | class intersection_info | |
92f5a8d4 TL |
425 | : public intersection_info_base<UniqueSubRange1, UniqueSubRange2, |
426 | TurnPoint, UmbrellaStrategy, RobustPolicy> | |
7c673cae | 427 | { |
92f5a8d4 TL |
428 | typedef intersection_info_base<UniqueSubRange1, UniqueSubRange2, |
429 | TurnPoint, UmbrellaStrategy, RobustPolicy> base; | |
b32b8144 FG |
430 | |
431 | public: | |
7c673cae | 432 | |
92f5a8d4 TL |
433 | typedef typename UniqueSubRange1::point_type point1_type; |
434 | typedef typename UniqueSubRange2::point_type point2_type; | |
b32b8144 | 435 | |
92f5a8d4 TL |
436 | typedef UmbrellaStrategy intersection_strategy_type; |
437 | typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; | |
438 | typedef typename UmbrellaStrategy::cs_tag cs_tag; | |
7c673cae | 439 | |
7c673cae | 440 | typedef typename base::side_calculator_type side_calculator_type; |
92f5a8d4 | 441 | typedef typename base::result_type result_type; |
7c673cae | 442 | |
7c673cae FG |
443 | typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info |
444 | typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info | |
445 | ||
92f5a8d4 TL |
446 | intersection_info(UniqueSubRange1 const& range_p, |
447 | UniqueSubRange2 const& range_q, | |
448 | UmbrellaStrategy const& umbrella_strategy, | |
7c673cae | 449 | RobustPolicy const& robust_policy) |
92f5a8d4 TL |
450 | : base(range_p, range_q, |
451 | umbrella_strategy, robust_policy) | |
452 | , m_intersection_strategy(umbrella_strategy) | |
7c673cae FG |
453 | , m_robust_policy(robust_policy) |
454 | {} | |
455 | ||
92f5a8d4 TL |
456 | inline result_type const& result() const { return base::m_result; } |
457 | inline i_info_type const& i_info() const { return base::m_result.template get<0>(); } | |
458 | inline d_info_type const& d_info() const { return base::m_result.template get<1>(); } | |
b32b8144 FG |
459 | |
460 | inline side_strategy_type get_side_strategy() const | |
461 | { | |
462 | return m_intersection_strategy.get_side_strategy(); | |
463 | } | |
464 | ||
7c673cae FG |
465 | // TODO: it's more like is_spike_ip_p |
466 | inline bool is_spike_p() const | |
467 | { | |
92f5a8d4 TL |
468 | if (base::p_is_last_segment()) |
469 | { | |
470 | return false; | |
471 | } | |
7c673cae FG |
472 | if (base::sides().pk_wrt_p1() == 0) |
473 | { | |
92f5a8d4 TL |
474 | // p: pi--------pj--------pk |
475 | // or: pi----pk==pj | |
476 | ||
7c673cae FG |
477 | if (! is_ip_j<0>()) |
478 | { | |
479 | return false; | |
480 | } | |
481 | ||
92f5a8d4 TL |
482 | // TODO: why is q used to determine spike property in p? |
483 | bool const has_qk = ! base::q_is_last_segment(); | |
484 | int const qk_p1 = has_qk ? base::sides().qk_wrt_p1() : 0; | |
485 | int const qk_p2 = has_qk ? base::sides().qk_wrt_p2() : 0; | |
486 | ||
7c673cae FG |
487 | if (qk_p1 == -qk_p2) |
488 | { | |
489 | if (qk_p1 == 0) | |
490 | { | |
92f5a8d4 TL |
491 | // qk is collinear with both p1 and p2, |
492 | // verify if pk goes backwards w.r.t. pi/pj | |
493 | return direction_code<cs_tag>(base::rpi(), base::rpj(), base::rpk()) == -1; | |
7c673cae | 494 | } |
92f5a8d4 TL |
495 | |
496 | // qk is at opposite side of p1/p2, therefore | |
497 | // p1/p2 (collinear) are opposite and form a spike | |
7c673cae FG |
498 | return true; |
499 | } | |
500 | } | |
501 | ||
502 | return false; | |
503 | } | |
504 | ||
7c673cae FG |
505 | inline bool is_spike_q() const |
506 | { | |
92f5a8d4 TL |
507 | if (base::q_is_last_segment()) |
508 | { | |
509 | return false; | |
510 | } | |
511 | ||
512 | // See comments at is_spike_p | |
7c673cae FG |
513 | if (base::sides().qk_wrt_q1() == 0) |
514 | { | |
515 | if (! is_ip_j<1>()) | |
516 | { | |
517 | return false; | |
518 | } | |
519 | ||
92f5a8d4 TL |
520 | // TODO: why is p used to determine spike property in q? |
521 | bool const has_pk = ! base::p_is_last_segment(); | |
522 | int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0; | |
523 | int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0; | |
7c673cae FG |
524 | |
525 | if (pk_q1 == -pk_q2) | |
526 | { | |
527 | if (pk_q1 == 0) | |
528 | { | |
92f5a8d4 | 529 | return direction_code<cs_tag>(base::rqi(), base::rqj(), base::rqk()) == -1; |
7c673cae FG |
530 | } |
531 | ||
532 | return true; | |
533 | } | |
534 | } | |
535 | ||
536 | return false; | |
537 | } | |
538 | ||
539 | private: | |
7c673cae FG |
540 | template <std::size_t OpId> |
541 | bool is_ip_j() const | |
542 | { | |
543 | int arrival = d_info().arrival[OpId]; | |
544 | bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; | |
545 | ||
546 | if (same_dirs) | |
547 | { | |
548 | if (i_info().count == 2) | |
549 | { | |
550 | return arrival != -1; | |
551 | } | |
552 | else | |
553 | { | |
554 | return arrival == 0; | |
555 | } | |
556 | } | |
557 | else | |
558 | { | |
559 | return arrival == 1; | |
560 | } | |
561 | } | |
562 | ||
92f5a8d4 | 563 | UmbrellaStrategy const& m_intersection_strategy; |
7c673cae FG |
564 | RobustPolicy const& m_robust_policy; |
565 | }; | |
566 | ||
567 | }} // namespace detail::overlay | |
568 | #endif // DOXYGEN_NO_DETAIL | |
569 | ||
570 | }} // namespace boost::geometry | |
571 | ||
572 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP |