ArraySamplers2-Impl.h
Go to the documentation of this file.
1 /*************************************************************************
2 > File Name: ArraySamplers2-Impl.h
3 > Project Name: CubbyFlow
4 > Author: Dongmin Kim
5 > Purpose: 2-D nearest array sampler class.
6 > Created Time: 2017/05/10
7 > Copyright (c) 2018, Dongmin Kim
8 *************************************************************************/
9 #ifndef CUBBYFLOW_ARRAY_SAMPLERS2_IMPL_H
10 #define CUBBYFLOW_ARRAY_SAMPLERS2_IMPL_H
11 
12 #include <Core/Math/MathUtils.h>
13 
14 namespace CubbyFlow
15 {
16  template <typename T, typename R>
18  const ConstArrayAccessor2<T>& accessor,
19  const Vector2<R>& gridSpacing,
20  const Vector2<R>& gridOrigin)
21  {
22  m_gridSpacing = gridSpacing;
23  m_origin = gridOrigin;
24  m_accessor = accessor;
25  }
26 
27  template <typename T, typename R>
29  {
30  m_gridSpacing = other.m_gridSpacing;
31  m_origin = other.m_origin;
32  m_accessor = other.m_accessor;
33  }
34 
35  template <typename T, typename R>
37  {
38  ssize_t i, j;
39  R fx, fy;
40 
41  assert(m_gridSpacing.x > std::numeric_limits<R>::epsilon());
42  assert(m_gridSpacing.y > std::numeric_limits<R>::epsilon());
43 
44  const Vector2<R> normalizedX = (pt - m_origin) / m_gridSpacing;
45 
46  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
47  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
48 
49  GetBarycentric(normalizedX.x, 0, iSize - 1, &i, &fx);
50  GetBarycentric(normalizedX.y, 0, jSize - 1, &j, &fy);
51 
52  i = std::min(static_cast<ssize_t>(i + fx + 0.5), iSize - 1);
53  j = std::min(static_cast<ssize_t>(j + fy + 0.5), jSize - 1);
54 
55  return m_accessor(i, j);
56  }
57 
58  template <typename T, typename R>
60  {
61  ssize_t i, j;
62  R fx, fy;
63 
64  assert(m_gridSpacing.x > std::numeric_limits<R>::epsilon());
65  assert(m_gridSpacing.y > std::numeric_limits<R>::epsilon());
66 
67  const Vector2<R> normalizedX = (pt - m_origin) / m_gridSpacing;
68 
69  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
70  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
71 
72  GetBarycentric(normalizedX.x, 0, iSize - 1, &i, &fx);
73  GetBarycentric(normalizedX.y, 0, jSize - 1, &j, &fy);
74 
75  index->x = std::min(static_cast<ssize_t>(i + fx + 0.5), iSize - 1);
76  index->y = std::min(static_cast<ssize_t>(j + fy + 0.5), jSize - 1);
77  }
78 
79  template <typename T, typename R>
80  std::function<T(const Vector2<R>&)> NearestArraySampler<T, R, 2>::Functor() const
81  {
82  NearestArraySampler sampler(*this);
83  return std::bind(&NearestArraySampler::operator(), sampler, std::placeholders::_1);
84  }
85 
86  template <typename T, typename R>
88  const ConstArrayAccessor2<T>& accessor,
89  const Vector2<R>& gridSpacing,
90  const Vector2<R>& gridOrigin)
91  {
92  m_gridSpacing = gridSpacing;
93  m_invGridSpacing = static_cast<R>(1) / m_gridSpacing;
94  m_origin = gridOrigin;
95  m_accessor = accessor;
96  }
97 
98  template <typename T, typename R>
100  {
101  m_gridSpacing = other.m_gridSpacing;
102  m_invGridSpacing = other.m_invGridSpacing;
103  m_origin = other.m_origin;
104  m_accessor = other.m_accessor;
105  }
106 
107  template <typename T, typename R>
109  {
110  ssize_t i, j;
111  R fx, fy;
112 
113  assert(m_gridSpacing.x > std::numeric_limits<R>::epsilon());
114  assert(m_gridSpacing.y > std::numeric_limits<R>::epsilon());
115 
116  const Vector2<R> normalizedX = (pt - m_origin) / m_gridSpacing;
117 
118  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
119  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
120 
121  GetBarycentric(normalizedX.x, 0, iSize - 1, &i, &fx);
122  GetBarycentric(normalizedX.y, 0, jSize - 1, &j, &fy);
123 
124  const ssize_t ip1 = std::min(i + 1, iSize - 1);
125  const ssize_t jp1 = std::min(j + 1, jSize - 1);
126 
127  return BiLerp(
128  m_accessor(i, j), m_accessor(ip1, j),
129  m_accessor(i, jp1), m_accessor(ip1, jp1),
130  fx, fy);
131  }
132 
133  template <typename T, typename R>
135  const Vector2<R>& pt,
136  std::array<Point2UI, 4>* indices,
137  std::array<R, 4>* weights) const
138  {
139  ssize_t i, j;
140  R fx, fy;
141 
142  assert(m_gridSpacing.x > std::numeric_limits<R>::epsilon());
143  assert(m_gridSpacing.y > std::numeric_limits<R>::epsilon());
144 
145  const Vector2<R> normalizedX = (pt - m_origin) / m_gridSpacing;
146 
147  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
148  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
149 
150  GetBarycentric(normalizedX.x, 0, iSize, &i, &fx);
151  GetBarycentric(normalizedX.y, 0, jSize, &j, &fy);
152 
153  const ssize_t ip1 = std::min(i + 1, iSize - 1);
154  const ssize_t jp1 = std::min(j + 1, jSize - 1);
155 
156  (*indices)[0] = Point2UI(i, j);
157  (*indices)[1] = Point2UI(ip1, j);
158  (*indices)[2] = Point2UI(i, jp1);
159  (*indices)[3] = Point2UI(ip1, jp1);
160 
161  (*weights)[0] = (1 - fx) * (1 - fy);
162  (*weights)[1] = fx * (1 - fy);
163  (*weights)[2] = (1 - fx) * fy;
164  (*weights)[3] = fx * fy;
165  }
166 
167  template <typename T, typename R>
169  const Vector2<R>& x,
170  std::array<Point2UI, 4>* indices,
171  std::array<Vector2<R>, 4>* weights) const
172  {
173  ssize_t i, j;
174  R fx, fy;
175 
176  assert(m_gridSpacing.x > 0.0);
177  assert(m_gridSpacing.y > 0.0);
178 
179  const Vector2<R> normalizedX = (x - m_origin) * m_invGridSpacing;
180 
181  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
182  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
183 
184  GetBarycentric(normalizedX.x, 0, iSize - 1, &i, &fx);
185  GetBarycentric(normalizedX.y, 0, jSize - 1, &j, &fy);
186 
187  const ssize_t ip1 = std::min(i + 1, iSize - 1);
188  const ssize_t jp1 = std::min(j + 1, jSize - 1);
189 
190  (*indices)[0] = Point2UI(i, j);
191  (*indices)[1] = Point2UI(ip1, j);
192  (*indices)[2] = Point2UI(i, jp1);
193  (*indices)[3] = Point2UI(ip1, jp1);
194 
195  (*weights)[0] = Vector2<R>(fy * m_invGridSpacing.x - m_invGridSpacing.x, fx * m_invGridSpacing.y - m_invGridSpacing.y);
196  (*weights)[1] = Vector2<R>(-fy * m_invGridSpacing.x + m_invGridSpacing.x, -fx * m_invGridSpacing.y);
197  (*weights)[2] = Vector2<R>(-fy * m_invGridSpacing.x, -fx * m_invGridSpacing.y + m_invGridSpacing.y);
198  (*weights)[3] = Vector2<R>(fy * m_invGridSpacing.x, fx * m_invGridSpacing.y);
199  }
200 
201  template <typename T, typename R>
202  std::function<T(const Vector2<R>&)> LinearArraySampler<T, R, 2>::Functor() const
203  {
204  LinearArraySampler sampler(*this);
205  return std::bind(&LinearArraySampler::operator(), sampler, std::placeholders::_1);
206  }
207 
208  template <typename T, typename R>
210  const ConstArrayAccessor2<T>& accessor,
211  const Vector2<R>& gridSpacing,
212  const Vector2<R>& gridOrigin)
213  {
214  m_gridSpacing = gridSpacing;
215  m_origin = gridOrigin;
216  m_accessor = accessor;
217  }
218 
219  template <typename T, typename R>
221  {
222  m_gridSpacing = other.m_gridSpacing;
223  m_origin = other.m_origin;
224  m_accessor = other.m_accessor;
225  }
226 
227  template <typename T, typename R>
229  {
230  ssize_t i, j;
231  R fx, fy;
232 
233  assert(m_gridSpacing.x > std::numeric_limits<R>::epsilon());
234  assert(m_gridSpacing.y > std::numeric_limits<R>::epsilon());
235 
236  const Vector2<R> normalizedX = (pt - m_origin) / m_gridSpacing;
237 
238  const ssize_t iSize = static_cast<ssize_t>(m_accessor.size().x);
239  const ssize_t jSize = static_cast<ssize_t>(m_accessor.size().y);
240 
241  GetBarycentric(normalizedX.x, 0, iSize - 1, &i, &fx);
242  GetBarycentric(normalizedX.y, 0, jSize - 1, &j, &fy);
243 
244  const ssize_t is[4] = { std::max(i - 1, ZERO_SSIZE), i, std::min(i + 1, iSize - 1), std::min(i + 2, iSize - 1) };
245  const ssize_t js[4] = { std::max(j - 1, ZERO_SSIZE), j, std::min(j + 1, jSize - 1), std::min(j + 2, jSize - 1) };
246 
247  // Calculate in i direction first
248  T values[4];
249 
250  for (int n = 0; n < 4; ++n)
251  {
252  values[n] = MonotonicCatmullRom(
253  m_accessor(is[0], js[n]),
254  m_accessor(is[1], js[n]),
255  m_accessor(is[2], js[n]),
256  m_accessor(is[3], js[n]),
257  fx);
258  }
259 
260  return MonotonicCatmullRom(values[0], values[1], values[2], values[3], fy);
261  }
262 
263  template <typename T, typename R>
264  std::function<T(const Vector2<R>&)> CubicArraySampler<T, R, 2>::Functor() const
265  {
266  CubicArraySampler sampler(*this);
267  return std::bind(&CubicArraySampler::operator(), sampler, std::placeholders::_1);
268  }
269 }
270 
271 #endif
2-D read-only array accessor class.
Definition: ArrayAccessor2.h:261
T x
X (or the first) component of the vector.
Definition: Vector2.h:29
T x
X (or the first) component of the point.
Definition: Point2.h:28
Generic N-D nearest array sampler class.
Definition: ArraySamplers.h:22
2-D point class.
Definition: Point2.h:25
Point2< size_t > Point2UI
Unsigned integer-type 2D point.
Definition: Point2.h:315
T y
Y (or the second) component of the point.
Definition: Point2.h:34
Definition: pybind11Utils.h:24
Generic N-D cubic array sampler class.
Definition: ArraySamplers.h:50
T y
Y (or the second) component of the vector.
Definition: Vector2.h:35
S BiLerp(const S &f00, const S &f10, const S &f01, const S &f11, T tx, T ty)
Computes bilinear interpolation.
Definition: MathUtils-Impl.h:190
constexpr ssize_t ZERO_SSIZE
Zero ssize_t.
Definition: Constants.h:20
2-D vector class.
Definition: Vector2.h:26
T MonotonicCatmullRom(const T &f0, const T &f1, const T &f2, const T &f3, T f)
Computes monotonic Catmull-Rom interpolation.
Definition: MathUtils-Impl.h:228
Generic N-D linear array sampler class.
Definition: ArraySamplers.h:36
void GetBarycentric(T x, ssize_t iLow, ssize_t iHigh, ssize_t *i, T *f)
Gets the barycentric coordinate.
Definition: MathUtils-Impl.h:151