/// <summary> /// Split a bezier curve into 2 bezier curves, at tau. /// </summary> /// <param name="bezierCurve">The original bezier curve.</param> /// <param name="tau">The t value were to split the curve, usually between 0 and 1, but not necessary.</param> public static (PdfPath.BezierCurve, PdfPath.BezierCurve) Split(this PdfPath.BezierCurve bezierCurve, double tau) { // De Casteljau Algorithm PdfPoint[][] points = new PdfPoint[4][]; points[0] = new[] { bezierCurve.StartPoint, bezierCurve.FirstControlPoint, bezierCurve.SecondControlPoint, bezierCurve.EndPoint }; points[1] = new PdfPoint[3]; points[2] = new PdfPoint[2]; points[3] = new PdfPoint[1]; for (int j = 1; j <= 3; j++) { for (int i = 0; i <= 3 - j; i++) { var x = (1 - tau) * points[j - 1][i].X + tau * points[j - 1][i + 1].X; var y = (1 - tau) * points[j - 1][i].Y + tau * points[j - 1][i + 1].Y; points[j][i] = new PdfPoint(x, y); } } return(new PdfPath.BezierCurve(points[0][0], points[1][0], points[2][0], points[3][0]), new PdfPath.BezierCurve(points[3][0], points[2][1], points[1][2], points[0][3])); }
private static PdfPoint[] Intersect(PdfPath.BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { var ts = IntersectT(bezierCurve, p1, p2); if (ts == null || ts.Length == 0) { return(EmptyArray <PdfPoint> .Instance); } List <PdfPoint> points = new List <PdfPoint>(); foreach (var t in ts) { PdfPoint point = new PdfPoint( PdfPath.BezierCurve.ValueWithT(bezierCurve.StartPoint.X, bezierCurve.FirstControlPoint.X, bezierCurve.SecondControlPoint.X, bezierCurve.EndPoint.X, t), PdfPath.BezierCurve.ValueWithT(bezierCurve.StartPoint.Y, bezierCurve.FirstControlPoint.Y, bezierCurve.SecondControlPoint.Y, bezierCurve.EndPoint.Y, t)); if (Contains(p1, p2, point)) { points.Add(point); } } return(points.ToArray()); }
/// <summary> /// Get the t values that are the intersections of the line and the curve. /// </summary> /// <returns>List of t values where the <see cref="PdfPath.BezierCurve"/> and the <see cref="PdfPath.Line"/> intersect.</returns> public static double[] FindIntersectionT(this PdfPath.BezierCurve bezierCurve, PdfPath.Line line) { // if the bounding boxes do not intersect, they cannot intersect var bezierBbox = bezierCurve.GetBoundingRectangle(); if (!bezierBbox.HasValue) { return(null); } var lineBbox = line.GetBoundingRectangle(); if (!lineBbox.HasValue) { return(null); } if (!bezierBbox.Value.IntersectsWith(lineBbox.Value)) { return(null); } double x1 = line.From.X; double y1 = line.From.Y; double x2 = line.To.X; double y2 = line.To.Y; return(FindIntersectionT(bezierCurve, x1, y1, x2, y2)); }
/// <summary> /// Get the <see cref="PdfPoint"/>s that are the intersections of the line and the curve. /// </summary> /// <returns></returns> public static PdfPoint[] Intersect(this PdfPath.BezierCurve bezierCurve, PdfPath.Line line) { var ts = FindIntersectionT(bezierCurve, line); if (ts.Count() == 0) { return(null); } List <PdfPoint> points = new List <PdfPoint>(); foreach (var t in ts) { PdfPoint point = new PdfPoint( PdfPath.BezierCurve.ValueWithT(bezierCurve.StartPoint.X, bezierCurve.FirstControlPoint.X, bezierCurve.SecondControlPoint.X, bezierCurve.EndPoint.X, t), PdfPath.BezierCurve.ValueWithT(bezierCurve.StartPoint.Y, bezierCurve.FirstControlPoint.Y, bezierCurve.SecondControlPoint.Y, bezierCurve.EndPoint.Y, t) ); points.Add(point); } return(points.ToArray()); }
private static double[] FindIntersectionT(PdfPath.BezierCurve bezierCurve, double x1, double y1, double x2, double y2) { double A = (y2 - y1); double B = (x1 - x2); double C = x1 * (y1 - y2) + y1 * (x2 - x1); double alpha = bezierCurve.StartPoint.X * A + bezierCurve.StartPoint.Y * B; double beta = 3.0 * (bezierCurve.FirstControlPoint.X * A + bezierCurve.FirstControlPoint.Y * B); double gamma = 3.0 * (bezierCurve.SecondControlPoint.X * A + bezierCurve.SecondControlPoint.Y * B); double delta = bezierCurve.EndPoint.X * A + bezierCurve.EndPoint.Y * B; double a = (-alpha + beta - gamma + delta); double b = (3 * alpha - 2 * beta + gamma); double c = -3 * alpha + beta; double d = alpha + C; var solution = SolveCubicEquation(a, b, c, d); return(solution.Where(s => !double.IsNaN(s)).Where(s => s >= -double.Epsilon && s <= 1.0).OrderBy(s => s).ToArray()); }
private static double[] IntersectT(PdfPath.BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { // if the bounding boxes do not intersect, they cannot intersect var bezierBbox = bezierCurve.GetBoundingRectangle(); if (!bezierBbox.HasValue) { return(null); } if (bezierBbox.Value.Left > Math.Max(p1.X, p2.X) || Math.Min(p1.X, p2.X) > bezierBbox.Value.Right) { return(null); } if (bezierBbox.Value.Top < Math.Min(p1.Y, p2.Y) || Math.Max(p1.Y, p2.Y) < bezierBbox.Value.Bottom) { return(null); } double A = (p2.Y - p1.Y); double B = (p1.X - p2.X); double C = p1.X * (p1.Y - p2.Y) + p1.Y * (p2.X - p1.X); double alpha = bezierCurve.StartPoint.X * A + bezierCurve.StartPoint.Y * B; double beta = 3.0 * (bezierCurve.FirstControlPoint.X * A + bezierCurve.FirstControlPoint.Y * B); double gamma = 3.0 * (bezierCurve.SecondControlPoint.X * A + bezierCurve.SecondControlPoint.Y * B); double delta = bezierCurve.EndPoint.X * A + bezierCurve.EndPoint.Y * B; double a = -alpha + beta - gamma + delta; double b = 3 * alpha - 2 * beta + gamma; double c = -3 * alpha + beta; double d = alpha + C; var solution = SolveCubicEquation(a, b, c, d); return(solution.Where(s => !double.IsNaN(s)).Where(s => s >= -epsilon && (s - 1) <= epsilon).OrderBy(s => s).ToArray()); }
/// <summary> /// Get the t values that are the intersections of the line and the curve. /// </summary> /// <returns>List of t values where the <see cref="PdfPath.BezierCurve"/> and the <see cref="PdfPath.Line"/> intersect.</returns> public static double[] IntersectT(this PdfPath.BezierCurve bezierCurve, PdfPath.Line line) { return(IntersectT(bezierCurve, line.From, line.To)); }
/// <summary> /// Get the t values that are the intersections of the line and the curve. /// </summary> /// <returns>List of t values where the <see cref="PdfPath.BezierCurve"/> and the <see cref="PdfLine"/> intersect.</returns> public static double[] IntersectT(this PdfPath.BezierCurve bezierCurve, PdfLine line) { return(IntersectT(bezierCurve, line.Point1, line.Point2)); }
/// <summary> /// Get the <see cref="PdfPoint"/>s that are the intersections of the line and the curve. /// </summary> public static PdfPoint[] Intersect(this PdfPath.BezierCurve bezierCurve, PdfPath.Line line) { return(Intersect(bezierCurve, line.From, line.To)); }
private static bool IntersectsWith(PdfPath.BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { return(Intersect(bezierCurve, p1, p2).Length > 0); }
/// <summary> /// Checks if the curve and the line are intersecting. /// <para>Avoid using this method as it is not optimised. Use <see cref="Intersect(PdfPath.BezierCurve, PdfPath.Line)"/> instead.</para> /// </summary> public static bool IntersectsWith(this PdfPath.BezierCurve bezierCurve, PdfPath.Line line) { return(IntersectsWith(bezierCurve, line.From, line.To)); }
/// <summary> /// Checks if the curve and the line are intersecting. /// <para>Avoid using this method as it is not optimised. Use <see cref="Intersect(PdfPath.BezierCurve, PdfLine)"/> instead.</para> /// </summary> public static bool IntersectsWith(this PdfPath.BezierCurve bezierCurve, PdfLine line) { return(IntersectsWith(bezierCurve, line.Point1, line.Point2)); }