• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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