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