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