using System; using Azimuth; using UnitTestSharp; namespace Blacklight.Bezier.UnitTests { public class CubicPieceTests : TestFixture { public static readonly CubicPiece Wave = new CubicPiece(new Vector(0, 0), new Vector(1, 2), new Vector(3, -1), new Vector(4, 0)); public class CtorTests : TestFixture { public void AssignsAllFourControlPoints() { var piece = new CubicPiece(new Vector(1, 2), new Vector(3, 4), new Vector(5, 6), new Vector(7, 8)); CheckEqual(new Vector(1, 2), piece.P0); CheckEqual(new Vector(3, 4), piece.P1); CheckEqual(new Vector(5, 6), piece.P2); CheckEqual(new Vector(7, 8), piece.P3); } } public class FromQuadraticTests : TestFixture { public void KeepsTheEndpoints() { CubicPiece piece = CubicPiece.FromQuadratic(new Vector(1, 2), new Vector(3, 5), new Vector(7, 4)); CheckEqual(new Vector(1, 2), piece.P0); CheckEqual(new Vector(7, 4), piece.P3); } public void TracesTheQuadraticAtTheSameParameter() { var start = new Vector(1, 2); var control = new Vector(3, 5); var end = new Vector(7, 4); CubicPiece piece = CubicPiece.FromQuadratic(start, control, end); for (double t = 0; t <= 1; t += 0.125) { double u = 1 - t; Vector quadratic = u * u * start + 2 * u * t * control + t * t * end; CheckGreater(1e-14, (piece.PointAt(t) - quadratic).Length().Value); } } } public class PointAtTests : TestFixture { public void Zero_IsTheFirstControlPoint() { CheckEqual(new Vector(0, 0), Wave.PointAt(0)); } public void One_IsTheLastControlPoint() { CheckEqual(new Vector(4, 0), Wave.PointAt(1)); } public void Half_WeighsTheInnerControlPointsThreeToOne() { CheckEqual(new Vector((0 + 3 * 1 + 3 * 3 + 4) / 8.0, (0 + 3 * 2 - 3 * 1 + 0) / 8.0), Wave.PointAt(0.5)); } } public class DerivativeAtTests : TestFixture { public void Zero_IsThreeTimesTheFirstLeg() { CheckEqual(new Vector(3, 6), Wave.DerivativeAt(0)); } public void One_IsThreeTimesTheLastLeg() { CheckEqual(new Vector(3, 3), Wave.DerivativeAt(1)); } public void Interior_MatchesAFiniteDifference() { const double step = 1e-6; Vector difference = (Wave.PointAt(0.3 + step) - Wave.PointAt(0.3 - step)) / (2 * step); CheckGreater(1e-8, (difference - Wave.DerivativeAt(0.3)).Length().Value); } } public class SecondDerivativeAtTests : TestFixture { public void Zero_IsSixTimesTheFirstTwoLegsDifference() { CheckEqual(6 * (new Vector(2, -3) - new Vector(1, 2)), Wave.SecondDerivativeAt(0)); } public void One_IsSixTimesTheLastTwoLegsDifference() { CheckEqual(6 * (new Vector(1, 1) - new Vector(2, -3)), Wave.SecondDerivativeAt(1)); } public void Interior_MatchesAFiniteDifference() { const double step = 1e-6; Vector difference = (Wave.DerivativeAt(0.3 + step) - Wave.DerivativeAt(0.3 - step)) / (2 * step); CheckGreater(1e-7, (difference - Wave.SecondDerivativeAt(0.3)).Length().Value); } } public class SegmentTests : TestFixture { public void TracesThePieceBetweenTheTwoParameters() { CubicPiece segment = Wave.Segment(0.2, 0.7); for (double s = 0; s <= 1; s += 0.125) { CheckGreater(1e-14, (segment.PointAt(s) - Wave.PointAt(0.2 + 0.5 * s)).Length().Value); } } public void Reversed_TracesItBackwards() { CubicPiece segment = Wave.Segment(0.7, 0.2); CheckGreater(1e-14, (segment.PointAt(0.25) - Wave.PointAt(0.575)).Length().Value); } } } }