• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 
5 // This file was modified by Oracle on 2013, 2014, 2015, 2017.
6 // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
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>
32 #include <boost/geometry/strategies/relate.hpp>
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 
190 
191 }} // namespace detail::relate
192 #endif // DOXYGEN_NO_DETAIL
193 
194 namespace resolve_strategy {
195 
196 struct relate
197 {
198     template <typename Geometry1, typename Geometry2, typename ResultHandler, typename Strategy>
applyboost::geometry::resolve_strategy::relate199     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>
applyboost::geometry::resolve_strategy::relate212     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 
233 namespace resolve_variant {
234 
235 template <typename Geometry1, typename Geometry2>
236 struct relate
237 {
238     template <typename Mask, typename Strategy>
applyboost::geometry::resolve_variant::relate239     static inline bool apply(Geometry1 const& geometry1,
240                              Geometry2 const& geometry2,
241                              Mask const& mask,
242                              Strategy const& strategy)
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 
255         resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
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 {
264     template <typename Mask, typename Strategy>
265     struct visitor : boost::static_visitor<bool>
266     {
267         Geometry2 const& m_geometry2;
268         Mask const& m_mask;
269         Strategy const& m_strategy;
270 
visitorboost::geometry::resolve_variant::relate::visitor271         visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
272             : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
273 
274         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::relate::visitor275         bool operator()(Geometry1 const& geometry1) const
276         {
277             return relate<Geometry1, Geometry2>
278                    ::apply(geometry1, m_geometry2, m_mask, m_strategy);
279         }
280     };
281 
282     template <typename Mask, typename Strategy>
283     static inline bool
applyboost::geometry::resolve_variant::relate284     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
285           Geometry2 const& geometry2,
286           Mask const& mask,
287           Strategy const& strategy)
288     {
289         return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
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 {
296     template <typename Mask, typename Strategy>
297     struct visitor : boost::static_visitor<bool>
298     {
299         Geometry1 const& m_geometry1;
300         Mask const& m_mask;
301         Strategy const& m_strategy;
302 
visitorboost::geometry::resolve_variant::relate::visitor303         visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
304             : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
305 
306         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::relate::visitor307         bool operator()(Geometry2 const& geometry2) const
308         {
309             return relate<Geometry1, Geometry2>
310                    ::apply(m_geometry1, geometry2, m_mask, m_strategy);
311         }
312     };
313 
314     template <typename Mask, typename Strategy>
315     static inline bool
applyboost::geometry::resolve_variant::relate316     apply(Geometry1 const& geometry1,
317           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
318           Mask const& mask,
319           Strategy const& strategy)
320     {
321         return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
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 {
334     template <typename Mask, typename Strategy>
335     struct visitor : boost::static_visitor<bool>
336     {
337         Mask const& m_mask;
338         Strategy const& m_strategy;
339 
visitorboost::geometry::resolve_variant::relate::visitor340         visitor(Mask const& mask, Strategy const& strategy)
341             : m_mask(mask), m_strategy(strategy) {}
342 
343         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::relate::visitor344         bool operator()(Geometry1 const& geometry1,
345                         Geometry2 const& geometry2) const
346         {
347             return relate<Geometry1, Geometry2>
348                    ::apply(geometry1, geometry2, m_mask, m_strategy);
349         }
350     };
351 
352     template <typename Mask, typename Strategy>
353     static inline bool
applyboost::geometry::resolve_variant::relate354     apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
355           boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
356           Mask const& mask,
357           Strategy const& strategy)
358     {
359         return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
360     }
361 };
362 
363 } // namespace resolve_variant
364 
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>
relate(Geometry1 const & geometry1,Geometry2 const & geometry2,Mask const & mask,Strategy const & 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 
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>
relate(Geometry1 const & geometry1,Geometry2 const & geometry2,Mask const & 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
416             >::apply(geometry1, geometry2, mask, default_strategy());
417 }
418 
419 }} // namespace boost::geometry
420 
421 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
422