1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
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.
7 
8 // This file was modified by Oracle on 2013-2018.
9 // Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
10 
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
20 
21 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP
22 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP
23 
24 #include <cstddef>
25 
26 #include <boost/geometry/core/cs.hpp>
27 
28 #include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
29 #include <boost/geometry/strategies/disjoint.hpp>
30 
31 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
32 #include <boost/geometry/util/select_most_precise.hpp>
33 
34 
35 namespace boost { namespace geometry { namespace strategy { namespace disjoint
36 {
37 
38 #ifndef DOXYGEN_NO_DETAIL
39 namespace detail
40 {
41 
42 struct box_box_on_spheroid
43 {
44     template <typename Box1, typename Box2>
applyboost::geometry::strategy::disjoint::detail::box_box_on_spheroid45     static inline bool apply(Box1 const& box1, Box2 const& box2)
46     {
47         typedef typename geometry::select_most_precise
48             <
49                 typename coordinate_type<Box1>::type,
50                 typename coordinate_type<Box2>::type
51             >::type calc_t;
52         typedef typename geometry::detail::cs_angular_units<Box1>::type units_t;
53         typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
54 
55         calc_t const b1_min = get<min_corner, 0>(box1);
56         calc_t const b1_max = get<max_corner, 0>(box1);
57         calc_t const b2_min = get<min_corner, 0>(box2);
58         calc_t const b2_max = get<max_corner, 0>(box2);
59 
60         // min <= max <=> diff >= 0
61         calc_t const diff1 = b1_max - b1_min;
62         calc_t const diff2 = b2_max - b2_min;
63 
64         // check the intersection if neither box cover the whole globe
65         if (diff1 < constants::period() && diff2 < constants::period())
66         {
67             // calculate positive longitude translation with b1_min as origin
68             calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
69             calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
70             calc_t b2_max_transl = b2_min_transl - constants::period() + diff2;
71 
72             // if the translation is too close then use the original point
73             // note that math::abs(b2_max_transl - b2_max) takes values very
74             // close to k*2*constants::period() for k=0,1,2,...
75             if (math::abs(b2_max_transl - b2_max) < constants::period() / 2)
76             {
77                 b2_max_transl = b2_max;
78             }
79 
80             if (b2_min_transl > b1_max  // b2_min right of b1_max
81              && b2_max_transl < b1_min) // b2_max left of b1_min
82             {
83                 return true;
84             }
85         }
86 
87         return box_box
88             <
89                 Box1, Box2, 1
90             >::apply(box1, box2);
91     }
92 };
93 
94 } // namespace detail
95 #endif // DOXYGEN_NO_DETAIL
96 
97 
98 struct spherical_box_box
99 {
100     template <typename Box1, typename Box2>
applyboost::geometry::strategy::disjoint::spherical_box_box101     static inline bool apply(Box1 const& box1, Box2 const& box2)
102     {
103         return detail::box_box_on_spheroid::apply(box1, box2);
104     }
105 };
106 
107 
108 namespace services
109 {
110 
111 template <typename Box1, typename Box2, int TopDim1, int TopDim2>
112 struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_equatorial_tag, spherical_equatorial_tag>
113 {
114     typedef disjoint::spherical_box_box type;
115 };
116 
117 template <typename Box1, typename Box2, int TopDim1, int TopDim2>
118 struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_polar_tag, spherical_polar_tag>
119 {
120     typedef disjoint::spherical_box_box type;
121 };
122 
123 template <typename Box1, typename Box2, int TopDim1, int TopDim2>
124 struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, geographic_tag, geographic_tag>
125 {
126     typedef disjoint::spherical_box_box type;
127 };
128 
129 } // namespace services
130 
131 }}}} // namespace boost::geometry::strategy::disjoint
132 
133 
134 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP
135