1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2015, Oracle and/or its affiliates.
4
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
9
10 #ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
11 #define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
12
13 #include <boost/geometry/core/assert.hpp>
14 #include <boost/geometry/util/math.hpp>
15 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
16
17
18 namespace boost { namespace geometry
19 {
20
21 namespace math
22 {
23
24 #ifndef DOXYGEN_NO_DETAIL
25 namespace detail
26 {
27
28
29 template <typename Units, typename CoordinateType>
30 class normalize_spheroidal_box_coordinates
31 {
32 private:
33 typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;
34 typedef constants_on_spheroid<CoordinateType, Units> constants;
35
is_band(CoordinateType const & longitude1,CoordinateType const & longitude2)36 static inline bool is_band(CoordinateType const& longitude1,
37 CoordinateType const& longitude2)
38 {
39 return ! math::smaller(math::abs(longitude1 - longitude2),
40 constants::period());
41 }
42
43 public:
apply(CoordinateType & longitude1,CoordinateType & latitude1,CoordinateType & longitude2,CoordinateType & latitude2,bool band)44 static inline void apply(CoordinateType& longitude1,
45 CoordinateType& latitude1,
46 CoordinateType& longitude2,
47 CoordinateType& latitude2,
48 bool band)
49 {
50 normalize::apply(longitude1, latitude1, false);
51 normalize::apply(longitude2, latitude2, false);
52
53 if (math::equals(latitude1, constants::min_latitude())
54 && math::equals(latitude2, constants::min_latitude()))
55 {
56 // box degenerates to the south pole
57 longitude1 = longitude2 = CoordinateType(0);
58 }
59 else if (math::equals(latitude1, constants::max_latitude())
60 && math::equals(latitude2, constants::max_latitude()))
61 {
62 // box degenerates to the north pole
63 longitude1 = longitude2 = CoordinateType(0);
64 }
65 else if (band)
66 {
67 // the box is a band between two small circles (parallel
68 // to the equator) on the spheroid
69 longitude1 = constants::min_longitude();
70 longitude2 = constants::max_longitude();
71 }
72 else if (longitude1 > longitude2)
73 {
74 // the box crosses the antimeridian, so we need to adjust
75 // the longitudes
76 longitude2 += constants::period();
77 }
78
79 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
80 BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));
81 BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));
82 BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));
83 #endif
84
85 BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
86 BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
87 BOOST_GEOMETRY_ASSERT
88 (! math::larger(longitude2 - longitude1, constants::period()));
89 }
90
apply(CoordinateType & longitude1,CoordinateType & latitude1,CoordinateType & longitude2,CoordinateType & latitude2)91 static inline void apply(CoordinateType& longitude1,
92 CoordinateType& latitude1,
93 CoordinateType& longitude2,
94 CoordinateType& latitude2)
95 {
96 bool const band = is_band(longitude1, longitude2);
97
98 apply(longitude1, latitude1, longitude2, latitude2, band);
99 }
100 };
101
102
103 } // namespace detail
104 #endif // DOXYGEN_NO_DETAIL
105
106
107 /*!
108 \brief Short utility to normalize the coordinates of a box on a spheroid
109 \tparam Units The units of the coordindate system in the spheroid
110 \tparam CoordinateType The type of the coordinates
111 \param longitude1 Minimum longitude of the box
112 \param latitude1 Minimum latitude of the box
113 \param longitude2 Maximum longitude of the box
114 \param latitude2 Maximum latitude of the box
115 \ingroup utility
116 */
117 template <typename Units, typename CoordinateType>
normalize_spheroidal_box_coordinates(CoordinateType & longitude1,CoordinateType & latitude1,CoordinateType & longitude2,CoordinateType & latitude2)118 inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
119 CoordinateType& latitude1,
120 CoordinateType& longitude2,
121 CoordinateType& latitude2)
122 {
123 detail::normalize_spheroidal_box_coordinates
124 <
125 Units, CoordinateType
126 >::apply(longitude1, latitude1, longitude2, latitude2);
127 }
128
129 /*!
130 \brief Short utility to normalize the coordinates of a box on a spheroid
131 \tparam Units The units of the coordindate system in the spheroid
132 \tparam CoordinateType The type of the coordinates
133 \param longitude1 Minimum longitude of the box
134 \param latitude1 Minimum latitude of the box
135 \param longitude2 Maximum longitude of the box
136 \param latitude2 Maximum latitude of the box
137 \param band Indicates whether the box should be treated as a band or
138 not and avoid the computation done in the other version of the function
139 \ingroup utility
140 */
141 template <typename Units, typename CoordinateType>
normalize_spheroidal_box_coordinates(CoordinateType & longitude1,CoordinateType & latitude1,CoordinateType & longitude2,CoordinateType & latitude2,bool band)142 inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
143 CoordinateType& latitude1,
144 CoordinateType& longitude2,
145 CoordinateType& latitude2,
146 bool band)
147 {
148 detail::normalize_spheroidal_box_coordinates
149 <
150 Units, CoordinateType
151 >::apply(longitude1, latitude1, longitude2, latitude2, band);
152 }
153
154
155 } // namespace math
156
157
158 }} // namespace boost::geometry
159
160 #endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
161