Boost GIL


point.hpp
1//
2// Copyright 2005-2007 Adobe Systems Incorporated
3//
4// Distributed under the Boost Software License, Version 1.0
5// See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt
7//
8#ifndef BOOST_GIL_POINT_HPP
9#define BOOST_GIL_POINT_HPP
10
11#include <boost/gil/utilities.hpp>
12#include <boost/gil/detail/std_common_type.hpp>
13
14#include <boost/config.hpp>
15
16#include <cstddef>
17#include <type_traits>
18
19namespace boost { namespace gil {
20
30
34template <typename T>
35class point
36{
37public:
38 using value_type = T;
39
40 template<std::size_t D>
41 struct axis
42 {
43 using coord_t = value_type;
44 };
45
46 static constexpr std::size_t num_dimensions = 2;
47
48 point() = default;
49 point(T px, T py) : x(px), y(py) {}
50
51 point operator<<(std::ptrdiff_t shift) const
52 {
53 return point(x << shift, y << shift);
54 }
55
56 point operator>>(std::ptrdiff_t shift) const
57 {
58 return point(x >> shift, y >> shift);
59 }
60
61 point& operator+=(point const& p)
62 {
63 x += p.x;
64 y += p.y;
65 return *this;
66 }
67
68 point& operator-=(point const& p)
69 {
70 x -= p.x;
71 y -= p.y;
72 return *this;
73 }
74
75 point& operator/=(double d)
76 {
77 if (d < 0 || 0 < d)
78 {
79 x = static_cast<T>(x / d);
80 y = static_cast<T>(y / d);
81 }
82 return *this;
83 }
84
85 point& operator*=(double d)
86 {
87 x = static_cast<T>(x * d);
88 y = static_cast<T>(y * d);
89 return *this;
90 }
91
92 T const& operator[](std::size_t i) const
93 {
94 return this->*mem_array[i];
95 }
96
97 T& operator[](std::size_t i)
98 {
99 return this->*mem_array[i];
100 }
101
102 T x{0};
103 T y{0};
104
105private:
106 // this static array of pointers to member variables makes operator[] safe
107 // and doesn't seem to exhibit any performance penalty.
108 static T point<T>::* const mem_array[num_dimensions];
109};
110
112template <typename T>
113using point2 = point<T>;
114
118
119template <typename T>
121{
124};
125
127template <typename T>
128BOOST_FORCEINLINE
129bool operator==(const point<T>& p1, const point<T>& p2)
130{
131 return p1.x == p2.x && p1.y == p2.y;
132}
133
135template <typename T>
136BOOST_FORCEINLINE
137bool operator!=(const point<T>& p1, const point<T>& p2)
138{
139 return p1.x != p2.x || p1.y != p2.y;
140}
141
143template <typename T>
144BOOST_FORCEINLINE
145point<T> operator+(const point<T>& p1, const point<T>& p2)
146{
147 return { p1.x + p2.x, p1.y + p2.y };
148}
149
151template <typename T>
152BOOST_FORCEINLINE
153point<T> operator-(const point<T>& p)
154{
155 return { -p.x, -p.y };
156}
157
159template <typename T>
160BOOST_FORCEINLINE
161point<T> operator-(const point<T>& p1, const point<T>& p2)
162{
163 return { p1.x - p2.x, p1.y - p2.y };
164}
165
167template <typename T, typename D>
168BOOST_FORCEINLINE
169auto operator/(point<T> const& p, D d)
170 -> typename std::enable_if
171 <
172 std::is_arithmetic<D>::value,
173 point<typename detail::std_common_type<T, D>::type>
174 >::type
175{
176 static_assert(std::is_arithmetic<D>::value, "denominator is not arithmetic type");
177 using result_type = typename detail::std_common_type<T, D>::type;
178 if (d < 0 || 0 < d)
179 {
180 double const x = static_cast<double>(p.x) / static_cast<double>(d);
181 double const y = static_cast<double>(p.y) / static_cast<double>(d);
182 return point<result_type>{
183 static_cast<result_type>(iround(x)),
184 static_cast<result_type>(iround(y))};
185 }
186 else
187 {
188 return point<result_type>{0, 0};
189 }
190}
191
193template <typename T, typename M>
194BOOST_FORCEINLINE
195auto operator*(point<T> const& p, M m)
196 -> typename std::enable_if
197 <
198 std::is_arithmetic<M>::value,
199 point<typename detail::std_common_type<T, M>::type>
200 >::type
201{
202 static_assert(std::is_arithmetic<M>::value, "multiplier is not arithmetic type");
203 using result_type = typename detail::std_common_type<T, M>::type;
204 return point<result_type>{p.x * m, p.y * m};
205}
206
208template <typename T, typename M>
209BOOST_FORCEINLINE
210auto operator*(M m, point<T> const& p)
211 -> typename std::enable_if
212 <
213 std::is_arithmetic<M>::value,
214 point<typename detail::std_common_type<T, M>::type>
215 >::type
216{
217 static_assert(std::is_arithmetic<M>::value, "multiplier is not arithmetic type");
218 using result_type = typename detail::std_common_type<T, M>::type;
219 return point<result_type>{p.x * m, p.y * m};
220}
221
223template <std::size_t K, typename T>
224BOOST_FORCEINLINE
225T const& axis_value(point<T> const& p)
226{
227 static_assert(K < point<T>::num_dimensions, "axis index out of range");
228 return p[K];
229}
230
232template <std::size_t K, typename T>
233BOOST_FORCEINLINE
234T& axis_value(point<T>& p)
235{
236 static_assert(K < point<T>::num_dimensions, "axis index out of range");
237 return p[K];
238}
239
246
248template <typename T>
249inline auto iround(point<T> const& p) -> point<std::ptrdiff_t>
250{
251 static_assert(std::is_integral<T>::value, "T is not integer");
252 return { static_cast<std::ptrdiff_t>(p.x), static_cast<std::ptrdiff_t>(p.y) };
253}
254
256inline auto iround(point<float> const& p) -> point<std::ptrdiff_t>
257{
258 return { iround(p.x), iround(p.y) };
259}
260
262inline auto iround(point<double> const& p) -> point<std::ptrdiff_t>
263{
264 return { iround(p.x), iround(p.y) };
265}
266
268inline auto ifloor(point<float> const& p) -> point<std::ptrdiff_t>
269{
270 return { ifloor(p.x), ifloor(p.y) };
271}
272
274inline auto ifloor(point<double> const& p) -> point<std::ptrdiff_t>
275{
276 return { ifloor(p.x), ifloor(p.y) };
277}
278
280inline auto iceil(point<float> const& p) -> point<std::ptrdiff_t>
281{
282 return { iceil(p.x), iceil(p.y) };
283}
284
286inline auto iceil(point<double> const& p) -> point<std::ptrdiff_t>
287{
288 return { iceil(p.x), iceil(p.y) };
289}
290
291}} // namespace boost::gil
292
293#endif
2D point both axes of which have the same dimension typeModels: Point2DConcept
Definition point.hpp:36
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition algorithm.hpp:36