123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
- #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
- #include <algorithm>
- #include <cstddef>
- #include <functional>
- #include <type_traits>
- #include <boost/geometry/core/access.hpp>
- #include <boost/geometry/core/coordinate_dimension.hpp>
- #include <boost/geometry/core/coordinate_system.hpp>
- #include <boost/geometry/core/coordinate_type.hpp>
- #include <boost/geometry/core/tags.hpp>
- #include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
- #include <boost/geometry/util/math.hpp>
- #include <boost/geometry/util/select_coordinate_type.hpp>
- #include <boost/geometry/algorithms/detail/normalize.hpp>
- #include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
- #include <boost/geometry/strategy/expand.hpp>
- #include <boost/geometry/strategy/cartesian/expand_point.hpp>
- namespace boost { namespace geometry
- {
- namespace strategy { namespace expand
- {
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail
- {
- template <std::size_t DimensionCount, bool IsEquatorial>
- struct point_loop_on_spheroid
- {
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& point)
- {
- typedef typename point_type<Box>::type box_point_type;
- typedef typename coordinate_type<Box>::type box_coordinate_type;
- typedef typename geometry::detail::cs_angular_units<Box>::type units_type;
- typedef math::detail::constants_on_spheroid
- <
- box_coordinate_type,
- units_type
- > constants;
-
- Point p_normalized;
- strategy::normalize::spherical_point::apply(point, p_normalized);
-
- box_point_type box_point;
- geometry::detail::envelope::transform_units(p_normalized, box_point);
- if (is_inverse_spheroidal_coordinates(box))
- {
- geometry::set_from_radian<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
- geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
- geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
- geometry::set_from_radian<max_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
- } else {
- strategy::normalize::spherical_box::apply(box, box);
- box_coordinate_type p_lon = geometry::get<0>(box_point);
- box_coordinate_type p_lat = geometry::get<1>(box_point);
- typename coordinate_type<Box>::type
- b_lon_min = geometry::get<min_corner, 0>(box),
- b_lat_min = geometry::get<min_corner, 1>(box),
- b_lon_max = geometry::get<max_corner, 0>(box),
- b_lat_max = geometry::get<max_corner, 1>(box);
- if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
- {
-
-
-
-
- geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
- geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
- return;
- }
- if (math::equals(b_lat_min, b_lat_max)
- && math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
- {
-
-
-
-
- geometry::set<min_corner, 0>(box, p_lon);
- geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
- geometry::set<max_corner, 0>(box, p_lon);
- geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
- return;
- }
-
- b_lat_min = (std::min)(b_lat_min, p_lat);
- b_lat_max = (std::max)(b_lat_max, p_lat);
-
- if (math::smaller(p_lon, b_lon_min))
- {
- box_coordinate_type p_lon_shifted = p_lon + constants::period();
- if (math::larger(p_lon_shifted, b_lon_max))
- {
-
- if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
- {
- b_lon_min = p_lon;
- }
- else
- {
- b_lon_max = p_lon_shifted;
- }
- }
- }
- else if (math::larger(p_lon, b_lon_max))
- {
-
-
- if (b_lon_min < 0
- && math::larger(p_lon - b_lon_max,
- constants::period() - p_lon + b_lon_min))
- {
- b_lon_min = p_lon;
- b_lon_max += constants::period();
- }
- else
- {
- b_lon_max = p_lon;
- }
- }
- geometry::set<min_corner, 0>(box, b_lon_min);
- geometry::set<min_corner, 1>(box, b_lat_min);
- geometry::set<max_corner, 0>(box, b_lon_max);
- geometry::set<max_corner, 1>(box, b_lat_max);
- }
- point_loop
- <
- 2, DimensionCount
- >::apply(box, point);
- }
- };
- }
- #endif
- struct spherical_point
- {
- template <typename Box, typename Point>
- static void apply(Box & box, Point const& point)
- {
- expand::detail::point_loop_on_spheroid
- <
- dimension<Point>::value,
- ! std::is_same<typename cs_tag<Point>::type, spherical_polar_tag>::value
- >::apply(box, point);
- }
- };
- #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
- namespace services
- {
- template <typename CalculationType>
- struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
- {
- typedef spherical_point type;
- };
- template <typename CalculationType>
- struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
- {
- typedef spherical_point type;
- };
- template <typename CalculationType>
- struct default_strategy<point_tag, geographic_tag, CalculationType>
- {
- typedef spherical_point type;
- };
- }
- #endif
- }}
- }}
- #endif
|