1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2014, 2019, 2020 Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 7 8 // Licensed under the Boost Software License version 1.0. 9 // http://www.boost.org/users/license.html 10 11 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP 12 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP 13 14 #include <boost/range.hpp> 15 16 #include <boost/geometry/core/point_type.hpp> 17 #include <boost/geometry/core/tags.hpp> 18 19 #include <boost/geometry/strategies/distance.hpp> 20 #include <boost/geometry/strategies/tags.hpp> 21 22 #include <boost/geometry/algorithms/covered_by.hpp> 23 24 #include <boost/geometry/algorithms/dispatch/distance.hpp> 25 26 #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> 27 #include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp> 28 29 30 namespace boost { namespace geometry 31 { 32 33 #ifndef DOXYGEN_NO_DETAIL 34 namespace detail { namespace distance 35 { 36 37 38 template <typename MultiPoint1, typename MultiPoint2, typename Strategy> 39 struct multipoint_to_multipoint 40 { 41 typedef typename strategy::distance::services::return_type 42 < 43 Strategy, 44 typename point_type<MultiPoint1>::type, 45 typename point_type<MultiPoint2>::type 46 >::type return_type; 47 applyboost::geometry::detail::distance::multipoint_to_multipoint48 static inline return_type apply(MultiPoint1 const& multipoint1, 49 MultiPoint2 const& multipoint2, 50 Strategy const& strategy) 51 { 52 if (boost::size(multipoint2) < boost::size(multipoint1)) 53 54 { 55 return point_or_segment_range_to_geometry_rtree 56 < 57 typename boost::range_iterator<MultiPoint2 const>::type, 58 MultiPoint1, 59 Strategy 60 >::apply(boost::begin(multipoint2), 61 boost::end(multipoint2), 62 multipoint1, 63 strategy); 64 } 65 66 return point_or_segment_range_to_geometry_rtree 67 < 68 typename boost::range_iterator<MultiPoint1 const>::type, 69 MultiPoint2, 70 Strategy 71 >::apply(boost::begin(multipoint1), 72 boost::end(multipoint1), 73 multipoint2, 74 strategy); 75 } 76 }; 77 78 79 template <typename MultiPoint, typename Linear, typename Strategy> 80 struct multipoint_to_linear 81 { 82 typedef typename strategy::distance::services::return_type 83 < 84 Strategy, 85 typename point_type<MultiPoint>::type, 86 typename point_type<Linear>::type 87 >::type return_type; 88 applyboost::geometry::detail::distance::multipoint_to_linear89 static inline return_type apply(MultiPoint const& multipoint, 90 Linear const& linear, 91 Strategy const& strategy) 92 { 93 return detail::distance::point_or_segment_range_to_geometry_rtree 94 < 95 typename boost::range_iterator<MultiPoint const>::type, 96 Linear, 97 Strategy 98 >::apply(boost::begin(multipoint), 99 boost::end(multipoint), 100 linear, 101 strategy); 102 } 103 applyboost::geometry::detail::distance::multipoint_to_linear104 static inline return_type apply(Linear const& linear, 105 MultiPoint const& multipoint, 106 Strategy const& strategy) 107 { 108 return apply(multipoint, linear, strategy); 109 } 110 }; 111 112 113 template <typename MultiPoint, typename Areal, typename Strategy> 114 class multipoint_to_areal 115 { 116 private: 117 template <typename CoveredByStrategy> 118 struct not_covered_by_areal 119 { not_covered_by_arealboost::geometry::detail::distance::multipoint_to_areal::not_covered_by_areal120 not_covered_by_areal(Areal const& areal, CoveredByStrategy const& strategy) 121 : m_areal(areal), m_strategy(strategy) 122 {} 123 124 template <typename Point> applyboost::geometry::detail::distance::multipoint_to_areal::not_covered_by_areal125 inline bool apply(Point const& point) const 126 { 127 return !geometry::covered_by(point, m_areal, m_strategy); 128 } 129 130 Areal const& m_areal; 131 CoveredByStrategy const& m_strategy; 132 }; 133 134 public: 135 typedef typename strategy::distance::services::return_type 136 < 137 Strategy, 138 typename point_type<MultiPoint>::type, 139 typename point_type<Areal>::type 140 >::type return_type; 141 apply(MultiPoint const & multipoint,Areal const & areal,Strategy const & strategy)142 static inline return_type apply(MultiPoint const& multipoint, 143 Areal const& areal, 144 Strategy const& strategy) 145 { 146 typedef typename Strategy::point_in_geometry_strategy_type pg_strategy_type; 147 148 typedef not_covered_by_areal<pg_strategy_type> predicate_type; 149 150 // predicate holds references so the strategy has to be created here 151 pg_strategy_type pg_strategy = strategy.get_point_in_geometry_strategy(); 152 predicate_type predicate(areal, pg_strategy); 153 154 if (check_iterator_range 155 < 156 predicate_type, false 157 >::apply(boost::begin(multipoint), 158 boost::end(multipoint), 159 predicate)) 160 { 161 return detail::distance::point_or_segment_range_to_geometry_rtree 162 < 163 typename boost::range_iterator<MultiPoint const>::type, 164 Areal, 165 Strategy 166 >::apply(boost::begin(multipoint), 167 boost::end(multipoint), 168 areal, 169 strategy); 170 } 171 return 0; 172 } 173 apply(Areal const & areal,MultiPoint const & multipoint,Strategy const & strategy)174 static inline return_type apply(Areal const& areal, 175 MultiPoint const& multipoint, 176 Strategy const& strategy) 177 { 178 return apply(multipoint, areal, strategy); 179 } 180 }; 181 182 183 }} // namespace detail::distance 184 #endif // DOXYGEN_NO_DETAIL 185 186 187 188 #ifndef DOXYGEN_NO_DISPATCH 189 namespace dispatch 190 { 191 192 193 template <typename MultiPoint1, typename MultiPoint2, typename Strategy> 194 struct distance 195 < 196 MultiPoint1, MultiPoint2, Strategy, 197 multi_point_tag, multi_point_tag, 198 strategy_tag_distance_point_point, false 199 > : detail::distance::multipoint_to_multipoint 200 < 201 MultiPoint1, MultiPoint2, Strategy 202 > 203 {}; 204 205 206 template <typename MultiPoint, typename Linear, typename Strategy> 207 struct distance 208 < 209 MultiPoint, Linear, Strategy, multi_point_tag, linear_tag, 210 strategy_tag_distance_point_segment, false 211 > : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy> 212 {}; 213 214 215 template <typename Linear, typename MultiPoint, typename Strategy> 216 struct distance 217 < 218 Linear, MultiPoint, Strategy, linear_tag, multi_point_tag, 219 strategy_tag_distance_point_segment, false 220 > : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy> 221 {}; 222 223 224 template <typename MultiPoint, typename Areal, typename Strategy> 225 struct distance 226 < 227 MultiPoint, Areal, Strategy, multi_point_tag, areal_tag, 228 strategy_tag_distance_point_segment, false 229 > : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy> 230 {}; 231 232 233 template <typename Areal, typename MultiPoint, typename Strategy> 234 struct distance 235 < 236 Areal, MultiPoint, Strategy, areal_tag, multi_point_tag, 237 strategy_tag_distance_point_segment, false 238 > : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy> 239 {}; 240 241 242 } // namespace dispatch 243 #endif // DOXYGEN_NO_DISPATCH 244 245 246 }} // namespace boost::geometry 247 248 249 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP 250