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