implementation.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018, 2019.
  7. // Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
  8. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  9. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  10. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  11. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  12. // Use, modification and distribution is subject to the Boost Software License,
  13. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
  16. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
  17. #include <cstddef>
  18. #include <vector>
  19. #include <boost/range.hpp>
  20. #include <boost/type_traits/is_base_of.hpp>
  21. #include <boost/geometry/core/access.hpp>
  22. #include <boost/geometry/core/tags.hpp>
  23. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  24. // For trivial checks
  25. #include <boost/geometry/algorithms/area.hpp>
  26. #include <boost/geometry/algorithms/length.hpp>
  27. #include <boost/geometry/util/math.hpp>
  28. #include <boost/geometry/util/select_coordinate_type.hpp>
  29. #include <boost/geometry/util/select_most_precise.hpp>
  30. #include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
  31. #include <boost/geometry/algorithms/detail/equals/interface.hpp>
  32. #include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
  33. #include <boost/geometry/algorithms/relate.hpp>
  34. #include <boost/geometry/views/detail/indexed_point_view.hpp>
  35. namespace boost { namespace geometry
  36. {
  37. #ifndef DOXYGEN_NO_DETAIL
  38. namespace detail { namespace equals
  39. {
  40. template
  41. <
  42. std::size_t Dimension,
  43. std::size_t DimensionCount
  44. >
  45. struct point_point
  46. {
  47. template <typename Point1, typename Point2, typename Strategy>
  48. static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
  49. {
  50. return Strategy::apply(point1, point2);
  51. }
  52. };
  53. template
  54. <
  55. std::size_t Dimension,
  56. std::size_t DimensionCount
  57. >
  58. struct box_box
  59. {
  60. template <typename Box1, typename Box2, typename Strategy>
  61. static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
  62. {
  63. if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
  64. || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
  65. {
  66. return false;
  67. }
  68. return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
  69. }
  70. };
  71. template <std::size_t DimensionCount>
  72. struct box_box<DimensionCount, DimensionCount>
  73. {
  74. template <typename Box1, typename Box2, typename Strategy>
  75. static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
  76. {
  77. return true;
  78. }
  79. };
  80. struct segment_segment
  81. {
  82. template <typename Segment1, typename Segment2, typename Strategy>
  83. static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
  84. Strategy const& strategy)
  85. {
  86. typename Strategy::point_in_point_strategy_type const&
  87. pt_pt_strategy = strategy.get_point_in_point_strategy();
  88. return equals::equals_point_point(
  89. indexed_point_view<Segment1 const, 0>(segment1),
  90. indexed_point_view<Segment2 const, 0>(segment2),
  91. pt_pt_strategy)
  92. ? equals::equals_point_point(
  93. indexed_point_view<Segment1 const, 1>(segment1),
  94. indexed_point_view<Segment2 const, 1>(segment2),
  95. pt_pt_strategy)
  96. : ( equals::equals_point_point(
  97. indexed_point_view<Segment1 const, 0>(segment1),
  98. indexed_point_view<Segment2 const, 1>(segment2),
  99. pt_pt_strategy)
  100. && equals::equals_point_point(
  101. indexed_point_view<Segment1 const, 1>(segment1),
  102. indexed_point_view<Segment2 const, 0>(segment2),
  103. pt_pt_strategy)
  104. );
  105. }
  106. };
  107. struct area_check
  108. {
  109. template <typename Geometry1, typename Geometry2, typename Strategy>
  110. static inline bool apply(Geometry1 const& geometry1,
  111. Geometry2 const& geometry2,
  112. Strategy const& strategy)
  113. {
  114. return geometry::math::equals(
  115. geometry::area(geometry1,
  116. strategy.template get_area_strategy<Geometry1>()),
  117. geometry::area(geometry2,
  118. strategy.template get_area_strategy<Geometry2>()));
  119. }
  120. };
  121. struct length_check
  122. {
  123. template <typename Geometry1, typename Geometry2, typename Strategy>
  124. static inline bool apply(Geometry1 const& geometry1,
  125. Geometry2 const& geometry2,
  126. Strategy const& strategy)
  127. {
  128. return geometry::math::equals(
  129. geometry::length(geometry1,
  130. strategy.template get_distance_strategy<Geometry1>()),
  131. geometry::length(geometry2,
  132. strategy.template get_distance_strategy<Geometry2>()));
  133. }
  134. };
  135. template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
  136. struct collected_vector
  137. {
  138. typedef typename geometry::select_most_precise
  139. <
  140. typename select_coordinate_type
  141. <
  142. Geometry1, Geometry2
  143. >::type,
  144. double
  145. >::type calculation_type;
  146. typedef geometry::collected_vector
  147. <
  148. calculation_type,
  149. Geometry1,
  150. typename IntersectionStrategy::side_strategy_type
  151. > type;
  152. };
  153. template <typename TrivialCheck>
  154. struct equals_by_collection
  155. {
  156. template <typename Geometry1, typename Geometry2, typename Strategy>
  157. static inline bool apply(Geometry1 const& geometry1,
  158. Geometry2 const& geometry2,
  159. Strategy const& strategy)
  160. {
  161. if (! TrivialCheck::apply(geometry1, geometry2, strategy))
  162. {
  163. return false;
  164. }
  165. typedef typename collected_vector
  166. <
  167. Geometry1, Geometry2, Strategy
  168. >::type collected_vector_type;
  169. std::vector<collected_vector_type> c1, c2;
  170. geometry::collect_vectors(c1, geometry1);
  171. geometry::collect_vectors(c2, geometry2);
  172. if (boost::size(c1) != boost::size(c2))
  173. {
  174. return false;
  175. }
  176. std::sort(c1.begin(), c1.end());
  177. std::sort(c2.begin(), c2.end());
  178. // Just check if these vectors are equal.
  179. return std::equal(c1.begin(), c1.end(), c2.begin());
  180. }
  181. };
  182. template<typename Geometry1, typename Geometry2>
  183. struct equals_by_relate
  184. : detail::relate::relate_impl
  185. <
  186. detail::de9im::static_mask_equals_type,
  187. Geometry1,
  188. Geometry2
  189. >
  190. {};
  191. // If collect_vectors which is a SideStrategy-dispatched optimization
  192. // is implemented in a way consistent with the Intersection/Side Strategy
  193. // then collect_vectors is used, otherwise relate is used.
  194. // NOTE: the result could be conceptually different for invalid
  195. // geometries in different coordinate systems because collect_vectors
  196. // and relate treat invalid geometries differently.
  197. template<typename TrivialCheck>
  198. struct equals_by_collection_or_relate
  199. {
  200. template <typename Geometry1, typename Geometry2, typename Strategy>
  201. static inline bool apply(Geometry1 const& geometry1,
  202. Geometry2 const& geometry2,
  203. Strategy const& strategy)
  204. {
  205. typedef typename boost::is_base_of
  206. <
  207. nyi::not_implemented_tag,
  208. typename collected_vector
  209. <
  210. Geometry1, Geometry2, Strategy
  211. >::type
  212. >::type enable_relate_type;
  213. return apply(geometry1, geometry2, strategy, enable_relate_type());
  214. }
  215. private:
  216. template <typename Geometry1, typename Geometry2, typename Strategy>
  217. static inline bool apply(Geometry1 const& geometry1,
  218. Geometry2 const& geometry2,
  219. Strategy const& strategy,
  220. boost::false_type /*enable_relate*/)
  221. {
  222. return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
  223. }
  224. template <typename Geometry1, typename Geometry2, typename Strategy>
  225. static inline bool apply(Geometry1 const& geometry1,
  226. Geometry2 const& geometry2,
  227. Strategy const& strategy,
  228. boost::true_type /*enable_relate*/)
  229. {
  230. return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
  231. }
  232. };
  233. struct equals_always_false
  234. {
  235. template <typename Geometry1, typename Geometry2, typename Strategy>
  236. static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const& )
  237. {
  238. return false;
  239. }
  240. };
  241. }} // namespace detail::equals
  242. #endif // DOXYGEN_NO_DETAIL
  243. #ifndef DOXYGEN_NO_DISPATCH
  244. namespace dispatch
  245. {
  246. template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
  247. struct equals<P1, P2, point_tag, point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
  248. : detail::equals::point_point<0, DimensionCount>
  249. {};
  250. template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
  251. struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
  252. : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
  253. {};
  254. template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
  255. struct equals<Point, MultiPoint, point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
  256. : detail::equals::equals_by_relate<Point, MultiPoint>
  257. {};
  258. template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
  259. struct equals<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, DimensionCount, Reverse>
  260. : detail::equals::box_box<0, DimensionCount>
  261. {};
  262. template <typename Ring1, typename Ring2, bool Reverse>
  263. struct equals<Ring1, Ring2, ring_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
  264. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  265. {};
  266. template <typename Polygon1, typename Polygon2, bool Reverse>
  267. struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, areal_tag, areal_tag, 2, Reverse>
  268. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  269. {};
  270. template <typename Polygon, typename Ring, bool Reverse>
  271. struct equals<Polygon, Ring, polygon_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
  272. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  273. {};
  274. template <typename Ring, typename Box, bool Reverse>
  275. struct equals<Ring, Box, ring_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
  276. : detail::equals::equals_by_collection<detail::equals::area_check>
  277. {};
  278. template <typename Polygon, typename Box, bool Reverse>
  279. struct equals<Polygon, Box, polygon_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
  280. : detail::equals::equals_by_collection<detail::equals::area_check>
  281. {};
  282. template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
  283. struct equals<Segment1, Segment2, segment_tag, segment_tag, linear_tag, linear_tag, DimensionCount, Reverse>
  284. : detail::equals::segment_segment
  285. {};
  286. template <typename LineString1, typename LineString2, bool Reverse>
  287. struct equals<LineString1, LineString2, linestring_tag, linestring_tag, linear_tag, linear_tag, 2, Reverse>
  288. : detail::equals::equals_by_relate<LineString1, LineString2>
  289. {};
  290. template <typename LineString, typename MultiLineString, bool Reverse>
  291. struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
  292. : detail::equals::equals_by_relate<LineString, MultiLineString>
  293. {};
  294. template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
  295. struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
  296. : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
  297. {};
  298. template <typename LineString, typename Segment, bool Reverse>
  299. struct equals<LineString, Segment, linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
  300. : detail::equals::equals_by_relate<LineString, Segment>
  301. {};
  302. template <typename MultiLineString, typename Segment, bool Reverse>
  303. struct equals<MultiLineString, Segment, multi_linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
  304. : detail::equals::equals_by_relate<MultiLineString, Segment>
  305. {};
  306. template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
  307. struct equals
  308. <
  309. MultiPolygon1, MultiPolygon2,
  310. multi_polygon_tag, multi_polygon_tag,
  311. areal_tag, areal_tag,
  312. 2,
  313. Reverse
  314. >
  315. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  316. {};
  317. template <typename Polygon, typename MultiPolygon, bool Reverse>
  318. struct equals
  319. <
  320. Polygon, MultiPolygon,
  321. polygon_tag, multi_polygon_tag,
  322. areal_tag, areal_tag,
  323. 2,
  324. Reverse
  325. >
  326. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  327. {};
  328. template <typename MultiPolygon, typename Ring, bool Reverse>
  329. struct equals
  330. <
  331. MultiPolygon, Ring,
  332. multi_polygon_tag, ring_tag,
  333. areal_tag, areal_tag,
  334. 2,
  335. Reverse
  336. >
  337. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  338. {};
  339. // NOTE: degenerated linear geometries, e.g. segment or linestring containing
  340. // 2 equal points, are considered to be invalid. Though theoretically
  341. // degenerated segments and linestrings could be treated as points and
  342. // multi-linestrings as multi-points.
  343. // This reasoning could also be applied to boxes.
  344. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  345. struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, linear_tag, DimensionCount, false>
  346. : detail::equals::equals_always_false
  347. {};
  348. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  349. struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, pointlike_tag, DimensionCount, false>
  350. : detail::equals::equals_always_false
  351. {};
  352. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  353. struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, areal_tag, DimensionCount, false>
  354. : detail::equals::equals_always_false
  355. {};
  356. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  357. struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, pointlike_tag, DimensionCount, false>
  358. : detail::equals::equals_always_false
  359. {};
  360. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  361. struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag, DimensionCount, false>
  362. : detail::equals::equals_always_false
  363. {};
  364. template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
  365. struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, linear_tag, DimensionCount, false>
  366. : detail::equals::equals_always_false
  367. {};
  368. } // namespace dispatch
  369. #endif // DOXYGEN_NO_DISPATCH
  370. }} // namespace boost::geometry
  371. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP