]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/include/boost/geometry/algorithms/equals.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / algorithms / equals.hpp
CommitLineData
7c673cae
FG
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.
9// Modifications copyright (c) 2014-2016 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_EQUALS_HPP
22#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
23
24
25#include <cstddef>
26#include <vector>
27
28#include <boost/range.hpp>
29
30#include <boost/variant/apply_visitor.hpp>
31#include <boost/variant/static_visitor.hpp>
32#include <boost/variant/variant_fwd.hpp>
33
34#include <boost/geometry/core/access.hpp>
35#include <boost/geometry/core/coordinate_dimension.hpp>
36#include <boost/geometry/core/geometry_id.hpp>
37#include <boost/geometry/core/reverse_dispatch.hpp>
38#include <boost/geometry/core/tags.hpp>
39
40#include <boost/geometry/geometries/concepts/check.hpp>
41
42#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
43#include <boost/geometry/algorithms/detail/not.hpp>
44#include <boost/geometry/algorithms/not_implemented.hpp>
45
46// For trivial checks
47#include <boost/geometry/algorithms/area.hpp>
48#include <boost/geometry/algorithms/length.hpp>
49#include <boost/geometry/util/math.hpp>
50#include <boost/geometry/util/select_coordinate_type.hpp>
51#include <boost/geometry/util/select_most_precise.hpp>
52
53#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
54#include <boost/geometry/algorithms/relate.hpp>
55#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
56
57#include <boost/geometry/views/detail/indexed_point_view.hpp>
58
59
60namespace boost { namespace geometry
61{
62
63#ifndef DOXYGEN_NO_DETAIL
64namespace detail { namespace equals
65{
66
67
68template
69<
70 std::size_t Dimension,
71 std::size_t DimensionCount
72>
73struct box_box
74{
75 template <typename Box1, typename Box2>
76 static inline bool apply(Box1 const& box1, Box2 const& box2)
77 {
78 if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
79 || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
80 {
81 return false;
82 }
83 return box_box<Dimension + 1, DimensionCount>::apply(box1, box2);
84 }
85};
86
87template <std::size_t DimensionCount>
88struct box_box<DimensionCount, DimensionCount>
89{
90 template <typename Box1, typename Box2>
91 static inline bool apply(Box1 const& , Box2 const& )
92 {
93 return true;
94 }
95};
96
97
98struct segment_segment
99{
100 template <typename Segment1, typename Segment2>
101 static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
102 {
103 return equals::equals_point_point(
104 indexed_point_view<Segment1 const, 0>(segment1),
105 indexed_point_view<Segment2 const, 0>(segment2) )
106 ? equals::equals_point_point(
107 indexed_point_view<Segment1 const, 1>(segment1),
108 indexed_point_view<Segment2 const, 1>(segment2) )
109 : ( equals::equals_point_point(
110 indexed_point_view<Segment1 const, 0>(segment1),
111 indexed_point_view<Segment2 const, 1>(segment2) )
112 && equals::equals_point_point(
113 indexed_point_view<Segment1 const, 1>(segment1),
114 indexed_point_view<Segment2 const, 0>(segment2) )
115 );
116 }
117};
118
119
120struct area_check
121{
122 template <typename Geometry1, typename Geometry2>
123 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
124 {
125 return geometry::math::equals(
126 geometry::area(geometry1),
127 geometry::area(geometry2));
128 }
129};
130
131
132struct length_check
133{
134 template <typename Geometry1, typename Geometry2>
135 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
136 {
137 return geometry::math::equals(
138 geometry::length(geometry1),
139 geometry::length(geometry2));
140 }
141};
142
143
144template <typename TrivialCheck>
145struct equals_by_collection
146{
147 template <typename Geometry1, typename Geometry2>
148 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
149 {
150 if (! TrivialCheck::apply(geometry1, geometry2))
151 {
152 return false;
153 }
154
155 typedef typename geometry::select_most_precise
156 <
157 typename select_coordinate_type
158 <
159 Geometry1, Geometry2
160 >::type,
161 double
162 >::type calculation_type;
163
164 typedef geometry::collected_vector
165 <
166 calculation_type,
167 Geometry1
168 > collected_vector;
169
170 std::vector<collected_vector> c1, c2;
171
172 geometry::collect_vectors(c1, geometry1);
173 geometry::collect_vectors(c2, geometry2);
174
175 if (boost::size(c1) != boost::size(c2))
176 {
177 return false;
178 }
179
180 std::sort(c1.begin(), c1.end());
181 std::sort(c2.begin(), c2.end());
182
183 // Just check if these vectors are equal.
184 return std::equal(c1.begin(), c1.end(), c2.begin());
185 }
186};
187
188template<typename Geometry1, typename Geometry2>
189struct equals_by_relate
190 : detail::relate::relate_impl
191 <
192 detail::de9im::static_mask_equals_type,
193 Geometry1,
194 Geometry2
195 >
196{};
197
198}} // namespace detail::equals
199#endif // DOXYGEN_NO_DETAIL
200
201
202#ifndef DOXYGEN_NO_DISPATCH
203namespace dispatch
204{
205
206template
207<
208 typename Geometry1,
209 typename Geometry2,
210 typename Tag1 = typename tag<Geometry1>::type,
211 typename Tag2 = typename tag<Geometry2>::type,
212 std::size_t DimensionCount = dimension<Geometry1>::type::value,
213 bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
214>
215struct equals: not_implemented<Tag1, Tag2>
216{};
217
218
219// If reversal is needed, perform it
220template
221<
222 typename Geometry1, typename Geometry2,
223 typename Tag1, typename Tag2,
224 std::size_t DimensionCount
225>
226struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
227 : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
228{
229 static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
230 {
231 return equals
232 <
233 Geometry2, Geometry1,
234 Tag2, Tag1,
235 DimensionCount,
236 false
237 >::apply(g2, g1);
238 }
239};
240
241
242template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
243struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
244 : geometry::detail::not_
245 <
246 detail::disjoint::point_point<P1, P2, 0, DimensionCount>
247 >
248{};
249
250
251template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
252struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
253 : detail::equals::box_box<0, DimensionCount>
254{};
255
256
257template <typename Ring1, typename Ring2, bool Reverse>
258struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
259 : detail::equals::equals_by_collection<detail::equals::area_check>
260{};
261
262
263template <typename Polygon1, typename Polygon2, bool Reverse>
264struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
265 : detail::equals::equals_by_collection<detail::equals::area_check>
266{};
267
268
269template <typename Polygon, typename Ring, bool Reverse>
270struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
271 : detail::equals::equals_by_collection<detail::equals::area_check>
272{};
273
274
275template <typename Ring, typename Box, bool Reverse>
276struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
277 : detail::equals::equals_by_collection<detail::equals::area_check>
278{};
279
280
281template <typename Polygon, typename Box, bool Reverse>
282struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
283 : detail::equals::equals_by_collection<detail::equals::area_check>
284{};
285
286template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
287struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
288 : detail::equals::segment_segment
289{};
290
291template <typename LineString1, typename LineString2, bool Reverse>
292struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
293 //: detail::equals::equals_by_collection<detail::equals::length_check>
294 : detail::equals::equals_by_relate<LineString1, LineString2>
295{};
296
297template <typename LineString, typename MultiLineString, bool Reverse>
298struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
299 : detail::equals::equals_by_relate<LineString, MultiLineString>
300{};
301
302template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
303struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
304 : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
305{};
306
307
308template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
309struct equals
310 <
311 MultiPolygon1, MultiPolygon2,
312 multi_polygon_tag, multi_polygon_tag,
313 2,
314 Reverse
315 >
316 : detail::equals::equals_by_collection<detail::equals::area_check>
317{};
318
319
320template <typename Polygon, typename MultiPolygon, bool Reverse>
321struct equals
322 <
323 Polygon, MultiPolygon,
324 polygon_tag, multi_polygon_tag,
325 2,
326 Reverse
327 >
328 : detail::equals::equals_by_collection<detail::equals::area_check>
329{};
330
331template <typename MultiPolygon, typename Ring, bool Reverse>
332struct equals
333 <
334 MultiPolygon, Ring,
335 multi_polygon_tag, ring_tag,
336 2,
337 Reverse
338 >
339 : detail::equals::equals_by_collection<detail::equals::area_check>
340{};
341
342
343} // namespace dispatch
344#endif // DOXYGEN_NO_DISPATCH
345
346
347namespace resolve_variant {
348
349template <typename Geometry1, typename Geometry2>
350struct equals
351{
352 static inline bool apply(Geometry1 const& geometry1,
353 Geometry2 const& geometry2)
354 {
355 concepts::check_concepts_and_equal_dimensions
356 <
357 Geometry1 const,
358 Geometry2 const
359 >();
360
361 return dispatch::equals<Geometry1, Geometry2>
362 ::apply(geometry1, geometry2);
363 }
364};
365
366template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
367struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
368{
369 struct visitor: static_visitor<bool>
370 {
371 Geometry2 const& m_geometry2;
372
373 visitor(Geometry2 const& geometry2)
374 : m_geometry2(geometry2)
375 {}
376
377 template <typename Geometry1>
378 inline bool operator()(Geometry1 const& geometry1) const
379 {
380 return equals<Geometry1, Geometry2>
381 ::apply(geometry1, m_geometry2);
382 }
383
384 };
385
386 static inline bool apply(
387 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
388 Geometry2 const& geometry2
389 )
390 {
391 return boost::apply_visitor(visitor(geometry2), geometry1);
392 }
393};
394
395template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
396struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
397{
398 struct visitor: static_visitor<bool>
399 {
400 Geometry1 const& m_geometry1;
401
402 visitor(Geometry1 const& geometry1)
403 : m_geometry1(geometry1)
404 {}
405
406 template <typename Geometry2>
407 inline bool operator()(Geometry2 const& geometry2) const
408 {
409 return equals<Geometry1, Geometry2>
410 ::apply(m_geometry1, geometry2);
411 }
412
413 };
414
415 static inline bool apply(
416 Geometry1 const& geometry1,
417 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2
418 )
419 {
420 return boost::apply_visitor(visitor(geometry1), geometry2);
421 }
422};
423
424template <
425 BOOST_VARIANT_ENUM_PARAMS(typename T1),
426 BOOST_VARIANT_ENUM_PARAMS(typename T2)
427>
428struct equals<
429 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
430 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
431>
432{
433 struct visitor: static_visitor<bool>
434 {
435 template <typename Geometry1, typename Geometry2>
436 inline bool operator()(Geometry1 const& geometry1,
437 Geometry2 const& geometry2) const
438 {
439 return equals<Geometry1, Geometry2>
440 ::apply(geometry1, geometry2);
441 }
442
443 };
444
445 static inline bool apply(
446 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
447 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2
448 )
449 {
450 return boost::apply_visitor(visitor(), geometry1, geometry2);
451 }
452};
453
454} // namespace resolve_variant
455
456
457/*!
458\brief \brief_check{are spatially equal}
459\details \details_check12{equals, is spatially equal}. Spatially equal means
460 that the same point set is included. A box can therefore be spatially equal
461 to a ring or a polygon, or a linestring can be spatially equal to a
462 multi-linestring or a segment. This only works theoretically, not all
463 combinations are implemented yet.
464\ingroup equals
465\tparam Geometry1 \tparam_geometry
466\tparam Geometry2 \tparam_geometry
467\param geometry1 \param_geometry
468\param geometry2 \param_geometry
469\return \return_check2{are spatially equal}
470
471\qbk{[include reference/algorithms/equals.qbk]}
472
473 */
474template <typename Geometry1, typename Geometry2>
475inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
476{
477 return resolve_variant::equals<Geometry1, Geometry2>
478 ::apply(geometry1, geometry2);
479}
480
481
482}} // namespace boost::geometry
483
484
485#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
486