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, 2014, 2017.
8 // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
9 
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
20 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
21 
22 
23 #include <boost/concept_check.hpp>
24 
25 #include <boost/variant/apply_visitor.hpp>
26 #include <boost/variant/static_visitor.hpp>
27 #include <boost/variant/variant_fwd.hpp>
28 
29 #include <boost/geometry/algorithms/not_implemented.hpp>
30 
31 #include <boost/geometry/core/tag.hpp>
32 #include <boost/geometry/core/tag_cast.hpp>
33 
34 #include <boost/geometry/geometries/concepts/check.hpp>
35 #include <boost/geometry/strategies/concepts/within_concept.hpp>
36 #include <boost/geometry/strategies/default_strategy.hpp>
37 #include <boost/geometry/strategies/within.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 struct within
67 {
68     template <typename Geometry1, typename Geometry2, typename Strategy>
applyboost::geometry::resolve_strategy::within69     static inline bool apply(Geometry1 const& geometry1,
70                              Geometry2 const& geometry2,
71                              Strategy const& strategy)
72     {
73         concepts::within::check
74             <
75                 typename tag<Geometry1>::type,
76                 typename tag<Geometry2>::type,
77                 typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
78                 Strategy
79             >();
80 
81         return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
82     }
83 
84     template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::within85     static inline bool apply(Geometry1 const& geometry1,
86                              Geometry2 const& geometry2,
87                              default_strategy)
88     {
89         typedef typename strategy::within::services::default_strategy
90             <
91                 Geometry1,
92                 Geometry2
93             >::type strategy_type;
94 
95         return apply(geometry1, geometry2, strategy_type());
96     }
97 };
98 
99 } // namespace resolve_strategy
100 
101 
102 namespace resolve_variant
103 {
104 
105 template <typename Geometry1, typename Geometry2>
106 struct within
107 {
108     template <typename Strategy>
applyboost::geometry::resolve_variant::within109     static inline bool apply(Geometry1 const& geometry1,
110                              Geometry2 const& geometry2,
111                              Strategy const& strategy)
112     {
113         concepts::check<Geometry1 const>();
114         concepts::check<Geometry2 const>();
115         assert_dimension_equal<Geometry1, Geometry2>();
116 
117         return resolve_strategy::within::apply(geometry1,
118                                                geometry2,
119                                                strategy);
120     }
121 };
122 
123 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
124 struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
125 {
126     template <typename Strategy>
127     struct visitor: boost::static_visitor<bool>
128     {
129         Geometry2 const& m_geometry2;
130         Strategy const& m_strategy;
131 
visitorboost::geometry::resolve_variant::within::visitor132         visitor(Geometry2 const& geometry2, Strategy const& strategy)
133             : m_geometry2(geometry2)
134             , m_strategy(strategy)
135         {}
136 
137         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::within::visitor138         bool operator()(Geometry1 const& geometry1) const
139         {
140             return within<Geometry1, Geometry2>::apply(geometry1,
141                                                        m_geometry2,
142                                                        m_strategy);
143         }
144     };
145 
146     template <typename Strategy>
147     static inline bool
applyboost::geometry::resolve_variant::within148     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
149           Geometry2 const& geometry2,
150           Strategy const& strategy)
151     {
152         return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
153                                     geometry1);
154     }
155 };
156 
157 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
158 struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
159 {
160     template <typename Strategy>
161     struct visitor: boost::static_visitor<bool>
162     {
163         Geometry1 const& m_geometry1;
164         Strategy const& m_strategy;
165 
visitorboost::geometry::resolve_variant::within::visitor166         visitor(Geometry1 const& geometry1, Strategy const& strategy)
167             : m_geometry1(geometry1)
168             , m_strategy(strategy)
169         {}
170 
171         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor172         bool operator()(Geometry2 const& geometry2) const
173         {
174             return within<Geometry1, Geometry2>::apply(m_geometry1,
175                                                        geometry2,
176                                                        m_strategy);
177         }
178     };
179 
180     template <typename Strategy>
181     static inline bool
applyboost::geometry::resolve_variant::within182     apply(Geometry1 const& geometry1,
183           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
184           Strategy const& strategy)
185     {
186         return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
187                                     geometry2
188         );
189     }
190 };
191 
192 template <
193     BOOST_VARIANT_ENUM_PARAMS(typename T1),
194     BOOST_VARIANT_ENUM_PARAMS(typename T2)
195 >
196 struct within<
197     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
198     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
199 >
200 {
201     template <typename Strategy>
202     struct visitor: boost::static_visitor<bool>
203     {
204         Strategy const& m_strategy;
205 
visitorboost::geometry::resolve_variant::within::visitor206         visitor(Strategy const& strategy): m_strategy(strategy) {}
207 
208         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor209         bool operator()(Geometry1 const& geometry1,
210                         Geometry2 const& geometry2) const
211         {
212             return within<Geometry1, Geometry2>::apply(geometry1,
213                                                        geometry2,
214                                                        m_strategy);
215         }
216     };
217 
218     template <typename Strategy>
219     static inline bool
applyboost::geometry::resolve_variant::within220     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
221           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
222           Strategy const& strategy)
223     {
224         return boost::apply_visitor(visitor<Strategy>(strategy),
225                                     geometry1,
226                                     geometry2);
227     }
228 };
229 
230 }
231 
232 
233 /*!
234 \brief \brief_check12{is completely inside}
235 \ingroup within
236 \details \details_check12{within, is completely inside}.
237 \tparam Geometry1 \tparam_geometry
238 \tparam Geometry2 \tparam_geometry
239 \param geometry1 \param_geometry which might be within the second geometry
240 \param geometry2 \param_geometry which might contain the first geometry
241 \return true if geometry1 is completely contained within geometry2,
242     else false
243 \note The default strategy is used for within detection
244 
245 
246 \qbk{[include reference/algorithms/within.qbk]}
247 
248 \qbk{
249 [heading Example]
250 [within]
251 [within_output]
252 }
253  */
254 template<typename Geometry1, typename Geometry2>
within(Geometry1 const & geometry1,Geometry2 const & geometry2)255 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
256 {
257     return resolve_variant::within
258         <
259             Geometry1,
260             Geometry2
261         >::apply(geometry1, geometry2, default_strategy());
262 }
263 
264 /*!
265 \brief \brief_check12{is completely inside} \brief_strategy
266 \ingroup within
267 \details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
268 \tparam Geometry1 \tparam_geometry
269 \tparam Geometry2 \tparam_geometry
270 \param geometry1 \param_geometry which might be within the second geometry
271 \param geometry2 \param_geometry which might contain the first geometry
272 \param strategy strategy to be used
273 \return true if geometry1 is completely contained within geometry2,
274     else false
275 
276 \qbk{distinguish,with strategy}
277 \qbk{[include reference/algorithms/within.qbk]}
278 \qbk{
279 [heading Available Strategies]
280 \* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
281 \* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
282 \* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
283 
284 [heading Example]
285 [within_strategy]
286 [within_strategy_output]
287 
288 }
289 */
290 template<typename Geometry1, typename Geometry2, typename Strategy>
within(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)291 inline bool within(Geometry1 const& geometry1,
292                    Geometry2 const& geometry2,
293                    Strategy const& strategy)
294 {
295     return resolve_variant::within
296         <
297             Geometry1,
298             Geometry2
299         >::apply(geometry1, geometry2, strategy);
300 }
301 
302 }} // namespace boost::geometry
303 
304 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
305