// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. // This file was modified by Oracle on 2015-2020. // Modifications copyright (c) 2015-2020, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { namespace strategy { namespace expand { #ifndef DOXYGEN_NO_DETAIL namespace detail { // implementation for the spherical and geographic coordinate systems template struct point_loop_on_spheroid { template static inline void apply(Box& box, Point const& point) { typedef typename point_type::type box_point_type; typedef typename coordinate_type::type box_coordinate_type; typedef typename geometry::detail::cs_angular_units::type units_type; typedef math::detail::constants_on_spheroid < box_coordinate_type, units_type > constants; // normalize input point and input box Point p_normalized; strategy::normalize::spherical_point::apply(point, p_normalized); // transform input point to be of the same type as the box point box_point_type box_point; geometry::detail::envelope::transform_units(p_normalized, box_point); if (is_inverse_spheroidal_coordinates(box)) { geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); geometry::set_from_radian(box, geometry::get_as_radian<1>(p_normalized)); geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); geometry::set_from_radian(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::type b_lon_min = geometry::get(box), b_lat_min = geometry::get(box), b_lon_max = geometry::get(box), b_lat_max = geometry::get(box); if (math::is_latitude_pole(p_lat)) { // the point of expansion is the either the north or the // south pole; the only important coordinate here is the // pole's latitude, as the longitude can be anything; // we, thus, take into account the point's latitude only and return geometry::set(box, (std::min)(p_lat, b_lat_min)); geometry::set(box, (std::max)(p_lat, b_lat_max)); return; } if (math::equals(b_lat_min, b_lat_max) && math::is_latitude_pole(b_lat_min)) { // the box degenerates to either the north or the south pole; // the only important coordinate here is the pole's latitude, // as the longitude can be anything; // we thus take into account the box's latitude only and return geometry::set(box, p_lon); geometry::set(box, (std::min)(p_lat, b_lat_min)); geometry::set(box, p_lon); geometry::set(box, (std::max)(p_lat, b_lat_max)); return; } // update latitudes b_lat_min = (std::min)(b_lat_min, p_lat); b_lat_max = (std::max)(b_lat_max, p_lat); // update longitudes 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)) { // here we could check using: ! math::larger(.., ..) 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)) { // in this case, and since p_lon is normalized in the range // (-180, 180], we must have that b_lon_max <= 180 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(box, b_lon_min); geometry::set(box, b_lat_min); geometry::set(box, b_lon_max); geometry::set(box, b_lat_max); } point_loop < 2, DimensionCount >::apply(box, point); } }; } // namespace detail #endif // DOXYGEN_NO_DETAIL struct spherical_point { template static void apply(Box & box, Point const& point) { expand::detail::point_loop_on_spheroid < dimension::value, ! std::is_same::type, spherical_polar_tag>::value >::apply(box, point); } }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { template struct default_strategy { typedef spherical_point type; }; template struct default_strategy { typedef spherical_point type; }; template struct default_strategy { typedef spherical_point type; }; } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS }} // namespace strategy::expand }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP