implementation.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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.
  7. // Modifications copyright (c) 2014-2017 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& strategy)
  49. {
  50. return ! detail::disjoint::point_point
  51. <
  52. Point1, Point2,
  53. Dimension, DimensionCount
  54. >::apply(point1, point2, strategy);
  55. }
  56. };
  57. template
  58. <
  59. std::size_t Dimension,
  60. std::size_t DimensionCount
  61. >
  62. struct box_box
  63. {
  64. template <typename Box1, typename Box2, typename Strategy>
  65. static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
  66. {
  67. if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
  68. || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
  69. {
  70. return false;
  71. }
  72. return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
  73. }
  74. };
  75. template <std::size_t DimensionCount>
  76. struct box_box<DimensionCount, DimensionCount>
  77. {
  78. template <typename Box1, typename Box2, typename Strategy>
  79. static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
  80. {
  81. return true;
  82. }
  83. };
  84. struct segment_segment
  85. {
  86. template <typename Segment1, typename Segment2, typename Strategy>
  87. static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
  88. {
  89. return equals::equals_point_point(
  90. indexed_point_view<Segment1 const, 0>(segment1),
  91. indexed_point_view<Segment2 const, 0>(segment2) )
  92. ? equals::equals_point_point(
  93. indexed_point_view<Segment1 const, 1>(segment1),
  94. indexed_point_view<Segment2 const, 1>(segment2) )
  95. : ( equals::equals_point_point(
  96. indexed_point_view<Segment1 const, 0>(segment1),
  97. indexed_point_view<Segment2 const, 1>(segment2) )
  98. && equals::equals_point_point(
  99. indexed_point_view<Segment1 const, 1>(segment1),
  100. indexed_point_view<Segment2 const, 0>(segment2) )
  101. );
  102. }
  103. };
  104. struct area_check
  105. {
  106. template <typename Geometry1, typename Geometry2, typename Strategy>
  107. static inline bool apply(Geometry1 const& geometry1,
  108. Geometry2 const& geometry2,
  109. Strategy const& strategy)
  110. {
  111. return geometry::math::equals(
  112. geometry::area(geometry1,
  113. strategy.template get_area_strategy<Geometry1>()),
  114. geometry::area(geometry2,
  115. strategy.template get_area_strategy<Geometry2>()));
  116. }
  117. };
  118. struct length_check
  119. {
  120. template <typename Geometry1, typename Geometry2, typename Strategy>
  121. static inline bool apply(Geometry1 const& geometry1,
  122. Geometry2 const& geometry2,
  123. Strategy const& strategy)
  124. {
  125. return geometry::math::equals(
  126. geometry::length(geometry1,
  127. strategy.template get_distance_strategy<Geometry1>()),
  128. geometry::length(geometry2,
  129. strategy.template get_distance_strategy<Geometry2>()));
  130. }
  131. };
  132. template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
  133. struct collected_vector
  134. {
  135. typedef typename geometry::select_most_precise
  136. <
  137. typename select_coordinate_type
  138. <
  139. Geometry1, Geometry2
  140. >::type,
  141. double
  142. >::type calculation_type;
  143. typedef geometry::collected_vector
  144. <
  145. calculation_type,
  146. Geometry1,
  147. typename IntersectionStrategy::side_strategy_type
  148. > type;
  149. };
  150. template <typename TrivialCheck>
  151. struct equals_by_collection
  152. {
  153. template <typename Geometry1, typename Geometry2, typename Strategy>
  154. static inline bool apply(Geometry1 const& geometry1,
  155. Geometry2 const& geometry2,
  156. Strategy const& strategy)
  157. {
  158. if (! TrivialCheck::apply(geometry1, geometry2, strategy))
  159. {
  160. return false;
  161. }
  162. typedef typename collected_vector
  163. <
  164. Geometry1, Geometry2, Strategy
  165. >::type collected_vector_type;
  166. std::vector<collected_vector_type> c1, c2;
  167. geometry::collect_vectors(c1, geometry1);
  168. geometry::collect_vectors(c2, geometry2);
  169. if (boost::size(c1) != boost::size(c2))
  170. {
  171. return false;
  172. }
  173. std::sort(c1.begin(), c1.end());
  174. std::sort(c2.begin(), c2.end());
  175. // Just check if these vectors are equal.
  176. return std::equal(c1.begin(), c1.end(), c2.begin());
  177. }
  178. };
  179. template<typename Geometry1, typename Geometry2>
  180. struct equals_by_relate
  181. : detail::relate::relate_impl
  182. <
  183. detail::de9im::static_mask_equals_type,
  184. Geometry1,
  185. Geometry2
  186. >
  187. {};
  188. // If collect_vectors which is a SideStrategy-dispatched optimization
  189. // is implemented in a way consistent with the Intersection/Side Strategy
  190. // then collect_vectors is used, otherwise relate is used.
  191. // NOTE: the result could be conceptually different for invalid
  192. // geometries in different coordinate systems because collect_vectors
  193. // and relate treat invalid geometries differently.
  194. template<typename TrivialCheck>
  195. struct equals_by_collection_or_relate
  196. {
  197. template <typename Geometry1, typename Geometry2, typename Strategy>
  198. static inline bool apply(Geometry1 const& geometry1,
  199. Geometry2 const& geometry2,
  200. Strategy const& strategy)
  201. {
  202. typedef typename boost::is_base_of
  203. <
  204. nyi::not_implemented_tag,
  205. typename collected_vector
  206. <
  207. Geometry1, Geometry2, Strategy
  208. >::type
  209. >::type enable_relate_type;
  210. return apply(geometry1, geometry2, strategy, enable_relate_type());
  211. }
  212. private:
  213. template <typename Geometry1, typename Geometry2, typename Strategy>
  214. static inline bool apply(Geometry1 const& geometry1,
  215. Geometry2 const& geometry2,
  216. Strategy const& strategy,
  217. boost::false_type /*enable_relate*/)
  218. {
  219. return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
  220. }
  221. template <typename Geometry1, typename Geometry2, typename Strategy>
  222. static inline bool apply(Geometry1 const& geometry1,
  223. Geometry2 const& geometry2,
  224. Strategy const& strategy,
  225. boost::true_type /*enable_relate*/)
  226. {
  227. return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
  228. }
  229. };
  230. }} // namespace detail::equals
  231. #endif // DOXYGEN_NO_DETAIL
  232. #ifndef DOXYGEN_NO_DISPATCH
  233. namespace dispatch
  234. {
  235. template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
  236. struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
  237. : detail::equals::point_point<0, DimensionCount>
  238. {};
  239. template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
  240. struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
  241. : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
  242. {};
  243. template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
  244. struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
  245. : detail::equals::equals_by_relate<Point, MultiPoint>
  246. {};
  247. template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
  248. struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
  249. : detail::equals::box_box<0, DimensionCount>
  250. {};
  251. template <typename Ring1, typename Ring2, bool Reverse>
  252. struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
  253. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  254. {};
  255. template <typename Polygon1, typename Polygon2, bool Reverse>
  256. struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
  257. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  258. {};
  259. template <typename Polygon, typename Ring, bool Reverse>
  260. struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
  261. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  262. {};
  263. template <typename Ring, typename Box, bool Reverse>
  264. struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
  265. : detail::equals::equals_by_collection<detail::equals::area_check>
  266. {};
  267. template <typename Polygon, typename Box, bool Reverse>
  268. struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
  269. : detail::equals::equals_by_collection<detail::equals::area_check>
  270. {};
  271. template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
  272. struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
  273. : detail::equals::segment_segment
  274. {};
  275. template <typename LineString1, typename LineString2, bool Reverse>
  276. struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
  277. : detail::equals::equals_by_relate<LineString1, LineString2>
  278. {};
  279. template <typename LineString, typename MultiLineString, bool Reverse>
  280. struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
  281. : detail::equals::equals_by_relate<LineString, MultiLineString>
  282. {};
  283. template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
  284. struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
  285. : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
  286. {};
  287. template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
  288. struct equals
  289. <
  290. MultiPolygon1, MultiPolygon2,
  291. multi_polygon_tag, multi_polygon_tag,
  292. 2,
  293. Reverse
  294. >
  295. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  296. {};
  297. template <typename Polygon, typename MultiPolygon, bool Reverse>
  298. struct equals
  299. <
  300. Polygon, MultiPolygon,
  301. polygon_tag, multi_polygon_tag,
  302. 2,
  303. Reverse
  304. >
  305. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  306. {};
  307. template <typename MultiPolygon, typename Ring, bool Reverse>
  308. struct equals
  309. <
  310. MultiPolygon, Ring,
  311. multi_polygon_tag, ring_tag,
  312. 2,
  313. Reverse
  314. >
  315. : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
  316. {};
  317. } // namespace dispatch
  318. #endif // DOXYGEN_NO_DISPATCH
  319. }} // namespace boost::geometry
  320. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP