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