Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@101
|
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
Chris@101
|
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
Chris@101
|
6
|
Chris@101
|
7 // This file was modified by Oracle on 2015.
|
Chris@101
|
8 // Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
Chris@101
|
9
|
Chris@101
|
10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@16
|
11
|
Chris@16
|
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
14
|
Chris@16
|
15 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
17 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
18
|
Chris@16
|
19 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
Chris@16
|
20 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/mpl/if.hpp>
|
Chris@16
|
23 #include <boost/type_traits.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/geometry/arithmetic/determinant.hpp>
|
Chris@16
|
26 #include <boost/geometry/core/access.hpp>
|
Chris@16
|
27 #include <boost/geometry/util/select_coordinate_type.hpp>
|
Chris@16
|
28 #include <boost/geometry/strategies/side.hpp>
|
Chris@16
|
29
|
Chris@101
|
30 #include <boost/geometry/algorithms/detail/relate/less.hpp>
|
Chris@101
|
31 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
Chris@101
|
32
|
Chris@16
|
33
|
Chris@16
|
34 namespace boost { namespace geometry
|
Chris@16
|
35 {
|
Chris@16
|
36
|
Chris@16
|
37 namespace strategy { namespace side
|
Chris@16
|
38 {
|
Chris@16
|
39
|
Chris@16
|
40 /*!
|
Chris@16
|
41 \brief Check at which side of a segment a point lies:
|
Chris@16
|
42 left of segment (> 0), right of segment (< 0), on segment (0)
|
Chris@16
|
43 \ingroup strategies
|
Chris@16
|
44 \tparam CalculationType \tparam_calculation
|
Chris@16
|
45 */
|
Chris@16
|
46 template <typename CalculationType = void>
|
Chris@16
|
47 class side_by_triangle
|
Chris@16
|
48 {
|
Chris@101
|
49 template <typename Policy>
|
Chris@101
|
50 struct eps_policy
|
Chris@101
|
51 {
|
Chris@101
|
52 eps_policy() {}
|
Chris@101
|
53 template <typename Type>
|
Chris@101
|
54 eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
|
Chris@101
|
55 : policy(a, b, c, d)
|
Chris@101
|
56 {}
|
Chris@101
|
57 Policy policy;
|
Chris@101
|
58 };
|
Chris@101
|
59
|
Chris@101
|
60 struct eps_empty
|
Chris@101
|
61 {
|
Chris@101
|
62 eps_empty() {}
|
Chris@101
|
63 template <typename Type>
|
Chris@101
|
64 eps_empty(Type const&, Type const&, Type const&, Type const&) {}
|
Chris@101
|
65 };
|
Chris@101
|
66
|
Chris@16
|
67 public :
|
Chris@16
|
68
|
Chris@16
|
69 // Template member function, because it is not always trivial
|
Chris@16
|
70 // or convenient to explicitly mention the typenames in the
|
Chris@16
|
71 // strategy-struct itself.
|
Chris@16
|
72
|
Chris@16
|
73 // Types can be all three different. Therefore it is
|
Chris@16
|
74 // not implemented (anymore) as "segment"
|
Chris@16
|
75
|
Chris@101
|
76 template
|
Chris@101
|
77 <
|
Chris@101
|
78 typename CoordinateType,
|
Chris@101
|
79 typename PromotedType,
|
Chris@101
|
80 typename P1,
|
Chris@101
|
81 typename P2,
|
Chris@101
|
82 typename P,
|
Chris@101
|
83 typename EpsPolicy
|
Chris@101
|
84 >
|
Chris@101
|
85 static inline
|
Chris@101
|
86 PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
|
Chris@101
|
87 {
|
Chris@101
|
88 CoordinateType const x = get<0>(p);
|
Chris@101
|
89 CoordinateType const y = get<1>(p);
|
Chris@101
|
90
|
Chris@101
|
91 CoordinateType const sx1 = get<0>(p1);
|
Chris@101
|
92 CoordinateType const sy1 = get<1>(p1);
|
Chris@101
|
93 CoordinateType const sx2 = get<0>(p2);
|
Chris@101
|
94 CoordinateType const sy2 = get<1>(p2);
|
Chris@101
|
95
|
Chris@101
|
96 PromotedType const dx = sx2 - sx1;
|
Chris@101
|
97 PromotedType const dy = sy2 - sy1;
|
Chris@101
|
98 PromotedType const dpx = x - sx1;
|
Chris@101
|
99 PromotedType const dpy = y - sy1;
|
Chris@101
|
100
|
Chris@101
|
101 eps_policy = EpsPolicy(dx, dy, dpx, dpy);
|
Chris@101
|
102
|
Chris@101
|
103 return geometry::detail::determinant<PromotedType>
|
Chris@101
|
104 (
|
Chris@101
|
105 dx, dy,
|
Chris@101
|
106 dpx, dpy
|
Chris@101
|
107 );
|
Chris@101
|
108
|
Chris@101
|
109 }
|
Chris@101
|
110
|
Chris@101
|
111 template
|
Chris@101
|
112 <
|
Chris@101
|
113 typename CoordinateType,
|
Chris@101
|
114 typename PromotedType,
|
Chris@101
|
115 typename P1,
|
Chris@101
|
116 typename P2,
|
Chris@101
|
117 typename P
|
Chris@101
|
118 >
|
Chris@101
|
119 static inline
|
Chris@101
|
120 PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
|
Chris@101
|
121 {
|
Chris@101
|
122 eps_empty dummy;
|
Chris@101
|
123 return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
|
Chris@101
|
124 }
|
Chris@101
|
125
|
Chris@101
|
126
|
Chris@101
|
127 template
|
Chris@101
|
128 <
|
Chris@101
|
129 typename CoordinateType,
|
Chris@101
|
130 typename PromotedType,
|
Chris@101
|
131 bool AreAllIntegralCoordinates
|
Chris@101
|
132 >
|
Chris@101
|
133 struct compute_side_value
|
Chris@101
|
134 {
|
Chris@101
|
135 template <typename P1, typename P2, typename P, typename EpsPolicy>
|
Chris@101
|
136 static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
Chris@101
|
137 {
|
Chris@101
|
138 return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
Chris@101
|
139 }
|
Chris@101
|
140 };
|
Chris@101
|
141
|
Chris@101
|
142 template <typename CoordinateType, typename PromotedType>
|
Chris@101
|
143 struct compute_side_value<CoordinateType, PromotedType, false>
|
Chris@101
|
144 {
|
Chris@101
|
145 template <typename P1, typename P2, typename P, typename EpsPolicy>
|
Chris@101
|
146 static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
Chris@101
|
147 {
|
Chris@101
|
148 // For robustness purposes, first check if any two points are
|
Chris@101
|
149 // the same; in this case simply return that the points are
|
Chris@101
|
150 // collinear
|
Chris@101
|
151 if (geometry::detail::equals::equals_point_point(p1, p2)
|
Chris@101
|
152 || geometry::detail::equals::equals_point_point(p1, p)
|
Chris@101
|
153 || geometry::detail::equals::equals_point_point(p2, p))
|
Chris@101
|
154 {
|
Chris@101
|
155 return PromotedType(0);
|
Chris@101
|
156 }
|
Chris@101
|
157
|
Chris@101
|
158 // The side_by_triangle strategy computes the signed area of
|
Chris@101
|
159 // the point triplet (p1, p2, p); as such it is (in theory)
|
Chris@101
|
160 // invariant under cyclic permutations of its three arguments.
|
Chris@101
|
161 //
|
Chris@101
|
162 // In the context of numerical errors that arise in
|
Chris@101
|
163 // floating-point computations, and in order to make the strategy
|
Chris@101
|
164 // consistent with respect to cyclic permutations of its three
|
Chris@101
|
165 // arguments, we cyclically permute them so that the first
|
Chris@101
|
166 // argument is always the lexicographically smallest point.
|
Chris@101
|
167
|
Chris@101
|
168 geometry::detail::relate::less less;
|
Chris@101
|
169 if (less(p, p1))
|
Chris@101
|
170 {
|
Chris@101
|
171 if (less(p, p2))
|
Chris@101
|
172 {
|
Chris@101
|
173 // p is the lexicographically smallest
|
Chris@101
|
174 return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
|
Chris@101
|
175 }
|
Chris@101
|
176 else
|
Chris@101
|
177 {
|
Chris@101
|
178 // p2 is the lexicographically smallest
|
Chris@101
|
179 return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
Chris@101
|
180 }
|
Chris@101
|
181 }
|
Chris@101
|
182
|
Chris@101
|
183 if (less(p1, p2))
|
Chris@101
|
184 {
|
Chris@101
|
185 // p1 is the lexicographically smallest
|
Chris@101
|
186 return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
Chris@101
|
187 }
|
Chris@101
|
188 else
|
Chris@101
|
189 {
|
Chris@101
|
190 // p2 is the lexicographically smallest
|
Chris@101
|
191 return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
Chris@101
|
192 }
|
Chris@101
|
193 }
|
Chris@101
|
194 };
|
Chris@101
|
195
|
Chris@101
|
196
|
Chris@16
|
197 template <typename P1, typename P2, typename P>
|
Chris@16
|
198 static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
Chris@16
|
199 {
|
Chris@101
|
200 typedef typename coordinate_type<P1>::type coordinate_type1;
|
Chris@101
|
201 typedef typename coordinate_type<P2>::type coordinate_type2;
|
Chris@101
|
202 typedef typename coordinate_type<P>::type coordinate_type3;
|
Chris@101
|
203
|
Chris@16
|
204 typedef typename boost::mpl::if_c
|
Chris@16
|
205 <
|
Chris@16
|
206 boost::is_void<CalculationType>::type::value,
|
Chris@16
|
207 typename select_most_precise
|
Chris@16
|
208 <
|
Chris@16
|
209 typename select_most_precise
|
Chris@16
|
210 <
|
Chris@101
|
211 coordinate_type1, coordinate_type2
|
Chris@16
|
212 >::type,
|
Chris@101
|
213 coordinate_type3
|
Chris@16
|
214 >::type,
|
Chris@16
|
215 CalculationType
|
Chris@16
|
216 >::type coordinate_type;
|
Chris@16
|
217
|
Chris@16
|
218 // Promote float->double, small int->int
|
Chris@16
|
219 typedef typename select_most_precise
|
Chris@16
|
220 <
|
Chris@16
|
221 coordinate_type,
|
Chris@16
|
222 double
|
Chris@16
|
223 >::type promoted_type;
|
Chris@16
|
224
|
Chris@101
|
225 bool const are_all_integral_coordinates =
|
Chris@101
|
226 boost::is_integral<coordinate_type1>::value
|
Chris@101
|
227 && boost::is_integral<coordinate_type2>::value
|
Chris@101
|
228 && boost::is_integral<coordinate_type3>::value;
|
Chris@16
|
229
|
Chris@101
|
230 eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
|
Chris@101
|
231 promoted_type s = compute_side_value
|
Chris@101
|
232 <
|
Chris@101
|
233 coordinate_type, promoted_type, are_all_integral_coordinates
|
Chris@101
|
234 >::apply(p1, p2, p, epsp);
|
Chris@16
|
235
|
Chris@16
|
236 promoted_type const zero = promoted_type();
|
Chris@101
|
237 return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
|
Chris@101
|
238 : s > zero ? 1
|
Chris@16
|
239 : -1;
|
Chris@16
|
240 }
|
Chris@101
|
241
|
Chris@16
|
242 };
|
Chris@16
|
243
|
Chris@16
|
244
|
Chris@16
|
245 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
Chris@16
|
246 namespace services
|
Chris@16
|
247 {
|
Chris@16
|
248
|
Chris@16
|
249 template <typename CalculationType>
|
Chris@16
|
250 struct default_strategy<cartesian_tag, CalculationType>
|
Chris@16
|
251 {
|
Chris@16
|
252 typedef side_by_triangle<CalculationType> type;
|
Chris@16
|
253 };
|
Chris@16
|
254
|
Chris@16
|
255 }
|
Chris@16
|
256 #endif
|
Chris@16
|
257
|
Chris@16
|
258 }} // namespace strategy::side
|
Chris@16
|
259
|
Chris@16
|
260 }} // namespace boost::geometry
|
Chris@16
|
261
|
Chris@16
|
262
|
Chris@16
|
263 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|