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) 2014-2015 Samuel Debionne, Grenoble, France. 7 8 // This file was modified by Oracle on 2015, 2016, 2017, 2018, 2019. 9 // Modifications copyright (c) 2015-2019, Oracle and/or its affiliates. 10 11 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle 12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 13 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 14 15 // Distributed under the Boost Software License, Version 1.0. 16 // (See accompanying file LICENSE_1_0.txt or copy at 17 // http://www.boost.org/LICENSE_1_0.txt) 18 19 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP 20 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP 21 22 #include <algorithm> 23 #include <cstddef> 24 25 #include <boost/geometry/core/cs.hpp> 26 #include <boost/geometry/core/coordinate_dimension.hpp> 27 #include <boost/geometry/core/coordinate_system.hpp> 28 #include <boost/geometry/core/tags.hpp> 29 30 #include <boost/geometry/algorithms/convert.hpp> 31 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> 32 #include <boost/geometry/algorithms/detail/normalize.hpp> 33 #include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> 34 #include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> 35 #include <boost/geometry/algorithms/dispatch/envelope.hpp> 36 37 #include <boost/geometry/geometries/helper_geometry.hpp> 38 39 #include <boost/geometry/strategies/expand.hpp> 40 41 #include <boost/geometry/views/detail/indexed_point_view.hpp> 42 43 namespace boost { namespace geometry 44 { 45 46 47 #ifndef DOXYGEN_NO_DETAIL 48 namespace detail { namespace envelope 49 { 50 51 template 52 < 53 std::size_t Index, 54 std::size_t DimensionCount 55 > 56 struct envelope_indexed_box_on_spheroid 57 { 58 template <typename BoxIn, typename BoxOut> applyboost::geometry::detail::envelope::envelope_indexed_box_on_spheroid59 static inline void apply(BoxIn const& box_in, BoxOut& mbr) 60 { 61 // transform() does not work with boxes of dimension higher 62 // than 2; to account for such boxes we transform the min/max 63 // points of the boxes using the indexed_point_view 64 detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in); 65 detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr); 66 67 // first transform the units 68 transform_units(box_in_corner, mbr_corner); 69 70 // now transform the remaining coordinates 71 detail::conversion::point_to_point 72 < 73 detail::indexed_point_view<BoxIn const, Index>, 74 detail::indexed_point_view<BoxOut, Index>, 75 2, 76 DimensionCount 77 >::apply(box_in_corner, mbr_corner); 78 } 79 }; 80 81 struct envelope_box_on_spheroid 82 { 83 template <typename BoxIn, typename BoxOut> applyboost::geometry::detail::envelope::envelope_box_on_spheroid84 static inline void apply(BoxIn const& box_in, BoxOut& mbr) 85 { 86 // BoxIn can be non-mutable 87 typename helper_geometry<BoxIn>::type box_in_normalized; 88 geometry::convert(box_in, box_in_normalized); 89 90 if (! is_inverse_spheroidal_coordinates(box_in)) 91 { 92 strategy::normalize::spherical_box::apply(box_in, box_in_normalized); 93 } 94 95 geometry::detail::envelope::envelope_indexed_box_on_spheroid 96 < 97 min_corner, dimension<BoxIn>::value 98 >::apply(box_in_normalized, mbr); 99 100 geometry::detail::envelope::envelope_indexed_box_on_spheroid 101 < 102 max_corner, dimension<BoxIn>::value 103 >::apply(box_in_normalized, mbr); 104 } 105 }; 106 107 }} // namespace detail::envelope 108 #endif // DOXYGEN_NO_DETAIL 109 110 111 namespace strategy { namespace expand 112 { 113 114 #ifndef DOXYGEN_NO_DETAIL 115 namespace detail 116 { 117 118 struct box_on_spheroid 119 { 120 template <typename BoxOut, typename BoxIn> applyboost::geometry::strategy::expand::detail::box_on_spheroid121 static inline void apply(BoxOut& box_out, BoxIn const& box_in) 122 { 123 // normalize both boxes and convert box-in to be of type of box-out 124 BoxOut mbrs[2]; 125 geometry::detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); 126 geometry::detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); 127 128 // compute the envelope of the two boxes 129 geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); 130 } 131 }; 132 133 134 } // namespace detail 135 #endif // DOXYGEN_NO_DETAIL 136 137 138 struct spherical_box 139 : detail::box_on_spheroid 140 {}; 141 142 143 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 144 145 namespace services 146 { 147 148 template <typename CalculationType> 149 struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType> 150 { 151 typedef spherical_box type; 152 }; 153 154 template <typename CalculationType> 155 struct default_strategy<box_tag, spherical_polar_tag, CalculationType> 156 { 157 typedef spherical_box type; 158 }; 159 160 template <typename CalculationType> 161 struct default_strategy<box_tag, geographic_tag, CalculationType> 162 { 163 typedef spherical_box type; 164 }; 165 166 } // namespace services 167 168 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS 169 170 171 }} // namespace strategy::expand 172 173 }} // namespace boost::geometry 174 175 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP 176