]>
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 | ||
5 | // This file was modified by Oracle on 2013, 2014, 2015. | |
6 | // Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. | |
7 | ||
8 | // Use, modification and distribution is subject to the Boost Software License, | |
9 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
10 | // http://www.boost.org/LICENSE_1_0.txt) | |
11 | ||
12 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
13 | ||
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 | ||
17 | #include <boost/geometry/policies/robustness/no_rescale_policy.hpp> | |
18 | ||
19 | namespace boost { namespace geometry { | |
20 | ||
21 | #ifndef DOXYGEN_NO_DETAIL | |
22 | namespace detail { namespace overlay { | |
23 | ||
24 | enum turn_position { position_middle, position_front, position_back }; | |
25 | ||
26 | template <typename Point, typename SegmentRatio> | |
27 | struct turn_operation_linear | |
28 | : public turn_operation<Point, SegmentRatio> | |
29 | { | |
30 | turn_operation_linear() | |
31 | : position(position_middle) | |
32 | , is_collinear(false) | |
33 | {} | |
34 | ||
35 | turn_position position; | |
36 | bool is_collinear; // valid only for Linear geometry | |
37 | }; | |
38 | ||
39 | template <typename TurnPointCSTag, typename PointP, typename PointQ, | |
40 | typename Pi = PointP, typename Pj = PointP, typename Pk = PointP, | |
41 | typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ | |
42 | > | |
43 | struct side_calculator | |
44 | { | |
45 | // This strategy should be the same as side strategy defined in | |
46 | // intersection_strategies<> which is used in various places | |
47 | // of the library | |
48 | typedef typename strategy::side::services::default_strategy | |
49 | < | |
50 | TurnPointCSTag | |
51 | >::type side; | |
52 | ||
53 | inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, | |
54 | Qi const& qi, Qj const& qj, Qk const& qk) | |
55 | : m_pi(pi), m_pj(pj), m_pk(pk) | |
56 | , m_qi(qi), m_qj(qj), m_qk(qk) | |
57 | {} | |
58 | ||
59 | inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); } | |
60 | inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); } | |
61 | inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); } | |
62 | inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); } | |
63 | ||
64 | inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); } | |
65 | inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); } | |
66 | ||
67 | Pi const& m_pi; | |
68 | Pj const& m_pj; | |
69 | Pk const& m_pk; | |
70 | Qi const& m_qi; | |
71 | Qj const& m_qj; | |
72 | Qk const& m_qk; | |
73 | }; | |
74 | ||
75 | template <typename Point1, typename Point2, typename RobustPolicy> | |
76 | struct robust_points | |
77 | { | |
78 | typedef typename geometry::robust_point_type | |
79 | < | |
80 | Point1, RobustPolicy | |
81 | >::type robust_point1_type; | |
82 | ||
83 | // TODO: define robust_point2_type using Point2? | |
84 | typedef robust_point1_type robust_point2_type; | |
85 | ||
86 | inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk, | |
87 | Point2 const& qi, Point2 const& qj, Point2 const& qk, | |
88 | RobustPolicy const& robust_policy) | |
89 | { | |
90 | geometry::recalculate(m_rpi, pi, robust_policy); | |
91 | geometry::recalculate(m_rpj, pj, robust_policy); | |
92 | geometry::recalculate(m_rpk, pk, robust_policy); | |
93 | geometry::recalculate(m_rqi, qi, robust_policy); | |
94 | geometry::recalculate(m_rqj, qj, robust_policy); | |
95 | geometry::recalculate(m_rqk, qk, robust_policy); | |
96 | } | |
97 | ||
98 | robust_point1_type m_rpi, m_rpj, m_rpk; | |
99 | robust_point2_type m_rqi, m_rqj, m_rqk; | |
100 | }; | |
101 | ||
102 | template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy> | |
103 | class intersection_info_base | |
104 | : private robust_points<Point1, Point2, RobustPolicy> | |
105 | { | |
106 | typedef robust_points<Point1, Point2, RobustPolicy> base; | |
107 | ||
108 | public: | |
109 | typedef Point1 point1_type; | |
110 | typedef Point2 point2_type; | |
111 | ||
112 | typedef typename base::robust_point1_type robust_point1_type; | |
113 | typedef typename base::robust_point2_type robust_point2_type; | |
114 | ||
115 | typedef typename cs_tag<TurnPoint>::type cs_tag; | |
116 | ||
117 | typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type> side_calculator_type; | |
118 | ||
119 | intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, | |
120 | Point2 const& qi, Point2 const& qj, Point2 const& qk, | |
121 | RobustPolicy const& robust_policy) | |
122 | : base(pi, pj, pk, qi, qj, qk, robust_policy) | |
123 | , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk, | |
124 | base::m_rqi, base::m_rqj, base::m_rqk) | |
125 | , m_pi(pi), m_pj(pj), m_pk(pk) | |
126 | , m_qi(qi), m_qj(qj), m_qk(qk) | |
127 | {} | |
128 | ||
129 | inline Point1 const& pi() const { return m_pi; } | |
130 | inline Point1 const& pj() const { return m_pj; } | |
131 | inline Point1 const& pk() const { return m_pk; } | |
132 | ||
133 | inline Point2 const& qi() const { return m_qi; } | |
134 | inline Point2 const& qj() const { return m_qj; } | |
135 | inline Point2 const& qk() const { return m_qk; } | |
136 | ||
137 | inline robust_point1_type const& rpi() const { return base::m_rpi; } | |
138 | inline robust_point1_type const& rpj() const { return base::m_rpj; } | |
139 | inline robust_point1_type const& rpk() const { return base::m_rpk; } | |
140 | ||
141 | inline robust_point2_type const& rqi() const { return base::m_rqi; } | |
142 | inline robust_point2_type const& rqj() const { return base::m_rqj; } | |
143 | inline robust_point2_type const& rqk() const { return base::m_rqk; } | |
144 | ||
145 | inline side_calculator_type const& sides() const { return m_side_calc; } | |
146 | ||
147 | private: | |
148 | side_calculator_type m_side_calc; | |
149 | ||
150 | point1_type const& m_pi; | |
151 | point1_type const& m_pj; | |
152 | point1_type const& m_pk; | |
153 | point2_type const& m_qi; | |
154 | point2_type const& m_qj; | |
155 | point2_type const& m_qk; | |
156 | }; | |
157 | ||
158 | template <typename Point1, typename Point2, typename TurnPoint> | |
159 | class intersection_info_base<Point1, Point2, TurnPoint, detail::no_rescale_policy> | |
160 | { | |
161 | public: | |
162 | typedef Point1 point1_type; | |
163 | typedef Point2 point2_type; | |
164 | ||
165 | typedef Point1 robust_point1_type; | |
166 | typedef Point2 robust_point2_type; | |
167 | ||
168 | typedef typename cs_tag<TurnPoint>::type cs_tag; | |
169 | ||
170 | typedef side_calculator<cs_tag, Point1, Point2> side_calculator_type; | |
171 | ||
172 | intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, | |
173 | Point2 const& qi, Point2 const& qj, Point2 const& qk, | |
174 | no_rescale_policy const& /*robust_policy*/) | |
175 | : m_side_calc(pi, pj, pk, qi, qj, qk) | |
176 | {} | |
177 | ||
178 | inline Point1 const& pi() const { return m_side_calc.m_pi; } | |
179 | inline Point1 const& pj() const { return m_side_calc.m_pj; } | |
180 | inline Point1 const& pk() const { return m_side_calc.m_pk; } | |
181 | ||
182 | inline Point2 const& qi() const { return m_side_calc.m_qi; } | |
183 | inline Point2 const& qj() const { return m_side_calc.m_qj; } | |
184 | inline Point2 const& qk() const { return m_side_calc.m_qk; } | |
185 | ||
186 | inline Point1 const& rpi() const { return pi(); } | |
187 | inline Point1 const& rpj() const { return pj(); } | |
188 | inline Point1 const& rpk() const { return pk(); } | |
189 | ||
190 | inline Point2 const& rqi() const { return qi(); } | |
191 | inline Point2 const& rqj() const { return qj(); } | |
192 | inline Point2 const& rqk() const { return qk(); } | |
193 | ||
194 | inline side_calculator_type const& sides() const { return m_side_calc; } | |
195 | ||
196 | private: | |
197 | side_calculator_type m_side_calc; | |
198 | }; | |
199 | ||
200 | ||
201 | template | |
202 | < | |
203 | typename Point1, | |
204 | typename Point2, | |
205 | typename TurnPoint, | |
206 | typename RobustPolicy | |
207 | > | |
208 | class intersection_info | |
209 | : public intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> | |
210 | { | |
211 | typedef intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> base; | |
212 | ||
213 | typedef typename intersection_strategies | |
214 | < | |
215 | typename base::cs_tag, | |
216 | Point1, | |
217 | Point2, | |
218 | TurnPoint, | |
219 | RobustPolicy | |
220 | >::segment_intersection_strategy_type strategy; | |
221 | ||
222 | public: | |
223 | typedef model::referring_segment<Point1 const> segment_type1; | |
224 | typedef model::referring_segment<Point2 const> segment_type2; | |
225 | typedef typename base::side_calculator_type side_calculator_type; | |
226 | ||
227 | typedef typename strategy::return_type result_type; | |
228 | typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info | |
229 | typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info | |
230 | ||
231 | intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, | |
232 | Point2 const& qi, Point2 const& qj, Point2 const& qk, | |
233 | RobustPolicy const& robust_policy) | |
234 | : base(pi, pj, pk, qi, qj, qk, robust_policy) | |
235 | , m_result(strategy::apply(segment_type1(pi, pj), | |
236 | segment_type2(qi, qj), | |
237 | robust_policy, | |
238 | base::rpi(), base::rpj(), | |
239 | base::rqi(), base::rqj())) | |
240 | , m_robust_policy(robust_policy) | |
241 | {} | |
242 | ||
243 | inline result_type const& result() const { return m_result; } | |
244 | inline i_info_type const& i_info() const { return m_result.template get<0>(); } | |
245 | inline d_info_type const& d_info() const { return m_result.template get<1>(); } | |
246 | ||
247 | // TODO: it's more like is_spike_ip_p | |
248 | inline bool is_spike_p() const | |
249 | { | |
250 | if (base::sides().pk_wrt_p1() == 0) | |
251 | { | |
252 | if (! is_ip_j<0>()) | |
253 | { | |
254 | return false; | |
255 | } | |
256 | ||
257 | int const qk_p1 = base::sides().qk_wrt_p1(); | |
258 | int const qk_p2 = base::sides().qk_wrt_p2(); | |
259 | ||
260 | if (qk_p1 == -qk_p2) | |
261 | { | |
262 | if (qk_p1 == 0) | |
263 | { | |
264 | return is_spike_of_collinear(base::pi(), base::pj(), | |
265 | base::pk()); | |
266 | } | |
267 | ||
268 | return true; | |
269 | } | |
270 | } | |
271 | ||
272 | return false; | |
273 | } | |
274 | ||
275 | // TODO: it's more like is_spike_ip_q | |
276 | inline bool is_spike_q() const | |
277 | { | |
278 | if (base::sides().qk_wrt_q1() == 0) | |
279 | { | |
280 | if (! is_ip_j<1>()) | |
281 | { | |
282 | return false; | |
283 | } | |
284 | ||
285 | int const pk_q1 = base::sides().pk_wrt_q1(); | |
286 | int const pk_q2 = base::sides().pk_wrt_q2(); | |
287 | ||
288 | if (pk_q1 == -pk_q2) | |
289 | { | |
290 | if (pk_q1 == 0) | |
291 | { | |
292 | return is_spike_of_collinear(base::qi(), base::qj(), | |
293 | base::qk()); | |
294 | } | |
295 | ||
296 | return true; | |
297 | } | |
298 | } | |
299 | ||
300 | return false; | |
301 | } | |
302 | ||
303 | private: | |
304 | template <typename Point> | |
305 | inline bool is_spike_of_collinear(Point const& i, Point const& j, | |
306 | Point const& k) const | |
307 | { | |
308 | typedef model::referring_segment<Point const> seg; | |
309 | ||
310 | typedef intersection_strategies | |
311 | < | |
312 | typename base::cs_tag, Point, Point, Point, RobustPolicy | |
313 | > si; | |
314 | ||
315 | typedef typename si::segment_intersection_strategy_type strategy; | |
316 | ||
317 | typename strategy::return_type result | |
318 | = strategy::apply(seg(i, j), seg(j, k), m_robust_policy); | |
319 | ||
320 | return result.template get<0>().count == 2; | |
321 | } | |
322 | ||
323 | template <std::size_t OpId> | |
324 | bool is_ip_j() const | |
325 | { | |
326 | int arrival = d_info().arrival[OpId]; | |
327 | bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; | |
328 | ||
329 | if (same_dirs) | |
330 | { | |
331 | if (i_info().count == 2) | |
332 | { | |
333 | return arrival != -1; | |
334 | } | |
335 | else | |
336 | { | |
337 | return arrival == 0; | |
338 | } | |
339 | } | |
340 | else | |
341 | { | |
342 | return arrival == 1; | |
343 | } | |
344 | } | |
345 | ||
346 | result_type m_result; | |
347 | RobustPolicy const& m_robust_policy; | |
348 | }; | |
349 | ||
350 | }} // namespace detail::overlay | |
351 | #endif // DOXYGEN_NO_DETAIL | |
352 | ||
353 | }} // namespace boost::geometry | |
354 | ||
355 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP |