• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
4 // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 
7 // This file was modified by Oracle on 2018.
8 // Modifications copyright (c) 2018, Oracle and/or its affiliates.
9 
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
20 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
21 
22 
23 #include <boost/geometry/core/access.hpp>
24 
25 #include <boost/geometry/geometries/concepts/point_concept.hpp>
26 
27 #include <boost/geometry/strategies/distance.hpp>
28 
29 #include <boost/geometry/util/math.hpp>
30 #include <boost/geometry/util/calculation_type.hpp>
31 
32 
33 namespace boost { namespace geometry
34 {
35 
36 namespace strategy { namespace distance
37 {
38 
39 #ifndef DOXYGEN_NO_DETAIL
40 namespace detail
41 {
42 
43 template <size_t I, typename T>
44 struct compute_pythagoras
45 {
46     template <typename Point1, typename Point2>
applyboost::geometry::strategy::distance::detail::compute_pythagoras47     static inline T apply(Point1 const& p1, Point2 const& p2)
48     {
49         T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
50         T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
51         T const d = c1 - c2;
52         return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
53     }
54 };
55 
56 template <typename T>
57 struct compute_pythagoras<0, T>
58 {
59     template <typename Point1, typename Point2>
applyboost::geometry::strategy::distance::detail::compute_pythagoras60     static inline T apply(Point1 const&, Point2 const&)
61     {
62         return boost::numeric_cast<T>(0);
63     }
64 };
65 
66 }
67 #endif // DOXYGEN_NO_DETAIL
68 
69 
70 namespace comparable
71 {
72 
73 /*!
74 \brief Strategy to calculate comparable distance between two points
75 \ingroup strategies
76 \tparam Point1 \tparam_first_point
77 \tparam Point2 \tparam_second_point
78 \tparam CalculationType \tparam_calculation
79 */
80 template <typename CalculationType = void>
81 class pythagoras
82 {
83 public :
84 
85     template <typename Point1, typename Point2>
86     struct calculation_type
87         : util::calculation_type::geometric::binary
88           <
89               Point1,
90               Point2,
91               CalculationType,
92               double,
93               double
94           >
95     {};
96 
97     template <typename Point1, typename Point2>
98     static inline typename calculation_type<Point1, Point2>::type
apply(Point1 const & p1,Point2 const & p2)99     apply(Point1 const& p1, Point2 const& p2)
100     {
101         BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );
102         BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
103 
104         // Calculate distance using Pythagoras
105         // (Leave comment above for Doxygen)
106 
107         assert_dimension_equal<Point1, Point2>();
108 
109         return detail::compute_pythagoras
110             <
111                 dimension<Point1>::value,
112                 typename calculation_type<Point1, Point2>::type
113             >::apply(p1, p2);
114     }
115 };
116 
117 } // namespace comparable
118 
119 
120 /*!
121 \brief Strategy to calculate the distance between two points
122 \ingroup strategies
123 \tparam CalculationType \tparam_calculation
124 
125 \qbk{
126 [heading Notes]
127 [note Can be used for points with two\, three or more dimensions]
128 [heading See also]
129 [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
130 }
131 
132 */
133 template
134 <
135     typename CalculationType = void
136 >
137 class pythagoras
138 {
139 public :
140 
141     template <typename P1, typename P2>
142     struct calculation_type
143         : util::calculation_type::geometric::binary
144           <
145               P1,
146               P2,
147               CalculationType,
148               double,
149               double // promote integer to double
150           >
151     {};
152 
153     /*!
154     \brief applies the distance calculation using pythagoras
155     \return the calculated distance (including taking the square root)
156     \param p1 first point
157     \param p2 second point
158     */
159     template <typename P1, typename P2>
160     static inline typename calculation_type<P1, P2>::type
apply(P1 const & p1,P2 const & p2)161     apply(P1 const& p1, P2 const& p2)
162     {
163         // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
164         return math::sqrt
165             (
166                  boost::numeric_cast<typename calculation_type<P1, P2>::type>
167                     (
168                         comparable::pythagoras<CalculationType>::apply(p1, p2)
169                     )
170             );
171     }
172 };
173 
174 
175 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
176 namespace services
177 {
178 
179 template <typename CalculationType>
180 struct tag<pythagoras<CalculationType> >
181 {
182     typedef strategy_tag_distance_point_point type;
183 };
184 
185 
186 template <typename CalculationType, typename P1, typename P2>
187 struct return_type<distance::pythagoras<CalculationType>, P1, P2>
188     : pythagoras<CalculationType>::template calculation_type<P1, P2>
189 {};
190 
191 
192 template <typename CalculationType>
193 struct comparable_type<pythagoras<CalculationType> >
194 {
195     typedef comparable::pythagoras<CalculationType> type;
196 };
197 
198 
199 template <typename CalculationType>
200 struct get_comparable<pythagoras<CalculationType> >
201 {
202     typedef comparable::pythagoras<CalculationType> comparable_type;
203 public :
applyboost::geometry::strategy::distance::services::get_comparable204     static inline comparable_type apply(pythagoras<CalculationType> const& )
205     {
206         return comparable_type();
207     }
208 };
209 
210 
211 template <typename CalculationType, typename Point1, typename Point2>
212 struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
213 {
214 private :
215     typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
216 public :
217     template <typename T>
applyboost::geometry::strategy::distance::services::result_from_distance218     static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
219     {
220         return return_type(value);
221     }
222 };
223 
224 
225 // Specializations for comparable::pythagoras
226 template <typename CalculationType>
227 struct tag<comparable::pythagoras<CalculationType> >
228 {
229     typedef strategy_tag_distance_point_point type;
230 };
231 
232 
233 template <typename CalculationType, typename P1, typename P2>
234 struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
235     : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
236 {};
237 
238 
239 
240 
241 template <typename CalculationType>
242 struct comparable_type<comparable::pythagoras<CalculationType> >
243 {
244     typedef comparable::pythagoras<CalculationType> type;
245 };
246 
247 
248 template <typename CalculationType>
249 struct get_comparable<comparable::pythagoras<CalculationType> >
250 {
251     typedef comparable::pythagoras<CalculationType> comparable_type;
252 public :
applyboost::geometry::strategy::distance::services::get_comparable253     static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
254     {
255         return comparable_type();
256     }
257 };
258 
259 
260 template <typename CalculationType, typename Point1, typename Point2>
261 struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
262 {
263 private :
264     typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
265 public :
266     template <typename T>
applyboost::geometry::strategy::distance::services::result_from_distance267     static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
268     {
269         return_type const v = value;
270         return v * v;
271     }
272 };
273 
274 
275 template <typename Point1, typename Point2>
276 struct default_strategy
277     <
278         point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag
279     >
280 {
281     typedef pythagoras<> type;
282 };
283 
284 
285 } // namespace services
286 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
287 
288 
289 }} // namespace strategy::distance
290 
291 
292 }} // namespace boost::geometry
293 
294 
295 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
296