point.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2014-2020.
  7. // Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
  8. // Contributed and/or modified by Menelaos Karavelas, 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_GEOMETRIES_POINT_HPP
  16. #define BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
  17. #include <cstddef>
  18. #include <type_traits>
  19. #include <boost/static_assert.hpp>
  20. #include <boost/geometry/core/access.hpp>
  21. #include <boost/geometry/core/assert.hpp>
  22. #include <boost/geometry/core/coordinate_type.hpp>
  23. #include <boost/geometry/core/coordinate_system.hpp>
  24. #include <boost/geometry/core/coordinate_dimension.hpp>
  25. #include <boost/geometry/core/make.hpp>
  26. #include <boost/geometry/core/tag.hpp>
  27. #include <boost/geometry/core/tags.hpp>
  28. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  29. #include <algorithm>
  30. #include <boost/geometry/core/assert.hpp>
  31. #endif
  32. namespace boost { namespace geometry
  33. {
  34. // Silence warning C4127: conditional expression is constant
  35. #if defined(_MSC_VER)
  36. #pragma warning(push)
  37. #pragma warning(disable : 4127)
  38. #endif
  39. namespace detail
  40. {
  41. template <typename Dummy, std::size_t N, std::size_t DimensionCount>
  42. struct is_coordinates_number_leq
  43. {
  44. static const bool value = (N <= DimensionCount);
  45. };
  46. template <typename Dummy, std::size_t N, std::size_t DimensionCount>
  47. struct is_coordinates_number_eq
  48. {
  49. static const bool value = (N == DimensionCount);
  50. };
  51. } // namespace detail
  52. namespace model
  53. {
  54. /*!
  55. \brief Basic point class, having coordinates defined in a neutral way
  56. \details Defines a neutral point class, fulfilling the Point Concept.
  57. Library users can use this point class, or use their own point classes.
  58. This point class is used in most of the samples and tests of Boost.Geometry
  59. This point class is used occasionally within the library, where a temporary
  60. point class is necessary.
  61. \ingroup geometries
  62. \tparam CoordinateType \tparam_numeric
  63. \tparam DimensionCount number of coordinates, usually 2 or 3
  64. \tparam CoordinateSystem coordinate system, for example cs::cartesian
  65. \qbk{[include reference/geometries/point.qbk]}
  66. \qbk{before.synopsis, [heading Model of]}
  67. \qbk{before.synopsis, [link geometry.reference.concepts.concept_point Point Concept]}
  68. */
  69. template
  70. <
  71. typename CoordinateType,
  72. std::size_t DimensionCount,
  73. typename CoordinateSystem
  74. >
  75. class point
  76. {
  77. BOOST_STATIC_ASSERT(DimensionCount > 0);
  78. // The following enum is used to fully instantiate the
  79. // CoordinateSystem class and check the correctness of the units
  80. // passed for non-Cartesian coordinate systems.
  81. enum { cs_check = sizeof(CoordinateSystem) };
  82. public:
  83. // TODO: constexpr requires LiteralType and until C++20
  84. // it has to have trivial destructor which makes access
  85. // debugging impossible with constexpr.
  86. #if !defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  87. /// \constructor_default_no_init
  88. constexpr point()
  89. // Workaround for VS2015
  90. #if defined(_MSC_VER) && (_MSC_VER < 1910)
  91. : m_values{} {}
  92. #else
  93. = default;
  94. #endif
  95. #else // defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  96. point()
  97. {
  98. m_created = 1;
  99. std::fill_n(m_values_initialized, DimensionCount, 0);
  100. }
  101. ~point()
  102. {
  103. m_created = 0;
  104. std::fill_n(m_values_initialized, DimensionCount, 0);
  105. }
  106. #endif
  107. /// @brief Constructor to set one value
  108. template
  109. <
  110. typename C = CoordinateType,
  111. std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 1, DimensionCount>::value, int> = 0
  112. >
  113. #if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  114. constexpr
  115. #endif
  116. explicit point(CoordinateType const& v0)
  117. : m_values{v0}
  118. {
  119. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  120. m_created = 1;
  121. std::fill_n(m_values_initialized, DimensionCount, 1);
  122. #endif
  123. }
  124. /// @brief Constructor to set two values
  125. template
  126. <
  127. typename C = CoordinateType,
  128. std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 2, DimensionCount>::value, int> = 0
  129. >
  130. #if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  131. constexpr
  132. #endif
  133. point(CoordinateType const& v0, CoordinateType const& v1)
  134. : m_values{ v0, v1 }
  135. {
  136. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  137. m_created = 1;
  138. std::fill_n(m_values_initialized, DimensionCount, 1);
  139. #endif
  140. }
  141. /// @brief Constructor to set three values
  142. template
  143. <
  144. typename C = CoordinateType,
  145. std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 3, DimensionCount>::value, int> = 0
  146. >
  147. #if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  148. constexpr
  149. #endif
  150. point(CoordinateType const& v0, CoordinateType const& v1, CoordinateType const& v2)
  151. : m_values{ v0, v1, v2 }
  152. {
  153. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  154. m_created = 1;
  155. std::fill_n(m_values_initialized, DimensionCount, 1);
  156. #endif
  157. }
  158. /// @brief Get a coordinate
  159. /// @tparam K coordinate to get
  160. /// @return the coordinate
  161. template <std::size_t K>
  162. #if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  163. constexpr
  164. #endif
  165. CoordinateType const& get() const
  166. {
  167. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  168. BOOST_GEOMETRY_ASSERT(m_created == 1);
  169. BOOST_GEOMETRY_ASSERT(m_values_initialized[K] == 1);
  170. #endif
  171. BOOST_STATIC_ASSERT(K < DimensionCount);
  172. return m_values[K];
  173. }
  174. /// @brief Set a coordinate
  175. /// @tparam K coordinate to set
  176. /// @param value value to set
  177. template <std::size_t K>
  178. void set(CoordinateType const& value)
  179. {
  180. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  181. BOOST_GEOMETRY_ASSERT(m_created == 1);
  182. m_values_initialized[K] = 1;
  183. #endif
  184. BOOST_STATIC_ASSERT(K < DimensionCount);
  185. m_values[K] = value;
  186. }
  187. private:
  188. CoordinateType m_values[DimensionCount];
  189. #if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
  190. int m_created;
  191. int m_values_initialized[DimensionCount];
  192. #endif
  193. };
  194. } // namespace model
  195. // Adapt the point to the concept
  196. #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
  197. namespace traits
  198. {
  199. template
  200. <
  201. typename CoordinateType,
  202. std::size_t DimensionCount,
  203. typename CoordinateSystem
  204. >
  205. struct tag<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
  206. {
  207. typedef point_tag type;
  208. };
  209. template
  210. <
  211. typename CoordinateType,
  212. std::size_t DimensionCount,
  213. typename CoordinateSystem
  214. >
  215. struct coordinate_type<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
  216. {
  217. typedef CoordinateType type;
  218. };
  219. template
  220. <
  221. typename CoordinateType,
  222. std::size_t DimensionCount,
  223. typename CoordinateSystem
  224. >
  225. struct coordinate_system<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
  226. {
  227. typedef CoordinateSystem type;
  228. };
  229. template
  230. <
  231. typename CoordinateType,
  232. std::size_t DimensionCount,
  233. typename CoordinateSystem
  234. >
  235. struct dimension<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
  236. : std::integral_constant<std::size_t, DimensionCount>
  237. {};
  238. template
  239. <
  240. typename CoordinateType,
  241. std::size_t DimensionCount,
  242. typename CoordinateSystem,
  243. std::size_t Dimension
  244. >
  245. struct access<model::point<CoordinateType, DimensionCount, CoordinateSystem>, Dimension>
  246. {
  247. static constexpr CoordinateType get(
  248. model::point<CoordinateType, DimensionCount, CoordinateSystem> const& p)
  249. {
  250. return p.template get<Dimension>();
  251. }
  252. static void set(
  253. model::point<CoordinateType, DimensionCount, CoordinateSystem>& p,
  254. CoordinateType const& value)
  255. {
  256. p.template set<Dimension>(value);
  257. }
  258. };
  259. template
  260. <
  261. typename CoordinateType,
  262. std::size_t DimensionCount,
  263. typename CoordinateSystem
  264. >
  265. struct make<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
  266. {
  267. typedef model::point<CoordinateType, DimensionCount, CoordinateSystem> point_type;
  268. static const bool is_specialized = true;
  269. template
  270. <
  271. typename C = CoordinateType,
  272. std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 1, DimensionCount>::value, int> = 0
  273. >
  274. static constexpr point_type apply(CoordinateType const& v0)
  275. {
  276. return point_type(v0);
  277. }
  278. template
  279. <
  280. typename C = CoordinateType,
  281. std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 2, DimensionCount>::value, int> = 0
  282. >
  283. static constexpr point_type apply(CoordinateType const& v0,
  284. CoordinateType const& v1)
  285. {
  286. return point_type(v0, v1);
  287. }
  288. template
  289. <
  290. typename C = CoordinateType,
  291. std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 3, DimensionCount>::value, int> = 0
  292. >
  293. static constexpr point_type apply(CoordinateType const& v0,
  294. CoordinateType const& v1,
  295. CoordinateType const& v2)
  296. {
  297. return point_type(v0, v1, v2);
  298. }
  299. };
  300. } // namespace traits
  301. #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
  302. #if defined(_MSC_VER)
  303. #pragma warning(pop)
  304. #endif
  305. }} // namespace boost::geometry
  306. #endif // BOOST_GEOMETRY_GEOMETRIES_POINT_HPP