assign.hpp 10 KB

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