• 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_BOX_BOX_HPP
21 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_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 <std::size_t I>
47 struct compute_pythagoras_box_box
48 {
49     template <typename Box1, typename Box2, typename T>
applyboost::geometry::strategy::distance::detail::compute_pythagoras_box_box50     static inline void apply(Box1 const& box1, Box2 const& box2, T& result)
51     {
52         T const b1_min_coord =
53             boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box1));
54         T const b1_max_coord =
55             boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box1));
56 
57         T const b2_min_coord =
58             boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box2));
59         T const b2_max_coord =
60             boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box2));
61 
62         if ( b1_max_coord < b2_min_coord )
63         {
64             T diff = b2_min_coord - b1_max_coord;
65             result += diff * diff;
66         }
67         if ( b1_min_coord > b2_max_coord )
68         {
69             T diff = b1_min_coord - b2_max_coord;
70             result += diff * diff;
71         }
72 
73         compute_pythagoras_box_box<I-1>::apply(box1, box2, result);
74     }
75 };
76 
77 template <>
78 struct compute_pythagoras_box_box<0>
79 {
80     template <typename Box1, typename Box2, typename T>
applyboost::geometry::strategy::distance::detail::compute_pythagoras_box_box81     static inline void apply(Box1 const&, Box2 const&, T&)
82     {
83     }
84 };
85 
86 }
87 #endif // DOXYGEN_NO_DETAIL
88 
89 
90 namespace comparable
91 {
92 
93 /*!
94 \brief Strategy to calculate comparable distance between two boxes
95 \ingroup strategies
96 \tparam Box1 \tparam_first_box
97 \tparam Box2 \tparam_second_box
98 \tparam CalculationType \tparam_calculation
99 */
100 template <typename CalculationType = void>
101 class pythagoras_box_box
102 {
103 public :
104 
105     template <typename Box1, typename Box2>
106     struct calculation_type
107     {
108         typedef typename util::calculation_type::geometric::binary
109             <
110                 Box1,
111                 Box2,
112                 CalculationType
113             >::type type;
114     };
115 
116     template <typename Box1, typename Box2>
117     static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const & box1,Box2 const & box2)118     apply(Box1 const& box1, Box2 const& box2)
119     {
120         BOOST_CONCEPT_ASSERT
121             ( (concepts::ConstPoint<typename point_type<Box1>::type>) );
122         BOOST_CONCEPT_ASSERT
123             ( (concepts::ConstPoint<typename point_type<Box2>::type>) );
124 
125         // Calculate distance using Pythagoras
126         // (Leave comment above for Doxygen)
127 
128         assert_dimension_equal<Box1, Box2>();
129 
130         typename calculation_type<Box1, Box2>::type result(0);
131 
132         detail::compute_pythagoras_box_box
133             <
134                 dimension<Box1>::value
135             >::apply(box1, box2, result);
136 
137         return result;
138     }
139 };
140 
141 } // namespace comparable
142 
143 
144 /*!
145 \brief Strategy to calculate the distance between two boxes
146 \ingroup strategies
147 \tparam CalculationType \tparam_calculation
148 
149 \qbk{
150 [heading Notes]
151 [note Can be used for boxes with two\, three or more dimensions]
152 [heading See also]
153 [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
154 }
155 
156 */
157 template
158 <
159     typename CalculationType = void
160 >
161 class pythagoras_box_box
162 {
163 public :
164 
165     template <typename Box1, typename Box2>
166     struct calculation_type
167         : util::calculation_type::geometric::binary
168           <
169               Box1,
170               Box2,
171               CalculationType,
172               double,
173               double // promote integer to double
174           >
175     {};
176 
177     /*!
178     \brief applies the distance calculation using pythagoras_box_box
179     \return the calculated distance (including taking the square root)
180     \param box1 first box
181     \param box2 second box
182     */
183     template <typename Box1, typename Box2>
184     static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const & box1,Box2 const & box2)185     apply(Box1 const& box1, Box2 const& box2)
186     {
187         // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
188         return math::sqrt
189             (
190                  boost::numeric_cast<typename calculation_type
191                      <
192                          Box1, Box2
193                      >::type>
194                     (
195                         comparable::pythagoras_box_box
196                             <
197                                 CalculationType
198                             >::apply(box1, box2)
199                     )
200             );
201     }
202 };
203 
204 
205 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
206 namespace services
207 {
208 
209 template <typename CalculationType>
210 struct tag<pythagoras_box_box<CalculationType> >
211 {
212     typedef strategy_tag_distance_box_box type;
213 };
214 
215 
216 template <typename CalculationType, typename Box1, typename Box2>
217 struct return_type<distance::pythagoras_box_box<CalculationType>, Box1, Box2>
218     : pythagoras_box_box<CalculationType>::template calculation_type<Box1, Box2>
219 {};
220 
221 
222 template <typename CalculationType>
223 struct comparable_type<pythagoras_box_box<CalculationType> >
224 {
225     typedef comparable::pythagoras_box_box<CalculationType> type;
226 };
227 
228 
229 template <typename CalculationType>
230 struct get_comparable<pythagoras_box_box<CalculationType> >
231 {
232     typedef comparable::pythagoras_box_box<CalculationType> comparable_type;
233 public :
234     static inline comparable_type
applyboost::geometry::strategy::distance::services::get_comparable235     apply(pythagoras_box_box<CalculationType> const& )
236     {
237         return comparable_type();
238     }
239 };
240 
241 
242 template <typename CalculationType, typename Box1, typename Box2>
243 struct result_from_distance<pythagoras_box_box<CalculationType>, Box1, Box2>
244 {
245 private:
246     typedef typename return_type
247         <
248             pythagoras_box_box<CalculationType>, Box1, Box2
249         >::type return_type;
250 public:
251     template <typename T>
252     static inline return_type
applyboost::geometry::strategy::distance::services::result_from_distance253     apply(pythagoras_box_box<CalculationType> const& , T const& value)
254     {
255         return return_type(value);
256     }
257 };
258 
259 
260 // Specializations for comparable::pythagoras_box_box
261 template <typename CalculationType>
262 struct tag<comparable::pythagoras_box_box<CalculationType> >
263 {
264     typedef strategy_tag_distance_box_box type;
265 };
266 
267 
268 template <typename CalculationType, typename Box1, typename Box2>
269 struct return_type<comparable::pythagoras_box_box<CalculationType>, Box1, Box2>
270     : comparable::pythagoras_box_box
271         <
272             CalculationType
273         >::template calculation_type<Box1, Box2>
274 {};
275 
276 
277 
278 
279 template <typename CalculationType>
280 struct comparable_type<comparable::pythagoras_box_box<CalculationType> >
281 {
282     typedef comparable::pythagoras_box_box<CalculationType> type;
283 };
284 
285 
286 template <typename CalculationType>
287 struct get_comparable<comparable::pythagoras_box_box<CalculationType> >
288 {
289     typedef comparable::pythagoras_box_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 Box1, typename Box2>
299 struct result_from_distance
300     <
301         comparable::pythagoras_box_box<CalculationType>, Box1, Box2
302     >
303 {
304 private :
305     typedef typename return_type
306         <
307             comparable::pythagoras_box_box<CalculationType>, Box1, Box2
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_box_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 BoxPoint1, typename BoxPoint2>
322 struct default_strategy
323     <
324         box_tag, box_tag, BoxPoint1, BoxPoint2, cartesian_tag, cartesian_tag
325     >
326 {
327     typedef pythagoras_box_box<> type;
328 };
329 
330 
331 } // namespace services
332 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
333 
334 
335 }} // namespace strategy::distance
336 
337 
338 }} // namespace boost::geometry
339 
340 
341 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP
342