assign.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2014 Samuel Debionne, Grenoble, France.
  6. // This file was modified by Oracle on 2020.
  7. // Modifications copyright (c) 2020 Oracle and/or its affiliates.
  8. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  9. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  10. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  11. // Use, modification and distribution is subject to the Boost Software License,
  12. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
  15. #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
  16. #include <cstddef>
  17. #include <boost/concept/requires.hpp>
  18. #include <boost/concept_check.hpp>
  19. #include <boost/numeric/conversion/bounds.hpp>
  20. #include <boost/numeric/conversion/cast.hpp>
  21. #include <boost/variant/apply_visitor.hpp>
  22. #include <boost/variant/static_visitor.hpp>
  23. #include <boost/variant/variant_fwd.hpp>
  24. #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
  25. #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
  26. #include <boost/geometry/algorithms/detail/assign_values.hpp>
  27. #include <boost/geometry/algorithms/convert.hpp>
  28. #include <boost/geometry/algorithms/append.hpp>
  29. #include <boost/geometry/algorithms/clear.hpp>
  30. #include <boost/geometry/arithmetic/arithmetic.hpp>
  31. #include <boost/geometry/core/access.hpp>
  32. #include <boost/geometry/core/exterior_ring.hpp>
  33. #include <boost/geometry/core/static_assert.hpp>
  34. #include <boost/geometry/core/tags.hpp>
  35. #include <boost/geometry/geometries/concepts/check.hpp>
  36. #include <boost/geometry/util/for_each_coordinate.hpp>
  37. namespace boost { namespace geometry
  38. {
  39. /*!
  40. \brief Assign a range of points to a linestring, ring or polygon
  41. \note The point-type of the range might be different from the point-type of the geometry
  42. \ingroup assign
  43. \tparam Geometry \tparam_geometry
  44. \tparam Range \tparam_range_point
  45. \param geometry \param_geometry
  46. \param range \param_range_point
  47. \qbk{
  48. [heading Notes]
  49. [note Assign automatically clears the geometry before assigning (use append if you don't want that)]
  50. [heading Example]
  51. [assign_points] [assign_points_output]
  52. [heading See also]
  53. \* [link geometry.reference.algorithms.append append]
  54. }
  55. */
  56. template <typename Geometry, typename Range>
  57. inline void assign_points(Geometry& geometry, Range const& range)
  58. {
  59. concepts::check<Geometry>();
  60. clear(geometry);
  61. geometry::append(geometry, range, -1, 0);
  62. }
  63. /*!
  64. \brief assign to a box inverse infinite
  65. \details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
  66. min corner is very large, the max corner is very small. This is a convenient starting point to
  67. collect the minimum bounding box of a geometry.
  68. \ingroup assign
  69. \tparam Geometry \tparam_geometry
  70. \param geometry \param_geometry
  71. \qbk{
  72. [heading Example]
  73. [assign_inverse] [assign_inverse_output]
  74. [heading See also]
  75. \* [link geometry.reference.algorithms.make.make_inverse make_inverse]
  76. }
  77. */
  78. template <typename Geometry>
  79. inline void assign_inverse(Geometry& geometry)
  80. {
  81. concepts::check<Geometry>();
  82. dispatch::assign_inverse
  83. <
  84. typename tag<Geometry>::type,
  85. Geometry
  86. >::apply(geometry);
  87. }
  88. /*!
  89. \brief assign zero values to a box, point
  90. \ingroup assign
  91. \details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
  92. \tparam Geometry \tparam_geometry
  93. \param geometry \param_geometry
  94. */
  95. template <typename Geometry>
  96. inline void assign_zero(Geometry& geometry)
  97. {
  98. concepts::check<Geometry>();
  99. dispatch::assign_zero
  100. <
  101. typename tag<Geometry>::type,
  102. Geometry
  103. >::apply(geometry);
  104. }
  105. /*!
  106. \brief Assign two coordinates to a geometry (usually a 2D point)
  107. \ingroup assign
  108. \tparam Geometry \tparam_geometry
  109. \tparam Type \tparam_numeric to specify the coordinates
  110. \param geometry \param_geometry
  111. \param c1 \param_x
  112. \param c2 \param_y
  113. \qbk{distinguish, 2 coordinate values}
  114. \qbk{
  115. [heading Example]
  116. [assign_2d_point] [assign_2d_point_output]
  117. [heading See also]
  118. \* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
  119. }
  120. */
  121. template <typename Geometry, typename Type>
  122. inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
  123. {
  124. concepts::check<Geometry>();
  125. dispatch::assign
  126. <
  127. typename tag<Geometry>::type,
  128. Geometry,
  129. geometry::dimension<Geometry>::type::value
  130. >::apply(geometry, c1, c2);
  131. }
  132. /*!
  133. \brief Assign three values to a geometry (usually a 3D point)
  134. \ingroup assign
  135. \tparam Geometry \tparam_geometry
  136. \tparam Type \tparam_numeric to specify the coordinates
  137. \param geometry \param_geometry
  138. \param c1 \param_x
  139. \param c2 \param_y
  140. \param c3 \param_z
  141. \qbk{distinguish, 3 coordinate values}
  142. \qbk{
  143. [heading Example]
  144. [assign_3d_point] [assign_3d_point_output]
  145. [heading See also]
  146. \* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
  147. }
  148. */
  149. template <typename Geometry, typename Type>
  150. inline void assign_values(Geometry& geometry,
  151. Type const& c1, Type const& c2, Type const& c3)
  152. {
  153. concepts::check<Geometry>();
  154. dispatch::assign
  155. <
  156. typename tag<Geometry>::type,
  157. Geometry,
  158. geometry::dimension<Geometry>::type::value
  159. >::apply(geometry, c1, c2, c3);
  160. }
  161. /*!
  162. \brief Assign four values to a geometry (usually a box or segment)
  163. \ingroup assign
  164. \tparam Geometry \tparam_geometry
  165. \tparam Type \tparam_numeric to specify the coordinates
  166. \param geometry \param_geometry
  167. \param c1 First coordinate (usually x1)
  168. \param c2 Second coordinate (usually y1)
  169. \param c3 Third coordinate (usually x2)
  170. \param c4 Fourth coordinate (usually y2)
  171. \qbk{distinguish, 4 coordinate values}
  172. */
  173. template <typename Geometry, typename Type>
  174. inline void assign_values(Geometry& geometry,
  175. Type const& c1, Type const& c2, Type const& c3, Type const& c4)
  176. {
  177. concepts::check<Geometry>();
  178. dispatch::assign
  179. <
  180. typename tag<Geometry>::type,
  181. Geometry,
  182. geometry::dimension<Geometry>::type::value
  183. >::apply(geometry, c1, c2, c3, c4);
  184. }
  185. namespace resolve_variant
  186. {
  187. template <typename Geometry1, typename Geometry2>
  188. struct assign
  189. {
  190. static inline void
  191. apply(Geometry1& geometry1, const Geometry2& geometry2)
  192. {
  193. concepts::check<Geometry1>();
  194. concepts::check<Geometry2 const>();
  195. concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
  196. static bool const same_point_order
  197. = point_order<Geometry1>::value == point_order<Geometry2>::value;
  198. BOOST_GEOMETRY_STATIC_ASSERT(
  199. same_point_order,
  200. "Assign is not supported for different point orders.",
  201. Geometry1, Geometry2);
  202. static bool const same_closure
  203. = closure<Geometry1>::value == closure<Geometry2>::value;
  204. BOOST_GEOMETRY_STATIC_ASSERT(
  205. same_closure,
  206. "Assign is not supported for different closures.",
  207. Geometry1, Geometry2);
  208. dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
  209. }
  210. };
  211. template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
  212. struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
  213. {
  214. struct visitor: static_visitor<void>
  215. {
  216. Geometry2 const& m_geometry2;
  217. visitor(Geometry2 const& geometry2)
  218. : m_geometry2(geometry2)
  219. {}
  220. template <typename Geometry1>
  221. result_type operator()(Geometry1& geometry1) const
  222. {
  223. return assign
  224. <
  225. Geometry1,
  226. Geometry2
  227. >::apply
  228. (geometry1, m_geometry2);
  229. }
  230. };
  231. static inline void
  232. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
  233. Geometry2 const& geometry2)
  234. {
  235. return boost::apply_visitor(visitor(geometry2), geometry1);
  236. }
  237. };
  238. template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
  239. struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  240. {
  241. struct visitor: static_visitor<void>
  242. {
  243. Geometry1& m_geometry1;
  244. visitor(Geometry1 const& geometry1)
  245. : m_geometry1(geometry1)
  246. {}
  247. template <typename Geometry2>
  248. result_type operator()(Geometry2 const& geometry2) const
  249. {
  250. return assign
  251. <
  252. Geometry1,
  253. Geometry2
  254. >::apply
  255. (m_geometry1, geometry2);
  256. }
  257. };
  258. static inline void
  259. apply(Geometry1& geometry1,
  260. variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
  261. {
  262. return boost::apply_visitor(visitor(geometry1), geometry2);
  263. }
  264. };
  265. template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
  266. struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
  267. {
  268. struct visitor: static_visitor<void>
  269. {
  270. template <typename Geometry1, typename Geometry2>
  271. result_type operator()(
  272. Geometry1& geometry1,
  273. Geometry2 const& geometry2) const
  274. {
  275. return assign
  276. <
  277. Geometry1,
  278. Geometry2
  279. >::apply
  280. (geometry1, geometry2);
  281. }
  282. };
  283. static inline void
  284. apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
  285. variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
  286. {
  287. return boost::apply_visitor(visitor(), geometry1, geometry2);
  288. }
  289. };
  290. } // namespace resolve_variant
  291. /*!
  292. \brief Assigns one geometry to another geometry
  293. \details The assign algorithm assigns one geometry, e.g. a BOX, to another
  294. geometry, e.g. a RING. This only works if it is possible and applicable.
  295. \ingroup assign
  296. \tparam Geometry1 \tparam_geometry
  297. \tparam Geometry2 \tparam_geometry
  298. \param geometry1 \param_geometry (target)
  299. \param geometry2 \param_geometry (source)
  300. \qbk{
  301. [heading Example]
  302. [assign] [assign_output]
  303. [heading See also]
  304. \* [link geometry.reference.algorithms.convert convert]
  305. }
  306. */
  307. template <typename Geometry1, typename Geometry2>
  308. inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
  309. {
  310. resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);
  311. }
  312. }} // namespace boost::geometry
  313. #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP