File indexing completed on 2025-01-18 09:36:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
0023 #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
0024
0025 #include <algorithm>
0026 #include <cstddef>
0027 #include <functional>
0028 #include <type_traits>
0029
0030 #include <boost/geometry/core/access.hpp>
0031 #include <boost/geometry/core/coordinate_dimension.hpp>
0032 #include <boost/geometry/core/coordinate_system.hpp>
0033 #include <boost/geometry/core/coordinate_type.hpp>
0034 #include <boost/geometry/core/tags.hpp>
0035
0036 #include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
0037 #include <boost/geometry/util/math.hpp>
0038 #include <boost/geometry/util/select_coordinate_type.hpp>
0039
0040 #include <boost/geometry/algorithms/detail/normalize.hpp>
0041 #include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
0042
0043 #include <boost/geometry/strategy/expand.hpp>
0044 #include <boost/geometry/strategy/cartesian/expand_point.hpp>
0045
0046
0047 namespace boost { namespace geometry
0048 {
0049
0050 namespace strategy { namespace expand
0051 {
0052
0053 #ifndef DOXYGEN_NO_DETAIL
0054 namespace detail
0055 {
0056
0057
0058 template <std::size_t DimensionCount, bool IsEquatorial>
0059 struct point_loop_on_spheroid
0060 {
0061 template <typename Box, typename Point>
0062 static inline void apply(Box& box, Point const& point)
0063 {
0064 typedef typename point_type<Box>::type box_point_type;
0065 typedef typename coordinate_type<Box>::type box_coordinate_type;
0066 typedef typename geometry::detail::cs_angular_units<Box>::type units_type;
0067
0068 typedef math::detail::constants_on_spheroid
0069 <
0070 box_coordinate_type,
0071 units_type
0072 > constants;
0073
0074
0075 Point p_normalized;
0076 strategy::normalize::spherical_point::apply(point, p_normalized);
0077
0078
0079 box_point_type box_point;
0080 geometry::detail::envelope::transform_units(p_normalized, box_point);
0081
0082 if (is_inverse_spheroidal_coordinates(box))
0083 {
0084 geometry::set_from_radian<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
0085 geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
0086 geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
0087 geometry::set_from_radian<max_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
0088
0089 } else {
0090
0091 strategy::normalize::spherical_box::apply(box, box);
0092
0093 box_coordinate_type p_lon = geometry::get<0>(box_point);
0094 box_coordinate_type p_lat = geometry::get<1>(box_point);
0095
0096 typename coordinate_type<Box>::type
0097 b_lon_min = geometry::get<min_corner, 0>(box),
0098 b_lat_min = geometry::get<min_corner, 1>(box),
0099 b_lon_max = geometry::get<max_corner, 0>(box),
0100 b_lat_max = geometry::get<max_corner, 1>(box);
0101
0102 if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
0103 {
0104
0105
0106
0107
0108 geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
0109 geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
0110 return;
0111 }
0112
0113 if (math::equals(b_lat_min, b_lat_max)
0114 && math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
0115 {
0116
0117
0118
0119
0120 geometry::set<min_corner, 0>(box, p_lon);
0121 geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
0122 geometry::set<max_corner, 0>(box, p_lon);
0123 geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
0124 return;
0125 }
0126
0127
0128 b_lat_min = (std::min)(b_lat_min, p_lat);
0129 b_lat_max = (std::max)(b_lat_max, p_lat);
0130
0131
0132 if (math::smaller(p_lon, b_lon_min))
0133 {
0134 box_coordinate_type p_lon_shifted = p_lon + constants::period();
0135
0136 if (math::larger(p_lon_shifted, b_lon_max))
0137 {
0138
0139 if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
0140 {
0141 b_lon_min = p_lon;
0142 }
0143 else
0144 {
0145 b_lon_max = p_lon_shifted;
0146 }
0147 }
0148 }
0149 else if (math::larger(p_lon, b_lon_max))
0150 {
0151
0152
0153 if (b_lon_min < 0
0154 && math::larger(p_lon - b_lon_max,
0155 constants::period() - p_lon + b_lon_min))
0156 {
0157 b_lon_min = p_lon;
0158 b_lon_max += constants::period();
0159 }
0160 else
0161 {
0162 b_lon_max = p_lon;
0163 }
0164 }
0165
0166 geometry::set<min_corner, 0>(box, b_lon_min);
0167 geometry::set<min_corner, 1>(box, b_lat_min);
0168 geometry::set<max_corner, 0>(box, b_lon_max);
0169 geometry::set<max_corner, 1>(box, b_lat_max);
0170 }
0171
0172 point_loop
0173 <
0174 2, DimensionCount
0175 >::apply(box, point);
0176 }
0177 };
0178
0179
0180 }
0181 #endif
0182
0183
0184 struct spherical_point
0185 {
0186 template <typename Box, typename Point>
0187 static void apply(Box & box, Point const& point)
0188 {
0189 expand::detail::point_loop_on_spheroid
0190 <
0191 dimension<Point>::value,
0192 ! std::is_same<typename cs_tag<Point>::type, spherical_polar_tag>::value
0193 >::apply(box, point);
0194 }
0195 };
0196
0197
0198 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0199
0200 namespace services
0201 {
0202
0203 template <typename CalculationType>
0204 struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
0205 {
0206 typedef spherical_point type;
0207 };
0208
0209 template <typename CalculationType>
0210 struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
0211 {
0212 typedef spherical_point type;
0213 };
0214
0215 template <typename CalculationType>
0216 struct default_strategy<point_tag, geographic_tag, CalculationType>
0217 {
0218 typedef spherical_point type;
0219 };
0220
0221
0222 }
0223
0224 #endif
0225
0226
0227 }}
0228
0229 }}
0230
0231 #endif