assign_values.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  6. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
  12. #include <cstddef>
  13. #include <boost/concept/requires.hpp>
  14. #include <boost/concept_check.hpp>
  15. #include <boost/mpl/assert.hpp>
  16. #include <boost/mpl/if.hpp>
  17. #include <boost/numeric/conversion/bounds.hpp>
  18. #include <boost/numeric/conversion/cast.hpp>
  19. #include <boost/type_traits.hpp>
  20. #include <boost/geometry/arithmetic/arithmetic.hpp>
  21. #include <boost/geometry/algorithms/append.hpp>
  22. #include <boost/geometry/algorithms/clear.hpp>
  23. #include <boost/geometry/core/access.hpp>
  24. #include <boost/geometry/core/exterior_ring.hpp>
  25. #include <boost/geometry/core/tags.hpp>
  26. #include <boost/geometry/geometries/concepts/check.hpp>
  27. #include <boost/geometry/util/for_each_coordinate.hpp>
  28. namespace boost { namespace geometry
  29. {
  30. #ifndef DOXYGEN_NO_DETAIL
  31. namespace detail { namespace assign
  32. {
  33. template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
  34. struct initialize
  35. {
  36. template <typename Box>
  37. static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
  38. {
  39. geometry::set<Index, Dimension>(box, value);
  40. initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
  41. }
  42. };
  43. template <std::size_t Index, std::size_t DimensionCount>
  44. struct initialize<Index, DimensionCount, DimensionCount>
  45. {
  46. template <typename Box>
  47. static inline void apply(Box&, typename coordinate_type<Box>::type const&)
  48. {}
  49. };
  50. struct assign_zero_point
  51. {
  52. template <typename Point>
  53. static inline void apply(Point& point)
  54. {
  55. geometry::assign_value(point, 0);
  56. }
  57. };
  58. struct assign_inverse_box_or_segment
  59. {
  60. template <typename BoxOrSegment>
  61. static inline void apply(BoxOrSegment& geometry)
  62. {
  63. typedef typename point_type<BoxOrSegment>::type point_type;
  64. typedef typename coordinate_type<point_type>::type bound_type;
  65. initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
  66. geometry, boost::numeric::bounds<bound_type>::highest()
  67. );
  68. initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
  69. geometry, boost::numeric::bounds<bound_type>::lowest()
  70. );
  71. }
  72. };
  73. struct assign_zero_box_or_segment
  74. {
  75. template <typename BoxOrSegment>
  76. static inline void apply(BoxOrSegment& geometry)
  77. {
  78. typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
  79. initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
  80. geometry, coordinate_type()
  81. );
  82. initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
  83. geometry, coordinate_type()
  84. );
  85. }
  86. };
  87. template
  88. <
  89. std::size_t Corner1, std::size_t Corner2,
  90. typename Box, typename Point
  91. >
  92. inline void assign_box_2d_corner(Box const& box, Point& point)
  93. {
  94. // Be sure both are 2-Dimensional
  95. assert_dimension<Box, 2>();
  96. assert_dimension<Point, 2>();
  97. // Copy coordinates
  98. typedef typename coordinate_type<Point>::type coordinate_type;
  99. geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
  100. geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
  101. }
  102. template
  103. <
  104. typename Geometry, typename Point,
  105. std::size_t Index,
  106. std::size_t Dimension, std::size_t DimensionCount
  107. >
  108. struct assign_point_to_index
  109. {
  110. static inline void apply(Point const& point, Geometry& geometry)
  111. {
  112. geometry::set<Index, Dimension>(geometry, boost::numeric_cast
  113. <
  114. typename coordinate_type<Geometry>::type
  115. >(geometry::get<Dimension>(point)));
  116. assign_point_to_index
  117. <
  118. Geometry, Point, Index, Dimension + 1, DimensionCount
  119. >::apply(point, geometry);
  120. }
  121. };
  122. template
  123. <
  124. typename Geometry, typename Point,
  125. std::size_t Index,
  126. std::size_t DimensionCount
  127. >
  128. struct assign_point_to_index
  129. <
  130. Geometry, Point,
  131. Index,
  132. DimensionCount, DimensionCount
  133. >
  134. {
  135. static inline void apply(Point const& , Geometry& )
  136. {
  137. }
  138. };
  139. template
  140. <
  141. typename Geometry, typename Point,
  142. std::size_t Index,
  143. std::size_t Dimension, std::size_t DimensionCount
  144. >
  145. struct assign_point_from_index
  146. {
  147. static inline void apply(Geometry const& geometry, Point& point)
  148. {
  149. geometry::set<Dimension>( point, boost::numeric_cast
  150. <
  151. typename coordinate_type<Point>::type
  152. >(geometry::get<Index, Dimension>(geometry)));
  153. assign_point_from_index
  154. <
  155. Geometry, Point, Index, Dimension + 1, DimensionCount
  156. >::apply(geometry, point);
  157. }
  158. };
  159. template
  160. <
  161. typename Geometry, typename Point,
  162. std::size_t Index,
  163. std::size_t DimensionCount
  164. >
  165. struct assign_point_from_index
  166. <
  167. Geometry, Point,
  168. Index,
  169. DimensionCount, DimensionCount
  170. >
  171. {
  172. static inline void apply(Geometry const&, Point&)
  173. {
  174. }
  175. };
  176. template <typename Geometry>
  177. struct assign_2d_box_or_segment
  178. {
  179. typedef typename coordinate_type<Geometry>::type coordinate_type;
  180. // Here we assign 4 coordinates to a box of segment
  181. // -> Most logical is: x1,y1,x2,y2
  182. // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
  183. template <typename Type>
  184. static inline void apply(Geometry& geometry,
  185. Type const& x1, Type const& y1, Type const& x2, Type const& y2)
  186. {
  187. geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
  188. geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
  189. geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
  190. geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
  191. }
  192. };
  193. }} // namespace detail::assign
  194. #endif // DOXYGEN_NO_DETAIL
  195. #ifndef DOXYGEN_NO_DISPATCH
  196. namespace dispatch
  197. {
  198. template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
  199. struct assign
  200. {
  201. BOOST_MPL_ASSERT_MSG
  202. (
  203. false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
  204. , (types<Geometry>)
  205. );
  206. };
  207. template <typename Point>
  208. struct assign<point_tag, Point, 2>
  209. {
  210. typedef typename coordinate_type<Point>::type coordinate_type;
  211. template <typename T>
  212. static inline void apply(Point& point, T const& c1, T const& c2)
  213. {
  214. set<0>(point, boost::numeric_cast<coordinate_type>(c1));
  215. set<1>(point, boost::numeric_cast<coordinate_type>(c2));
  216. }
  217. };
  218. template <typename Point>
  219. struct assign<point_tag, Point, 3>
  220. {
  221. typedef typename coordinate_type<Point>::type coordinate_type;
  222. template <typename T>
  223. static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
  224. {
  225. set<0>(point, boost::numeric_cast<coordinate_type>(c1));
  226. set<1>(point, boost::numeric_cast<coordinate_type>(c2));
  227. set<2>(point, boost::numeric_cast<coordinate_type>(c3));
  228. }
  229. };
  230. template <typename Box>
  231. struct assign<box_tag, Box, 2>
  232. : detail::assign::assign_2d_box_or_segment<Box>
  233. {};
  234. template <typename Segment>
  235. struct assign<segment_tag, Segment, 2>
  236. : detail::assign::assign_2d_box_or_segment<Segment>
  237. {};
  238. template <typename GeometryTag, typename Geometry>
  239. struct assign_zero {};
  240. template <typename Point>
  241. struct assign_zero<point_tag, Point>
  242. : detail::assign::assign_zero_point
  243. {};
  244. template <typename Box>
  245. struct assign_zero<box_tag, Box>
  246. : detail::assign::assign_zero_box_or_segment
  247. {};
  248. template <typename Segment>
  249. struct assign_zero<segment_tag, Segment>
  250. : detail::assign::assign_zero_box_or_segment
  251. {};
  252. template <typename GeometryTag, typename Geometry>
  253. struct assign_inverse {};
  254. template <typename Box>
  255. struct assign_inverse<box_tag, Box>
  256. : detail::assign::assign_inverse_box_or_segment
  257. {};
  258. template <typename Segment>
  259. struct assign_inverse<segment_tag, Segment>
  260. : detail::assign::assign_inverse_box_or_segment
  261. {};
  262. } // namespace dispatch
  263. #endif // DOXYGEN_NO_DISPATCH
  264. /*!
  265. \brief Assign two coordinates to a geometry (usually a 2D point)
  266. \ingroup assign
  267. \tparam Geometry \tparam_geometry
  268. \tparam Type \tparam_numeric to specify the coordinates
  269. \param geometry \param_geometry
  270. \param c1 \param_x
  271. \param c2 \param_y
  272. \qbk{distinguish, 2 coordinate values}
  273. \qbk{
  274. [heading Example]
  275. [assign_2d_point] [assign_2d_point_output]
  276. [heading See also]
  277. \* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
  278. }
  279. */
  280. template <typename Geometry, typename Type>
  281. inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
  282. {
  283. concept::check<Geometry>();
  284. dispatch::assign
  285. <
  286. typename tag<Geometry>::type,
  287. Geometry,
  288. geometry::dimension<Geometry>::type::value
  289. >::apply(geometry, c1, c2);
  290. }
  291. /*!
  292. \brief Assign three values to a geometry (usually a 3D point)
  293. \ingroup assign
  294. \tparam Geometry \tparam_geometry
  295. \tparam Type \tparam_numeric to specify the coordinates
  296. \param geometry \param_geometry
  297. \param c1 \param_x
  298. \param c2 \param_y
  299. \param c3 \param_z
  300. \qbk{distinguish, 3 coordinate values}
  301. \qbk{
  302. [heading Example]
  303. [assign_3d_point] [assign_3d_point_output]
  304. [heading See also]
  305. \* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
  306. }
  307. */
  308. template <typename Geometry, typename Type>
  309. inline void assign_values(Geometry& geometry,
  310. Type const& c1, Type const& c2, Type const& c3)
  311. {
  312. concept::check<Geometry>();
  313. dispatch::assign
  314. <
  315. typename tag<Geometry>::type,
  316. Geometry,
  317. geometry::dimension<Geometry>::type::value
  318. >::apply(geometry, c1, c2, c3);
  319. }
  320. /*!
  321. \brief Assign four values to a geometry (usually a box or segment)
  322. \ingroup assign
  323. \tparam Geometry \tparam_geometry
  324. \tparam Type \tparam_numeric to specify the coordinates
  325. \param geometry \param_geometry
  326. \param c1 First coordinate (usually x1)
  327. \param c2 Second coordinate (usually y1)
  328. \param c3 Third coordinate (usually x2)
  329. \param c4 Fourth coordinate (usually y2)
  330. \qbk{distinguish, 4 coordinate values}
  331. */
  332. template <typename Geometry, typename Type>
  333. inline void assign_values(Geometry& geometry,
  334. Type const& c1, Type const& c2, Type const& c3, Type const& c4)
  335. {
  336. concept::check<Geometry>();
  337. dispatch::assign
  338. <
  339. typename tag<Geometry>::type,
  340. Geometry,
  341. geometry::dimension<Geometry>::type::value
  342. >::apply(geometry, c1, c2, c3, c4);
  343. }
  344. }} // namespace boost::geometry
  345. #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP