using System;
using System.Drawing;
using SharpVectors.Polynomials;
#if TEST
using NUnit.Framework;
#endif
namespace SharpVectors.Dom.Svg{
public abstract class SvgPathSegCurvetoCubic : SvgPathSegCurveto
{
#region constructors
protected SvgPathSegCurvetoCubic(SvgPathSegType type) : base(type)
{
}
#endregion
#region abstract properties
public abstract override PointF AbsXY{get;}
public abstract override PointF CubicX1Y1{get;}
public abstract override PointF CubicX2Y2{get;}
#endregion
#region protected methods
protected override SqrtPolynomial getArcLengthPolynomial()
{
double c3x, c3y, c2x, c2y, c1x, c1y;
PointF p1 = PreviousSeg.AbsXY;
PointF p2 = CubicX1Y1;
PointF p3 = CubicX2Y2;
PointF p4 = AbsXY;
// convert curve into polynomial
c3x = -1.0*p1.X + 3.0*p2.X - 3.0*p3.X + p4.X;
c3y = -1.0*p1.Y + 3.0*p2.Y - 3.0*p3.Y + p4.Y;
c2x = 3.0*p1.X - 6.0*p2.X + 3.0*p3.X;
c2y = 3.0*p1.Y - 6.0*p2.Y + 3.0*p3.Y;
c1x = -3.0*p1.X + 3.0*p2.X;
c1y = -3.0*p1.Y + 3.0*p2.Y;
// build polynomial
// dx = dx/dt
// dy = dy/dt
// sqrt poly = sqrt( (dx*dx) + (dy*dy) )
return new SqrtPolynomial(
c1x*c1x + c1y*c1y,
4.0*(c1x*c2x + c1y*c2y),
4.0*(c2x*c2x + c2y*c2y) + 6.0*(c1x*c3x + c1y*c3y),
12.0*(c2x*c3x + c2y*c3y),
9.0*(c3x*c3x + c3y*c3y)
);
}
#endregion
#region unit tests
#if TEST
[TestFixture]
public abstract class CubicTests
{
protected SvgPathSegList segments;
private SvgPathSegCurvetoCubic segment;
[SetUp]
public void SetUp()
{
segments = makeSegments();
segment = getTestSegment();
}
[Test]
public void TestArcLengthPolynomial()
{
SqrtPolynomial poly = segment.getArcLengthPolynomial();
Assert.AreEqual(4, poly.Degree);
Assert.AreEqual(900, poly[4]);
Assert.AreEqual(-3600, poly[3]);
Assert.AreEqual(279000, poly[2]);
Assert.AreEqual(-259200, poly[1]);
Assert.AreEqual(145800, poly[0]);
}
[Test]
public void TestArcLength()
{
SqrtPolynomial poly = segment.getArcLengthPolynomial();
float result1 = segment.Length;
double result2 = Math.Floor(poly.Simpson(0, 1)*1e6)/1e6;
Assert.AreEqual(327.877900, result1);
Assert.AreEqual(327.877935, result2);
}
public abstract SvgPathSegList makeSegments();
public abstract SvgPathSegCurvetoCubic getTestSegment();
}
#endif
#endregion
}
}
|