assign.hpp 10 KB

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