1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
7 
8 // This file was modified by Oracle on 2013, 2014, 2015, 2017.
9 // Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
10 
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12 
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15 
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
19 
20 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
21 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
22 
23 
24 #include <deque>
25 
26 #include <boost/variant/apply_visitor.hpp>
27 #include <boost/variant/static_visitor.hpp>
28 #include <boost/variant/variant_fwd.hpp>
29 
30 #include <boost/geometry/core/reverse_dispatch.hpp>
31 #include <boost/geometry/core/tag.hpp>
32 #include <boost/geometry/core/tag_cast.hpp>
33 #include <boost/geometry/core/tags.hpp>
34 
35 #include <boost/geometry/geometries/concepts/check.hpp>
36 
37 #include <boost/geometry/strategies/default_strategy.hpp>
38 #include <boost/geometry/strategies/relate.hpp>
39 
40 
41 namespace boost { namespace geometry
42 {
43 
44 #ifndef DOXYGEN_NO_DISPATCH
45 namespace dispatch {
46 
47 // TODO: Since CastedTags are used is Reverse needed?
48 
49 template
50 <
51     typename Geometry1,
52     typename Geometry2,
53     typename Tag1 = typename tag<Geometry1>::type,
54     typename Tag2 = typename tag<Geometry2>::type,
55     typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
56     typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
57     bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
58 >
59 struct touches
60     : not_implemented<Tag1, Tag2>
61 {};
62 
63 // If reversal is needed, perform it
64 template
65 <
66     typename Geometry1, typename Geometry2,
67     typename Tag1, typename Tag2,
68     typename CastedTag1, typename CastedTag2
69 >
70 struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
71     : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
72 {
73     template <typename Strategy>
applyboost::geometry::dispatch::touches74     static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
75     {
76         return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
77     }
78 };
79 
80 } // namespace dispatch
81 #endif // DOXYGEN_NO_DISPATCH
82 
83 
84 namespace resolve_strategy
85 {
86 
87 struct touches
88 {
89     template <typename Geometry1, typename Geometry2, typename Strategy>
applyboost::geometry::resolve_strategy::touches90     static inline bool apply(Geometry1 const& geometry1,
91                              Geometry2 const& geometry2,
92                              Strategy const& strategy)
93     {
94         return dispatch::touches
95             <
96                 Geometry1, Geometry2
97             >::apply(geometry1, geometry2, strategy);
98     }
99 
100     template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::touches101     static inline bool apply(Geometry1 const& geometry1,
102                              Geometry2 const& geometry2,
103                              default_strategy)
104     {
105         typedef typename strategy::relate::services::default_strategy
106             <
107                 Geometry1,
108                 Geometry2
109             >::type strategy_type;
110 
111         return dispatch::touches
112             <
113                 Geometry1, Geometry2
114             >::apply(geometry1, geometry2, strategy_type());
115     }
116 };
117 
118 } // namespace resolve_strategy
119 
120 
121 namespace resolve_variant {
122 
123 template <typename Geometry1, typename Geometry2>
124 struct touches
125 {
126     template <typename Strategy>
applyboost::geometry::resolve_variant::touches127     static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
128     {
129         concepts::check<Geometry1 const>();
130         concepts::check<Geometry2 const>();
131 
132         return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
133     }
134 };
135 
136 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
137 struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
138 {
139     template <typename Strategy>
140     struct visitor: boost::static_visitor<bool>
141     {
142         Geometry2 const& m_geometry2;
143         Strategy const& m_strategy;
144 
visitorboost::geometry::resolve_variant::touches::visitor145         visitor(Geometry2 const& geometry2, Strategy const& strategy)
146             : m_geometry2(geometry2)
147             , m_strategy(strategy)
148         {}
149 
150         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::touches::visitor151         bool operator()(Geometry1 const& geometry1) const
152         {
153             return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
154         }
155     };
156 
157     template <typename Strategy>
applyboost::geometry::resolve_variant::touches158     static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
159                              Geometry2 const& geometry2,
160                              Strategy const& strategy)
161     {
162         return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
163     }
164 };
165 
166 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
167 struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
168 {
169     template <typename Strategy>
170     struct visitor: boost::static_visitor<bool>
171     {
172         Geometry1 const& m_geometry1;
173         Strategy const& m_strategy;
174 
visitorboost::geometry::resolve_variant::touches::visitor175         visitor(Geometry1 const& geometry1, Strategy const& strategy)
176             : m_geometry1(geometry1)
177             , m_strategy(strategy)
178         {}
179 
180         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::touches::visitor181         bool operator()(Geometry2 const& geometry2) const
182         {
183             return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
184         }
185     };
186 
187     template <typename Strategy>
applyboost::geometry::resolve_variant::touches188     static inline bool apply(Geometry1 const& geometry1,
189                              boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
190                              Strategy const& strategy)
191     {
192         return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
193     }
194 };
195 
196 template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
197           BOOST_VARIANT_ENUM_PARAMS(typename T2)>
198 struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
199                boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
200 {
201     template <typename Strategy>
202     struct visitor: boost::static_visitor<bool>
203     {
204         Strategy const& m_strategy;
205 
visitorboost::geometry::resolve_variant::touches::visitor206         visitor(Strategy const& strategy)
207             : m_strategy(strategy)
208         {}
209 
210         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::touches::visitor211         bool operator()(Geometry1 const& geometry1,
212                         Geometry2 const& geometry2) const
213         {
214             return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
215         }
216     };
217 
218     template <typename Strategy>
applyboost::geometry::resolve_variant::touches219     static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
220                              boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
221                              Strategy const& strategy)
222     {
223         return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
224     }
225 };
226 
227 template <typename Geometry>
228 struct self_touches;
229 
230 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
231 struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
232 {
233     struct visitor: boost::static_visitor<bool>
234     {
235         template <typename Geometry>
operator ()boost::geometry::resolve_variant::self_touches::visitor236         bool operator()(Geometry const& geometry) const
237         {
238             return self_touches<Geometry>::apply(geometry);
239         }
240     };
241 
242     static inline bool
applyboost::geometry::resolve_variant::self_touches243     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
244     {
245         return boost::apply_visitor(visitor(), geometry);
246     }
247 };
248 
249 } // namespace resolve_variant
250 
251 
252 /*!
253 \brief \brief_check{has at least one touching point (self-tangency)}
254 \note This function can be called for one geometry (self-tangency) and
255     also for two geometries (touch)
256 \ingroup touches
257 \tparam Geometry \tparam_geometry
258 \param geometry \param_geometry
259 \return \return_check{is self-touching}
260 
261 \qbk{distinguish,one geometry}
262 \qbk{[def __one_parameter__]}
263 \qbk{[include reference/algorithms/touches.qbk]}
264 */
265 template <typename Geometry>
touches(Geometry const & geometry)266 inline bool touches(Geometry const& geometry)
267 {
268     return resolve_variant::self_touches<Geometry>::apply(geometry);
269 }
270 
271 
272 /*!
273 \brief \brief_check2{have at least one touching point (tangent - non overlapping)}
274 \ingroup touches
275 \tparam Geometry1 \tparam_geometry
276 \tparam Geometry2 \tparam_geometry
277 \param geometry1 \param_geometry
278 \param geometry2 \param_geometry
279 \return \return_check2{touch each other}
280 
281 \qbk{distinguish,two geometries}
282 \qbk{[include reference/algorithms/touches.qbk]}
283  */
284 template <typename Geometry1, typename Geometry2>
touches(Geometry1 const & geometry1,Geometry2 const & geometry2)285 inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
286 {
287     return resolve_variant::touches
288         <
289             Geometry1, Geometry2
290         >::apply(geometry1, geometry2, default_strategy());
291 }
292 
293 /*!
294 \brief \brief_check2{have at least one touching point (tangent - non overlapping)}
295 \ingroup touches
296 \tparam Geometry1 \tparam_geometry
297 \tparam Geometry2 \tparam_geometry
298 \tparam Strategy \tparam_strategy{Touches}
299 \param geometry1 \param_geometry
300 \param geometry2 \param_geometry
301 \param strategy \param_strategy{touches}
302 \return \return_check2{touch each other}
303 
304 \qbk{distinguish,with strategy}
305 \qbk{[include reference/algorithms/touches.qbk]}
306  */
307 template <typename Geometry1, typename Geometry2, typename Strategy>
touches(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)308 inline bool touches(Geometry1 const& geometry1,
309                     Geometry2 const& geometry2,
310                     Strategy const& strategy)
311 {
312     return resolve_variant::touches
313         <
314             Geometry1, Geometry2
315         >::apply(geometry1, geometry2, strategy);
316 }
317 
318 
319 }} // namespace boost::geometry
320 
321 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
322