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, 2018.
8 // Modifications copyright (c) 2013-2018 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<Geometry1, Geometry2, Strategy>();
74 
75         return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
76     }
77 
78     template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::within79     static inline bool apply(Geometry1 const& geometry1,
80                              Geometry2 const& geometry2,
81                              default_strategy)
82     {
83         typedef typename strategy::within::services::default_strategy
84             <
85                 Geometry1,
86                 Geometry2
87             >::type strategy_type;
88 
89         return apply(geometry1, geometry2, strategy_type());
90     }
91 };
92 
93 } // namespace resolve_strategy
94 
95 
96 namespace resolve_variant
97 {
98 
99 template <typename Geometry1, typename Geometry2>
100 struct within
101 {
102     template <typename Strategy>
applyboost::geometry::resolve_variant::within103     static inline bool apply(Geometry1 const& geometry1,
104                              Geometry2 const& geometry2,
105                              Strategy const& strategy)
106     {
107         concepts::check<Geometry1 const>();
108         concepts::check<Geometry2 const>();
109         assert_dimension_equal<Geometry1, Geometry2>();
110 
111         return resolve_strategy::within::apply(geometry1,
112                                                geometry2,
113                                                strategy);
114     }
115 };
116 
117 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
118 struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
119 {
120     template <typename Strategy>
121     struct visitor: boost::static_visitor<bool>
122     {
123         Geometry2 const& m_geometry2;
124         Strategy const& m_strategy;
125 
visitorboost::geometry::resolve_variant::within::visitor126         visitor(Geometry2 const& geometry2, Strategy const& strategy)
127             : m_geometry2(geometry2)
128             , m_strategy(strategy)
129         {}
130 
131         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::within::visitor132         bool operator()(Geometry1 const& geometry1) const
133         {
134             return within<Geometry1, Geometry2>::apply(geometry1,
135                                                        m_geometry2,
136                                                        m_strategy);
137         }
138     };
139 
140     template <typename Strategy>
141     static inline bool
applyboost::geometry::resolve_variant::within142     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
143           Geometry2 const& geometry2,
144           Strategy const& strategy)
145     {
146         return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
147                                     geometry1);
148     }
149 };
150 
151 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
152 struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
153 {
154     template <typename Strategy>
155     struct visitor: boost::static_visitor<bool>
156     {
157         Geometry1 const& m_geometry1;
158         Strategy const& m_strategy;
159 
visitorboost::geometry::resolve_variant::within::visitor160         visitor(Geometry1 const& geometry1, Strategy const& strategy)
161             : m_geometry1(geometry1)
162             , m_strategy(strategy)
163         {}
164 
165         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor166         bool operator()(Geometry2 const& geometry2) const
167         {
168             return within<Geometry1, Geometry2>::apply(m_geometry1,
169                                                        geometry2,
170                                                        m_strategy);
171         }
172     };
173 
174     template <typename Strategy>
175     static inline bool
applyboost::geometry::resolve_variant::within176     apply(Geometry1 const& geometry1,
177           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
178           Strategy const& strategy)
179     {
180         return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
181                                     geometry2
182         );
183     }
184 };
185 
186 template <
187     BOOST_VARIANT_ENUM_PARAMS(typename T1),
188     BOOST_VARIANT_ENUM_PARAMS(typename T2)
189 >
190 struct within<
191     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
192     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
193 >
194 {
195     template <typename Strategy>
196     struct visitor: boost::static_visitor<bool>
197     {
198         Strategy const& m_strategy;
199 
visitorboost::geometry::resolve_variant::within::visitor200         visitor(Strategy const& strategy): m_strategy(strategy) {}
201 
202         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::within::visitor203         bool operator()(Geometry1 const& geometry1,
204                         Geometry2 const& geometry2) const
205         {
206             return within<Geometry1, Geometry2>::apply(geometry1,
207                                                        geometry2,
208                                                        m_strategy);
209         }
210     };
211 
212     template <typename Strategy>
213     static inline bool
applyboost::geometry::resolve_variant::within214     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
215           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
216           Strategy const& strategy)
217     {
218         return boost::apply_visitor(visitor<Strategy>(strategy),
219                                     geometry1,
220                                     geometry2);
221     }
222 };
223 
224 }
225 
226 
227 /*!
228 \brief \brief_check12{is completely inside}
229 \ingroup within
230 \details \details_check12{within, is completely inside}.
231 \tparam Geometry1 \tparam_geometry
232 \tparam Geometry2 \tparam_geometry
233 \param geometry1 \param_geometry which might be within the second geometry
234 \param geometry2 \param_geometry which might contain the first geometry
235 \return true if geometry1 is completely contained within geometry2,
236     else false
237 \note The default strategy is used for within detection
238 
239 
240 \qbk{[include reference/algorithms/within.qbk]}
241 
242 \qbk{
243 [heading Example]
244 [within]
245 [within_output]
246 }
247  */
248 template<typename Geometry1, typename Geometry2>
within(Geometry1 const & geometry1,Geometry2 const & geometry2)249 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
250 {
251     return resolve_variant::within
252         <
253             Geometry1,
254             Geometry2
255         >::apply(geometry1, geometry2, default_strategy());
256 }
257 
258 /*!
259 \brief \brief_check12{is completely inside} \brief_strategy
260 \ingroup within
261 \details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
262 \tparam Geometry1 \tparam_geometry
263 \tparam Geometry2 \tparam_geometry
264 \param geometry1 \param_geometry which might be within the second geometry
265 \param geometry2 \param_geometry which might contain the first geometry
266 \param strategy strategy to be used
267 \return true if geometry1 is completely contained within geometry2,
268     else false
269 
270 \qbk{distinguish,with strategy}
271 \qbk{[include reference/algorithms/within.qbk]}
272 \qbk{
273 [heading Available Strategies]
274 \* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
275 \* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
276 \* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
277 
278 [heading Example]
279 [within_strategy]
280 [within_strategy_output]
281 
282 }
283 */
284 template<typename Geometry1, typename Geometry2, typename Strategy>
within(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)285 inline bool within(Geometry1 const& geometry1,
286                    Geometry2 const& geometry2,
287                    Strategy const& strategy)
288 {
289     return resolve_variant::within
290         <
291             Geometry1,
292             Geometry2
293         >::apply(geometry1, geometry2, strategy);
294 }
295 
296 }} // namespace boost::geometry
297 
298 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
299