1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
8 // This file was modified by Oracle on 2015, 2017, 2019.
9 // Modifications copyright (c) 2015-2019 Oracle and/or its affiliates.
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
18 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP
19 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP
21 #include <boost/geometry/algorithms/detail/direction_code.hpp>
22 #include <boost/geometry/algorithms/detail/recalculate.hpp>
23 #include <boost/geometry/core/cs.hpp>
24 #include <boost/geometry/policies/robustness/robust_point_type.hpp>
25 #include <boost/geometry/strategies/side.hpp>
26 #include <boost/geometry/util/condition.hpp>
27 #include <boost/geometry/util/math.hpp>
30 namespace boost { namespace geometry
34 #ifndef DOXYGEN_NO_DETAIL
38 // Checks if a point ("last_point") causes a spike w.r.t.
39 // the specified two other points (segment_a, segment_b)
44 // Above, lp generates a spike w.r.t. segment(a,b)
45 // So specify last point first, then (a,b)
46 // The segment's orientation does matter: if lp is to the right of b
47 // no spike is reported
50 typename Point1, typename Point2, typename Point3,
53 inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
54 Point2 const& segment_a, // next | back - 2
55 Point3 const& segment_b, // curr | back - 1 | spike's vertex
56 SideStrategy const& strategy)
58 typedef typename SideStrategy::cs_tag cs_tag;
60 int const side = strategy.apply(segment_a, segment_b, last_point);
63 // Last point is collinear w.r.t previous segment.
64 return direction_code<cs_tag>(segment_a, segment_b, last_point) < 1;
74 typename SideStrategy,
77 inline bool point_is_spike_or_equal(Point1 const& last_point,
78 Point2 const& segment_a,
79 Point3 const& segment_b,
80 SideStrategy const& strategy,
81 RobustPolicy const& robust_policy)
83 if (point_is_spike_or_equal(last_point, segment_a, segment_b, strategy))
88 if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))
93 // Try using specified robust policy
94 typedef typename geometry::robust_point_type
98 >::type robust_point_type;
100 robust_point_type last_point_rob, segment_a_rob, segment_b_rob;
101 geometry::recalculate(last_point_rob, last_point, robust_policy);
102 geometry::recalculate(segment_a_rob, segment_a, robust_policy);
103 geometry::recalculate(segment_b_rob, segment_b, robust_policy);
105 return point_is_spike_or_equal
119 typename SideStrategy,
120 typename RobustPolicy
122 inline bool point_is_collinear(Point1 const& last_point,
123 Point2 const& segment_a,
124 Point3 const& segment_b,
125 SideStrategy const& strategy,
126 RobustPolicy const& robust_policy)
128 int const side = strategy.apply(segment_a, segment_b, last_point);
134 // This part (or whole method, because it is then trivial)
135 // will be removed after rescaling
136 if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))
141 // Redo, using specified robust policy
142 typedef typename geometry::robust_point_type
146 >::type robust_point_type;
148 robust_point_type last_point_rob, segment_a_rob, segment_b_rob;
149 geometry::recalculate(last_point_rob, last_point, robust_policy);
150 geometry::recalculate(segment_a_rob, segment_a, robust_policy);
151 geometry::recalculate(segment_b_rob, segment_b, robust_policy);
153 int const side_rob = strategy.apply(segment_a_rob, segment_b_rob, last_point_rob);
154 return side_rob == 0;
158 //! Version with intuitive order (A, B, C). The original order was
159 //! unclear (C, A, B). It was used in a different way in has_spikes.
160 //! On longer term the C,A,B version can be deprecated
166 typename SideStrategy
168 inline bool is_spike_or_equal(Point1 const& a,
171 SideStrategy const& strategy)
173 return point_is_spike_or_equal(c, a, b, strategy);
177 } // namespace detail
180 }} // namespace boost::geometry
183 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP