xref: /aosp_15_r20/external/eigen/unsupported/test/splines.cpp (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
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