| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // @dart = 2.9 |
| |
| part of touch; |
| |
| /** |
| * Functions to model constant acceleration as a cubic Bezier |
| * curve (http://en.wikipedia.org/wiki/Bezier_curve). These functions are |
| * intended to generate the transition timing function for CSS transitions. |
| * Please see |
| * [http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag]. |
| * |
| * The main operation of computing a cubic Bezier is split up into multiple |
| * functions so that, should it be required, more operations and cases can be |
| * supported in the future. |
| */ |
| class BezierPhysics { |
| static const _ONE_THIRD = 1 / 3; |
| static const _TWO_THIRDS = 2 / 3; |
| |
| /** |
| * A list [:[x1, y1, x2, y2]:] of the intermediate control points of a cubic |
| * bezier when the final velocity is zero. This is a special case for which |
| * these control points are constants. |
| */ |
| static const List<num> _FINAL_VELOCITY_ZERO_BEZIER = const [ |
| _ONE_THIRD, |
| _TWO_THIRDS, |
| _TWO_THIRDS, |
| 1 |
| ]; |
| |
| /** |
| * Given consistent kinematics parameters for constant acceleration, returns |
| * the intermediate control points of the cubic Bezier curve that models the |
| * motion. All input values must have correct signs. |
| * Returns a list [:[x1, y1, x2, y2]:] representing the intermediate control |
| * points of the cubic Bezier. |
| */ |
| static List<num> calculateCubicBezierFromKinematics(num initialVelocity, |
| num finalVelocity, num totalTime, num totalDisplacement) { |
| // Total time must be greater than 0. |
| assert(!GoogleMath.nearlyEquals(totalTime, 0) && totalTime > 0); |
| // Total displacement must not be 0. |
| assert(!GoogleMath.nearlyEquals(totalDisplacement, 0)); |
| // Parameters must form a consistent constant acceleration model in |
| // Newtonian kinematics. |
| assert(GoogleMath.nearlyEquals(totalDisplacement, |
| (initialVelocity + finalVelocity) * 0.5 * totalTime)); |
| |
| if (GoogleMath.nearlyEquals(finalVelocity, 0)) { |
| return _FINAL_VELOCITY_ZERO_BEZIER; |
| } |
| List<num> controlPoint = _tangentLinesToQuadraticBezier( |
| initialVelocity, finalVelocity, totalTime, totalDisplacement); |
| controlPoint = _normalizeQuadraticBezier( |
| controlPoint[0], controlPoint[1], totalTime, totalDisplacement); |
| return _quadraticToCubic(controlPoint[0], controlPoint[1]); |
| } |
| |
| /** |
| * Given a quadratic curve crossing points (0, 0) and (x2, y2), calculates the |
| * intermediate control point (x1, y1) of the equivalent quadratic Bezier |
| * curve with starting point (0, 0) and ending point (x2, y2). |
| * [m0] The slope of the line tangent to the curve at (0, 0). |
| * [m2] The slope of the line tangent to the curve at a different |
| * point (x2, y2). |
| * [x2] The x-coordinate of the other point on the curve. |
| * [y2] The y-coordinate of the other point on the curve. |
| * Returns a list [:[x1, y1]:] representing the intermediate |
| * control point of the quadratic Bezier. |
| */ |
| static List<num> _tangentLinesToQuadraticBezier( |
| num m0, num m2, num x2, num y2) { |
| if (GoogleMath.nearlyEquals(m0, m2)) { |
| return [0, 0]; |
| } |
| num x1 = (y2 - x2 * m2) / (m0 - m2); |
| num y1 = x1 * m0; |
| return [x1, y1]; |
| } |
| |
| /** |
| * Normalizes a quadratic Bezier curve to have end point at (1, 1). |
| * [x1] The x-coordinate of the intermediate control point. |
| * [y1] The y-coordinate of the intermediate control point. |
| * [x2] The x-coordinate of the end point. |
| * [y2] The y-coordinate of the end point. |
| * Returns a list [:[x1, y1]:] representing the intermediate control point. |
| */ |
| static List<num> _normalizeQuadraticBezier(num x1, num y1, num x2, num y2) { |
| // The end point must not lie on any axes. |
| assert(!GoogleMath.nearlyEquals(x2, 0) && !GoogleMath.nearlyEquals(y2, 0)); |
| return [x1 / x2, y1 / y2]; |
| } |
| |
| /** |
| * Converts a quadratic Bezier curve defined by the control points |
| * (x0, y0) = (0, 0), (x1, y1) = (x, y), and (x2, y2) = (1, 1) into an |
| * equivalent cubic Bezier curve with four control points. Note that the start |
| * and end points will be unchanged. |
| * [x] The x-coordinate of the intermediate control point. |
| * [y] The y-coordinate of the intermediate control point. |
| * Returns a list [:[x1, y1, x2, y2]:] containing the two |
| * intermediate points of the equivalent cubic Bezier curve. |
| */ |
| static List<num> _quadraticToCubic(num x, num y) { |
| // The intermediate control point must have coordinates within the |
| // interval [0,1]. |
| assert(x >= 0 && x <= 1 && y >= 0 && y <= 1); |
| num x1 = x * _TWO_THIRDS; |
| num y1 = y * _TWO_THIRDS; |
| num x2 = x1 + _ONE_THIRD; |
| num y2 = y1 + _ONE_THIRD; |
| return [x1, y1, x2, y2]; |
| } |
| } |