1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2013, 2014, 2015, 2017.
6 // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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)
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
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>
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>
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>
35 namespace boost { namespace geometry {
38 #ifndef DOXYGEN_NO_DETAIL
39 namespace detail { namespace relate {
41 // Those are used only to allow dispatch::relate to produce compile-time error
43 template <typename Geometry,
44 typename Tag = typename geometry::tag<Geometry>::type>
45 struct is_supported_by_generic
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;
55 template <typename Geometry1,
57 typename Tag1 = typename geometry::tag<Geometry1>::type,
58 typename Tag2 = typename geometry::tag<Geometry2>::type>
61 static const bool value = is_supported_by_generic<Geometry1>::value
62 && is_supported_by_generic<Geometry2>::value;
66 template <typename Point, typename Geometry, typename Tag>
67 struct is_generic<Point, Geometry, point_tag, Tag>
69 static const bool value = is_supported_by_generic<Geometry>::value;
72 template <typename Geometry, typename Point, typename Tag>
73 struct is_generic<Geometry, Point, Tag, point_tag>
75 static const bool value = is_supported_by_generic<Geometry>::value;
78 template <typename Point1, typename Point2>
79 struct is_generic<Point1, Point2, point_tag, point_tag>
81 static const bool value = false;
85 }} // namespace detail::relate
86 #endif // DOXYGEN_NO_DETAIL
89 #ifndef DOXYGEN_NO_DISPATCH
93 template <typename Geometry1,
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
101 struct relate : not_implemented<Tag1, Tag2>
104 } // namespace dispatch
105 #endif // DOXYGEN_NO_DISPATCH
107 #ifndef DOXYGEN_NO_DETAIL
108 namespace detail { namespace relate {
110 template <typename Geometry1, typename Geometry2>
111 struct interruption_enabled
113 static const bool value =
114 dispatch::relate<Geometry1, Geometry2>::interruption_enabled;
117 template <typename Geometry1,
120 bool IsSequence = boost::mpl::is_sequence<Result>::value>
121 struct result_handler_type
122 : not_implemented<Result>
125 template <typename Geometry1, typename Geometry2>
126 struct result_handler_type<Geometry1, Geometry2, geometry::de9im::mask, false>
130 geometry::de9im::mask,
139 template <typename Geometry1, typename Geometry2, typename Head, typename Tail>
140 struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false>
144 boost::tuples::cons<Head, Tail>,
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
161 geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,
165 typedef static_mask_handler
167 geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,
176 template <typename Geometry1, typename Geometry2, typename StaticSequence>
177 struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
179 typedef static_mask_handler
191 }} // namespace detail::relate
192 #endif // DOXYGEN_NO_DETAIL
194 namespace resolve_strategy {
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)
208 >::apply(geometry1, geometry2, handler, strategy);
211 template <typename Geometry1, typename Geometry2, typename ResultHandler>
212 static inline void apply(Geometry1 const& geometry1,
213 Geometry2 const& geometry2,
214 ResultHandler & handler,
217 typedef typename strategy::relate::services::default_strategy
221 >::type strategy_type;
227 >::apply(geometry1, geometry2, handler, strategy_type());
231 } // resolve_strategy
233 namespace resolve_variant {
235 template <typename Geometry1, typename Geometry2>
238 template <typename Mask, typename Strategy>
239 static inline bool apply(Geometry1 const& geometry1,
240 Geometry2 const& geometry2,
242 Strategy const& strategy)
244 concepts::check<Geometry1 const>();
245 concepts::check<Geometry2 const>();
246 assert_dimension_equal<Geometry1, Geometry2>();
248 typename detail::relate::result_handler_type
253 >::type handler(mask);
255 resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
257 return handler.result();
261 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
262 struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
264 template <typename Mask, typename Strategy>
265 struct visitor : boost::static_visitor<bool>
267 Geometry2 const& m_geometry2;
269 Strategy const& m_strategy;
271 visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
272 : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
274 template <typename Geometry1>
275 bool operator()(Geometry1 const& geometry1) const
277 return relate<Geometry1, Geometry2>
278 ::apply(geometry1, m_geometry2, m_mask, m_strategy);
282 template <typename Mask, typename Strategy>
284 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
285 Geometry2 const& geometry2,
287 Strategy const& strategy)
289 return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
293 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
294 struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
296 template <typename Mask, typename Strategy>
297 struct visitor : boost::static_visitor<bool>
299 Geometry1 const& m_geometry1;
301 Strategy const& m_strategy;
303 visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
304 : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
306 template <typename Geometry2>
307 bool operator()(Geometry2 const& geometry2) const
309 return relate<Geometry1, Geometry2>
310 ::apply(m_geometry1, geometry2, m_mask, m_strategy);
314 template <typename Mask, typename Strategy>
316 apply(Geometry1 const& geometry1,
317 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
319 Strategy const& strategy)
321 return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
326 BOOST_VARIANT_ENUM_PARAMS(typename T1),
327 BOOST_VARIANT_ENUM_PARAMS(typename T2)
330 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
331 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
334 template <typename Mask, typename Strategy>
335 struct visitor : boost::static_visitor<bool>
338 Strategy const& m_strategy;
340 visitor(Mask const& mask, Strategy const& strategy)
341 : m_mask(mask), m_strategy(strategy) {}
343 template <typename Geometry1, typename Geometry2>
344 bool operator()(Geometry1 const& geometry1,
345 Geometry2 const& geometry2) const
347 return relate<Geometry1, Geometry2>
348 ::apply(geometry1, geometry2, m_mask, m_strategy);
352 template <typename Mask, typename Strategy>
354 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
355 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
357 Strategy const& strategy)
359 return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
363 } // namespace resolve_variant
366 \brief Checks relation between a pair of geometries defined by a mask.
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.
378 \qbk{distinguish,with strategy}
379 \qbk{[include reference/algorithms/relate.qbk]}
381 template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy>
382 inline bool relate(Geometry1 const& geometry1,
383 Geometry2 const& geometry2,
385 Strategy const& strategy)
387 return resolve_variant::relate
391 >::apply(geometry1, geometry2, mask, strategy);
395 \brief Checks relation between a pair of geometries defined by a mask.
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.
405 \qbk{[include reference/algorithms/relate.qbk]}
407 template <typename Geometry1, typename Geometry2, typename Mask>
408 inline bool relate(Geometry1 const& geometry1,
409 Geometry2 const& geometry2,
412 return resolve_variant::relate
416 >::apply(geometry1, geometry2, mask, default_strategy());
419 }} // namespace boost::geometry
421 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP