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
40namespace 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
50namespace model
51{
52
53namespace detail
54{
55
56template <std::size_t DimensionCount, std::size_t Index>
57struct 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
67template <> 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
73template <> struct array_assign<1, 1>
74{
75 template <typename T> static inline void apply(T [], T const& ) {}
76};
77
78template <> 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*/
102template
103<
104 typename CoordinateType,
105 std::size_t DimensionCount,
106 typename CoordinateSystem
107>
108class 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
119public:
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
211private:
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
226namespace traits
227{
228template
229<
230 typename CoordinateType,
231 std::size_t DimensionCount,
232 typename CoordinateSystem
233>
234struct tag<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
235{
236 typedef point_tag type;
237};
238
239template
240<
241 typename CoordinateType,
242 std::size_t DimensionCount,
243 typename CoordinateSystem
244>
245struct coordinate_type<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
246{
247 typedef CoordinateType type;
248};
249
250template
251<
252 typename CoordinateType,
253 std::size_t DimensionCount,
254 typename CoordinateSystem
255>
256struct coordinate_system<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
257{
258 typedef CoordinateSystem type;
259};
260
261template
262<
263 typename CoordinateType,
264 std::size_t DimensionCount,
265 typename CoordinateSystem
266>
267struct dimension<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
268 : boost::mpl::int_<DimensionCount>
269{};
270
271template
272<
273 typename CoordinateType,
274 std::size_t DimensionCount,
275 typename CoordinateSystem,
276 std::size_t Dimension
277>
278struct 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