// 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 = [
    _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];
  }
}
