00001
00002 namespace Tests
00003 {
00004 using System;
00005 using Microsoft.VisualStudio.TestTools.UnitTesting;
00006 using NewGamePhysics.Mathematics;
00007
00011 [TestClass]
00012 public class UnitTestSpline
00013 {
00014 public UnitTestSpline()
00015 {
00016 }
00017
00021 private TestContext testContextInstance;
00022
00027 public TestContext TestContext
00028 {
00029 get
00030 {
00031 return this.testContextInstance;
00032 }
00033 set
00034 {
00035 this.testContextInstance = value;
00036 }
00037 }
00038
00042 [TestMethod]
00043 [ExpectedException(typeof(InvalidOperationException))]
00044 public void SplineExceptionOnNoPointsAdded()
00045 {
00046 CubicSpline spline = new CubicSpline();
00047 Assert.IsFalse(spline.CanInterpolate);
00048 double[] y = spline.Interpolate(1.5);
00049 }
00050
00054 [TestMethod]
00055 [ExpectedException(typeof(InvalidOperationException))]
00056 public void SplineExceptionOnOnlyOnePointAdded()
00057 {
00058 CubicSpline spline = new CubicSpline();
00059 spline.AddDataPoint(1.0, new double[] { 1.0 });
00060 Assert.AreEqual(1, spline.Count);
00061 Assert.IsFalse(spline.CanInterpolate);
00062 double[] y = spline.Interpolate(1.5);
00063 }
00064
00068 [TestMethod]
00069 [ExpectedException(typeof(ArgumentOutOfRangeException))]
00070 public void SplineExceptionInvalidDimension()
00071 {
00072 CubicSpline spline = new CubicSpline(0);
00073 }
00074
00078 [TestMethod]
00079 [ExpectedException(typeof(ArgumentOutOfRangeException))]
00080 public void SplineExceptionAddingWithDimensionMismatch()
00081 {
00082 CubicSpline spline = new CubicSpline(2);
00083 Assert.AreEqual(2, spline.Dimensions);
00084 spline.AddDataPoint(1.0, new double[] { 1.0 });
00085 }
00086
00090 [TestMethod]
00091 [ExpectedException(typeof(InvalidOperationException))]
00092 public void SplineExceptionOnOnlyTwoPointsAdded()
00093 {
00094 double[,] data = {{1.0, 1.0},
00095 {2.0, 2.0}};
00096
00097 CubicSpline spline = new CubicSpline();
00098 for (int i = 0; i < 2; i++)
00099 {
00100 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00101 }
00102
00103 Assert.AreEqual(2, spline.Count);
00104 Assert.IsFalse(spline.CanInterpolate);
00105 double[] y = spline.Interpolate(1.5);
00106 }
00107
00111 [TestMethod]
00112 [ExpectedException(typeof(InvalidOperationException))]
00113 public void SplineExceptionOnOnlyThreePointsAdded()
00114 {
00115 double[,] data = {{1.0, 1.0},
00116 {2.0, 2.0},
00117 {3.0, 1.0}};
00118
00119 CubicSpline spline = new CubicSpline();
00120 for (int i = 0; i < 3; i++)
00121 {
00122 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00123 }
00124
00125 Assert.AreEqual(3, spline.Count);
00126 Assert.IsFalse(spline.CanInterpolate);
00127 double[] y = spline.Interpolate(1.5);
00128 }
00129
00133 [TestMethod]
00134 public void SplineInterpolateFourPointLine()
00135 {
00136 double[,] data = {{0.0, 0.0},
00137 {1.0, 1.0},
00138 {2.0, 2.0},
00139 {3.0, 3.0}};
00140
00141 CubicSpline spline = new CubicSpline();
00142 for (int i = 0; i < 4; i++)
00143 {
00144 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00145 }
00146
00147 Assert.AreEqual(4, spline.Count);
00148 Assert.IsTrue(spline.CanInterpolate);
00149
00150 for (int i = 0; i <= 30; i++)
00151 {
00152 double x = 0.1 * (double)i;
00153 double[] y = spline.Interpolate(x);
00154 Assert.AreEqual(x, y[0]);
00155 }
00156 }
00157
00161 [TestMethod]
00162 public void SplineRejectDuplicatePointsWhenAdding()
00163 {
00164 double[,] data = {{0.0, 0.0},
00165 {1.0, 1.0},
00166 {2.0, 2.0},
00167 {3.0, 3.0},
00168 };
00169
00170 CubicSpline spline = new CubicSpline();
00171 for (int i = 0; i < 4; i++)
00172 {
00173 bool addResult = spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00174 Assert.IsTrue(addResult);
00175 }
00176
00177
00178 for (int i = 0; i < 4; i++)
00179 {
00180 bool addResult = spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00181 Assert.IsFalse(addResult);
00182 }
00183
00184 Assert.AreEqual(4, spline.Count);
00185 Assert.IsTrue(spline.CanInterpolate);
00186 }
00187
00191 [TestMethod]
00192 public void SplineCanClearDataArrayThenAddAndInterpolate()
00193 {
00194 double[,] data = {{0.0, 0.0},
00195 {1.0, 1.0},
00196 {2.0, 2.0},
00197 {3.0, 3.0},
00198 };
00199
00200 CubicSpline spline = new CubicSpline();
00201
00202
00203 for (int t = 0; t < 3; t++)
00204 {
00205 for (int i = 0; i < 4; i++)
00206 {
00207 bool addResult = spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00208 Assert.IsTrue(addResult);
00209 }
00210
00211 Assert.AreEqual(4, spline.Count);
00212 Assert.IsTrue(spline.CanInterpolate);
00213
00214
00215 Random random = new Random();
00216 for (int j = 0; j < 10; j++)
00217 {
00218 double x = random.NextDouble();
00219 double[] y = spline.Interpolate(x);
00220 Assert.AreEqual(x, y[0]);
00221 }
00222
00223
00224 spline.Clear();
00225 Assert.AreEqual(0, spline.Count);
00226 Assert.IsFalse(spline.CanInterpolate);
00227 }
00228 }
00229
00233 [TestMethod]
00234 public void SplineInterpolateFourPointShape()
00235 {
00236 double[,] data = {{1.0, 1.0},
00237 {2.0, 2.0},
00238 {3.0, 1.0},
00239 {4.0, 3.0}};
00240
00241 CubicSpline spline = new CubicSpline();
00242 for (int i = 0; i < 4; i++)
00243 {
00244 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00245 }
00246
00247 Assert.AreEqual(4, spline.Count);
00248 Assert.IsTrue(spline.CanInterpolate);
00249
00250 double[] testinput = { 1.5, 2.5, 3.5, 3.9 };
00251 double[] testoutput = { 1.6, 1.6, 2.0, 2.85 };
00252
00253 for (int i=0; i<testinput.Length; i++)
00254 {
00255 double[] y = spline.Interpolate(testinput[i]);
00256 Assert.AreEqual(testoutput[i], y[0], 0.1);
00257 }
00258 }
00259
00263 [TestMethod]
00264 public void SplineInterpolateFourPointShape2D()
00265 {
00266 double[,] data = {{1.0, 1.0, 2.0},
00267 {2.0, 2.0, 4.0},
00268 {3.0, 1.0, 2.0},
00269 {4.0, 3.0, 6.0}};
00270
00271 CubicSpline spline = new CubicSpline(2);
00272 Assert.AreEqual(2, spline.Dimensions);
00273 for (int i = 0; i < 4; i++)
00274 {
00275 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1], data[i, 2] });
00276 }
00277
00278 Assert.AreEqual(4, spline.Count);
00279 Assert.IsTrue(spline.CanInterpolate);
00280
00281 double[] testinput = { 1.5, 2.5, 3.5, 3.9 };
00282 double[] testoutput = { 1.6, 1.6, 2.0, 2.85 };
00283
00284 for (int i = 0; i < testinput.Length; i++)
00285 {
00286 double[] y = spline.Interpolate(testinput[i]);
00287 Assert.AreEqual(testoutput[i], y[0], 0.1);
00288 Assert.AreEqual(2 * testoutput[i], y[1], 0.2);
00289 }
00290 }
00291
00295 [TestMethod]
00296 public void SplineInterpolatePastEdgeOfFourPointShape()
00297 {
00298 double[,] data = {{1.0, 1.0},
00299 {2.0, 2.0},
00300 {3.0, 1.0},
00301 {4.0, 2.0}};
00302
00303 CubicSpline spline = new CubicSpline();
00304 for (int i = 0; i < 4; i++)
00305 {
00306 spline.AddDataPoint(data[i, 0], new double[] { data[i, 1] });
00307 }
00308
00309 Assert.AreEqual(4, spline.Count);
00310 Assert.IsTrue(spline.CanInterpolate);
00311
00312 double[] testinput = { 0.8, 0.9, 4.1, 4.2 };
00313 double[] testoutput = { 0.8, 0.9, 2.1, 2.2 };
00314
00315 for (int i = 0; i < testinput.Length; i++)
00316 {
00317 double[] y = spline.Interpolate(testinput[i]);
00318 Assert.AreEqual(testoutput[i], y[0], 0.1);
00319 }
00320 }
00321
00325 [TestMethod]
00326 public void SplineInterpolateSineWave()
00327 {
00328
00329 int N = 12;
00330 double[] x = new double[N];
00331 double[] y = new double[N];
00332 double xx = Math.PI;
00333 double step = 4 * Math.PI / (N - 1);
00334
00335 for (int i = 0; i < N; ++i, xx += step)
00336 {
00337 double yy = Math.Sin(2 * xx) / xx;
00338 x[i] = xx;
00339 y[i] = yy;
00340 }
00341
00342 CubicSpline spline = new CubicSpline();
00343 for (int i = 0; i < N; i++)
00344 {
00345 spline.AddDataPoint(x[i], new double[] { y[i] });
00346 }
00347
00348 Assert.AreEqual(N, spline.Count);
00349 Assert.IsTrue(spline.CanInterpolate);
00350
00351 N = 30;
00352 xx = Math.PI;
00353 step = 3 * Math.PI / (N - 1);
00354 for (int i = 0; i < N; ++i, xx += step)
00355 {
00356 double yExpected = Math.Sin(2 * xx) / xx;
00357 double[] yCalculated = spline.Interpolate(xx);
00358 Assert.AreEqual(yExpected, yCalculated[0], 0.1);
00359 }
00360 }
00361 }
00362 }
00363