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