private static bool TryToRunSpiro(SpiroShape shape, IBezierContext bc) { if (shape == null || bc == null) { return(false); } try { var points = shape.Points.ToArray(); if (shape.IsTagged) { return(Spiro.TaggedSpiroCPsToBezier0(points, bc)); } else { return(Spiro.SpiroCPsToBezier0(points, points.Length, shape.IsClosed, bc)); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } return(false); }
/// <summary> /// Convert a set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// Open contours do not need to start with '{', nor to end with '}'. /// /// Close contours do not need to end with 'z'. /// /// This function is kept for backwards compatibility for older programs. /// Please use the function that return success/failure replies when done. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="n">The number of elements in the spiros array.</param> /// <param name="isClosed">Whether this describes a closed (True) or open (False) contour.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag. True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[4]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// var bc = new PathBezierContext(); /// var success = Spiro.SpiroCPsToBezier0(points, 4, true, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool SpiroCPsToBezier0(SpiroControlPoint[] spiros, int n, bool isClosed, IBezierContext bc) { SpiroSegment[] s; if (n <= 0) return false; if (isClosed) s = SpiroImpl.run_spiro(spiros, n); else { SpiroPointType oldty_start = spiros[0].Type; SpiroPointType oldty_end = spiros[n - 1].Type; spiros[0].Type = SpiroPointType.OpenContour; spiros[n - 1].Type = SpiroPointType.EndOpenContour; s = SpiroImpl.run_spiro(spiros, n); spiros[n - 1].Type = oldty_end; spiros[0].Type = oldty_start; } if (s != null) { SpiroImpl.spiro_to_bpath(s, n, bc); return true; // success } return false; // spiro did not converge or encountered non-finite values }
public static void spiro_to_bpath(SpiroSegment[] s, int n, IBezierContext bc) { int i, nsegs; double x0, y0, x1, y1; if (s == null || n <= 0 || bc == null) { return; } nsegs = s[n - 1].Type == SpiroPointType.EndOpenContour ? n - 1 : n; for (i = 0; i < nsegs; i++) { x0 = s[i].X; x1 = s[i + 1].X; y0 = s[i].Y; y1 = s[i + 1].Y; if (i == 0) { bc.MoveTo(x0, y0, s[0].Type == SpiroPointType.OpenContour ? true : false); } bc.MarkKnot(i, get_knot_th(s, i), s[i].X, s[i].Y, s[i].Type); spiro_seg_to_bpath(s[i].ks, x0, y0, x1, y1, bc, 0); } if (nsegs == n - 1) { bc.MarkKnot(n - 1, get_knot_th(s, n - 1), s[n - 1].X, s[n - 1].Y, s[n - 1].Type); } }
/// <summary> /// Convert a tagged set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// The spiros array should indicate it's own end. /// /// Open contours must have the ty field of the first cp set to '{' and have the ty field of the last cp set to '}'. /// /// Closed contours must have an extra cp at the end whose ty is 'z' the x and y values of this extra cp are ignored. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag.True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool TaggedSpiroCPsToBezier0(SpiroControlPoint[] spiros, IBezierContext bc) { var s = TaggedSpiroCPsToSegments(spiros); if (s != null) { SpiroImpl.spiro_to_bpath(s, s.Length - 1, bc); return(true); // success } return(false); // spiro did not converge or encountered non-finite values }
/// <summary> /// Convert a tagged set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// The spiros array should indicate it's own end. /// /// Open contours must have the ty field of the first cp set to '{' and have the ty field of the last cp set to '}'. /// /// Closed contours must have an extra cp at the end whose ty is 'z' the x and y values of this extra cp are ignored. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag.True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool TaggedSpiroCPsToBezier0(SpiroControlPoint[] spiros, IBezierContext bc) { SpiroSegment[] s; int n; n = 0; while (true) { if (spiros[n].Type == SpiroPointType.End || spiros[n].Type == SpiroPointType.EndOpenContour) { break; } // invalid input if (n >= spiros.Length) { return(false); } ++n; } if (spiros[n].Type == SpiroPointType.EndOpenContour) { ++n; } if (n <= 0) { return(false); // invalid input } s = SpiroImpl.run_spiro(spiros, n); if (s != null) { SpiroImpl.spiro_to_bpath(s, n, bc); return(true); // success } return(false); // spiro did not converge or encountered non-finite values }
/// <summary> /// Convert a tagged set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// The spiros array should indicate it's own end. /// /// Open contours must have the ty field of the first cp set to '{' and have the ty field of the last cp set to '}'. /// /// Closed contours must have an extra cp at the end whose ty is 'z' the x and y values of this extra cp are ignored. /// /// This function is kept for backwards compatibility for older programs. /// Please use the functions that return success/failure replies when done. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="bc">A bézier results output context.</param> public static void TaggedSpiroCPsToBezier(SpiroControlPoint[] spiros, IBezierContext bc) { TaggedSpiroCPsToBezier0(spiros, bc); }
/// <summary> /// Convert a set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// Open contours do not need to start with '{', nor to end with '}'. /// /// Close contours do not need to end with 'z'. /// /// This function is kept for backwards compatibility for older programs. /// Please use the function that return success/failure replies when done. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="n">The number of elements in the spiros array.</param> /// <param name="isClosed">Whether this describes a closed (True) or open (False) contour.</param> /// <param name="bc">A bézier results output context.</param> public static void SpiroCPsToBezier(SpiroControlPoint[] spiros, int n, bool isClosed, IBezierContext bc) { SpiroCPsToBezier0(spiros, n, isClosed, bc); }
/// <summary> /// Convert a tagged set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// The spiros array should indicate it's own end. /// /// Open contours must have the ty field of the first cp set to '{' and have the ty field of the last cp set to '}'. /// /// Closed contours must have an extra cp at the end whose ty is 'z' the x and y values of this extra cp are ignored. /// /// If you can't use TaggedSpiroCPsToBezier0() this function is enhanced version of the original function, /// where spiro success/failure replies are passd back through done output parameter. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="bc">A bézier results output context.</param> /// <param name="done">An boolean success flag.True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</param> public static void TaggedSpiroCPsToBezier1(SpiroControlPoint[] spiros, IBezierContext bc, out bool done) { done = TaggedSpiroCPsToBezier0(spiros, bc); }
/// <summary> /// Convert a set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// Open contours do not need to start with '{', nor to end with '}'. /// /// Close contours do not need to end with 'z'. /// /// If you can't use SpiroCPsToBezier0() this function is enhanced version of the original function, /// where spiro success/failure replies are passd back through done output parameter. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="n">The number of elements in the spiros array.</param> /// <param name="isClosed">Whether this describes a closed (True) or open (False) contour.</param> /// <param name="bc">A bézier results output context.</param> /// <param name="done">An boolean success flag. True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</param> public static void SpiroCPsToBezier1(SpiroControlPoint[] spiros, int n, bool isClosed, IBezierContext bc, out bool done) { done = SpiroCPsToBezier0(spiros, n, isClosed, bc); }
/// <summary> /// Convert a set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// Open contours do not need to start with '{', nor to end with '}'. /// /// Close contours do not need to end with 'z'. /// /// This function is kept for backwards compatibility for older programs. /// Please use the function that return success/failure replies when done. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="n">The number of elements in the spiros array.</param> /// <param name="isClosed">Whether this describes a closed (True) or open (False) contour.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag. True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[4]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// var bc = new PathBezierContext(); /// var success = Spiro.SpiroCPsToBezier0(points, 4, true, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool SpiroCPsToBezier0(SpiroControlPoint[] spiros, int n, bool isClosed, IBezierContext bc) { SpiroSegment[]? s = SpiroCPsToSegments(spiros, n, isClosed); if (s != null) { SpiroImpl.spiro_to_bpath(s, n, bc); return(true); // success } return(false); // spiro did not converge or encountered non-finite values }
public static void spiro_to_bpath(SpiroSegment[] s, int n, IBezierContext bc) { int i, nsegs; double x0, y0, x1, y1; if (s == null || n <= 0 || bc == null) return; nsegs = s[n - 1].Type == SpiroPointType.EndOpenContour ? n - 1 : n; for (i = 0; i < nsegs; i++) { x0 = s[i].X; x1 = s[i + 1].X; y0 = s[i].Y; y1 = s[i + 1].Y; if (i == 0) bc.MoveTo(x0, y0, s[0].Type == SpiroPointType.OpenContour ? true : false); bc.MarkKnot(i, get_knot_th(s, i), s[i].X, s[i].Y, s[i].Type); spiro_seg_to_bpath(s[i].ks, x0, y0, x1, y1, bc, 0); } if (nsegs == n - 1) bc.MarkKnot(n - 1, get_knot_th(s, n - 1), s[n - 1].X, s[n - 1].Y, s[n - 1].Type); }
public static void spiro_seg_to_bpath(double[] ks, double x0, double y0, double x1, double y1, IBezierContext bc, int depth) { double bend, seg_ch, seg_th, ch, th, scale, rot; double th_even, th_odd, ul, vl, ur, vr; double thsub, xmid, ymid, cth, sth; double[] ksub = new double[4]; double[] xysub = new double[2]; double[] xy = new double[2]; bend = Math.Abs(ks[0]) + Math.Abs(0.5 * ks[1]) + Math.Abs(0.125 * ks[2]) + Math.Abs((1.0 / 48) * ks[3]); if (bend <= 1e-8) { bc.LineTo(x1, y1); } else { seg_ch = hypot(x1 - x0, y1 - y0); seg_th = Math.Atan2(y1 - y0, x1 - x0); integrate_spiro(ks, xy, N); ch = hypot(xy[0], xy[1]); th = Math.Atan2(xy[1], xy[0]); scale = seg_ch / ch; rot = seg_th - th; if (depth > 5 || bend < 1.0) { th_even = (1.0 / 384) * ks[3] + (1.0 / 8) * ks[1] + rot; th_odd = (1.0 / 48) * ks[2] + 0.5 * ks[0]; ul = (scale * (1.0 / 3)) * Math.Cos(th_even - th_odd); vl = (scale * (1.0 / 3)) * Math.Sin(th_even - th_odd); ur = (scale * (1.0 / 3)) * Math.Cos(th_even + th_odd); vr = (scale * (1.0 / 3)) * Math.Sin(th_even + th_odd); bc.CurveTo(x0 + ul, y0 + vl, x1 - ur, y1 - vr, x1, y1); } else { // subdivide ksub[0] = .5 * ks[0] - .125 * ks[1] + (1.0 / 64) * ks[2] - (1.0 / 768) * ks[3]; ksub[1] = .25 * ks[1] - (1.0 / 16) * ks[2] + (1.0 / 128) * ks[3]; ksub[2] = .125 * ks[2] - (1.0 / 32) * ks[3]; ksub[3] = (1.0 / 16) * ks[3]; thsub = rot - .25 * ks[0] + (1.0 / 32) * ks[1] - (1.0 / 384) * ks[2] + (1.0 / 6144) * ks[3]; cth = .5 * scale * Math.Cos(thsub); sth = .5 * scale * Math.Sin(thsub); integrate_spiro(ksub, xysub, N); xmid = x0 + cth * xysub[0] - sth * xysub[1]; ymid = y0 + cth * xysub[1] + sth * xysub[0]; spiro_seg_to_bpath(ksub, x0, y0, xmid, ymid, bc, depth + 1); ksub[0] += .25 * ks[1] + (1.0 / 384) * ks[3]; ksub[1] += .125 * ks[2]; ksub[2] += (1.0 / 16) * ks[3]; spiro_seg_to_bpath(ksub, xmid, ymid, x1, y1, bc, depth + 1); } } }
/// <summary> /// Convert a tagged set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// The spiros array should indicate it's own end. /// /// Open contours must have the ty field of the first cp set to '{' and have the ty field of the last cp set to '}'. /// /// Closed contours must have an extra cp at the end whose ty is 'z' the x and y values of this extra cp are ignored. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag.True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// /// var points = new SpiroControlPoint[5]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// points[4].X = 0; points[4].Y = 0; points[4].Type = SpiroPointType.End; /// var bc = new PathBezierContext(); /// var success = Spiro.TaggedSpiroCPsToBezier0(points, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool TaggedSpiroCPsToBezier0(SpiroControlPoint[] spiros, IBezierContext bc) { SpiroSegment[] s; int n; n = 0; while (true) { if (spiros[n].Type == SpiroPointType.End || spiros[n].Type == SpiroPointType.EndOpenContour) break; // invalid input if (n >= spiros.Length) return false; ++n; } if (spiros[n].Type == SpiroPointType.EndOpenContour) ++n; if (n <= 0) return false; // invalid input s = SpiroImpl.run_spiro(spiros, n); if (s != null) { SpiroImpl.spiro_to_bpath(s, n, bc); return true; // success } return false; // spiro did not converge or encountered non-finite values }
private static bool TryToRunSpiro(SpiroShape shape, IBezierContext bc) { if (shape == null || bc == null) return false; try { var points = shape.Points.ToArray(); if (shape.IsTagged) return Spiro.TaggedSpiroCPsToBezier0(points, bc); else return Spiro.SpiroCPsToBezier0(points, points.Length, shape.IsClosed, bc); } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } return false; }
/// <summary> /// Convert a set of spiro control points into a set of bézier curves. /// /// As it does so it will call the appropriate routine in your bézier context with this information /// – this should allow you to create your own internal representation of those curves. /// /// Open contours do not need to start with '{', nor to end with '}'. /// /// Close contours do not need to end with 'z'. /// /// This function is kept for backwards compatibility for older programs. /// Please use the function that return success/failure replies when done. /// </summary> /// <param name="spiros">An array of input spiros.</param> /// <param name="n">The number of elements in the spiros array.</param> /// <param name="isClosed">Whether this describes a closed (True) or open (False) contour.</param> /// <param name="bc">A bézier results output context.</param> /// <returns>An boolean success flag. True = completed task and have valid bézier results, or False = unable to complete task, bézier results are invalid.</returns> /// <example> /// var points = new SpiroControlPoint[4]; /// points[0].X = -100; points[0].Y = 0; points[0].Type = SpiroPointType.G4; /// points[1].X = 0; points[1].Y = 100; points[1].Type = SpiroPointType.G4; /// points[2].X = 100; points[2].Y = 0; points[2].Type = SpiroPointType.G4; /// points[3].X = 0; points[3].Y = -100; points[3].Type = SpiroPointType.G4; /// var bc = new PathBezierContext(); /// var success = Spiro.SpiroCPsToBezier0(points, 4, true, bc); /// Console.WriteLine(bc); /// Console.WriteLine("Success: {0} ", success); /// </example> public static bool SpiroCPsToBezier0(SpiroControlPoint[] spiros, int n, bool isClosed, IBezierContext bc) { SpiroSegment[] s; if (n <= 0) { return(false); } if (isClosed) { s = SpiroImpl.run_spiro(spiros, n); } else { SpiroPointType oldty_start = spiros[0].Type; SpiroPointType oldty_end = spiros[n - 1].Type; spiros[0].Type = SpiroPointType.OpenContour; spiros[n - 1].Type = SpiroPointType.EndOpenContour; s = SpiroImpl.run_spiro(spiros, n); spiros[n - 1].Type = oldty_end; spiros[0].Type = oldty_start; } if (s != null) { SpiroImpl.spiro_to_bpath(s, n, bc); return(true); // success } return(false); // spiro did not converge or encountered non-finite values }