assign.hpp 10 KB

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