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