Code-Eli  0.3.6
explicit_bezier_curve_fit_test_suite.hpp
Go to the documentation of this file.
1 /*********************************************************************************
2 * Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * David D. Marshall - initial code and implementation
11 ********************************************************************************/
12 
13 #ifndef explicit_bezier_curve_fit_test_suite_hpp
14 #define explicit_bezier_curve_fit_test_suite_hpp
15 
16 #include <cmath> // std::pow, std::exp
17 
18 #include <typeinfo> // typeid
19 #include <string> // std::string
20 #include <sstream> // std::stringstream
21 #include <iomanip> // std::setw
22 #include <limits> // std::numeric_limits
23 
24 #include "eli/constants/math.hpp"
29 
30 template<typename data__>
31 class explicit_bezier_curve_fit_test_suite : public Test::Suite
32 {
33  private:
37  typedef typename curve_type::data_type data_type;
40 
41  protected:
42  void AddTests(const float &)
43  {
44  // add the tests
50  }
51  void AddTests(const double &)
52  {
53  // add the tests
59  }
60  void AddTests(const long double &)
61  {
62  // add the tests
68  }
69 
70  public:
72  {
73  AddTests(data__());
74  }
76  {
77  }
78 
79  private:
80  void octave_print(int figno, const std::vector<point_type, Eigen::aligned_allocator<point_type> > &pts, const curve_type &bez) const
81  {
82  size_t i;
83 
84  std::cout << "figure(" << figno << ");" << std::endl;
85  std::cout << "xpts=[" << pts[0].x();
86  for (i=1; i<pts.size(); ++i)
87  std::cout << ", " << pts[i].x();
88  std::cout << "];" << std::endl;
89  std::cout << "ypts=[" << pts[0].y();
90  for (i=1; i<pts.size(); ++i)
91  std::cout << ", " << pts[i].y();
92  std::cout << "];" << std::endl;
93 
94  std::vector<data_type> t(101);
95  for (i=0; i<t.size(); ++i)
96  t[i]=static_cast<data_type>(i)/(t.size()-1);
97 
98  std::cout << "xint=[" << bez.f(t[0])(0);
99  for (i=1; i<t.size(); ++i)
100  std::cout << ", " << bez.f(t[i])(0);
101  std::cout << "];" << std::endl;
102  std::cout << "yint=[" << bez.f(t[0])(1);
103  for (i=1; i<t.size(); ++i)
104  std::cout << ", " << bez.f(t[i])(1);
105  std::cout << "];" << std::endl;
106 
107  std::cout << "plot(xpts, ypts, 'bo', xint, yint, 'k-');" << std::endl;
108  }
109 
110  void create_circle(std::vector<point_type, Eigen::aligned_allocator<point_type> > &pts)
111  {
112  // NOTE: This will create a semi-circle
113  size_t n=pts.size();
114  for (size_t i=0; i<n; ++i)
115  {
116  data__ theta(eli::constants::math<data__>::pi()*static_cast<data__>(i)/(n-1));
117  pts[i](0)=(1-std::cos(theta))/2;
118  pts[i](1)=std::sin(theta);
119  }
120  }
121 
123  {
124  fit_container_type fcon;
125  size_t i, deg(5);
126  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(10);
127  curve_type ebez;
128  std::vector<data_type> t;
129  data_type err_out, err_ref;
130 
131  // get points
132  create_circle(pts);
133 
134  // configure fit container
135  fcon.set_points(pts.begin(), pts.end());
136 
137  // fit points
138  err_out=ebez.fit(t, fcon, deg);
139 
140  // calculate the error at the point
141  for (err_ref=0, i=0; i<pts.size(); ++i)
142  {
143  err_ref+=eli::geom::point::distance(pts[i], ebez.f(t[i]));
144  }
145 
146  TEST_ASSERT(err_ref==err_out);
147  TEST_ASSERT(err_out < 0.430);
148 
149  // check if went through points
150  TEST_ASSERT(pts[0]!=ebez.f(t[0]));
151  TEST_ASSERT(pts[pts.size()-1]!=ebez.f(t[t.size()-1]));
152 
153 // octave_print(1, pts, ebez);
154  }
155 
157  {
158  data_type eps(std::numeric_limits<data__>::epsilon());
159  fit_container_type fcon;
160  size_t i, deg(5);
161  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(10);
162  curve_type ebez;
163  std::vector<data_type> t;
164  data_type err_out, err_ref;
165 
166  // get points
167  create_circle(pts);
168 
169  // configure fit container
170  fcon.set_points(pts.begin(), pts.end());
172  fcon.add_end_C0_constraint();
173 
174  // fit points
175  err_out=ebez.fit(t, fcon, deg);
176 
177  // calculate the error at the point
178  for (err_ref=0, i=0; i<pts.size(); ++i)
179  {
180  err_ref+=eli::geom::point::distance(pts[i], ebez.f(t[i]));
181  }
182 
183  TEST_ASSERT(err_out==err_ref);
184  TEST_ASSERT(err_out < 0.431);
185 
186  // check if went through points
187  TEST_ASSERT(pts[0]==ebez.f(t[0]));
188  TEST_ASSERT((pts[pts.size()-1]-ebez.f(t[t.size()-1])).norm()<65*eps);
189 
190 // octave_print(2, pts, ebez);
191  }
192 
194  {
195  data_type eps(std::numeric_limits<data__>::epsilon());
196  fit_container_type fcon;
197  size_t i, deg(5);
198  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(10);
199  curve_type ebez;
200  std::vector<data_type> t;
201  data_type err_out, err_ref;
202 
203  // get points
204  create_circle(pts);
205 
206  // configure fit container
207  point_type fp;
209  fcon.set_points(pts.begin(), pts.end());
211  fcon.add_end_C0_constraint();
212  fcon.add_C1_constraint(4);
213  fcon.get_constraint(4, ci);
214  fp << 1, ci.get_fp()(0);
215 
216  // fit points
217  err_out=ebez.fit(t, fcon, deg);
218 
219  // calculate the error at the point
220  for (err_ref=0, i=0; i<pts.size(); ++i)
221  {
222  err_ref+=eli::geom::point::distance(pts[i], ebez.f(t[i]));
223  }
224 
225  TEST_ASSERT(err_out==err_ref);
226  TEST_ASSERT(err_out < 0.682);
227 
228  // check if went through points
229  TEST_ASSERT(pts[0]==ebez.f(t[0]));
230  TEST_ASSERT((pts[pts.size()-1]-ebez.f(t[t.size()-1])).norm()<40*eps);
231  TEST_ASSERT((pts[4]-ebez.f(t[4])).norm()<35*eps);
232  TEST_ASSERT((fp-ebez.fp(t[4])).norm()<48*eps);
233 
234 // octave_print(3, pts, ebez);
235  }
236 
238  {
239  data_type eps(std::numeric_limits<data__>::epsilon());
240  fit_container_type fcon;
241  size_t i, deg(7);
242  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(10);
243  curve_type ebez;
244  std::vector<data_type> t;
245  data_type err_out, err_ref;
246 
247  // get points
248  create_circle(pts);
249 
250  // configure fit container
251  point_type fp, fpp;
253  fcon.set_points(pts.begin(), pts.end());
255  fcon.add_end_C0_constraint();
256  fcon.add_C2_constraint(4);
257  fcon.get_constraint(4, ci);
258  fp << 1, ci.get_fp()(0);
259  fpp << 0, ci.get_fpp()(0);
260 
261  // fit points
262  err_out=ebez.fit(t, fcon, deg);
263 
264  // calculate the error at the point
265  for (err_ref=0, i=0; i<pts.size(); ++i)
266  {
267  err_ref+=eli::geom::point::distance(pts[i], ebez.f(t[i]));
268  }
269 
270  TEST_ASSERT(err_out==err_ref);
271  TEST_ASSERT(err_out < 0.310);
272 
273  // check if went through points
274  TEST_ASSERT((pts[0]-ebez.f(t[0])).norm()<6*eps);
275  TEST_ASSERT((pts[pts.size()-1]-ebez.f(t[t.size()-1])).norm()<512*eps);
276  TEST_ASSERT((pts[4]-ebez.f(t[4])).norm()<35*eps);
277  TEST_ASSERT((fp-ebez.fp(t[4])).norm()<240*eps);
278  TEST_ASSERT((fpp-ebez.fpp(t[4])).norm()<1.54e3*eps);
279 
280 // octave_print(4, pts, ebez);
281  }
282 
284  {
285  data_type eps(std::numeric_limits<data__>::epsilon());
286  // interpolate through all points
287  {
288  fit_container_type fcon;
289  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(5);
290  curve_type ebez;
291  std::vector<data_type> t;
292 
293  // get points
294  create_circle(pts);
295 
296  // configure fit container
297  fcon.set_points(pts.begin(), pts.end());
298 
299  // fit points
300  ebez.interpolate(t, fcon);
301 
302  TEST_ASSERT(static_cast<size_t>(ebez.degree()+1)==pts.size());
303 
304  // check if went through points
305  TEST_ASSERT(ebez.f(t[0])==pts[0]);
306  TEST_ASSERT((ebez.f(t[1])-pts[1]).norm()<3*eps);
307  TEST_ASSERT((ebez.f(t[2])-pts[2]).norm()<7*eps);
308  TEST_ASSERT((ebez.f(t[3])-pts[3]).norm()<23*eps);
309 
310 // octave_print(5, pts, ebez);
311  }
312 
313  // interpolate through all points and specify C1
314  {
315  fit_container_type fcon;
316  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(5);
317  curve_type ebez;
318  std::vector<data_type> t;
319 
320  // get points
321  create_circle(pts);
322 
323  // configure fit container
324  point_type fp;
326  fcon.set_points(pts.begin(), pts.end());
327  fcon.add_C1_constraint(1);
328  fcon.get_constraint(1, ci);
329  fp << 1, ci.get_fp()(0);
330 
331  // fit points
332  ebez.interpolate(t, fcon);
333 
334  TEST_ASSERT(static_cast<size_t>(ebez.degree()+1)==(pts.size()+1));
335 
336  // check if went through points
337  TEST_ASSERT((ebez.f(t[0])-pts[0]).norm()<2*eps);
338  TEST_ASSERT((ebez.f(t[1])-pts[1]).norm()<3*eps);
339  TEST_ASSERT((ebez.f(t[2])-pts[2]).norm()<9*eps);
340  TEST_ASSERT((ebez.f(t[3])-pts[3]).norm()<44*eps);
341  TEST_ASSERT((fp-ebez.fp(t[1])).norm()<48*eps);
342 
343 // octave_print(6, pts, ebez);
344  }
345 
346  // interpolate through all points and specify C2
347  {
348  fit_container_type fcon;
349  std::vector<point_type, Eigen::aligned_allocator<point_type> > pts(5);
350  curve_type ebez;
351  std::vector<data_type> t;
352 
353  // get points
354  create_circle(pts);
355 
356  // configure fit container
357  point_type fp, fpp;
359  fcon.set_points(pts.begin(), pts.end());
360  fcon.add_C2_constraint(1);
361  fcon.get_constraint(1, ci);
362  fp << 1, ci.get_fp()(0);
363  fpp << 0, ci.get_fpp()(0);
364 
365  // fit points
366  ebez.interpolate(t, fcon);
367 
368  TEST_ASSERT(static_cast<size_t>(ebez.degree()+1)==(pts.size()+2));
369 
370  // check if went through points
371  TEST_ASSERT((ebez.f(t[0])-pts[0]).norm()<3*eps);
372  TEST_ASSERT((ebez.f(t[1])-pts[1]).norm()<3*eps);
373  TEST_ASSERT((ebez.f(t[2])-pts[2]).norm()<9*eps);
374  TEST_ASSERT((ebez.f(t[3])-pts[3]).norm()<70*eps);
375  TEST_ASSERT((fp-ebez.fp(t[1])).norm()<48*eps);
376  TEST_ASSERT((fpp-ebez.fpp(t[1])).norm()<81*eps);
377 
378 // octave_print(7, pts, ebez);
379  }
380  }
381 };
382 #endif
383 
eli::geom::curve::explicit_bezier< data__ > curve_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:34
curve_type::point_type point_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:36
point_type f(const data_type &t) const
Definition: explicit_bezier.hpp:100
Derived1__::Scalar distance(const Eigen::MatrixBase< Derived1__ > &p1, const Eigen::MatrixBase< Derived2__ > &p2)
Definition: distance.hpp:33
curve_type::index_type index_type
Definition: explicit_bezier.hpp:42
void AddTests(const double &)
Definition: explicit_bezier_curve_fit_test_suite.hpp:51
void fit_C0_ends_test()
Definition: explicit_bezier_curve_fit_test_suite.hpp:156
curve_type::data_type data_type
Definition: explicit_bezier.hpp:39
point_type fpp(const data_type &t) const
Definition: explicit_bezier.hpp:114
error_code add_C2_constraint(const index_type &i)
Definition: fit_container.hpp:611
Definition: explicit_bezier_curve_fit_test_suite.hpp:31
Definition: fit_container.hpp:34
explicit_bezier_curve_fit_test_suite()
Definition: explicit_bezier_curve_fit_test_suite.hpp:71
Definition: explicit_bezier.hpp:32
curve_type::control_point_type control_point_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:35
curve_type::data_type data_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:37
Definition: math.hpp:25
error_code add_start_C0_constraint()
Definition: fit_container.hpp:502
data_type fit(const fit_container_type &fcon, const index_type &deg_in)
Definition: explicit_bezier.hpp:154
error_code add_end_C0_constraint()
Definition: fit_container.hpp:532
error_code get_constraint(const index_type &i, constraint_info &ci) const
Definition: fit_container.hpp:476
void octave_print(int figno, const std::vector< point_type, Eigen::aligned_allocator< point_type > > &pts, const curve_type &bez) const
Definition: explicit_bezier_curve_fit_test_suite.hpp:80
point_type get_fpp() const
Definition: fit_container.hpp:87
curve_type::fit_container_type fit_container_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:39
void fit_free_ends_test()
Definition: explicit_bezier_curve_fit_test_suite.hpp:122
curve_type::point_type control_point_type
Definition: explicit_bezier.hpp:41
error_code add_C1_constraint(const index_type &i)
Definition: fit_container.hpp:575
void AddTests(const float &)
Definition: explicit_bezier_curve_fit_test_suite.hpp:42
curve_type::index_type index_type
Definition: explicit_bezier_curve_fit_test_suite.hpp:38
index_type degree() const
Definition: explicit_bezier.hpp:80
void AddTests(const long double &)
Definition: explicit_bezier_curve_fit_test_suite.hpp:60
point_type get_fp() const
Definition: fit_container.hpp:86
point_type fp(const data_type &t) const
Definition: explicit_bezier.hpp:107
void fit_C1_ends_test()
Definition: explicit_bezier_curve_fit_test_suite.hpp:193
Eigen::Matrix< data_type, 1, 2 > point_type
Definition: explicit_bezier.hpp:40
void interpolate(const fit_container_type &fcon)
Definition: explicit_bezier.hpp:284
void create_circle(std::vector< point_type, Eigen::aligned_allocator< point_type > > &pts)
Definition: explicit_bezier_curve_fit_test_suite.hpp:110
Definition: fit_container.hpp:50
void fit_C2_ends_test()
Definition: explicit_bezier_curve_fit_test_suite.hpp:237
~explicit_bezier_curve_fit_test_suite()
Definition: explicit_bezier_curve_fit_test_suite.hpp:75
void set_points(it__ itb, it__ ite)
Definition: fit_container.hpp:444
void interpolate_test()
Definition: explicit_bezier_curve_fit_test_suite.hpp:283