assign.hpp 11 KB

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