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.

281 lines
8.4 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/StormEigen/Splines>
  11. namespace StormEigen {
  12. // lets do some explicit instantiations and thus
  13. // force the compilation of all spline functions...
  14. template class Spline<double, 2, Dynamic>;
  15. template class Spline<double, 3, Dynamic>;
  16. template class Spline<double, 2, 2>;
  17. template class Spline<double, 2, 3>;
  18. template class Spline<double, 2, 4>;
  19. template class Spline<double, 2, 5>;
  20. template class Spline<float, 2, Dynamic>;
  21. template class Spline<float, 3, Dynamic>;
  22. template class Spline<float, 3, 2>;
  23. template class Spline<float, 3, 3>;
  24. template class Spline<float, 3, 4>;
  25. template class Spline<float, 3, 5>;
  26. }
  27. Spline<double, 2, Dynamic> closed_spline2d()
  28. {
  29. RowVectorXd knots(12);
  30. knots << 0,
  31. 0,
  32. 0,
  33. 0,
  34. 0.867193179093898,
  35. 1.660330955342408,
  36. 2.605084834823134,
  37. 3.484154586374428,
  38. 4.252699478956276,
  39. 4.252699478956276,
  40. 4.252699478956276,
  41. 4.252699478956276;
  42. MatrixXd ctrls(8,2);
  43. ctrls << -0.370967741935484, 0.236842105263158,
  44. -0.231401860693277, 0.442245185027632,
  45. 0.344361228532831, 0.773369994120753,
  46. 0.828990216203802, 0.106550882647595,
  47. 0.407270163678382, -1.043452922172848,
  48. -0.488467813584053, -0.390098582530090,
  49. -0.494657189446427, 0.054804824897884,
  50. -0.370967741935484, 0.236842105263158;
  51. ctrls.transposeInPlace();
  52. return Spline<double, 2, Dynamic>(knots, ctrls);
  53. }
  54. /* create a reference spline */
  55. Spline<double, 3, Dynamic> spline3d()
  56. {
  57. RowVectorXd knots(11);
  58. knots << 0,
  59. 0,
  60. 0,
  61. 0.118997681558377,
  62. 0.162611735194631,
  63. 0.498364051982143,
  64. 0.655098003973841,
  65. 0.679702676853675,
  66. 1.000000000000000,
  67. 1.000000000000000,
  68. 1.000000000000000;
  69. MatrixXd ctrls(8,3);
  70. ctrls << 0.959743958516081, 0.340385726666133, 0.585267750979777,
  71. 0.223811939491137, 0.751267059305653, 0.255095115459269,
  72. 0.505957051665142, 0.699076722656686, 0.890903252535799,
  73. 0.959291425205444, 0.547215529963803, 0.138624442828679,
  74. 0.149294005559057, 0.257508254123736, 0.840717255983663,
  75. 0.254282178971531, 0.814284826068816, 0.243524968724989,
  76. 0.929263623187228, 0.349983765984809, 0.196595250431208,
  77. 0.251083857976031, 0.616044676146639, 0.473288848902729;
  78. ctrls.transposeInPlace();
  79. return Spline<double, 3, Dynamic>(knots, ctrls);
  80. }
  81. /* compares evaluations against known results */
  82. void eval_spline3d()
  83. {
  84. Spline3d spline = spline3d();
  85. RowVectorXd u(10);
  86. u << 0.351659507062997,
  87. 0.830828627896291,
  88. 0.585264091152724,
  89. 0.549723608291140,
  90. 0.917193663829810,
  91. 0.285839018820374,
  92. 0.757200229110721,
  93. 0.753729094278495,
  94. 0.380445846975357,
  95. 0.567821640725221;
  96. MatrixXd pts(10,3);
  97. pts << 0.707620811535916, 0.510258911240815, 0.417485437023409,
  98. 0.603422256426978, 0.529498282727551, 0.270351549348981,
  99. 0.228364197569334, 0.423745615677815, 0.637687289287490,
  100. 0.275556796335168, 0.350856706427970, 0.684295784598905,
  101. 0.514519311047655, 0.525077224890754, 0.351628308305896,
  102. 0.724152914315666, 0.574461155457304, 0.469860285484058,
  103. 0.529365063753288, 0.613328702656816, 0.237837040141739,
  104. 0.522469395136878, 0.619099658652895, 0.237139665242069,
  105. 0.677357023849552, 0.480655768435853, 0.422227610314397,
  106. 0.247046593173758, 0.380604672404750, 0.670065791405019;
  107. pts.transposeInPlace();
  108. for (int i=0; i<u.size(); ++i)
  109. {
  110. Vector3d pt = spline(u(i));
  111. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  112. }
  113. }
  114. /* compares evaluations on corner cases */
  115. void eval_spline3d_onbrks()
  116. {
  117. Spline3d spline = spline3d();
  118. RowVectorXd u = spline.knots();
  119. MatrixXd pts(11,3);
  120. pts << 0.959743958516081, 0.340385726666133, 0.585267750979777,
  121. 0.959743958516081, 0.340385726666133, 0.585267750979777,
  122. 0.959743958516081, 0.340385726666133, 0.585267750979777,
  123. 0.430282980289940, 0.713074680056118, 0.720373307943349,
  124. 0.558074875553060, 0.681617921034459, 0.804417124839942,
  125. 0.407076008291750, 0.349707710518163, 0.617275937419545,
  126. 0.240037008286602, 0.738739390398014, 0.324554153129411,
  127. 0.302434111480572, 0.781162443963899, 0.240177089094644,
  128. 0.251083857976031, 0.616044676146639, 0.473288848902729,
  129. 0.251083857976031, 0.616044676146639, 0.473288848902729,
  130. 0.251083857976031, 0.616044676146639, 0.473288848902729;
  131. pts.transposeInPlace();
  132. for (int i=0; i<u.size(); ++i)
  133. {
  134. Vector3d pt = spline(u(i));
  135. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  136. }
  137. }
  138. void eval_closed_spline2d()
  139. {
  140. Spline2d spline = closed_spline2d();
  141. RowVectorXd u(12);
  142. u << 0,
  143. 0.332457030395796,
  144. 0.356467130532952,
  145. 0.453562180176215,
  146. 0.648017921874804,
  147. 0.973770235555003,
  148. 1.882577647219307,
  149. 2.289408593930498,
  150. 3.511951429883045,
  151. 3.884149321369450,
  152. 4.236261590369414,
  153. 4.252699478956276;
  154. MatrixXd pts(12,2);
  155. pts << -0.370967741935484, 0.236842105263158,
  156. -0.152576775123250, 0.448975001279334,
  157. -0.133417538277668, 0.461615613865667,
  158. -0.053199060826740, 0.507630360006299,
  159. 0.114249591147281, 0.570414135097409,
  160. 0.377810316891987, 0.560497102875315,
  161. 0.665052120135908, -0.157557441109611,
  162. 0.516006487053228, -0.559763292174825,
  163. -0.379486035348887, -0.331959640488223,
  164. -0.462034726249078, -0.039105670080824,
  165. -0.378730600917982, 0.225127015099919,
  166. -0.370967741935484, 0.236842105263158;
  167. pts.transposeInPlace();
  168. for (int i=0; i<u.size(); ++i)
  169. {
  170. Vector2d pt = spline(u(i));
  171. VERIFY( (pt - pts.col(i)).norm() < 1e-14 );
  172. }
  173. }
  174. void check_global_interpolation2d()
  175. {
  176. typedef Spline2d::PointType PointType;
  177. typedef Spline2d::KnotVectorType KnotVectorType;
  178. typedef Spline2d::ControlPointVectorType ControlPointVectorType;
  179. ControlPointVectorType points = ControlPointVectorType::Random(2,100);
  180. KnotVectorType chord_lengths; // knot parameters
  181. StormEigen::ChordLengths(points, chord_lengths);
  182. // interpolation without knot parameters
  183. {
  184. const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3);
  185. for (StormEigen::DenseIndex i=0; i<points.cols(); ++i)
  186. {
  187. PointType pt = spline( chord_lengths(i) );
  188. PointType ref = points.col(i);
  189. VERIFY( (pt - ref).matrix().norm() < 1e-14 );
  190. }
  191. }
  192. // interpolation with given knot parameters
  193. {
  194. const Spline2d spline = SplineFitting<Spline2d>::Interpolate(points,3,chord_lengths);
  195. for (StormEigen::DenseIndex i=0; i<points.cols(); ++i)
  196. {
  197. PointType pt = spline( chord_lengths(i) );
  198. PointType ref = points.col(i);
  199. VERIFY( (pt - ref).matrix().norm() < 1e-14 );
  200. }
  201. }
  202. }
  203. void check_global_interpolation_with_derivatives2d()
  204. {
  205. typedef Spline2d::PointType PointType;
  206. typedef Spline2d::KnotVectorType KnotVectorType;
  207. const unsigned int numPoints = 100;
  208. const unsigned int dimension = 2;
  209. const unsigned int degree = 3;
  210. ArrayXXd points = ArrayXXd::Random(dimension, numPoints);
  211. KnotVectorType knots;
  212. StormEigen::ChordLengths(points, knots);
  213. ArrayXXd derivatives = ArrayXXd::Random(dimension, numPoints);
  214. VectorXd derivativeIndices(numPoints);
  215. for (StormEigen::DenseIndex i = 0; i < numPoints; ++i)
  216. derivativeIndices(i) = static_cast<double>(i);
  217. const Spline2d spline = SplineFitting<Spline2d>::InterpolateWithDerivatives(
  218. points, derivatives, derivativeIndices, degree);
  219. for (StormEigen::DenseIndex i = 0; i < points.cols(); ++i)
  220. {
  221. PointType point = spline(knots(i));
  222. PointType referencePoint = points.col(i);
  223. VERIFY_IS_APPROX(point, referencePoint);
  224. PointType derivative = spline.derivatives(knots(i), 1).col(1);
  225. PointType referenceDerivative = derivatives.col(i);
  226. VERIFY_IS_APPROX(derivative, referenceDerivative);
  227. }
  228. }
  229. void test_splines()
  230. {
  231. for (int i = 0; i < g_repeat; ++i)
  232. {
  233. CALL_SUBTEST( eval_spline3d() );
  234. CALL_SUBTEST( eval_spline3d_onbrks() );
  235. CALL_SUBTEST( eval_closed_spline2d() );
  236. CALL_SUBTEST( check_global_interpolation2d() );
  237. CALL_SUBTEST( check_global_interpolation_with_derivatives2d() );
  238. }
  239. }