You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
7.1 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2010-2011 Hauke Heibel <heibel@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "main.h"
  10. #include <unsupported/Eigen/Splines>
  11. // lets do some explicit instantiations and thus
  12. // force the compilation of all spline functions...
  13. template class Spline<double, 2, Dynamic>;
  14. template class Spline<double, 3, Dynamic>;
  15. template class Spline<double, 2, 2>;
  16. template class Spline<double, 2, 3>;
  17. template class Spline<double, 2, 4>;
  18. template class Spline<double, 2, 5>;
  19. template class Spline<float, 2, Dynamic>;
  20. template class Spline<float, 3, Dynamic>;
  21. template class Spline<float, 3, 2>;
  22. template class Spline<float, 3, 3>;
  23. template class Spline<float, 3, 4>;
  24. template class Spline<float, 3, 5>;
  25. Spline<double, 2, Dynamic> closed_spline2d()
  26. {
  27. RowVectorXd knots(12);
  28. knots << 0,
  29. 0,
  30. 0,
  31. 0,
  32. 0.867193179093898,
  33. 1.660330955342408,
  34. 2.605084834823134,
  35. 3.484154586374428,
  36. 4.252699478956276,
  37. 4.252699478956276,
  38. 4.252699478956276,
  39. 4.252699478956276;
  40. MatrixXd ctrls(8,2);
  41. ctrls << -0.370967741935484, 0.236842105263158,
  42. -0.231401860693277, 0.442245185027632,
  43. 0.344361228532831, 0.773369994120753,
  44. 0.828990216203802, 0.106550882647595,
  45. 0.407270163678382, -1.043452922172848,
  46. -0.488467813584053, -0.390098582530090,
  47. -0.494657189446427, 0.054804824897884,
  48. -0.370967741935484, 0.236842105263158;
  49. ctrls.transposeInPlace();
  50. return Spline<double, 2, Dynamic>(knots, ctrls);
  51. }
  52. /* create a reference spline */
  53. Spline<double, 3, Dynamic> spline3d()
  54. {
  55. RowVectorXd knots(11);
  56. knots << 0,
  57. 0,
  58. 0,
  59. 0.118997681558377,
  60. 0.162611735194631,
  61. 0.498364051982143,
  62. 0.655098003973841,
  63. 0.679702676853675,
  64. 1.000000000000000,
  65. 1.000000000000000,
  66. 1.000000000000000;
  67. MatrixXd ctrls(8,3);
  68. ctrls << 0.959743958516081, 0.340385726666133, 0.585267750979777,
  69. 0.223811939491137, 0.751267059305653, 0.255095115459269,
  70. 0.505957051665142, 0.699076722656686, 0.890903252535799,
  71. 0.959291425205444, 0.547215529963803, 0.138624442828679,
  72. 0.149294005559057, 0.257508254123736, 0.840717255983663,
  73. 0.254282178971531, 0.814284826068816, 0.243524968724989,
  74. 0.929263623187228, 0.349983765984809, 0.196595250431208,
  75. 0.251083857976031, 0.616044676146639, 0.473288848902729;
  76. ctrls.transposeInPlace();
  77. return Spline<double, 3, Dynamic>(knots, ctrls);
  78. }
  79. /* compares evaluations against known results */
  80. void eval_spline3d()
  81. {
  82. Spline3d spline = spline3d();
  83. RowVectorXd u(10);
  84. u << 0.351659507062997,
  85. 0.830828627896291,
  86. 0.585264091152724,
  87. 0.549723608291140,
  88. 0.917193663829810,
  89. 0.285839018820374,
  90. 0.757200229110721,
  91. 0.753729094278495,
  92. 0.380445846975357,
  93. 0.567821640725221;
  94. MatrixXd pts(10,3);
  95. pts << 0.707620811535916, 0.510258911240815, 0.417485437023409,
  96. 0.603422256426978, 0.529498282727551, 0.270351549348981,
  97. 0.228364197569334, 0.423745615677815, 0.637687289287490,
  98. 0.275556796335168, 0.350856706427970, 0.684295784598905,
  99. 0.514519311047655, 0.525077224890754, 0.351628308305896,
  100. 0.724152914315666, 0.574461155457304, 0.469860285484058,
  101. 0.529365063753288, 0.613328702656816, 0.237837040141739,
  102. 0.522469395136878, 0.619099658652895, 0.237139665242069,
  103. 0.677357023849552, 0.480655768435853, 0.422227610314397,
  104. 0.247046593173758, 0.380604672404750, 0.670065791405019;
  105. pts.transposeInPlace();
  106. for (int i=0; i<u.size(); ++i)
  107. {
  108. Vector3d pt = spline(u(i));
  109. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  110. }
  111. }
  112. /* compares evaluations on corner cases */
  113. void eval_spline3d_onbrks()
  114. {
  115. Spline3d spline = spline3d();
  116. RowVectorXd u = spline.knots();
  117. MatrixXd pts(11,3);
  118. pts << 0.959743958516081, 0.340385726666133, 0.585267750979777,
  119. 0.959743958516081, 0.340385726666133, 0.585267750979777,
  120. 0.959743958516081, 0.340385726666133, 0.585267750979777,
  121. 0.430282980289940, 0.713074680056118, 0.720373307943349,
  122. 0.558074875553060, 0.681617921034459, 0.804417124839942,
  123. 0.407076008291750, 0.349707710518163, 0.617275937419545,
  124. 0.240037008286602, 0.738739390398014, 0.324554153129411,
  125. 0.302434111480572, 0.781162443963899, 0.240177089094644,
  126. 0.251083857976031, 0.616044676146639, 0.473288848902729,
  127. 0.251083857976031, 0.616044676146639, 0.473288848902729,
  128. 0.251083857976031, 0.616044676146639, 0.473288848902729;
  129. pts.transposeInPlace();
  130. for (int i=0; i<u.size(); ++i)
  131. {
  132. Vector3d pt = spline(u(i));
  133. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  134. }
  135. }
  136. void eval_closed_spline2d()
  137. {
  138. Spline2d spline = closed_spline2d();
  139. RowVectorXd u(12);
  140. u << 0,
  141. 0.332457030395796,
  142. 0.356467130532952,
  143. 0.453562180176215,
  144. 0.648017921874804,
  145. 0.973770235555003,
  146. 1.882577647219307,
  147. 2.289408593930498,
  148. 3.511951429883045,
  149. 3.884149321369450,
  150. 4.236261590369414,
  151. 4.252699478956276;
  152. MatrixXd pts(12,2);
  153. pts << -0.370967741935484, 0.236842105263158,
  154. -0.152576775123250, 0.448975001279334,
  155. -0.133417538277668, 0.461615613865667,
  156. -0.053199060826740, 0.507630360006299,
  157. 0.114249591147281, 0.570414135097409,
  158. 0.377810316891987, 0.560497102875315,
  159. 0.665052120135908, -0.157557441109611,
  160. 0.516006487053228, -0.559763292174825,
  161. -0.379486035348887, -0.331959640488223,
  162. -0.462034726249078, -0.039105670080824,
  163. -0.378730600917982, 0.225127015099919,
  164. -0.370967741935484, 0.236842105263158;
  165. pts.transposeInPlace();
  166. for (int i=0; i<u.size(); ++i)
  167. {
  168. Vector2d pt = spline(u(i));
  169. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  170. }
  171. }
  172. void check_global_interpolation2d()
  173. {
  174. typedef Spline2d::PointType PointType;
  175. typedef Spline2d::KnotVectorType KnotVectorType;
  176. typedef Spline2d::ControlPointVectorType ControlPointVectorType;
  177. ControlPointVectorType points = ControlPointVectorType::Random(2,100);
  178. KnotVectorType chord_lengths; // knot parameters
  179. Eigen::ChordLengths(points, chord_lengths);
  180. // interpolation without knot parameters
  181. {
  182. const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3);
  183. for (Eigen::DenseIndex i=0; i<points.cols(); ++i)
  184. {
  185. PointType pt = spline( chord_lengths(i) );
  186. PointType ref = points.col(i);
  187. VERIFY( (pt - ref).matrix().norm() < 1e-14 );
  188. }
  189. }
  190. // interpolation with given knot parameters
  191. {
  192. const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3,chord_lengths);
  193. for (Eigen::DenseIndex i=0; i<points.cols(); ++i)
  194. {
  195. PointType pt = spline( chord_lengths(i) );
  196. PointType ref = points.col(i);
  197. VERIFY( (pt - ref).matrix().norm() < 1e-14 );
  198. }
  199. }
  200. }
  201. void test_splines()
  202. {
  203. CALL_SUBTEST( eval_spline3d() );
  204. CALL_SUBTEST( eval_spline3d_onbrks() );
  205. CALL_SUBTEST( eval_closed_spline2d() );
  206. CALL_SUBTEST( check_global_interpolation2d() );
  207. }