1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 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
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)
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
17 #include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
19 namespace boost { namespace geometry {
21 #ifndef DOXYGEN_NO_DETAIL
22 namespace detail { namespace overlay {
24 enum turn_position { position_middle, position_front, position_back };
26 template <typename Point, typename SegmentRatio>
27 struct turn_operation_linear
28 : public turn_operation<Point, SegmentRatio>
30 turn_operation_linear()
31 : position(position_middle)
35 turn_position position;
36 bool is_collinear; // valid only for Linear geometry
39 template <typename TurnPointCSTag, typename PointP, typename PointQ,
40 typename SideStrategy,
41 typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
42 typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
44 struct side_calculator
46 inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
47 Qi const& qi, Qj const& qj, Qk const& qk,
48 SideStrategy const& side_strategy)
49 : m_pi(pi), m_pj(pj), m_pk(pk)
50 , m_qi(qi), m_qj(qj), m_qk(qk)
51 , m_side_strategy(side_strategy)
54 inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
55 inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); }
56 inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
57 inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); }
59 inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
60 inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); }
69 SideStrategy m_side_strategy;
72 template <typename Point1, typename Point2, typename RobustPolicy>
75 typedef typename geometry::robust_point_type
78 >::type robust_point1_type;
80 // TODO: define robust_point2_type using Point2?
81 typedef robust_point1_type robust_point2_type;
83 inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk,
84 Point2 const& qi, Point2 const& qj, Point2 const& qk,
85 RobustPolicy const& robust_policy)
87 geometry::recalculate(m_rpi, pi, robust_policy);
88 geometry::recalculate(m_rpj, pj, robust_policy);
89 geometry::recalculate(m_rpk, pk, robust_policy);
90 geometry::recalculate(m_rqi, qi, robust_policy);
91 geometry::recalculate(m_rqj, qj, robust_policy);
92 geometry::recalculate(m_rqk, qk, robust_policy);
95 robust_point1_type m_rpi, m_rpj, m_rpk;
96 robust_point2_type m_rqi, m_rqj, m_rqk;
99 template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
100 class intersection_info_base
101 : private robust_points<Point1, Point2, RobustPolicy>
103 typedef robust_points<Point1, Point2, RobustPolicy> base;
106 typedef Point1 point1_type;
107 typedef Point2 point2_type;
109 typedef typename base::robust_point1_type robust_point1_type;
110 typedef typename base::robust_point2_type robust_point2_type;
112 typedef typename cs_tag<TurnPoint>::type cs_tag;
114 typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
115 typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type;
117 intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
118 Point2 const& qi, Point2 const& qj, Point2 const& qk,
119 IntersectionStrategy const& intersection_strategy,
120 RobustPolicy const& robust_policy)
121 : base(pi, pj, pk, qi, qj, qk, robust_policy)
122 , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk,
123 base::m_rqi, base::m_rqj, base::m_rqk,
124 intersection_strategy.get_side_strategy())
125 , m_pi(pi), m_pj(pj), m_pk(pk)
126 , m_qi(qi), m_qj(qj), m_qk(qk)
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; }
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; }
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; }
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; }
145 inline side_calculator_type const& sides() const { return m_side_calc; }
148 side_calculator_type m_side_calc;
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;
158 template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy>
159 class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
162 typedef Point1 point1_type;
163 typedef Point2 point2_type;
165 typedef Point1 robust_point1_type;
166 typedef Point2 robust_point2_type;
168 typedef typename cs_tag<TurnPoint>::type cs_tag;
170 typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
171 typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type;
173 intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
174 Point2 const& qi, Point2 const& qj, Point2 const& qk,
175 IntersectionStrategy const& intersection_strategy,
176 no_rescale_policy const& /*robust_policy*/)
177 : m_side_calc(pi, pj, pk, qi, qj, qk,
178 intersection_strategy.get_side_strategy())
181 inline Point1 const& pi() const { return m_side_calc.m_pi; }
182 inline Point1 const& pj() const { return m_side_calc.m_pj; }
183 inline Point1 const& pk() const { return m_side_calc.m_pk; }
185 inline Point2 const& qi() const { return m_side_calc.m_qi; }
186 inline Point2 const& qj() const { return m_side_calc.m_qj; }
187 inline Point2 const& qk() const { return m_side_calc.m_qk; }
189 inline Point1 const& rpi() const { return pi(); }
190 inline Point1 const& rpj() const { return pj(); }
191 inline Point1 const& rpk() const { return pk(); }
193 inline Point2 const& rqi() const { return qi(); }
194 inline Point2 const& rqj() const { return qj(); }
195 inline Point2 const& rqk() const { return qk(); }
197 inline side_calculator_type const& sides() const { return m_side_calc; }
200 side_calculator_type m_side_calc;
209 typename IntersectionStrategy,
210 typename RobustPolicy
212 class intersection_info
213 : public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy>
215 typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base;
218 typedef segment_intersection_points
221 typename geometry::segment_ratio_type
223 TurnPoint, RobustPolicy
225 > intersection_point_type;
227 // NOTE: formerly defined in intersection_strategies
228 typedef policies::relate::segments_tupled
230 policies::relate::segments_intersection_points
232 intersection_point_type
234 policies::relate::segments_direction
235 > intersection_policy_type;
237 typedef IntersectionStrategy intersection_strategy_type;
238 typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
240 typedef model::referring_segment<Point1 const> segment_type1;
241 typedef model::referring_segment<Point2 const> segment_type2;
242 typedef typename base::side_calculator_type side_calculator_type;
244 typedef typename intersection_policy_type::return_type result_type;
245 typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
246 typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
248 intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
249 Point2 const& qi, Point2 const& qj, Point2 const& qk,
250 IntersectionStrategy const& intersection_strategy,
251 RobustPolicy const& robust_policy)
252 : base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy)
253 , m_result(intersection_strategy.apply(
254 segment_type1(pi, pj),
255 segment_type2(qi, qj),
256 intersection_policy_type(),
258 base::rpi(), base::rpj(),
259 base::rqi(), base::rqj()))
260 , m_intersection_strategy(intersection_strategy)
261 , m_robust_policy(robust_policy)
264 inline result_type const& result() const { return m_result; }
265 inline i_info_type const& i_info() const { return m_result.template get<0>(); }
266 inline d_info_type const& d_info() const { return m_result.template get<1>(); }
268 inline intersection_strategy_type const& get_intersection_strategy() const
270 return m_intersection_strategy;
273 inline side_strategy_type get_side_strategy() const
275 return m_intersection_strategy.get_side_strategy();
278 // TODO: it's more like is_spike_ip_p
279 inline bool is_spike_p() const
281 if (base::sides().pk_wrt_p1() == 0)
288 int const qk_p1 = base::sides().qk_wrt_p1();
289 int const qk_p2 = base::sides().qk_wrt_p2();
295 return is_spike_of_collinear(base::pi(), base::pj(),
306 // TODO: it's more like is_spike_ip_q
307 inline bool is_spike_q() const
309 if (base::sides().qk_wrt_q1() == 0)
316 int const pk_q1 = base::sides().pk_wrt_q1();
317 int const pk_q2 = base::sides().pk_wrt_q2();
323 return is_spike_of_collinear(base::qi(), base::qj(),
335 template <typename Point>
336 inline bool is_spike_of_collinear(Point const& i, Point const& j,
337 Point const& k) const
339 typedef model::referring_segment<Point const> seg;
341 // no need to calcualte direction info
342 typedef policies::relate::segments_intersection_points
344 intersection_point_type
347 typename policy_type::return_type const result
348 = m_intersection_strategy.apply(seg(i, j), seg(j, k),
352 return result.count == 2;
355 template <std::size_t OpId>
358 int arrival = d_info().arrival[OpId];
359 bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;
363 if (i_info().count == 2)
365 return arrival != -1;
378 result_type m_result;
379 IntersectionStrategy const& m_intersection_strategy;
380 RobustPolicy const& m_robust_policy;
383 }} // namespace detail::overlay
384 #endif // DOXYGEN_NO_DETAIL
386 }} // namespace boost::geometry
388 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP