public void drawEllipticalArcToContext(int degree, double threshold)
{
// find the number of Bézier curves needed
bool found = false;
int n = 1;
while ((!found) && (n < 1024))
{
double dEta2 = (eta2 - eta1) / n;
if (dEta2 <= 0.5 * Math.PI)
{
double etaB2 = eta1;
found = true;
for (int i = 0; found && (i < n); ++i)
{
double etaA = etaB2;
etaB2 += dEta2;
found = (estimateError(degree, etaA, etaB2) <= threshold);
}
}
n = n << 1;
}
double dEta = (eta2 - eta1) / n;
double etaB = eta1;
double cosEtaB = Math.Cos(etaB);
double sinEtaB = Math.Sin(etaB);
double aCosEtaB = a * cosEtaB;
double bSinEtaB = b * sinEtaB;
double aSinEtaB = a * sinEtaB;
double bCosEtaB = b * cosEtaB;
double xB = cx + aCosEtaB * cosTheta - bSinEtaB * sinTheta;
double yB = cy + aCosEtaB * sinTheta + bSinEtaB * cosTheta;
double xBDot = -aSinEtaB * cosTheta - bCosEtaB * sinTheta;
double yBDot = -aSinEtaB * sinTheta + bCosEtaB * cosTheta;
if (isPieSlice)
{
context.MoveTo((float)cx, (float)cy);
}
else
{
context.MoveTo((float)xB, (float)yB);
}
double t = Math.Tan(0.5 * dEta);
double alpha = Math.Sin(dEta) * (Math.Sqrt(4 + 3 * t * t) - 1) / 3;
for (int i = 0; i < n; ++i)
{
//double etaA = etaB;
double xA = xB;
double yA = yB;
double xADot = xBDot;
double yADot = yBDot;
etaB += dEta;
cosEtaB = Math.Cos(etaB);
sinEtaB = Math.Sin(etaB);
aCosEtaB = a * cosEtaB;
bSinEtaB = b * sinEtaB;
aSinEtaB = a * sinEtaB;
bCosEtaB = b * cosEtaB;
xB = cx + aCosEtaB * cosTheta - bSinEtaB * sinTheta;
yB = cy + aCosEtaB * sinTheta + bSinEtaB * cosTheta;
xBDot = -aSinEtaB * cosTheta - bCosEtaB * sinTheta;
yBDot = -aSinEtaB * sinTheta + bCosEtaB * cosTheta;
if (degree == 1)
{
context.AddLineToPoint((float)xB, (float)yB);
}
else if (degree == 2)
{
double k = (yBDot * (xB - xA) - xBDot * (yB - yA))
/ (xADot * yBDot - yADot * xBDot);
context.AddQuadCurveToPoint((float)(xA + k * xADot),(float)(yA + k * yADot),
(float)xB, (float)yB);
}
else
{
context.AddCurveToPoint((float)(xA + alpha * xADot), (float)(yA + alpha * yADot),
(float)(xB - alpha * xBDot), (float)(yB - alpha * yBDot),
(float)xB, (float)yB);
}
}
if (isPieSlice)
{
context.ClosePath();
}
}