OGLplus (0.52.0) a C++ wrapper for OpenGL

curve.hpp
Go to the documentation of this file.
1 
12 #pragma once
13 #ifndef OGLPLUS_MATH_CURVE_1107121519_HPP
14 #define OGLPLUS_MATH_CURVE_1107121519_HPP
15 
16 #include <oglplus/math/vector.hpp>
17 #include <oglplus/math/compile_time.hpp>
18 
19 #include <vector>
20 #include <array>
21 #include <cmath>
22 #include <cassert>
23 
24 namespace oglplus {
25 
27 
39 template <typename Type, typename Parameter, unsigned Order>
41 {
42 private:
43  ::std::vector<Type> _points;
44  bool _connected;
45 public:
46  static bool Connected(const ::std::vector<Type>& points)
47  {
48  return ((points.size() - 1) % Order) == 0;
49  }
50 
52  bool Connected(void) const
53  {
54  return _connected;
55  }
56 
57  static bool Separated(const ::std::vector<Type>& points)
58  {
59  return (points.size() % (Order+1)) == 0;
60  }
61 
63  bool Separated(void) const
64  {
65  return !_connected;
66  }
67 
69  static bool PointsOk(const ::std::vector<Type>& points)
70  {
71  if(points.empty()) return false;
72  return (Connected(points) || Separated(points));
73  }
74 
76 
81  BezierCurves(::std::vector<Type>&& points)
82  : _points(std::move(points))
83  , _connected(Connected(_points))
84  {
85  assert(PointsOk(_points));
86  }
87 
89 
93  BezierCurves(::std::vector<Type>&& points, bool connected)
94  : _points(std::move(points))
95  , _connected(connected)
96  {
97  assert(PointsOk(_points));
98  assert(Connected(_points) == _connected);
99  }
100 
102 
107  BezierCurves(const ::std::vector<Type>& points)
108  : _points(points)
109  , _connected(Connected(_points))
110  {
111  assert(PointsOk(_points));
112  }
113 
115 
119  BezierCurves(const ::std::vector<Type>& points, bool connected)
120  : _points(points)
121  , _connected(connected)
122  {
123  assert(PointsOk(_points));
124  assert(Connected(_points) == _connected);
125  }
126 
127  template <std::size_t N>
128  BezierCurves(const ::std::array<Type, N>& points)
129  : _points(points.begin(), points.end())
130  , _connected(Connected(_points))
131  {
132  assert(PointsOk(_points));
133  }
134 
135  template <std::size_t N>
136  BezierCurves(const ::std::array<Type, N>& points, bool connected)
137  : _points(points.begin(), points.end())
138  , _connected(connected)
139  {
140  assert(PointsOk(_points));
141  assert(Connected(_points) == _connected);
142  }
143 
144  unsigned SegmentStep(void) const
145  {
146  assert(PointsOk(_points));
147 
148  if(_connected) return Order;
149  else return Order+1;
150  }
151 
153  unsigned SegmentCount(void) const
154  {
155  assert(PointsOk(_points));
156 
157  if(_connected) return (_points.size() - 1) / Order;
158  else return _points.size() / (Order+1);
159  }
160 
162  const ::std::vector<Type>& ControlPoints(void) const
163  {
164  return _points;
165  }
166 
169  {
170  const Parameter zero(0);
171  const Parameter one(1);
172  if(t < zero) t += ::std::floor(::std::fabs(t))+one;
173  else if(t > one) t -= ::std::floor(t);
174  assert(t >= zero && t <= one);
175  return t;
176  }
177 
179  Type Position01(Parameter t) const
180  {
181  const Parameter zero(0);
182  const Parameter one(1);
183 
184  if(t == one) t = zero;
185  assert(t >= zero && t < one);
186 
187  Parameter toffs = t*SegmentCount();
188 
189  unsigned poffs = unsigned(toffs) * SegmentStep();
190 
191  assert(poffs < _points.size() - Order);
192  Parameter t_sub = toffs - ::std::floor(toffs);
193  return math::Bezier<Type, Parameter, Order>::Position(
194  _points.data() + poffs,
195  _points.size() - poffs,
196  t_sub
197  );
198  }
199 
201  Type Position(Parameter t) const
202  {
203  return Position01(Wrap(t));
204  }
205 
207  void Approximate(std::vector<Type>& dest, unsigned n) const
208  {
209  unsigned sstep = SegmentStep();
210  unsigned s = SegmentCount();
211 
212  dest.resize(s*n+1);
213 
214  auto p = dest.begin();
215  const Parameter t_step = Parameter(1)/n;
216 
217  for(unsigned i=0; i!=s; ++i)
218  {
219  unsigned poffs = i*sstep;
220  Parameter t_sub = Parameter(0);
221  const Type* data = _points.data() + poffs;
222  unsigned size = _points.size() - poffs;
223  for(unsigned j=0; j!=n; ++j)
224  {
225  typedef math::Bezier<Type, Parameter, Order> b;
226  assert(p != dest.end());
227  *p = Type(b::Position(data, size, t_sub));
228  ++p;
229 
230  t_sub += t_step;
231  }
232  }
233  assert(p != dest.end());
234  *p = _points.back();
235  ++p;
236  assert(p == dest.end());
237  }
238 
240  ::std::vector<Type> Approximate(unsigned n) const
241  {
242  ::std::vector<Type> result;
243  Approximate(result, n);
244  return result;
245  }
246 
248  BezierCurves<Type, Parameter, Order-1> Derivative(void) const
249  {
250  unsigned sstep = SegmentStep();
251  unsigned s = SegmentCount();
252 
253  ::std::vector<Type> new_points(s * Order);
254  auto p = new_points.begin();
255 
256  for(unsigned i=0; i!=s; ++i)
257  {
258  for(unsigned j=0; j!=Order; ++j)
259  {
260  unsigned k = i*sstep+j;
261  assert(p != new_points.end());
262  *p = (_points[k+1] - _points[k]) * Order;
263  ++p;
264  }
265  }
266  assert(p == new_points.end());
267 
268  return BezierCurves<Type, Parameter, Order-1>(
269  std::move(new_points),
270  false
271  );
272  }
273 };
274 
276 
283 template <typename Type, typename Parameter>
285  : public BezierCurves<Type, Parameter, 3>
286 {
287 private:
288  template <typename StdRange>
289  static std::vector<Type> _make_cpoints(
290  const StdRange& points,
291  Parameter r
292  )
293  {
294  std::size_t i = 0, n = points.size();
295  assert(n != 0);
296  std::vector<Type> result(n * 3 + 1);
297  auto ir = result.begin();
298  while(i != n)
299  {
300  unsigned a = (n+i-1)%n;
301  unsigned b = i;
302  unsigned c = (i+1)%n;
303  unsigned d = (i+2)%n;
304  assert(ir != result.end());
305  *ir = points[b];
306  ++ir;
307  assert(ir != result.end());
308  *ir = Type(points[b] + (points[c] - points[a])*r);
309  ++ir;
310  assert(ir != result.end());
311  *ir = Type(points[c] + (points[b] - points[d])*r);
312  ++ir;
313  ++i;
314  }
315  assert(ir != result.end());
316  *ir = points[0]; ++ir;
317  assert(ir == result.end());
318  return result;
319  }
320 public:
323  const ::std::vector<Type>& points,
324  Parameter r = Parameter(1)/Parameter(3)
325  ): BezierCurves<Type, Parameter, 3>(_make_cpoints(points, r))
326  { }
327 
328  template <std::size_t N>
330  const ::std::array<Type, N>& points,
331  Parameter r = Parameter(1)/Parameter(3)
332  ): BezierCurves<Type, Parameter, 3>(_make_cpoints(points, r))
333  { }
334 };
335 
336 } // namespace oglplus
337 
338 #endif // include guard
::std::vector< Type > Approximate(unsigned n) const
Returns a sequence of points on the curve (n points per segment)
Definition: curve.hpp:240
BezierCurves(const ::std::vector< Type > &points, bool connected)
Creates the bezier curves from the control points.
Definition: curve.hpp:119
A sequence of Bezier curves, possibly connected at end points.
Definition: curve.hpp:40
CubicBezierLoop(const ::std::vector< Type > &points, Parameter r=Parameter(1)/Parameter(3))
Creates a loop passing through the sequence of the input points.
Definition: curve.hpp:322
bool Separated(void) const
Returns true if the individual curves are connected.
Definition: curve.hpp:63
PARAMETER_BUFFER_ARB.
const ::std::vector< Type > & ControlPoints(void) const
Returns the contol points of the curve.
Definition: curve.hpp:162
Type Position01(Parameter t) const
Gets the point on the curve at position t (must be between 0.0, 1.0)
Definition: curve.hpp:179
void Approximate(std::vector< Type > &dest, unsigned n) const
Makes a sequence of points on the curve (n points per segment)
Definition: curve.hpp:207
BezierCurves< Type, Parameter, Order-1 > Derivative(void) const
Returns a derivative of this curve.
Definition: curve.hpp:248
static Parameter Wrap(Parameter t)
Wraps the parameter value to [0.0, 1.0].
Definition: curve.hpp:168
A closed smooth cubic Bezier spline passing through all input points.
Definition: curve.hpp:284
unsigned SegmentCount(void) const
Returns the count of individual curves in the sequence.
Definition: curve.hpp:153
BezierCurves(::std::vector< Type > &&points)
Creates the bezier curves from the control points.
Definition: curve.hpp:81
BezierCurves(const ::std::vector< Type > &points)
Creates the bezier curves from the control points.
Definition: curve.hpp:107
static bool PointsOk(const ::std::vector< Type > &points)
Checks if the sequence of control points is OK for this curve type.
Definition: curve.hpp:69
BezierCurves(::std::vector< Type > &&points, bool connected)
Creates the bezier curves from the control points.
Definition: curve.hpp:93
bool Connected(void) const
Returns true if the individual curves are connected.
Definition: curve.hpp:52
Type Position(Parameter t) const
Gets the point on the curve at position t wrapped to [0.0, 1.0].
Definition: curve.hpp:201
A vector class.

Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Mon Sep 22 2014 by Doxygen (version 1.8.6).