jdawi...@gmail.com
unread,May 20, 2017, 8:55:29 AM5/20/17You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
I was considering drawing a sin wave; wanted to do so efficiently; and though that others might wish to reuse the results.
Preliminaries:
• Control points are {x0,y0}, {x1,y1}, {x2,y2}, {x3,y3}.
• Have defined /HalfPi 1.57079632679489661923 def
Let’s try to have a single curve be 180°. Want to go through end-points, with correct tangents, and also want the tangent in the middle to be at a slope of 1:1 = 45°. That defines everything:
y0 = y1 = -1
y2 = y3 = +1
x0 = -HalfPi
x1 = HalfPi - 2
x2 = -x1
x3 = -x0
The largest y error is about one part in 1/1302, which happens at about x ≈ ±1.004 ≈ 32.48°.
Not bad. One part in 1302 is less than a pixel on a 1200 dpi printer if the sin wave is less than 2.17″ high (recall that, bottom-to-top, the whole wave is of height 2).
Optically, it is indistinguishable from a an actual sin wave, and given that setflat has a minimum value of 0.2 (PLRM3 p669), is plenty good enough. For PostScript, this is my recommendation.
We can do better if a single curve can be only 90°. With the ends in the correct place with the correct slopes, and having lost the symmetry of the previous arrangement, there are now two free parameters — which can be thought of as the speeds of departure from the ends.
x0 = y0 = 0
x1 = y1 = z1
x3 = HalfPi
x2 = x2 - z2
y2 = y3 = 1
Next, some Mathematica:
Quiet[Remove["Global`*"], {Remove::rmnsm}]; Print["Mathematica $Version = “", $Version, "”"]; Print["Execution time = ", DateString[DateList[], {"Hour", ":", "Minute", " on ", "DayNameShort", " ", "Day", " ", "MonthNameShort", " ", "Year"}]];
KnotsFromCoeffs[{c0_, c1_, c2_, c3_}] = {c0, c0 + c1/3, c0 + (2 c1 + c2)/3, c0 + c1 + c2 + c3};
CoeffsFromKnots[{z0_, z1_, z2_, z3_}] = {z0, -3 z0 + 3 z1, 3 z0 - 6 z1 + 3 z2, -z0 + 3 z1 - 3 z2 + z3};
{x0, x1, x2, x3} = {0, z1, Pi/2 - z2, Pi/2};
{y0, y1, y2, y3} = {0, z1, 1, 1};
zx = CoeffsFromKnots[{x0, x1, x2, x3}];
zy = CoeffsFromKnots[{y0, y1, y2, y3}];
Print[x = (zx[[1]] + t zx[[2]] + t t zx[[3]] + t t t zx[[4]]) // FullSimplify];
Print[y = (zy[[1]] + t zy[[2]] + t t zy[[3]] + t t t zy[[4]]) // FullSimplify];
errorTerm = ((Sin[x] - y)^2)*D[x, t]
Quiet[error = Hold[NIntegrate[errorTerm, {t, 0.0, 1.0}]]];
fm = FindMinimum[error, {z1, 0.512}, {z2, 0.568}, WorkingPrecision -> 24, AccuracyGoal -> 13]
1 / Sqrt[fm[[1]]/(Pi/2)]
{z1, z2} = {z1, z2} /. fm[[2]]; Plot[y - Sin[x], {t, 0, 1}]
That returns
z1 = 0.512065039021454886
z2 = 0.568537830614325103
The root-mean-square average error of the curve is 1/25326; the largest error is 1/15426.
But I think one part is 1302 is good enough for PostScript.