| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| part of newton; |
| |
| class SpringDescription { |
| /// The mass of the spring (m) |
| final double mass; |
| |
| /// The spring constant (k) |
| final double springConstant; |
| |
| /// The damping coefficient. |
| /// Note: Not to be confused with the damping ratio. Use the separate |
| /// constructor provided for this purpose |
| final double damping; |
| |
| SpringDescription( |
| {double this.mass, double this.springConstant, double this.damping}) { |
| assert(mass != null); |
| assert(springConstant != null); |
| assert(damping != null); |
| } |
| |
| /// Create a spring given the mass, spring constant and the damping ratio. The |
| /// damping ratio is especially useful trying to determing the type of spring |
| /// to create. A ratio of 1.0 creates a critically damped spring, > 1.0 |
| /// creates an overdamped spring and < 1.0 an underdamped one. |
| SpringDescription.withDampingRatio( |
| {double mass, double springConstant, double ratio: 1.0}) |
| : mass = mass, |
| springConstant = springConstant, |
| damping = ratio * 2.0 * math.sqrt(mass * springConstant); |
| } |
| |
| enum SpringType { unknown, criticallyDamped, underDamped, overDamped, } |
| |
| /// Creates a spring simulation. Depending on the spring description, a |
| /// critically, under or overdamped spring will be created. |
| class SpringSimulation extends Simulation { |
| final double _endPosition; |
| |
| final _SpringSolution _solution; |
| |
| /// A spring description with the provided spring description, start distance, |
| /// end distance and velocity. |
| SpringSimulation( |
| SpringDescription desc, double start, double end, double velocity) |
| : this._endPosition = end, |
| _solution = new _SpringSolution(desc, start - end, velocity); |
| |
| SpringType get type => _solution.type; |
| |
| double x(double time) => _endPosition + _solution.x(time); |
| |
| double dx(double time) => _solution.dx(time); |
| |
| @override |
| bool isDone(double time) => |
| _nearEqual(x(time), _endPosition, this.tolerance.distance) && |
| _nearZero(dx(time), this.tolerance.velocity); |
| } |
| |
| /// A SpringSimulation where the value of x() is guaranteed to have exactly the |
| /// end value when the simulation isDone(). |
| class ScrollSpringSimulation extends SpringSimulation { |
| ScrollSpringSimulation(SpringDescription desc, double start, double end, double velocity) |
| : super(desc, start, end, velocity); |
| |
| bool _isDone(double position, double velocity) { |
| return _nearEqual(position, _endPosition, tolerance.distance) && _nearZero(velocity, tolerance.velocity); |
| } |
| |
| @override |
| double x(double time) { |
| double xAtTime = super.x(time); |
| return _isDone(xAtTime, dx(time)) ? _endPosition : xAtTime; |
| } |
| |
| @override |
| bool isDone(double time) => _isDone(x(time), dx(time)); |
| } |