From 0a4cc82ae458ef0b47646e04c10f3f01add2db20 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Sun, 6 Mar 2016 00:34:53 -0800 Subject: [PATCH] Remove Simulatable and restyle simulation_group.dart --- packages/newton/lib/src/simulation.dart | 16 +- packages/newton/lib/src/simulation_group.dart | 3 +- .../newton/lib/src/spring_simulation.dart | 186 ++++++++++-------- 3 files changed, 112 insertions(+), 93 deletions(-) diff --git a/packages/newton/lib/src/simulation.dart b/packages/newton/lib/src/simulation.dart index def3b376c2..8e494ac724 100644 --- a/packages/newton/lib/src/simulation.dart +++ b/packages/newton/lib/src/simulation.dart @@ -4,19 +4,17 @@ import 'tolerance.dart'; -abstract class Simulatable { +/// The base class for all simulations. The user is meant to instantiate an +/// instance of a simulation and query the same for the position and velocity +/// of the body at a given interval. +abstract class Simulation { + Tolerance tolerance = toleranceDefault; + /// The current position of the object in the simulation double x(double time); /// The current velocity of the object in the simulation - double dx(double time); -} - -/// The base class for all simulations. The user is meant to instantiate an -/// instance of a simulation and query the same for the position and velocity -/// of the body at a given interval. -abstract class Simulation implements Simulatable { - Tolerance tolerance = toleranceDefault; + double dx(double time); // TODO(ianh): remove this; see https://github.com/flutter/flutter/issues/2092 /// Returns if the simulation is done at a given time bool isDone(double time); diff --git a/packages/newton/lib/src/simulation_group.dart b/packages/newton/lib/src/simulation_group.dart index 76fb440d61..fe36d739d9 100644 --- a/packages/newton/lib/src/simulation_group.dart +++ b/packages/newton/lib/src/simulation_group.dart @@ -10,7 +10,8 @@ import 'utils.dart'; /// must implement the appropriate methods to select the appropriate simulation /// at a given time interval. The simulation group takes care to call the `step` /// method at appropriate intervals. If more fine grained control over the the -/// step is necessary, subclasses may override `Simulatable` methods. +/// step is necessary, subclasses may override the [x], [dx], and [isDone] +/// methods. abstract class SimulationGroup extends Simulation { /// The currently active simulation diff --git a/packages/newton/lib/src/spring_simulation.dart b/packages/newton/lib/src/spring_simulation.dart index 8406a7930a..324a753b16 100644 --- a/packages/newton/lib/src/spring_simulation.dart +++ b/packages/newton/lib/src/spring_simulation.dart @@ -7,120 +7,154 @@ import 'dart:math' as math; import 'simulation.dart'; import 'utils.dart'; -abstract class _SpringSolution implements Simulatable { +enum SpringType { unknown, criticallyDamped, underDamped, overDamped } + +abstract class _SpringSolution { factory _SpringSolution( - SpringDescription desc, double initialPosition, double initialVelocity) { - double cmk = - desc.damping * desc.damping - 4 * desc.mass * desc.springConstant; - - if (cmk == 0.0) { + SpringDescription desc, + double initialPosition, + double initialVelocity + ) { + double cmk = desc.damping * desc.damping - 4 * desc.mass * desc.springConstant; + if (cmk == 0.0) return new _CriticalSolution(desc, initialPosition, initialVelocity); - } else if (cmk > 0.0) { + if (cmk > 0.0) return new _OverdampedSolution(desc, initialPosition, initialVelocity); - } else { - return new _UnderdampedSolution(desc, initialPosition, initialVelocity); - } - - return null; + return new _UnderdampedSolution(desc, initialPosition, initialVelocity); } + double x(double time); + double dx(double time); SpringType get type; } class _CriticalSolution implements _SpringSolution { - final double _r, _c1, _c2; - factory _CriticalSolution( - SpringDescription desc, double distance, double velocity) { + SpringDescription desc, + double distance, + double velocity + ) { final double r = -desc.damping / (2.0 * desc.mass); final double c1 = distance; final double c2 = velocity / (r * distance); return new _CriticalSolution.withArgs(r, c1, c2); } - SpringType get type => SpringType.criticallyDamped; - _CriticalSolution.withArgs(double r, double c1, double c2) - : _r = r, - _c1 = c1, - _c2 = c2; + : _r = r, + _c1 = c1, + _c2 = c2; - double x(double time) => (_c1 + _c2 * time) * math.pow(math.E, _r * time); + final double _r, _c1, _c2; + + double x(double time) { + return (_c1 + _c2 * time) * math.pow(math.E, _r * time); + } double dx(double time) { final double power = math.pow(math.E, _r * time); return _r * (_c1 + _c2 * time) * power + _c2 * power; } + + SpringType get type => SpringType.criticallyDamped; } class _OverdampedSolution implements _SpringSolution { - final double _r1, _r2, _c1, _c2; - factory _OverdampedSolution( - SpringDescription desc, double distance, double velocity) { - final double cmk = - desc.damping * desc.damping - 4 * desc.mass * desc.springConstant; - + SpringDescription desc, + double distance, + double velocity + ) { + final double cmk = desc.damping * desc.damping - 4 * desc.mass * desc.springConstant; final double r1 = (-desc.damping - math.sqrt(cmk)) / (2.0 * desc.mass); final double r2 = (-desc.damping + math.sqrt(cmk)) / (2.0 * desc.mass); final double c2 = (velocity - r1 * distance) / (r2 - r1); final double c1 = distance - c2; - return new _OverdampedSolution.withArgs(r1, r2, c1, c2); } _OverdampedSolution.withArgs(double r1, double r2, double c1, double c2) - : _r1 = r1, - _r2 = r2, - _c1 = c1, - _c2 = c2; + : _r1 = r1, + _r2 = r2, + _c1 = c1, + _c2 = c2; + + final double _r1, _r2, _c1, _c2; + + double x(double time) { + return _c1 * math.pow(math.E, _r1 * time) + + _c2 * math.pow(math.E, _r2 * time); + } + + double dx(double time) { + return _c1 * _r1 * math.pow(math.E, _r1 * time) + + _c2 * _r2 * math.pow(math.E, _r2 * time); + } SpringType get type => SpringType.overDamped; - - double x(double time) => - (_c1 * math.pow(math.E, _r1 * time) + _c2 * math.pow(math.E, _r2 * time)); - - double dx(double time) => (_c1 * _r1 * math.pow(math.E, _r1 * time) + - _c2 * _r2 * math.pow(math.E, _r2 * time)); } class _UnderdampedSolution implements _SpringSolution { - final double _w, _r, _c1, _c2; - factory _UnderdampedSolution( - SpringDescription desc, double distance, double velocity) { + SpringDescription desc, + double distance, + double velocity + ) { final double w = math.sqrt(4.0 * desc.mass * desc.springConstant - - desc.damping * desc.damping) / - (2.0 * desc.mass); + desc.damping * desc.damping) / (2.0 * desc.mass); final double r = -(desc.damping / 2.0 * desc.mass); final double c1 = distance; final double c2 = (velocity - r * distance) / w; - return new _UnderdampedSolution.withArgs(w, r, c1, c2); } _UnderdampedSolution.withArgs(double w, double r, double c1, double c2) - : _w = w, - _r = r, - _c1 = c1, - _c2 = c2; + : _w = w, + _r = r, + _c1 = c1, + _c2 = c2; - SpringType get type => SpringType.underDamped; + final double _w, _r, _c1, _c2; - double x(double time) => math.pow(math.E, _r * time) * - (_c1 * math.cos(_w * time) + _c2 * math.sin(_w * time)); + double x(double time) { + return math.pow(math.E, _r * time) * + (_c1 * math.cos(_w * time) + _c2 * math.sin(_w * time)); + } double dx(double time) { final double power = math.pow(math.E, _r * time); final double cosine = math.cos(_w * time); final double sine = math.sin(_w * time); - - return power * (_c2 * _w * cosine - _c1 * _w * sine) + - _r * power * (_c2 * sine + _c1 * cosine); + return power * (_c2 * _w * cosine - _c1 * _w * sine) + + _r * power * (_c2 * sine + _c1 * cosine); } + + SpringType get type => SpringType.underDamped; } class SpringDescription { + SpringDescription({ + this.mass, + this.springConstant, + 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); + /// The mass of the spring (m) final double mass; @@ -131,41 +165,23 @@ class SpringDescription { /// Not to be confused with the damping ratio. Use the separate /// constructor provided for this purpose final double damping; - - SpringDescription( - { this.mass, this.springConstant, 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); + SpringDescription desc, + double start, + double end, + double velocity + ) : _endPosition = end, + _solution = new _SpringSolution(desc, start - end, velocity); + + final double _endPosition; + final _SpringSolution _solution; SpringType get type => _solution.type; @@ -182,8 +198,12 @@ class SpringSimulation extends Simulation { /// 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); + ScrollSpringSimulation( + SpringDescription desc, + double start, + double end, + double velocity + ) : super(desc, start, end, velocity); double x(double time) => isDone(time) ? _endPosition : super.x(time); }