using System;
using Azimuth;
using UnitTestSharp;
namespace Blacklight.Bezier.UnitTests
{
public class CubicInputUncertaintyTests : TestFixture
{
public static readonly Vector InnerPoint1 = new Vector(0.3, 0.8);
public static readonly Vector InnerPoint2 = new Vector(0.9, 0.6);
///
/// Returns a sample a little off the curve's interior, where every input moves the distance.
///
public static CubicSample OffTheMiddle()
{
CubicPiece piece = CubicSample.PieceInFrame(InnerPoint1, InnerPoint2);
return new CubicSample(CubicSampleSets.AlongNormal(piece, t: 0.4, offset: 0.05), InnerPoint1,
InnerPoint2);
}
public static CubicReferenceResult Solve(CubicSample sample)
{
return CubicReferenceDistance.Solve(sample.ToPiece(), sample.Pixel);
}
///
/// Returns the point moved by one float spacing per coordinate, each in the direction given by its sign.
///
public static Vector NudgedBySpacing(Vector point, Vector direction)
{
return point + new Vector(Math.Sign(direction.X) * InputUncertainty.FloatSpacing(point.X),
Math.Sign(direction.Y) * InputUncertainty.FloatSpacing(point.Y));
}
public class TowardPixelTests : TestFixture
{
public void OffTheCurve_IsTheUnitNormalAtTheFoot()
{
CubicSample sample = OffTheMiddle();
Vector normal = sample.ToPiece().DerivativeAt(0.4).NormalizedCopy().PerpCCW();
CheckGreater(1e-12, (CubicInputUncertainty.TowardPixel(sample, Solve(sample)) - normal).Length()
.Value);
}
public void OnTheCurve_IsZero()
{
var sample = new CubicSample(Vector.Zero, InnerPoint1, InnerPoint2);
CheckEqual(Vector.Zero, CubicInputUncertainty.TowardPixel(sample, Solve(sample)));
}
}
public class SpacingAlongTests : TestFixture
{
public void AlongAnAxis_IsThatCoordinatesSpacing()
{
CheckEqual(InputUncertainty.FloatSpacing(5),
CubicInputUncertainty.SpacingAlong(new Vector(0, -1), new Vector(3, 5)));
}
public void Diagonally_WeighsBothSpacings()
{
CheckEqual(0.6 * InputUncertainty.FloatSpacing(3) + 0.8 * InputUncertainty.FloatSpacing(5),
CubicInputUncertainty.SpacingAlong(new Vector(-0.6, 0.8), new Vector(3, 5)));
}
}
public class OfPixelTests : TestFixture
{
public void IsHowFarRoundingThePixelCanMoveTheDistance()
{
CubicSample sample = OffTheMiddle();
CubicReferenceResult reference = Solve(sample);
Vector toward = CubicInputUncertainty.TowardPixel(sample, reference);
var nudged = new CubicSample(NudgedBySpacing(sample.Pixel, toward), sample.P1, sample.P2);
double moved = Solve(nudged).Distance - reference.Distance;
CheckGreater(1e-4, Math.Abs(moved / CubicInputUncertainty.OfPixel(sample, reference) - 1));
}
}
public class OfShapeTests : TestFixture
{
public void IsHowFarRoundingTheInnerPointsCanMoveTheDistance()
{
CubicSample sample = OffTheMiddle();
CubicReferenceResult reference = Solve(sample);
Vector away = -CubicInputUncertainty.TowardPixel(sample, reference);
var nudged = new CubicSample(sample.Pixel, NudgedBySpacing(sample.P1, away),
NudgedBySpacing(sample.P2, away));
double moved = Solve(nudged).Distance - reference.Distance;
CheckGreater(1e-4, Math.Abs(moved / CubicInputUncertainty.OfShape(sample, reference) - 1));
}
public void ClosestAtAnEnd_IsZero()
{
var sample = new CubicSample(new Vector(-1, -1), InnerPoint1, InnerPoint2);
CheckEqual(0.0, CubicInputUncertainty.OfShape(sample, Solve(sample)));
}
}
public class OfTests : TestFixture
{
public void IsThePixelAndShapeTogether()
{
CubicSample sample = OffTheMiddle();
CubicReferenceResult reference = Solve(sample);
CheckEqual(CubicInputUncertainty.OfPixel(sample, reference)
+ CubicInputUncertainty.OfShape(sample, reference), CubicInputUncertainty.Of(sample, reference));
}
}
}
}