1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
7 // This file was modified by Oracle on 2013-2021.
8 // Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
17
18 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
19 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
20
21
22 #include <boost/concept_check.hpp>
23
24 #include <boost/variant/apply_visitor.hpp>
25 #include <boost/variant/static_visitor.hpp>
26 #include <boost/variant/variant_fwd.hpp>
27
28 #include <boost/geometry/algorithms/not_implemented.hpp>
29
30 #include <boost/geometry/core/tag.hpp>
31 #include <boost/geometry/core/tag_cast.hpp>
32
33 #include <boost/geometry/geometries/concepts/check.hpp>
34 #include <boost/geometry/strategies/concepts/within_concept.hpp>
35 #include <boost/geometry/strategies/default_strategy.hpp>
36 #include <boost/geometry/strategies/detail.hpp>
37 #include <boost/geometry/strategies/relate/services.hpp>
38
39
40 namespace boost { namespace geometry
41 {
42
43 #ifndef DOXYGEN_NO_DISPATCH
44 namespace dispatch
45 {
46
47 template
48 <
49 typename Geometry1,
50 typename Geometry2,
51 typename Tag1 = typename tag<Geometry1>::type,
52 typename Tag2 = typename tag<Geometry2>::type
53 >
54 struct within
55 : not_implemented<Tag1, Tag2>
56 {};
57
58
59 } // namespace dispatch
60 #endif // DOXYGEN_NO_DISPATCH
61
62
63 namespace resolve_strategy
64 {
65
66 template
67 <
68 typename Strategy,
69 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
70 >
71 struct within
72 {
73 template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::within74 static inline bool apply(Geometry1 const& geometry1,
75 Geometry2 const& geometry2,
76 Strategy const& strategy)
77 {
78 concepts::within::check<Geometry1, Geometry2, Strategy>();
79
80 return dispatch::within
81 <
82 Geometry1, Geometry2
83 >::apply(geometry1, geometry2, strategy);
84 }
85 };
86
87 template <typename Strategy>
88 struct within<Strategy, false>
89 {
90 template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::within91 static inline bool apply(Geometry1 const& geometry1,
92 Geometry2 const& geometry2,
93 Strategy const& strategy)
94 {
95 using strategies::relate::services::strategy_converter;
96
97 return within
98 <
99 decltype(strategy_converter<Strategy>::get(strategy))
100 >::apply(geometry1, geometry2,
101 strategy_converter<Strategy>::get(strategy));
102 }
103 };
104
105 template <>
106 struct within<default_strategy, false>
107 {
108 template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::within109 static inline bool apply(Geometry1 const& geometry1,
110 Geometry2 const& geometry2,
111 default_strategy)
112 {
113 typedef typename strategies::relate::services::default_strategy
114 <
115 Geometry1,
116 Geometry2
117 >::type strategy_type;
118
119 return within
120 <
121 strategy_type
122 >::apply(geometry1, geometry2, strategy_type());
123 }
124 };
125
126 } // namespace resolve_strategy
127
128
129 namespace resolve_variant
130 {
131
132 template <typename Geometry1, typename Geometry2>
133 struct within
134 {
135 template <typename Strategy>
applyboost::geometry::resolve_variant::within136 static inline bool apply(Geometry1 const& geometry1,
137 Geometry2 const& geometry2,
138 Strategy const& strategy)
139 {
140 concepts::check<Geometry1 const>();
141 concepts::check<Geometry2 const>();
142 assert_dimension_equal<Geometry1, Geometry2>();
143
144 return resolve_strategy::within
145 <
146 Strategy
147 >::apply(geometry1, geometry2, strategy);
148 }
149 };
150
151 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
152 struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
153 {
154 template <typename Strategy>
155 struct visitor: boost::static_visitor<bool>
156 {
157 Geometry2 const& m_geometry2;
158 Strategy const& m_strategy;
159
visitorboost::geometry::resolve_variant::within::visitor160 visitor(Geometry2 const& geometry2, Strategy const& strategy)
161 : m_geometry2(geometry2)
162 , m_strategy(strategy)
163 {}
164
165 template <typename Geometry1>
operator ()boost::geometry::resolve_variant::within::visitor166 bool operator()(Geometry1 const& geometry1) const
167 {
168 return within<Geometry1, Geometry2>::apply(geometry1,
169 m_geometry2,
170 m_strategy);
171 }
172 };
173
174 template <typename Strategy>
175 static inline bool
applyboost::geometry::resolve_variant::within176 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
177 Geometry2 const& geometry2,
178 Strategy const& strategy)
179 {
180 return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
181 geometry1);
182 }
183 };
184
185 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
186 struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
187 {
188 template <typename Strategy>
189 struct visitor: boost::static_visitor<bool>
190 {
191 Geometry1 const& m_geometry1;
192 Strategy const& m_strategy;
193
visitorboost::geometry::resolve_variant::within::visitor194 visitor(Geometry1 const& geometry1, Strategy const& strategy)
195 : m_geometry1(geometry1)
196 , m_strategy(strategy)
197 {}
198
199 template <typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor200 bool operator()(Geometry2 const& geometry2) const
201 {
202 return within<Geometry1, Geometry2>::apply(m_geometry1,
203 geometry2,
204 m_strategy);
205 }
206 };
207
208 template <typename Strategy>
209 static inline bool
applyboost::geometry::resolve_variant::within210 apply(Geometry1 const& geometry1,
211 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
212 Strategy const& strategy)
213 {
214 return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
215 geometry2
216 );
217 }
218 };
219
220 template <
221 BOOST_VARIANT_ENUM_PARAMS(typename T1),
222 BOOST_VARIANT_ENUM_PARAMS(typename T2)
223 >
224 struct within<
225 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
226 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
227 >
228 {
229 template <typename Strategy>
230 struct visitor: boost::static_visitor<bool>
231 {
232 Strategy const& m_strategy;
233
visitorboost::geometry::resolve_variant::within::visitor234 visitor(Strategy const& strategy): m_strategy(strategy) {}
235
236 template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor237 bool operator()(Geometry1 const& geometry1,
238 Geometry2 const& geometry2) const
239 {
240 return within<Geometry1, Geometry2>::apply(geometry1,
241 geometry2,
242 m_strategy);
243 }
244 };
245
246 template <typename Strategy>
247 static inline bool
applyboost::geometry::resolve_variant::within248 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
249 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
250 Strategy const& strategy)
251 {
252 return boost::apply_visitor(visitor<Strategy>(strategy),
253 geometry1,
254 geometry2);
255 }
256 };
257
258 }
259
260
261 /*!
262 \brief \brief_check12{is completely inside}
263 \ingroup within
264 \details \details_check12{within, is completely inside}.
265 \tparam Geometry1 \tparam_geometry
266 \tparam Geometry2 \tparam_geometry
267 \param geometry1 \param_geometry which might be within the second geometry
268 \param geometry2 \param_geometry which might contain the first geometry
269 \return true if geometry1 is completely contained within geometry2,
270 else false
271 \note The default strategy is used for within detection
272
273
274 \qbk{[include reference/algorithms/within.qbk]}
275
276 \qbk{
277 [heading Example]
278 [within]
279 [within_output]
280 }
281 */
282 template<typename Geometry1, typename Geometry2>
within(Geometry1 const & geometry1,Geometry2 const & geometry2)283 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
284 {
285 return resolve_variant::within
286 <
287 Geometry1,
288 Geometry2
289 >::apply(geometry1, geometry2, default_strategy());
290 }
291
292 /*!
293 \brief \brief_check12{is completely inside} \brief_strategy
294 \ingroup within
295 \details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
296 \tparam Geometry1 \tparam_geometry
297 \tparam Geometry2 \tparam_geometry
298 \param geometry1 \param_geometry which might be within the second geometry
299 \param geometry2 \param_geometry which might contain the first geometry
300 \param strategy strategy to be used
301 \return true if geometry1 is completely contained within geometry2,
302 else false
303
304 \qbk{distinguish,with strategy}
305 \qbk{[include reference/algorithms/within.qbk]}
306 \qbk{
307 [heading Available Strategies]
308 \* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
309 \* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
310 \* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
311
312 [heading Example]
313 [within_strategy]
314 [within_strategy_output]
315
316 }
317 */
318 template<typename Geometry1, typename Geometry2, typename Strategy>
within(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)319 inline bool within(Geometry1 const& geometry1,
320 Geometry2 const& geometry2,
321 Strategy const& strategy)
322 {
323 return resolve_variant::within
324 <
325 Geometry1,
326 Geometry2
327 >::apply(geometry1, geometry2, strategy);
328 }
329
330 }} // namespace boost::geometry
331
332 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
333