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 
13 #include <boost/config.hpp>
14 
15 #include <cstddef>
16 #include <type_traits>
17 
18 namespace boost { namespace gil {
19 
29 
33 template <typename T>
34 class point
35 {
36 public:
37  using value_type = T;
38 
39  template<std::size_t D>
40  struct axis
41  {
42  using coord_t = value_type;
43  };
44 
45  static constexpr std::size_t num_dimensions = 2;
46 
47  point() = default;
48  point(T px, T py) : x(px), y(py) {}
49 
50  point operator<<(std::ptrdiff_t shift) const
51  {
52  return point(x << shift, y << shift);
53  }
54 
55  point operator>>(std::ptrdiff_t shift) const
56  {
57  return point(x >> shift, y >> shift);
58  }
59 
60  point& operator+=(point const& p)
61  {
62  x += p.x;
63  y += p.y;
64  return *this;
65  }
66 
67  point& operator-=(point const& p)
68  {
69  x -= p.x;
70  y -= p.y;
71  return *this;
72  }
73 
74  point& operator/=(double d)
75  {
76  if (d < 0 || 0 < d)
77  {
78  x = static_cast<T>(x / d);
79  y = static_cast<T>(y / d);
80  }
81  return *this;
82  }
83 
84  point& operator*=(double d)
85  {
86  x = static_cast<T>(x * d);
87  y = static_cast<T>(y * d);
88  return *this;
89  }
90 
91  T const& operator[](std::size_t i) const
92  {
93  return this->*mem_array[i];
94  }
95 
96  T& operator[](std::size_t i)
97  {
98  return this->*mem_array[i];
99  }
100 
101  T x{0};
102  T y{0};
103 
104 private:
105  // this static array of pointers to member variables makes operator[] safe
106  // and doesn't seem to exhibit any performance penalty.
107  static T point<T>::* const mem_array[num_dimensions];
108 };
109 
111 template <typename T>
112 using point2 = point<T>;
113 
116 using point_t = point<std::ptrdiff_t>;
117 
118 template <typename T>
119 T point<T>::* const point<T>::mem_array[point<T>::num_dimensions] =
120 {
121  &point<T>::x,
122  &point<T>::y
123 };
124 
126 template <typename T>
127 BOOST_FORCEINLINE
128 bool operator==(const point<T>& p1, const point<T>& p2)
129 {
130  return p1.x == p2.x && p1.y == p2.y;
131 }
132 
134 template <typename T>
135 BOOST_FORCEINLINE
136 bool operator!=(const point<T>& p1, const point<T>& p2)
137 {
138  return p1.x != p2.x || p1.y != p2.y;
139 }
140 
142 template <typename T>
143 BOOST_FORCEINLINE
144 point<T> operator+(const point<T>& p1, const point<T>& p2)
145 {
146  return { p1.x + p2.x, p1.y + p2.y };
147 }
148 
150 template <typename T>
151 BOOST_FORCEINLINE
152 point<T> operator-(const point<T>& p)
153 {
154  return { -p.x, -p.y };
155 }
156 
158 template <typename T>
159 BOOST_FORCEINLINE
160 point<T> operator-(const point<T>& p1, const point<T>& p2)
161 {
162  return { p1.x - p2.x, p1.y - p2.y };
163 }
164 
166 template <typename T, typename D>
167 BOOST_FORCEINLINE
168 auto operator/(point<T> const& p, D d) -> point<typename std::common_type<T, D>::type>
169 {
170  static_assert(std::is_arithmetic<D>::value, "denominator is not arithmetic type");
171  using result_type = typename std::common_type<T, D>::type;
172  if (d < 0 || 0 < d)
173  {
174  double const x = p.x / static_cast<double>(d);
175  double const y = p.y / static_cast<double>(d);
176  return point<result_type>{
177  static_cast<result_type>(iround(x)),
178  static_cast<result_type>(iround(y))};
179  }
180  else
181  {
182  return point<result_type>{0, 0};
183  }
184 }
185 
187 template <typename T, typename M>
188 BOOST_FORCEINLINE
189 auto operator*(point<T> const& p, M m) -> point<typename std::common_type<T, M>::type>
190 {
191  static_assert(std::is_arithmetic<M>::value, "multiplier is not arithmetic type");
192  using result_type = typename std::common_type<T, M>::type;
193  return point<result_type>{p.x * m, p.y * m};
194 }
195 
197 template <typename T, typename M>
198 BOOST_FORCEINLINE
199 auto operator*(M m, point<T> const& p) -> point<typename std::common_type<T, M>::type>
200 {
201  static_assert(std::is_arithmetic<M>::value, "multiplier is not arithmetic type");
202  using result_type = typename std::common_type<T, M>::type;
203  return point<result_type>{p.x * m, p.y * m};
204 }
205 
207 template <std::size_t K, typename T>
208 BOOST_FORCEINLINE
209 T const& axis_value(point<T> const& p)
210 {
211  static_assert(K < point<T>::num_dimensions, "axis index out of range");
212  return p[K];
213 }
214 
216 template <std::size_t K, typename T>
217 BOOST_FORCEINLINE
218 T& axis_value(point<T>& p)
219 {
220  static_assert(K < point<T>::num_dimensions, "axis index out of range");
221  return p[K];
222 }
223 
230 
232 template <typename T>
233 inline point<std::ptrdiff_t> iround(point<T> const& p)
234 {
235  static_assert(std::is_integral<T>::value, "T is not integer");
236  return { static_cast<std::ptrdiff_t>(p.x), static_cast<std::ptrdiff_t>(p.y) };
237 }
238 
240 inline point<std::ptrdiff_t> iround(point<float> const& p)
241 {
242  return { iround(p.x), iround(p.y) };
243 }
244 
246 inline point<std::ptrdiff_t> iround(point<double> const& p)
247 {
248  return { iround(p.x), iround(p.y) };
249 }
250 
252 inline point<std::ptrdiff_t> ifloor(point<float> const& p)
253 {
254  return { ifloor(p.x), ifloor(p.y) };
255 }
256 
258 inline point<std::ptrdiff_t> ifloor(point<double> const& p)
259 {
260  return { ifloor(p.x), ifloor(p.y) };
261 }
262 
264 inline point<std::ptrdiff_t> iceil(point<float> const& p)
265 {
266  return { iceil(p.x), iceil(p.y) };
267 }
268 
270 inline point<std::ptrdiff_t> iceil(point<double> const& p)
271 {
272  return { iceil(p.x), iceil(p.y) };
273 }
274 
275 }} // namespace boost::gil
276 
277 #endif
Definition: algorithm.hpp:30