Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h3>General solution</h3> <p>Update: using the geometric interpretation of calculus as the area under a line, I've worked out how to simplify the derivation a lot.</p> <p>So we're interpolating from y0 at time t0 to y1 at time t1 with acceleration ratio ra and deceleration ratio rd. The definition of the ratios give us the time at which we stop accelerating, ta = t0 + ra * (t1 - t0), and at which we start decelerating, td = t1 - rd * (t1 - t0).</p> <p>I understand the documentation you quote to mean that it's constant acceleration from t0 to ta, and constant deceleration from td to t1. We'll take the maximum speed reached to be vm.</p> <pre> Speed | _____________________________________ vm + /| |\ | / \ | / | | \ | / \ | / | | \ | / \ | / | | \ |/ \ +--------+-----------------------------------+--------+---- Time t0 ta td t1</pre> <p>Then the area of the parallelogram is the distance travelled from t0 to t1, which is y1 - y0. The area of a parallelogram is the product of the height with the average of the parallel sides. So</p> <p>y1 - y0 = vm * ((t1 - t0) + (td - ta)) / 2</p> <p>or</p> <p>vm = 2 * (y1 - y0) / (t1 + td - ta - t0)</p> <p>Using just the area of the triangles at the end, we can find how far we've travelled when we stop accelerating, ya = y(ta), and when we start decelerating, yd = y(td).</p> <p>ya = y0 + vm * (ta - t0) / 2</p> <p>yd = y1 - vm * (t1 - td) / 2</p> <p>Finally we produce a quadratic Bezier for [t0, ta], a straight line (ta, ya) - (td, yd), and a quadratic Bezier for [td, t1].</p> <p>For the first Bezier, we have the obvious control points P0 = (t0, y0) and P2 = (ta, ya). To find P1 we use the property that P0-P1 is tangent to the curve and P1-P2 is tangent to the curve (in general, for an order-n curve P0-P1 and P(n-1)-Pn are tangent). So P1 is at the intersection of y=y0 and the straight line of the middle segment. Similarly for the other Bezier: Q0 = (td, yd), Q2 = (t1, y1), and Q1 is at the intersection of y=y1 and the straight line of the middle segment.</p> <hr> <h3>Worked example:</h3> <p>No fade in (acceleration ratio = 0), deceleration ratio = 0.5, t0 = 0, t1 = 10 (seconds), y0 = 20, y1 = 400. I think this corresponds to your specific question.</p> <p>ta = 0 (and we can omit the first quadratic Bezier); td = t1 - 0.5 * (t1 - t0) = 5.</p> <p>vm = 2 * (y1 - y0) / (t1 + td - ta - t0) = 2 * (400 - 20) / (10 + 5 - 0 - 0) = 2 * 380 / 15 = 152 / 3 ~= 50.67.</p> <p>Ignore ya because we're skipping that Bezier.</p> <p>yd = y1 - vm * (t1 - td) / 2 = 400 - 152/3 * (10-5)/2 = 400 - 380/3 = 820/3 ~= 273.3</p> <p>So the straight line goes from (t=0, y=20) to (t=5, y=273.3). The deceleration Bezier has Q0 = (5, 273.3), Q2 = (10, 400).</p> <p>To find Q1 we extend the straight line to y=400. The line has equation y - 20 = (t - 0) * (273.3 - 20) / (5 - 0), so t = 5 * (400 - 20) / (273.3 - 20) = 7.5.</p> <p>So we have straight line (0,20)-(5,273.3) and a quadratic Bezier with control points (5,273.3), (7.5,400) and (10,400).</p> <h3>Translating this into your keyframe</h3> <p>However, there's a slight hitch, which is that Microsoft hasn't deigned to give us quadratic splines. We have to lift the quadratic Q0, Q1, Q2, to the cubic Q0, (Q0 + 2 Q1) /3, (2 Q1 + Q2) / 3, Q2.</p> <p>We also have to rescale the control points to 0-1. If we apply that rescaling first, we have (0,0)-(0.5,1)-(1,1). So the cubic is (0,0)-(0.333,0.667)-(0.667,1)-(1,1).</p> <p>I know splines, but not WPF. I think that the following will do what you want:</p> <pre> &lt;DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="20" /&gt; &lt;LinearDoubleKeyFrame KeyTime="0:0:5" Value="273.333" /&gt; &lt;SplineDoubleKeyFrame KeyTime="0:0:10" Value="400" KeySpline="0.333,0.667,0.667,1"/&gt; </pre> <h3>Universality of the transformation</h3> <p>Rescaling the first Bezier, we map (t0, y0) to (0, 0) and (ta, ya) to (1, 1). Therefore we map (P1.t, P1.y) to ((P1.t - t0) / (ta - t0), (P1.y - y0) / (ya - y0)). But P1 is at the intersection of y = y0 with the straight line of gradient vm through (ta, ya), which therefore has equation (y - ya) = (t - ta) * vm. So P1.y = y0 and P1.t = ta + (y0 - ya) / vm = ta - (ya - y0) / vm. Plugging in our identity ya = y0 + vm * (ta - t0) / 2, we get P1.t = ta - (vm * (ta - t0) / 2) / vm = ta - (ta - t0) / 2 = (ta + t0) / 2.</p> <p>So rescaling we map P1 to (0.5, 0). Therefore when we lift it to a cubic Bezier, the intermediate control points are always at (1/3, 0) and (2/3, 1/3).</p> <p>Similarly the deceleration spline always has its scaled intermediate points at (1/3, 2/3) and (2/3, 1).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload