/// <summary> /// Draws a quadratic Bezier curve to the specified point /// </summary> /// <param name="control">The control point used to specify the shape of the curve.</param> /// <param name="endPoint">The destination point for the end of the curve.</param> public void QuadraticBezierTo(Point control, Point endPoint) { _impl.QuadraticBezierTo(control, endPoint); _currentPoint = endPoint; }
/// <summary> /// Draws a quadratic Bezier curve to the specified point /// </summary> /// <param name="control">The control point used to specify the shape of the curve.</param> /// <param name="endPoint">The destination point for the end of the curve.</param> public void QuadraticBezierTo(Point control, Point endPoint) { _impl.QuadraticBezierTo(control, endPoint); }
/// <summary> /// Builds the arc outline using given StreamGeometryContext /// </summary> /// <param name="path">A StreamGeometryContext to output the path commands to</param> /// <param name="degree">degree of the Bezier curve to use</param> /// <param name="threshold">acceptable error</param> /// <param name="openNewFigure">if true, a new figure will be started in the specified StreamGeometryContext</param> public void BuildArc(IStreamGeometryContextImpl path, int degree, double threshold, bool openNewFigure) { if (degree < 1 || degree > _maxDegree) throw new ArgumentException($"degree should be between {1} and {_maxDegree}", nameof(degree)); // find the number of Bezier curves needed bool found = false; int n = 1; double dEta; double etaB; while (!found && n < 1024) { dEta = (Eta2 - Eta1) / n; if (dEta <= 0.5 * Math.PI) { etaB = Eta1; found = true; for (int i = 0; found && i < n; ++i) { double etaA = etaB; etaB += dEta; found = EstimateError(degree, etaA, etaB) <= threshold; } } n = n << 1; } dEta = (Eta2 - Eta1) / n; 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; /* This controls the drawing in case of pies if (openNewFigure) { if (IsPieSlice) { path.BeginFigure(new Point(Cx, Cy), false, false); path.LineTo(new Point(xB, yB), true, true); } else { path.BeginFigure(new Point(xB, yB), false, false); } } else { //path.LineTo(new Point(xB, yB), true, true); } */ //otherwise we're supposed to be already at the (xB,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) { path.LineTo(new Point(xB, yB)); } else if (degree == 2) { double k = (yBDot * (xB - xA) - xBDot * (yB - yA)) / (xADot * yBDot - yADot * xBDot); path.QuadraticBezierTo(new Point(xA + k * xADot, yA + k * yADot), new Point(xB, yB)); } else { path.CubicBezierTo( new Point(xA + alpha * xADot, yA + alpha * yADot), new Point(xB - alpha * xBDot, yB - alpha * yBDot), new Point(xB, yB) ); } } if (IsPieSlice) { path.LineTo(new Point(Cx, Cy)); } }