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) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
7 
8 // This file was modified by Oracle on 2014, 2015, 2016, 2017.
9 // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
10 
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
20 
21 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
22 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
23 
24 
25 #include <cstddef>
26 
27 #include <boost/variant/apply_visitor.hpp>
28 #include <boost/variant/static_visitor.hpp>
29 #include <boost/variant/variant_fwd.hpp>
30 
31 #include <boost/geometry/core/coordinate_dimension.hpp>
32 #include <boost/geometry/core/reverse_dispatch.hpp>
33 
34 #include <boost/geometry/geometries/concepts/check.hpp>
35 
36 #include <boost/geometry/algorithms/not_implemented.hpp>
37 
38 #include <boost/geometry/strategies/default_strategy.hpp>
39 #include <boost/geometry/strategies/relate.hpp>
40 
41 
42 namespace boost { namespace geometry
43 {
44 
45 #ifndef DOXYGEN_NO_DISPATCH
46 namespace dispatch
47 {
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     std::size_t DimensionCount = dimension<Geometry1>::type::value,
56     bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
57 >
58 struct equals: not_implemented<Tag1, Tag2>
59 {};
60 
61 
62 // If reversal is needed, perform it
63 template
64 <
65     typename Geometry1, typename Geometry2,
66     typename Tag1, typename Tag2,
67     std::size_t DimensionCount
68 >
69 struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
70     : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
71 {
72     template <typename Strategy>
applyboost::geometry::dispatch::equals73     static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
74     {
75         return equals
76             <
77                 Geometry2, Geometry1,
78                 Tag2, Tag1,
79                 DimensionCount,
80                 false
81             >::apply(g2, g1, strategy);
82     }
83 };
84 
85 
86 } // namespace dispatch
87 #endif // DOXYGEN_NO_DISPATCH
88 
89 
90 namespace resolve_strategy
91 {
92 
93 struct equals
94 {
95     template <typename Geometry1, typename Geometry2, typename Strategy>
applyboost::geometry::resolve_strategy::equals96     static inline bool apply(Geometry1 const& geometry1,
97                              Geometry2 const& geometry2,
98                              Strategy const& strategy)
99     {
100         return dispatch::equals
101             <
102                 Geometry1, Geometry2
103             >::apply(geometry1, geometry2, strategy);
104     }
105 
106     template <typename Geometry1, typename Geometry2>
applyboost::geometry::resolve_strategy::equals107     static inline bool apply(Geometry1 const& geometry1,
108                              Geometry2 const& geometry2,
109                              default_strategy)
110     {
111         typedef typename strategy::relate::services::default_strategy
112             <
113                 Geometry1,
114                 Geometry2
115             >::type strategy_type;
116 
117         return dispatch::equals
118             <
119                 Geometry1, Geometry2
120             >::apply(geometry1, geometry2, strategy_type());
121     }
122 };
123 
124 } // namespace resolve_strategy
125 
126 
127 namespace resolve_variant {
128 
129 template <typename Geometry1, typename Geometry2>
130 struct equals
131 {
132     template <typename Strategy>
applyboost::geometry::resolve_variant::equals133     static inline bool apply(Geometry1 const& geometry1,
134                              Geometry2 const& geometry2,
135                              Strategy const& strategy)
136     {
137         concepts::check_concepts_and_equal_dimensions
138             <
139                 Geometry1 const,
140                 Geometry2 const
141             >();
142 
143         return resolve_strategy::equals
144                 ::apply(geometry1, geometry2, strategy);
145     }
146 };
147 
148 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
149 struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
150 {
151     template <typename Strategy>
152     struct visitor: static_visitor<bool>
153     {
154         Geometry2 const& m_geometry2;
155         Strategy const& m_strategy;
156 
visitorboost::geometry::resolve_variant::equals::visitor157         visitor(Geometry2 const& geometry2, Strategy const& strategy)
158             : m_geometry2(geometry2)
159             , m_strategy(strategy)
160         {}
161 
162         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::equals::visitor163         inline bool operator()(Geometry1 const& geometry1) const
164         {
165             return equals<Geometry1, Geometry2>
166                    ::apply(geometry1, m_geometry2, m_strategy);
167         }
168 
169     };
170 
171     template <typename Strategy>
applyboost::geometry::resolve_variant::equals172     static inline bool apply(
173         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
174         Geometry2 const& geometry2,
175         Strategy const& strategy
176     )
177     {
178         return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
179     }
180 };
181 
182 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
183 struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
184 {
185     template <typename Strategy>
186     struct visitor: static_visitor<bool>
187     {
188         Geometry1 const& m_geometry1;
189         Strategy const& m_strategy;
190 
visitorboost::geometry::resolve_variant::equals::visitor191         visitor(Geometry1 const& geometry1, Strategy const& strategy)
192             : m_geometry1(geometry1)
193             , m_strategy(strategy)
194         {}
195 
196         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::equals::visitor197         inline bool operator()(Geometry2 const& geometry2) const
198         {
199             return equals<Geometry1, Geometry2>
200                    ::apply(m_geometry1, geometry2, m_strategy);
201         }
202 
203     };
204 
205     template <typename Strategy>
applyboost::geometry::resolve_variant::equals206     static inline bool apply(
207         Geometry1 const& geometry1,
208         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
209         Strategy const& strategy
210     )
211     {
212         return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
213     }
214 };
215 
216 template <
217     BOOST_VARIANT_ENUM_PARAMS(typename T1),
218     BOOST_VARIANT_ENUM_PARAMS(typename T2)
219 >
220 struct equals<
221     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
222     boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
223 >
224 {
225     template <typename Strategy>
226     struct visitor: static_visitor<bool>
227     {
228         Strategy const& m_strategy;
229 
visitorboost::geometry::resolve_variant::equals::visitor230         visitor(Strategy const& strategy)
231             : m_strategy(strategy)
232         {}
233 
234         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::equals::visitor235         inline bool operator()(Geometry1 const& geometry1,
236                                Geometry2 const& geometry2) const
237         {
238             return equals<Geometry1, Geometry2>
239                    ::apply(geometry1, geometry2, m_strategy);
240         }
241 
242     };
243 
244     template <typename Strategy>
applyboost::geometry::resolve_variant::equals245     static inline bool apply(
246         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
247         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
248         Strategy const& strategy
249     )
250     {
251         return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
252     }
253 };
254 
255 } // namespace resolve_variant
256 
257 
258 /*!
259 \brief \brief_check{are spatially equal}
260 \details \details_check12{equals, is spatially equal}. Spatially equal means
261     that the same point set is included. A box can therefore be spatially equal
262     to a ring or a polygon, or a linestring can be spatially equal to a
263     multi-linestring or a segment. This only works theoretically, not all
264     combinations are implemented yet.
265 \ingroup equals
266 \tparam Geometry1 \tparam_geometry
267 \tparam Geometry2 \tparam_geometry
268 \tparam Strategy \tparam_strategy{Equals}
269 \param geometry1 \param_geometry
270 \param geometry2 \param_geometry
271 \param strategy \param_strategy{equals}
272 \return \return_check2{are spatially equal}
273 
274 \qbk{distinguish,with strategy}
275 \qbk{[include reference/algorithms/equals.qbk]}
276  */
277 template <typename Geometry1, typename Geometry2, typename Strategy>
equals(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)278 inline bool equals(Geometry1 const& geometry1,
279                    Geometry2 const& geometry2,
280                    Strategy const& strategy)
281 {
282     return resolve_variant::equals
283             <
284                 Geometry1, Geometry2
285             >::apply(geometry1, geometry2, strategy);
286 }
287 
288 
289 /*!
290 \brief \brief_check{are spatially equal}
291 \details \details_check12{equals, is spatially equal}. Spatially equal means
292     that the same point set is included. A box can therefore be spatially equal
293     to a ring or a polygon, or a linestring can be spatially equal to a
294     multi-linestring or a segment. This only works theoretically, not all
295     combinations are implemented yet.
296 \ingroup equals
297 \tparam Geometry1 \tparam_geometry
298 \tparam Geometry2 \tparam_geometry
299 \param geometry1 \param_geometry
300 \param geometry2 \param_geometry
301 \return \return_check2{are spatially equal}
302 
303 \qbk{[include reference/algorithms/equals.qbk]}
304  */
305 template <typename Geometry1, typename Geometry2>
equals(Geometry1 const & geometry1,Geometry2 const & geometry2)306 inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
307 {
308     return resolve_variant::equals<Geometry1, Geometry2>
309                           ::apply(geometry1, geometry2, default_strategy());
310 }
311 
312 
313 }} // namespace boost::geometry
314 
315 
316 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
317 
318