]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
20effc67 TL |
5 | // This file was modified by Oracle on 2013-2020. |
6 | // Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. | |
7c673cae FG |
7 | |
8 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
9 | ||
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
14 | #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP | |
15 | #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP | |
16 | ||
17 | ||
20effc67 TL |
18 | #include <tuple> |
19 | ||
7c673cae FG |
20 | #include <boost/variant/apply_visitor.hpp> |
21 | #include <boost/variant/static_visitor.hpp> | |
22 | #include <boost/variant/variant_fwd.hpp> | |
23 | ||
20effc67 TL |
24 | #include <boost/geometry/algorithms/detail/relate/de9im.hpp> |
25 | #include <boost/geometry/algorithms/not_implemented.hpp> | |
7c673cae FG |
26 | #include <boost/geometry/core/coordinate_dimension.hpp> |
27 | #include <boost/geometry/core/tag.hpp> | |
28 | #include <boost/geometry/core/tags.hpp> | |
29 | #include <boost/geometry/core/topological_dimension.hpp> | |
7c673cae FG |
30 | #include <boost/geometry/geometries/concepts/check.hpp> |
31 | #include <boost/geometry/strategies/default_strategy.hpp> | |
1e59de90 TL |
32 | #include <boost/geometry/strategies/detail.hpp> |
33 | #include <boost/geometry/strategies/relate/services.hpp> | |
20effc67 TL |
34 | #include <boost/geometry/util/sequence.hpp> |
35 | #include <boost/geometry/util/type_traits.hpp> | |
7c673cae FG |
36 | |
37 | ||
38 | namespace boost { namespace geometry { | |
39 | ||
40 | ||
41 | #ifndef DOXYGEN_NO_DETAIL | |
42 | namespace detail { namespace relate { | |
43 | ||
20effc67 TL |
44 | // is_generic allows dispatch::relate to generate compile-time error |
45 | template <typename Geometry1, typename Geometry2> | |
7c673cae FG |
46 | struct is_generic |
47 | { | |
20effc67 TL |
48 | static const bool value = (util::is_polysegmental<Geometry1>::value |
49 | && util::is_polysegmental<Geometry2>::value) | |
50 | || | |
51 | (util::is_point<Geometry1>::value | |
52 | && util::is_polysegmental<Geometry2>::value) | |
53 | || | |
54 | (util::is_polysegmental<Geometry1>::value | |
55 | && util::is_point<Geometry2>::value); | |
7c673cae FG |
56 | }; |
57 | ||
7c673cae FG |
58 | }} // namespace detail::relate |
59 | #endif // DOXYGEN_NO_DETAIL | |
60 | ||
61 | ||
62 | #ifndef DOXYGEN_NO_DISPATCH | |
63 | namespace dispatch { | |
64 | ||
65 | ||
66 | template <typename Geometry1, | |
67 | typename Geometry2, | |
68 | typename Tag1 = typename geometry::tag<Geometry1>::type, | |
69 | typename Tag2 = typename geometry::tag<Geometry2>::type, | |
70 | int TopDim1 = geometry::topological_dimension<Geometry1>::value, | |
71 | int TopDim2 = geometry::topological_dimension<Geometry2>::value, | |
72 | bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value | |
73 | > | |
74 | struct relate : not_implemented<Tag1, Tag2> | |
75 | {}; | |
76 | ||
77 | } // namespace dispatch | |
78 | #endif // DOXYGEN_NO_DISPATCH | |
79 | ||
80 | #ifndef DOXYGEN_NO_DETAIL | |
81 | namespace detail { namespace relate { | |
82 | ||
83 | template <typename Geometry1, typename Geometry2> | |
84 | struct interruption_enabled | |
85 | { | |
86 | static const bool value = | |
87 | dispatch::relate<Geometry1, Geometry2>::interruption_enabled; | |
88 | }; | |
89 | ||
20effc67 | 90 | template <typename Geometry1, typename Geometry2, typename Result> |
7c673cae FG |
91 | struct result_handler_type |
92 | : not_implemented<Result> | |
93 | {}; | |
94 | ||
95 | template <typename Geometry1, typename Geometry2> | |
20effc67 | 96 | struct result_handler_type<Geometry1, Geometry2, geometry::de9im::mask> |
7c673cae FG |
97 | { |
98 | typedef mask_handler | |
99 | < | |
100 | geometry::de9im::mask, | |
101 | interruption_enabled | |
102 | < | |
103 | Geometry1, | |
104 | Geometry2 | |
105 | >::value | |
106 | > type; | |
107 | }; | |
108 | ||
20effc67 TL |
109 | template <typename Geometry1, typename Geometry2, typename ...Masks> |
110 | struct result_handler_type<Geometry1, Geometry2, std::tuple<Masks...>> | |
7c673cae FG |
111 | { |
112 | typedef mask_handler | |
113 | < | |
20effc67 | 114 | std::tuple<Masks...>, |
7c673cae FG |
115 | interruption_enabled |
116 | < | |
117 | Geometry1, | |
118 | Geometry2 | |
119 | >::value | |
120 | > type; | |
121 | }; | |
122 | ||
123 | template <typename Geometry1, typename Geometry2, | |
124 | char II, char IB, char IE, | |
125 | char BI, char BB, char BE, | |
126 | char EI, char EB, char EE> | |
127 | struct result_handler_type | |
128 | < | |
129 | Geometry1, | |
130 | Geometry2, | |
20effc67 | 131 | geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> |
7c673cae FG |
132 | > |
133 | { | |
134 | typedef static_mask_handler | |
135 | < | |
136 | geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, | |
137 | interruption_enabled | |
138 | < | |
139 | Geometry1, | |
140 | Geometry2 | |
141 | >::value | |
142 | > type; | |
143 | }; | |
144 | ||
20effc67 TL |
145 | template <typename Geometry1, typename Geometry2, typename ...StaticMasks> |
146 | struct result_handler_type<Geometry1, Geometry2, util::type_sequence<StaticMasks...>> | |
7c673cae FG |
147 | { |
148 | typedef static_mask_handler | |
149 | < | |
20effc67 | 150 | util::type_sequence<StaticMasks...>, |
7c673cae FG |
151 | interruption_enabled |
152 | < | |
153 | Geometry1, | |
154 | Geometry2 | |
155 | >::value | |
156 | > type; | |
157 | }; | |
158 | ||
b32b8144 | 159 | |
7c673cae FG |
160 | }} // namespace detail::relate |
161 | #endif // DOXYGEN_NO_DETAIL | |
162 | ||
b32b8144 FG |
163 | namespace resolve_strategy { |
164 | ||
1e59de90 TL |
165 | |
166 | template | |
167 | < | |
168 | typename Strategy, | |
169 | bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value | |
170 | > | |
b32b8144 FG |
171 | struct relate |
172 | { | |
1e59de90 | 173 | template <typename Geometry1, typename Geometry2, typename ResultHandler> |
b32b8144 FG |
174 | static inline void apply(Geometry1 const& geometry1, |
175 | Geometry2 const& geometry2, | |
176 | ResultHandler & handler, | |
177 | Strategy const& strategy) | |
178 | { | |
179 | dispatch::relate | |
180 | < | |
181 | Geometry1, | |
182 | Geometry2 | |
183 | >::apply(geometry1, geometry2, handler, strategy); | |
184 | } | |
1e59de90 | 185 | }; |
b32b8144 | 186 | |
1e59de90 TL |
187 | template <typename Strategy> |
188 | struct relate<Strategy, false> | |
189 | { | |
190 | template <typename Geometry1, typename Geometry2, typename ResultHandler> | |
191 | static inline void apply(Geometry1 const& geometry1, | |
192 | Geometry2 const& geometry2, | |
193 | ResultHandler & handler, | |
194 | Strategy const& strategy) | |
195 | { | |
196 | using strategies::relate::services::strategy_converter; | |
197 | dispatch::relate | |
198 | < | |
199 | Geometry1, | |
200 | Geometry2 | |
201 | >::apply(geometry1, geometry2, handler, | |
202 | strategy_converter<Strategy>::get(strategy)); | |
203 | } | |
204 | }; | |
205 | ||
206 | template <> | |
207 | struct relate<default_strategy, false> | |
208 | { | |
b32b8144 FG |
209 | template <typename Geometry1, typename Geometry2, typename ResultHandler> |
210 | static inline void apply(Geometry1 const& geometry1, | |
211 | Geometry2 const& geometry2, | |
212 | ResultHandler & handler, | |
213 | default_strategy) | |
214 | { | |
1e59de90 | 215 | typedef typename strategies::relate::services::default_strategy |
b32b8144 FG |
216 | < |
217 | Geometry1, | |
218 | Geometry2 | |
219 | >::type strategy_type; | |
220 | ||
221 | dispatch::relate | |
222 | < | |
223 | Geometry1, | |
224 | Geometry2 | |
225 | >::apply(geometry1, geometry2, handler, strategy_type()); | |
226 | } | |
227 | }; | |
228 | ||
229 | } // resolve_strategy | |
230 | ||
7c673cae FG |
231 | namespace resolve_variant { |
232 | ||
233 | template <typename Geometry1, typename Geometry2> | |
234 | struct relate | |
235 | { | |
b32b8144 | 236 | template <typename Mask, typename Strategy> |
7c673cae FG |
237 | static inline bool apply(Geometry1 const& geometry1, |
238 | Geometry2 const& geometry2, | |
b32b8144 FG |
239 | Mask const& mask, |
240 | Strategy const& strategy) | |
7c673cae FG |
241 | { |
242 | concepts::check<Geometry1 const>(); | |
243 | concepts::check<Geometry2 const>(); | |
244 | assert_dimension_equal<Geometry1, Geometry2>(); | |
245 | ||
246 | typename detail::relate::result_handler_type | |
247 | < | |
248 | Geometry1, | |
249 | Geometry2, | |
250 | Mask | |
251 | >::type handler(mask); | |
252 | ||
1e59de90 | 253 | resolve_strategy::relate<Strategy>::apply(geometry1, geometry2, handler, strategy); |
7c673cae FG |
254 | |
255 | return handler.result(); | |
256 | } | |
257 | }; | |
258 | ||
259 | template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> | |
260 | struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> | |
261 | { | |
b32b8144 | 262 | template <typename Mask, typename Strategy> |
7c673cae FG |
263 | struct visitor : boost::static_visitor<bool> |
264 | { | |
265 | Geometry2 const& m_geometry2; | |
266 | Mask const& m_mask; | |
b32b8144 | 267 | Strategy const& m_strategy; |
7c673cae | 268 | |
b32b8144 FG |
269 | visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy) |
270 | : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {} | |
7c673cae FG |
271 | |
272 | template <typename Geometry1> | |
273 | bool operator()(Geometry1 const& geometry1) const | |
274 | { | |
275 | return relate<Geometry1, Geometry2> | |
b32b8144 | 276 | ::apply(geometry1, m_geometry2, m_mask, m_strategy); |
7c673cae FG |
277 | } |
278 | }; | |
279 | ||
b32b8144 | 280 | template <typename Mask, typename Strategy> |
7c673cae FG |
281 | static inline bool |
282 | apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, | |
283 | Geometry2 const& geometry2, | |
b32b8144 FG |
284 | Mask const& mask, |
285 | Strategy const& strategy) | |
7c673cae | 286 | { |
b32b8144 | 287 | return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1); |
7c673cae FG |
288 | } |
289 | }; | |
290 | ||
291 | template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> | |
292 | struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > | |
293 | { | |
b32b8144 | 294 | template <typename Mask, typename Strategy> |
7c673cae FG |
295 | struct visitor : boost::static_visitor<bool> |
296 | { | |
297 | Geometry1 const& m_geometry1; | |
298 | Mask const& m_mask; | |
b32b8144 | 299 | Strategy const& m_strategy; |
7c673cae | 300 | |
b32b8144 FG |
301 | visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy) |
302 | : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {} | |
7c673cae FG |
303 | |
304 | template <typename Geometry2> | |
305 | bool operator()(Geometry2 const& geometry2) const | |
306 | { | |
307 | return relate<Geometry1, Geometry2> | |
b32b8144 | 308 | ::apply(m_geometry1, geometry2, m_mask, m_strategy); |
7c673cae FG |
309 | } |
310 | }; | |
311 | ||
b32b8144 | 312 | template <typename Mask, typename Strategy> |
7c673cae FG |
313 | static inline bool |
314 | apply(Geometry1 const& geometry1, | |
315 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, | |
b32b8144 FG |
316 | Mask const& mask, |
317 | Strategy const& strategy) | |
7c673cae | 318 | { |
b32b8144 | 319 | return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2); |
7c673cae FG |
320 | } |
321 | }; | |
322 | ||
323 | template < | |
324 | BOOST_VARIANT_ENUM_PARAMS(typename T1), | |
325 | BOOST_VARIANT_ENUM_PARAMS(typename T2) | |
326 | > | |
327 | struct relate< | |
328 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, | |
329 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> | |
330 | > | |
331 | { | |
b32b8144 | 332 | template <typename Mask, typename Strategy> |
7c673cae FG |
333 | struct visitor : boost::static_visitor<bool> |
334 | { | |
335 | Mask const& m_mask; | |
b32b8144 | 336 | Strategy const& m_strategy; |
7c673cae | 337 | |
b32b8144 FG |
338 | visitor(Mask const& mask, Strategy const& strategy) |
339 | : m_mask(mask), m_strategy(strategy) {} | |
7c673cae FG |
340 | |
341 | template <typename Geometry1, typename Geometry2> | |
342 | bool operator()(Geometry1 const& geometry1, | |
343 | Geometry2 const& geometry2) const | |
344 | { | |
345 | return relate<Geometry1, Geometry2> | |
b32b8144 | 346 | ::apply(geometry1, geometry2, m_mask, m_strategy); |
7c673cae FG |
347 | } |
348 | }; | |
349 | ||
b32b8144 | 350 | template <typename Mask, typename Strategy> |
7c673cae FG |
351 | static inline bool |
352 | apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, | |
353 | boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, | |
b32b8144 FG |
354 | Mask const& mask, |
355 | Strategy const& strategy) | |
7c673cae | 356 | { |
b32b8144 | 357 | return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2); |
7c673cae FG |
358 | } |
359 | }; | |
360 | ||
361 | } // namespace resolve_variant | |
362 | ||
b32b8144 FG |
363 | /*! |
364 | \brief Checks relation between a pair of geometries defined by a mask. | |
365 | \ingroup relate | |
366 | \tparam Geometry1 \tparam_geometry | |
367 | \tparam Geometry2 \tparam_geometry | |
368 | \tparam Mask An intersection model Mask type. | |
369 | \tparam Strategy \tparam_strategy{Relate} | |
370 | \param geometry1 \param_geometry | |
371 | \param geometry2 \param_geometry | |
372 | \param mask An intersection model mask object. | |
373 | \param strategy \param_strategy{relate} | |
374 | \return true if the relation is compatible with the mask, false otherwise. | |
375 | ||
376 | \qbk{distinguish,with strategy} | |
377 | \qbk{[include reference/algorithms/relate.qbk]} | |
378 | */ | |
379 | template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy> | |
380 | inline bool relate(Geometry1 const& geometry1, | |
381 | Geometry2 const& geometry2, | |
382 | Mask const& mask, | |
383 | Strategy const& strategy) | |
384 | { | |
385 | return resolve_variant::relate | |
386 | < | |
387 | Geometry1, | |
388 | Geometry2 | |
389 | >::apply(geometry1, geometry2, mask, strategy); | |
390 | } | |
391 | ||
7c673cae FG |
392 | /*! |
393 | \brief Checks relation between a pair of geometries defined by a mask. | |
394 | \ingroup relate | |
395 | \tparam Geometry1 \tparam_geometry | |
396 | \tparam Geometry2 \tparam_geometry | |
397 | \tparam Mask An intersection model Mask type. | |
398 | \param geometry1 \param_geometry | |
399 | \param geometry2 \param_geometry | |
400 | \param mask An intersection model mask object. | |
401 | \return true if the relation is compatible with the mask, false otherwise. | |
402 | ||
403 | \qbk{[include reference/algorithms/relate.qbk]} | |
404 | */ | |
405 | template <typename Geometry1, typename Geometry2, typename Mask> | |
406 | inline bool relate(Geometry1 const& geometry1, | |
407 | Geometry2 const& geometry2, | |
408 | Mask const& mask) | |
409 | { | |
410 | return resolve_variant::relate | |
411 | < | |
412 | Geometry1, | |
413 | Geometry2 | |
b32b8144 | 414 | >::apply(geometry1, geometry2, mask, default_strategy()); |
7c673cae FG |
415 | } |
416 | ||
417 | }} // namespace boost::geometry | |
418 | ||
419 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP |