Code-Eli  0.3.6
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 bezier_curve_fit_test_suite_hpp
14 #define 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 bezier_curve_fit_test_suite : public Test::Suite
32 {
33  private:
41 
42  tolerance_type tol;
43 
44  protected:
45  void AddTests(const float &)
46  {
47  // add the tests
54  }
55  void AddTests(const double &)
56  {
57  // add the tests
64  }
65  void AddTests(const long double &)
66  {
67  // add the tests
74  }
75 
76  public:
78  {
79  AddTests(data__());
80  }
82  {
83  }
84 
85  private:
86  void octave_print(int figno, const std::vector<point_type> &pts, const bezier_type &bez) const
87  {
88  size_t i;
89 
90  std::cout << "figure(" << figno << ");" << std::endl;
91  std::cout << "xpts=[" << pts[0].x();
92  for (i=1; i<pts.size(); ++i)
93  std::cout << ", " << pts[i].x();
94  std::cout << "];" << std::endl;
95  std::cout << "ypts=[" << pts[0].y();
96  for (i=1; i<pts.size(); ++i)
97  std::cout << ", " << pts[i].y();
98  std::cout << "];" << std::endl;
99 
100  std::vector<data__> t(101);
101  for (i=0; i<t.size(); ++i)
102  t[i]=static_cast<data__>(i)/(t.size()-1);
103 
104  std::cout << "xint=[" << bez.f(t[0])(0);
105  for (i=1; i<t.size(); ++i)
106  std::cout << ", " << bez.f(t[i])(0);
107  std::cout << "];" << std::endl;
108  std::cout << "yint=[" << bez.f(t[0])(1);
109  for (i=1; i<t.size(); ++i)
110  std::cout << ", " << bez.f(t[i])(1);
111  std::cout << "];" << std::endl;
112 
113  std::cout << "plot(xpts, ypts, 'bo', xint, yint, 'k-');" << std::endl;
114  }
115 
116  void create_circle(std::vector<point_type> &pts)
117  {
118  // NOTE: This will not create a closed circle, the last point will be
119  // the point just prior to the 2*pi point
120  size_t n=pts.size();
121  for (size_t i=0; i<n; ++i)
122  {
123  data__ theta(eli::constants::math<data__>::two_pi()*static_cast<data__>(i)/n);
124  pts[i](0)=std::cos(theta);
125  pts[i](1)=std::sin(theta);
126  pts[i](2)=0;
127  }
128  }
129 
131  {
132  // open curve
133  {
134  fit_container_type fcon;
135  size_t i, deg(5);
136  std::vector<point_type> pts(10);
137  bezier_type bez;
138  std::vector<data_type> t;
139 
140  // get points
141  create_circle(pts);
142 
143  // configure fit container
144  fcon.set_points(pts.begin(), pts.end());
146 
147  // fit points
148  bez.fit(t, fcon, deg);
149 
150  // calculate the error at the point
151  data_type err(0);
152  for (i=0; i<pts.size(); ++i)
153  {
154  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
155  }
156 
157  TEST_ASSERT(bez.open());
158  TEST_ASSERT(err < 0.110);
159 
160  // check if went through points
161  TEST_ASSERT(pts[0]!=bez.f(t[0]));
162  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
163  TEST_ASSERT(bez.f(0)!=bez.f(1));
164 
165 // octave_print(1, pts, bez);
166  }
167 
168  // closed curve
169  {
170  fit_container_type fcon;
171  size_t i, deg(5);
172  std::vector<point_type> pts(10);
173  bezier_type bez;
174  std::vector<data_type> t;
175 
176  // get points
177  create_circle(pts);
178 
179  // configure fit container
180  fcon.set_points(pts.begin(), pts.end());
182 
183  // fit points
184  bez.fit(t, fcon, deg);
185 
186  // calculate the error at the point
187  data_type err(0);
188  for (i=0; i<pts.size(); ++i)
189  {
190  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
191  }
192 
193  TEST_ASSERT(bez.closed());
194  TEST_ASSERT(err < 0.765);
195 
196  // check if went through points
197  TEST_ASSERT(pts[0]!=bez.f(t[0]));
198  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
199  TEST_ASSERT(bez.f(0)==bez.f(1));
200 
201 // octave_print(2, pts, bez);
202  }
203  }
204 
206  {
207  data_type eps(std::numeric_limits<data__>::epsilon());
208 
209  // open curve
210  {
211  fit_container_type fcon;
212  size_t i, deg(5);
213  std::vector<point_type> pts(10);
214  bezier_type bez;
215  std::vector<data_type> t;
216 
217  // get points
218  create_circle(pts);
219 
220  // configure fit container
221  fcon.set_points(pts.begin(), pts.end());
224  fcon.add_end_C0_constraint();
225 
226  // fit points
227  bez.fit(t, fcon, deg);
228 
229  // calculate the error at the point
230  data_type err(0);
231  for (i=0; i<pts.size(); ++i)
232  {
233  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
234  }
235 
236  TEST_ASSERT(bez.open());
237  TEST_ASSERT(err < 0.105);
238 
239  // check if went through points
240  TEST_ASSERT(pts[0]==bez.f(t[0]));
241  TEST_ASSERT((pts[pts.size()-1]-bez.f(t[t.size()-1])).norm()<81*eps);
242  TEST_ASSERT(bez.f(0)!=bez.f(1));
243 // if (typeid(data__)==typeid(double))
244 // {
245 // std::cout << "998 rat=" << (pts[pts.size()-1]-bez.f(t[t.size()-1])).norm()/eps << std::endl;
246 // }
247 
248 // octave_print(3, pts, bez);
249  }
250 
251  // closed curve
252  {
253  fit_container_type fcon;
254  size_t i, deg(5);
255  std::vector<point_type> pts(10);
256  bezier_type bez;
257  std::vector<data_type> t;
258 
259  // get points
260  create_circle(pts);
261 
262  // configure fit container
263  fcon.set_points(pts.begin(), pts.end());
266 
267  // fit points
268  bez.fit(t, fcon, deg);
269 
270  // calculate the error at the point
271  data_type err(0);
272  for (i=0; i<pts.size(); ++i)
273  {
274  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
275  }
276 
277  TEST_ASSERT(bez.closed());
278  TEST_ASSERT(err < 0.207);
279 
280  // check if went through points
281  TEST_ASSERT(pts[0]==bez.f(t[0]));
282  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
283  TEST_ASSERT(bez.f(0)==bez.f(1));
284 
285 // octave_print(4, pts, bez);
286  }
287 
288  // closed curve with additional point constraint
289  {
290  fit_container_type fcon;
291  size_t i, deg(5);
292  std::vector<point_type> pts(10);
293  bezier_type bez;
294  std::vector<data_type> t;
295 
296  // get points
297  create_circle(pts);
298 
299  // configure fit container
300  fcon.set_points(pts.begin(), pts.end());
303  fcon.add_C0_constraint(5);
304 
305  // fit points
306  bez.fit(t, fcon, deg);
307 
308  // calculate the error at the point
309  data_type err(0);
310  for (i=0; i<pts.size(); ++i)
311  {
312  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
313  }
314 
315  TEST_ASSERT(bez.closed());
316  TEST_ASSERT(err < 0.233);
317 
318  // check if went through points
319  TEST_ASSERT(pts[0]==bez.f(t[0]));
320  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
321  TEST_ASSERT(bez.f(0)==bez.f(1));
322  TEST_ASSERT((bez.f(t[5])-pts[5]).norm()<15*eps);
323 
324 // octave_print(5, pts, bez);
325  }
326  }
327 
329  {
330  // open curve
331  {
332  fit_container_type fcon;
333  size_t i, deg(5);
334  std::vector<point_type> pts(10);
335  bezier_type bez;
336  std::vector<data_type> t;
337 
338  // get points
339  create_circle(pts);
340 
341  // configure fit container
342  constraint_point_type fp1, fp2;
343  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
344  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
345  fp1(2)=0;
346  fp2(0)=-eli::constants::math<data_type>::two_pi()*pts[pts.size()-1](1);
347  fp2(1)=eli::constants::math<data_type>::two_pi()*pts[pts.size()-1](0);
348  fp2(2)=0;
349  fcon.set_points(pts.begin(), pts.end());
351  fcon.add_start_C1_constraint(fp1);
352  fcon.add_end_C1_constraint(fp2);
353 
354  // fit points
355  bez.fit(t, fcon, deg);
356 
357  // calculate the error at the point
358  data_type err(0);
359  for (i=0; i<pts.size(); ++i)
360  {
361  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
362  }
363 
364  TEST_ASSERT(bez.open());
365  TEST_ASSERT(err < 0.366);
366 
367  // check if went through points
368  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
369  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
370  TEST_ASSERT(tol.approximately_equal(pts[pts.size()-1], bez.f(t[t.size()-1])));
371  TEST_ASSERT(tol.approximately_equal(fp2, bez.fp(t[t.size()-1])));
372  TEST_ASSERT(bez.f(0)!=bez.f(1));
373 
374 // octave_print(6, pts, bez);
375  }
376 
377  // closed curve
378  {
379  fit_container_type fcon;
380  size_t i, deg(5);
381  std::vector<point_type> pts(10);
382  bezier_type bez;
383  std::vector<data_type> t;
384 
385  // get points
386  create_circle(pts);
387 
388  // configure fit container
389  constraint_point_type fp1;
390  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
391  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
392  fp1(2)=0;
393  fcon.set_points(pts.begin(), pts.end());
395  fcon.add_start_C1_constraint(fp1);
396 
397  // fit points
398  bez.fit(t, fcon, deg);
399 
400  // calculate the error at the point
401  data_type err(0);
402  for (i=0; i<pts.size(); ++i)
403  {
404  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
405  }
406 
407  TEST_ASSERT(bez.closed());
408  TEST_ASSERT(err < 0.331);
409 
410  // check if went through points
411  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
412  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
413  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
414  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
415 
416 // octave_print(7, pts, bez);
417  }
418 
419  // closed curve with additional point constraint
420  {
421  fit_container_type fcon;
422  size_t i, deg(5);
423  std::vector<point_type> pts(10);
424  bezier_type bez;
425  std::vector<data_type> t;
426 
427  // get points
428  create_circle(pts);
429 
430  // configure fit container
431  constraint_point_type fp1, fp2;
432  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
433  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
434  fp1(2)=0;
435  fp2(0)=-eli::constants::math<data_type>::two_pi()*pts[5](1);
436  fp2(1)=eli::constants::math<data_type>::two_pi()*pts[5](0);
437  fp2(2)=0;
438  fcon.set_points(pts.begin(), pts.end());
440  fcon.add_start_C1_constraint(fp1);
441  fcon.add_C1_constraint(5, fp2);
442 
443  // fit points
444  bez.fit(t, fcon, deg);
445 
446  // calculate the error at the point
447  data_type err(0);
448  for (i=0; i<pts.size(); ++i)
449  {
450  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
451  }
452 
453  TEST_ASSERT(bez.closed());
454  TEST_ASSERT(err < 0.418);
455 
456  // check if went through points
457  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
458  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
459  // precision in float calculation is totally lost
460  if (typeid(data_type)!=typeid(float))
461  {
462  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
463  }
464  TEST_ASSERT(tol.approximately_equal(pts[5], bez.f(t[5])));
465  TEST_ASSERT(tol.approximately_equal(fp2, bez.fp(t[5])));
466  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
467 
468 // octave_print(8, pts, bez);
469  }
470  }
471 
473  {
474  // open curve
475  {
476  fit_container_type fcon;
477  size_t i, deg(7);
478  std::vector<point_type> pts(20);
479  bezier_type bez;
480  std::vector<data_type> t;
481 
482  // get points
483  create_circle(pts);
484 
485  // configure fit container
486  constraint_point_type fp1, fpp1, fp2, fpp2;
487  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
488  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
489  fp1(2)=0;
490  fpp1(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](0);
491  fpp1(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](1);
492  fpp1(2)=0;
493  fp2(0)=-eli::constants::math<data_type>::two_pi()*pts[pts.size()-1](1);
494  fp2(1)=eli::constants::math<data_type>::two_pi()*pts[pts.size()-1](0);
495  fp2(2)=0;
496  fpp2(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[pts.size()-1](0);
497  fpp2(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[pts.size()-1](1);
498  fpp2(2)=0;
499  fcon.set_points(pts.begin(), pts.end());
501  fcon.add_start_C2_constraint(fp1, fpp1);
502  fcon.add_end_C2_constraint(fp2, fpp2);
503 
504  // fit points
505  bez.fit(t, fcon, deg);
506 
507  // calculate the error at the point
508  data_type err(0);
509  for (i=0; i<pts.size(); ++i)
510  {
511  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
512  }
513 
514  TEST_ASSERT(bez.open());
515  TEST_ASSERT(err < 0.372);
516 
517  // check if went through points
518  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
519  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
520  TEST_ASSERT(tol.approximately_equal(fpp1, bez.fpp(t[0])));
521  TEST_ASSERT(tol.approximately_equal(pts[pts.size()-1], bez.f(t[t.size()-1])));
522  TEST_ASSERT(tol.approximately_equal(fp2, bez.fp(t[t.size()-1])));
523  TEST_ASSERT(tol.approximately_equal(fpp2, bez.fpp(t[t.size()-1])));
524  TEST_ASSERT(bez.f(0)!=bez.f(1));
525 
526 // octave_print(9, pts, bez);
527  }
528 
529  // closed curve
530  {
531  fit_container_type fcon;
532  size_t i, deg(7);
533  std::vector<point_type> pts(20);
534  bezier_type bez;
535  std::vector<data_type> t;
536 
537  // get points
538  create_circle(pts);
539 
540  // configure fit container
541  constraint_point_type fp1, fpp1;
542  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
543  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
544  fp1(2)=0;
545  fpp1(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](0);
546  fpp1(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](1);
547  fpp1(2)=0;
548  fcon.set_points(pts.begin(), pts.end());
550  fcon.add_start_C2_constraint(fp1, fpp1);
551 
552  // fit points
553  bez.fit(t, fcon, deg);
554 
555  // calculate the error at the point
556  data_type err(0);
557  for (i=0; i<pts.size(); ++i)
558  {
559  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
560  }
561 
562  TEST_ASSERT(bez.closed());
563  TEST_ASSERT(err < 0.0479);
564 
565  // check if went through points
566  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
567  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
568  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
569  TEST_ASSERT(tol.approximately_equal(fpp1, bez.fpp(t[0])));
570  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
571 
572 // octave_print(10, pts, bez);
573  }
574 
575  // closed curve with additional point constraint
576  {
577  fit_container_type fcon;
578  size_t i, deg(7);
579  std::vector<point_type> pts(20);
580  bezier_type bez;
581  std::vector<data_type> t;
582 
583  // get points
584  create_circle(pts);
585 
586  // configure fit container
587  constraint_point_type fp1, fpp1, fp2, fpp2;
588  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
589  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
590  fp1(2)=0;
591  fpp1(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](0);
592  fpp1(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](1);
593  fpp1(2)=0;
594  fp2(0)=-eli::constants::math<data_type>::two_pi()*pts[10](1);
595  fp2(1)=eli::constants::math<data_type>::two_pi()*pts[10](0);
596  fp2(2)=0;
597  fpp2(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[10](0);
598  fpp2(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[10](1);
599  fpp2(2)=0;
600  fcon.set_points(pts.begin(), pts.end());
602  fcon.add_start_C2_constraint(fp1, fpp1);
603  fcon.add_C2_constraint(10, fp2, fpp2);
604 
605  // fit points
606  bez.fit(t, fcon, deg);
607 
608  // calculate the error at the point
609  data_type err(0);
610  for (i=0; i<pts.size(); ++i)
611  {
612  err+=eli::geom::point::distance(pts[i], bez.f(t[i]));
613  }
614 
615  TEST_ASSERT(bez.closed());
616  TEST_ASSERT(err < 0.0785);
617 
618  // check if went through points
619  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
620  TEST_ASSERT(tol.approximately_equal(pts[0], bez.f(t[0])));
621  TEST_ASSERT(tol.approximately_equal(fp1, bez.fp(t[0])));
622  TEST_ASSERT(tol.approximately_equal(fpp1, bez.fpp(t[0])));
623  TEST_ASSERT(tol.approximately_equal(pts[10], bez.f(t[10])));
624  TEST_ASSERT(tol.approximately_equal(fp2, bez.fp(t[10])));
625  TEST_ASSERT(tol.approximately_equal(fpp2, bez.fpp(t[10])));
626  TEST_ASSERT(pts[pts.size()-1]!=bez.f(t[t.size()-1]));
627 
628 // octave_print(11, pts, bez);
629  }
630  }
631 
633  {
634  // fit no constraints C0 closed
635  {
636  fit_container_type fcon;
637  size_t deg(7);
638  std::vector<point_type> pts(20);
639  bezier_type bez;
640  std::vector<data_type> t;
641 
642  // get points
643  create_circle(pts);
644 
645  // configure fit container
646  fcon.set_points(pts.begin(), pts.end());
648 
649  // fit points
650  data_type err;
651  err=bez.fit_with_error(t, fcon, deg);
652 
653  TEST_ASSERT(bez.closed());
654  TEST_ASSERT(err < 0.393);
655 
656  // check if went through points
657  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
658  TEST_ASSERT(bez.fp(0)!=bez.fp(1));
659  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
660 
661 // octave_print(12, pts, bez);
662  }
663 
664  // fit no constraints C1 closed
665  {
666  fit_container_type fcon;
667  size_t deg(7);
668  std::vector<point_type> pts(20);
669  bezier_type bez;
670  std::vector<data_type> t;
671 
672  // get points
673  create_circle(pts);
674 
675  // configure fit container
676  fcon.set_points(pts.begin(), pts.end());
678 
679  // fit points
680  data_type err;
681  err=bez.fit_with_error(t, fcon, deg);
682 
683  TEST_ASSERT(bez.closed());
684  TEST_ASSERT(err < 0.0312);
685 
686  // check if went through points
687  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
688  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
689  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
690 
691 // octave_print(13, pts, bez);
692  }
693 
694  // fit no constraints C2 closed
695  {
696  fit_container_type fcon;
697  size_t deg(7);
698  std::vector<point_type> pts(20);
699  bezier_type bez;
700  std::vector<data_type> t;
701 
702  // get points
703  create_circle(pts);
704 
705  // configure fit container
706  fcon.set_points(pts.begin(), pts.end());
708 
709  // fit points
710  data_type err;
711  err=bez.fit_with_error(t, fcon, deg);
712 
713  TEST_ASSERT(bez.closed());
714  TEST_ASSERT(err < 0.0343);
715 
716  // check if went through points
717  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
718  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
719  TEST_ASSERT(tol.approximately_equal(bez.fpp(0), bez.fpp(1)));
720 
721 // octave_print(14, pts, bez);
722  }
723 
724  // fit start constraints C0 closed
725  {
726  fit_container_type fcon;
727  size_t deg(7);
728  std::vector<point_type> pts(20);
729  bezier_type bez;
730  std::vector<data_type> t;
731 
732  // get points
733  create_circle(pts);
734 
735  // configure fit container
736  fcon.set_points(pts.begin(), pts.end());
739 
740  // fit points
741  data_type err;
742  err=bez.fit_with_error(t, fcon, deg);
743 
744  TEST_ASSERT(bez.closed());
745  TEST_ASSERT(err < 0.0185);
746 
747  // check if went through points
748  TEST_ASSERT(tol.approximately_equal(bez.f(0), pts[0]));
749  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
750  TEST_ASSERT(bez.fp(0)!=bez.fp(1));
751  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
752 
753 // octave_print(15, pts, bez);
754  }
755 
756  // fit start constraints C1 closed
757  {
758  fit_container_type fcon;
759  size_t deg(7);
760  std::vector<point_type> pts(20);
761  bezier_type bez;
762  std::vector<data_type> t;
763 
764  // get points
765  create_circle(pts);
766 
767  // configure fit container
768  constraint_point_type fp0;
769  fp0(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
770  fp0(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
771  fp0(2)=eli::constants::math<data_type>::two_pi()*pts[0](2);
772  fcon.set_points(pts.begin(), pts.end());
774  fcon.add_start_C1_constraint(fp0);
775 
776  // fit points
777  data_type err;
778  err=bez.fit_with_error(t, fcon, deg);
779 
780  TEST_ASSERT(bez.closed());
781  TEST_ASSERT(err < 0.0395);
782 
783  // check if went through points
784  TEST_ASSERT(tol.approximately_equal(bez.f(0), pts[0]));
785  TEST_ASSERT(tol.approximately_equal(bez.fp(0), fp0));
786  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
787  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
788  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
789 
790 // octave_print(16, pts, bez);
791  }
792 
793  // fit start constraints C2 closed
794  {
795  fit_container_type fcon;
796  size_t deg(7);
797  std::vector<point_type> pts(20);
798  bezier_type bez;
799  std::vector<data_type> t;
800 
801  // get points
802  create_circle(pts);
803 
804  // configure fit container
805  constraint_point_type fp0, fpp0;
806  fp0(0)=-eli::constants::math<data_type>::two_pi()*pts[0](1);
807  fp0(1)=eli::constants::math<data_type>::two_pi()*pts[0](0);
808  fp0(2)=eli::constants::math<data_type>::two_pi()*pts[0](2);
809  fpp0(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](0);
810  fpp0(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[0](1);
811  fpp0(2)=4*eli::constants::math<data_type>::pi_squared()*pts[0](2);
812  fcon.set_points(pts.begin(), pts.end());
814  fcon.add_start_C2_constraint(fp0, fpp0);
815 
816  // fit points
817  data_type err;
818  err=bez.fit_with_error(t, fcon, deg);
819 
820  TEST_ASSERT(bez.closed());
821  TEST_ASSERT(err < 0.141);
822 
823  // check if went through points
824  TEST_ASSERT(tol.approximately_equal(bez.f(0), pts[0]));
825  TEST_ASSERT(tol.approximately_equal(bez.fp(0), fp0));
826  TEST_ASSERT(tol.approximately_equal(bez.fpp(0), fpp0));
827  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
828  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
829  TEST_ASSERT(tol.approximately_equal(bez.fpp(0), bez.fpp(1)));
830 
831 // octave_print(17, pts, bez);
832  }
833 
834  // fit middle constraints C0 closed
835  {
836  fit_container_type fcon;
837  size_t deg(7);
838  std::vector<point_type> pts(20);
839  bezier_type bez;
840  std::vector<data_type> t;
841 
842  // get points
843  create_circle(pts);
844 
845  // configure fit container
846  int ci=5;
847  data_type t5;
848  point_type f5;
849  f5=pts[ci];
850  fcon.set_points(pts.begin(), pts.end());
852  fcon.add_C0_constraint(ci);
853 
854  // fit points
855  data_type err;
856  err=bez.fit_with_error(t, fcon, deg);
857 
858  TEST_ASSERT(bez.closed());
859  TEST_ASSERT(err < 0.0180);
860 
861  // check if went through points
862  t5=t[ci];
863  TEST_ASSERT(tol.approximately_equal(bez.f(t5), f5));
864  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
865  TEST_ASSERT(bez.fp(0)!=bez.fp(1));
866  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
867 
868 // octave_print(18, pts, bez);
869  }
870 
871  // fit middle constraints C1 closed
872  {
873  fit_container_type fcon;
874  size_t deg(7);
875  std::vector<point_type> pts(20);
876  bezier_type bez;
877  std::vector<data_type> t;
878 
879  // get points
880  create_circle(pts);
881 
882  // configure fit container
883  int ci=5;
884  data_type t5;
885  point_type f5;
886  f5=pts[ci];
887  fcon.set_points(pts.begin(), pts.end());
889  fcon.add_C0_constraint(ci);
890 
891  // fit points
892  data_type err;
893  err=bez.fit_with_error(t, fcon, deg);
894 
895  TEST_ASSERT(bez.closed());
896  TEST_ASSERT(err < 0.0316);
897 
898  // check if went through points
899  t5=t[ci];
900  TEST_ASSERT(tol.approximately_equal(bez.f(t5), f5));
901  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
902  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
903  TEST_ASSERT(bez.fpp(0)!=bez.fpp(1));
904 
905 // octave_print(19, pts, bez);
906  }
907 
908  // fit middle constraints C2 closed
909  {
910  fit_container_type fcon;
911  size_t deg(7);
912  std::vector<point_type> pts(20);
913  bezier_type bez;
914  std::vector<data_type> t;
915 
916  // get points
917  data_type err;
918  create_circle(pts);
919 
920  // configure fit container
921  int ci=5;
922  data_type t5;
923  point_type f5;
924  f5=pts[ci];
925  fcon.set_points(pts.begin(), pts.end());
927  fcon.add_C0_constraint(ci);
928 
929  // fit points
930  err=bez.fit_with_error(t, fcon, deg);
931 
932  TEST_ASSERT(bez.closed());
933  TEST_ASSERT(err < 0.0353);
934 
935  // check if went through points
936  t5=t[ci];
937  TEST_ASSERT(tol.approximately_equal(bez.f(t5), f5));
938  TEST_ASSERT(tol.approximately_equal(bez.f(0), bez.f(1)));
939  TEST_ASSERT(tol.approximately_equal(bez.fp(0), bez.fp(1)));
940  TEST_ASSERT(tol.approximately_equal(bez.fpp(0), bez.fpp(1)));
941 
942 // TEST_ASSERT((bez.f(t5)-f5).norm()<4*eps);
943 // TEST_ASSERT(bez.f(0)==bez.f(1));
944 // TEST_ASSERT((bez.fp(1)-bez.fp(0)).norm()<2.72e3*eps);
945 // TEST_ASSERT((bez.fpp(1)-bez.fpp(0)).norm()<1.19e4*eps);
946 // if (typeid(data__)==typeid(long double))
947 // {
948 // std::cout << "1788 rat=" << (bez.f(1)-bez.f(0)).norm()/eps << std::endl;
949 // std::cout << "1789 rat=" << (bez.fp(1)-bez.fp(0)).norm()/eps << std::endl;
950 // std::cout << "1790 rat=" << (bez.fpp(1)-bez.fpp(0)).norm()/eps << std::endl;
951 // }
952 // if (typeid(data__)==typeid(long double))
953 // {
954 // std::cout << "1794 rat=" << (bez.fp(1)-bez.fp(0)).norm()/eps << std::endl;
955 // }
956 
957 // octave_print(20, pts, bez);
958  }
959  }
960 
962  {
963  data_type eps(std::numeric_limits<data__>::epsilon());
964 
965  // interpolate through all points open
966  {
967  fit_container_type fcon;
968  std::vector<point_type> pts(4);
969  bezier_type bez;
970  std::vector<data_type> t;
971 
972  // get points
973  create_circle(pts);
974 
975  // configure fit container
976  fcon.set_points(pts.begin(), pts.end());
977 
978  // fit points
979  bez.interpolate(t, fcon);
980 
981  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size());
982  TEST_ASSERT(bez.open());
983 
984  // check if went through points
985  TEST_ASSERT(bez.f(t[0])==pts[0]);
986  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<4*eps);
987  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<7*eps);
988  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<13*eps);
989 
990 // octave_print(18, pts, bez);
991  }
992 
993  // interpolate through all points closed
994  {
995  fit_container_type fcon;
996  std::vector<point_type> pts(4);
997  bezier_type bez;
998  std::vector<data_type> t;
999 
1000  // get points
1001  create_circle(pts);
1002 
1003  // configure fit container
1004  fcon.set_points(pts.begin(), pts.end());
1006 
1007  // fit points
1008  bez.interpolate(t, fcon);
1009 
1010  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size()+1);
1011  TEST_ASSERT(bez.closed());
1012 
1013  // check if went through points
1014  TEST_ASSERT(bez.f(t[0])==pts[0]);
1015  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<3*eps);
1016  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<13*eps);
1017  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<37*eps);
1018  TEST_ASSERT(bez.f(0)==bez.f(1));
1019 
1020 // octave_print(19, pts, bez);
1021  }
1022 
1023  // interpolate through all points and specify C1 open
1024  {
1025  fit_container_type fcon;
1026  std::vector<point_type> pts(4);
1027  bezier_type bez;
1028  std::vector<data_type> t;
1029 
1030  // get points
1031  create_circle(pts);
1032 
1033  // configure fit container
1034  point_type fp1;
1035  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[1](1);
1036  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[1](0);
1037  fp1(2)=0;
1038  fcon.set_points(pts.begin(), pts.end());
1039  fcon.add_C1_constraint(1, fp1);
1040 
1041  // fit points
1042  bez.interpolate(t, fcon);
1043 
1044  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size()+1);
1045  TEST_ASSERT(bez.open());
1046 
1047  // check if went through points
1048  TEST_ASSERT((bez.f(t[0])-pts[0]).norm()<4*eps);
1049  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<10*eps);
1050  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<28*eps);
1051  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<63*eps);
1052  TEST_ASSERT((bez.fp(t[1])-fp1).norm()<17*eps);
1053 
1054 // octave_print(20, pts, bez);
1055  }
1056 
1057  // interpolate through all points and specify C1 closed
1058  {
1059  fit_container_type fcon;
1060  std::vector<point_type> pts(4);
1061  bezier_type bez;
1062  std::vector<data_type> t;
1063 
1064  // get points
1065  create_circle(pts);
1066 
1067  // configure fit container
1068  point_type fp1;
1069  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[1](1);
1070  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[1](0);
1071  fp1(2)=0;
1072  fcon.set_points(pts.begin(), pts.end());
1073  fcon.add_C1_constraint(1, fp1);
1075 
1076  // fit points
1077  bez.interpolate(t, fcon);
1078 
1079  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size()+3);
1080  TEST_ASSERT(bez.closed());
1081 
1082  // check if went through points
1083  TEST_ASSERT((bez.f(t[0])-pts[0]).norm()<5*eps);
1084  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<3*eps);
1085  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<21*eps);
1086  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<89*eps);
1087  TEST_ASSERT((bez.fp(t[1])-fp1).norm()<22*eps);
1088  TEST_ASSERT((bez.f(0)-bez.f(1)).norm()<202*eps);
1089  TEST_ASSERT(bez.f(0)==bez.f(1));
1090 
1091 // octave_print(21, pts, bez);
1092  }
1093 
1094  // interpolate through all points and specify C2 open
1095  {
1096  fit_container_type fcon;
1097  std::vector<point_type> pts(4);
1098  bezier_type bez;
1099  std::vector<data_type> t;
1100 
1101  // get points
1102  create_circle(pts);
1103 
1104  // configure fit container
1105  point_type fp1, fpp1;
1106  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[1](1);
1107  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[1](0);
1108  fp1(2)=0;
1109  fpp1(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[1](0);
1110  fpp1(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[1](1);
1111  fpp1(2)=0;
1112  fcon.set_points(pts.begin(), pts.end());
1113  fcon.add_C2_constraint(1, fp1, fpp1);
1114 
1115  // fit points
1116  bez.interpolate(t, fcon);
1117 
1118  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size()+2);
1119  TEST_ASSERT(bez.open());
1120 
1121  // check if went through points
1122  TEST_ASSERT((bez.f(t[0])-pts[0]).norm()<9*eps);
1123  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<9*eps);
1124  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<84*eps);
1125  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<2*eps);
1126  TEST_ASSERT((bez.fp(t[1])-fp1).norm()<130*eps);
1127  TEST_ASSERT((bez.fpp(t[1])-fpp1).norm()<353*eps);
1128 
1129 // octave_print(22, pts, bez);
1130  }
1131 
1132  // interpolate through all points and specify C2 closed
1133  {
1134  fit_container_type fcon;
1135  std::vector<point_type> pts(4);
1136  bezier_type bez;
1137  std::vector<data_type> t;
1138 
1139  // get points
1140  create_circle(pts);
1141 
1142  // configure fit container
1143  point_type fp1, fpp1;
1144  fp1(0)=-eli::constants::math<data_type>::two_pi()*pts[1](1);
1145  fp1(1)=eli::constants::math<data_type>::two_pi()*pts[1](0);
1146  fp1(2)=0;
1147  fpp1(0)=-4*eli::constants::math<data_type>::pi_squared()*pts[1](0);
1148  fpp1(1)=-4*eli::constants::math<data_type>::pi_squared()*pts[1](1);
1149  fpp1(2)=0;
1150  fcon.set_points(pts.begin(), pts.end());
1151  fcon.add_C2_constraint(1, fp1, fpp1);
1153 
1154  // fit points
1155  bez.interpolate(t, fcon);
1156 
1157  TEST_ASSERT(static_cast<size_t>(bez.degree()+1)==pts.size()+5);
1158  TEST_ASSERT(bez.closed());
1159 
1160  // check if went through points
1161  TEST_ASSERT((bez.f(t[0])-pts[0]).norm()<4*eps);
1162  TEST_ASSERT((bez.f(t[1])-pts[1]).norm()<4*eps);
1163  TEST_ASSERT((bez.f(t[2])-pts[2]).norm()<32*eps);
1164  TEST_ASSERT((bez.f(t[3])-pts[3]).norm()<93*eps);
1165  TEST_ASSERT((bez.fp(t[1])-fp1).norm()<45*eps);
1166  TEST_ASSERT((bez.fpp(t[1])-fpp1).norm()<398*eps);
1167  TEST_ASSERT(bez.f(0)==bez.f(1));
1168  TEST_ASSERT((bez.fp(0)-bez.fp(1)).norm()<5.30e3*eps);
1169  TEST_ASSERT((bez.fpp(0)-bez.fpp(1)).norm()<24.1e3*eps);
1170 
1171 // octave_print(23, pts, bez);
1172  }
1173  }
1174 };
1175 
1176 #endif
1177 
fit_container_type::constraint_point_type constraint_point_type
Definition: bezier_curve_fit_test_suite.hpp:36
~bezier_curve_fit_test_suite()
Definition: bezier_curve_fit_test_suite.hpp:81
Definition: continuity.hpp:26
bool open() const
Definition: bezier.hpp:311
Definition: continuity.hpp:28
Derived1__::Scalar distance(const Eigen::MatrixBase< Derived1__ > &p1, const Eigen::MatrixBase< Derived2__ > &p2)
Definition: distance.hpp:33
error_code add_start_C2_constraint()
Definition: fit_container.hpp:517
void interpolate_test()
Definition: bezier_curve_fit_test_suite.hpp:961
constraint_info::point_type constraint_point_type
Definition: fit_container.hpp:117
Eigen::Matrix< data_type, 1, dim__ > point_type
Definition: bezier.hpp:114
error_code add_C0_constraint(const index_type &i)
Definition: fit_container.hpp:562
void AddTests(const long double &)
Definition: bezier_curve_fit_test_suite.hpp:65
bezier_type::tolerance_type tolerance_type
Definition: bezier_curve_fit_test_suite.hpp:40
eli::geom::curve::bezier< data__, 3 > bezier_type
Definition: bezier_curve_fit_test_suite.hpp:34
point_type f(const data_type &t) const
Definition: bezier.hpp:324
error_code add_C2_constraint(const index_type &i)
Definition: fit_container.hpp:611
bool closed() const
Definition: bezier.hpp:312
tol__ tolerance_type
Definition: bezier.hpp:118
Definition: fit_container.hpp:34
void fit_C0_ends_test()
Definition: bezier_curve_fit_test_suite.hpp:205
void fit_C1_ends_test()
Definition: bezier_curve_fit_test_suite.hpp:328
void fit_free_ends_test()
Definition: bezier_curve_fit_test_suite.hpp:130
data_type fit_with_error(const fit_container_type &fcon, const index_type &deg_in)
Definition: bezier.hpp:538
Definition: math.hpp:25
error_code add_start_C0_constraint()
Definition: fit_container.hpp:502
index_type degree() const
Definition: bezier.hpp:191
void create_circle(std::vector< point_type > &pts)
Definition: bezier_curve_fit_test_suite.hpp:116
error_code add_end_C0_constraint()
Definition: fit_container.hpp:532
error_code add_start_C1_constraint()
Definition: fit_container.hpp:507
bezier_type::index_type index_type
Definition: bezier_curve_fit_test_suite.hpp:37
point_type fpp(const data_type &t) const
Definition: bezier.hpp:369
Definition: continuity.hpp:27
bezier_type::fit_container_type fit_container_type
Definition: bezier_curve_fit_test_suite.hpp:35
Definition: bezier_curve_fit_test_suite.hpp:31
void fit_C2_ends_test()
Definition: bezier_curve_fit_test_suite.hpp:472
bezier_curve_fit_test_suite()
Definition: bezier_curve_fit_test_suite.hpp:77
void interpolate(const fit_container_type &fcon)
Definition: bezier.hpp:550
error_code add_C1_constraint(const index_type &i)
Definition: fit_container.hpp:575
void set_end_flag(const eli::geom::general::continuity &op)
Definition: fit_container.hpp:399
void fit(const fit_container_type &fcon, const index_type &deg_in)
Definition: bezier.hpp:527
void fit_closed_test()
Definition: bezier_curve_fit_test_suite.hpp:632
bezier_type::data_type data_type
Definition: bezier_curve_fit_test_suite.hpp:39
tolerance_type tol
Definition: bezier_curve_fit_test_suite.hpp:42
point_type fp(const data_type &t) const
Definition: bezier.hpp:344
data__ data_type
Definition: bezier.hpp:113
void octave_print(int figno, const std::vector< point_type > &pts, const bezier_type &bez) const
Definition: bezier_curve_fit_test_suite.hpp:86
bezier_type::point_type point_type
Definition: bezier_curve_fit_test_suite.hpp:38
error_code add_end_C2_constraint()
Definition: fit_container.hpp:547
Definition: bezier.hpp:109
void set_points(it__ itb, it__ ite)
Definition: fit_container.hpp:444
error_code add_end_C1_constraint()
Definition: fit_container.hpp:537
void AddTests(const float &)
Definition: bezier_curve_fit_test_suite.hpp:45
Definition: continuity.hpp:29
point_type::Index index_type
Definition: bezier.hpp:116
void AddTests(const double &)
Definition: bezier_curve_fit_test_suite.hpp:55