Merge pull request #2452 from Hixie/unsimulatable
Remove Simulatable and restyle simulation_group.dart
This commit is contained in:
commit
36694ac068
@ -4,19 +4,17 @@
|
|||||||
|
|
||||||
import 'tolerance.dart';
|
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
|
/// The current position of the object in the simulation
|
||||||
double x(double time);
|
double x(double time);
|
||||||
|
|
||||||
/// The current velocity of the object in the simulation
|
/// The current velocity of the object in the simulation
|
||||||
double dx(double time);
|
double dx(double time); // TODO(ianh): remove this; see https://github.com/flutter/flutter/issues/2092
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
|
||||||
|
|
||||||
/// Returns if the simulation is done at a given time
|
/// Returns if the simulation is done at a given time
|
||||||
bool isDone(double time);
|
bool isDone(double time);
|
||||||
|
@ -10,7 +10,8 @@ import 'utils.dart';
|
|||||||
/// must implement the appropriate methods to select the appropriate simulation
|
/// must implement the appropriate methods to select the appropriate simulation
|
||||||
/// at a given time interval. The simulation group takes care to call the `step`
|
/// 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
|
/// 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 {
|
abstract class SimulationGroup extends Simulation {
|
||||||
|
|
||||||
/// The currently active simulation
|
/// The currently active simulation
|
||||||
|
@ -7,120 +7,154 @@ import 'dart:math' as math;
|
|||||||
import 'simulation.dart';
|
import 'simulation.dart';
|
||||||
import 'utils.dart';
|
import 'utils.dart';
|
||||||
|
|
||||||
abstract class _SpringSolution implements Simulatable {
|
enum SpringType { unknown, criticallyDamped, underDamped, overDamped }
|
||||||
|
|
||||||
|
abstract class _SpringSolution {
|
||||||
factory _SpringSolution(
|
factory _SpringSolution(
|
||||||
SpringDescription desc, double initialPosition, double initialVelocity) {
|
SpringDescription desc,
|
||||||
double cmk =
|
double initialPosition,
|
||||||
desc.damping * desc.damping - 4 * desc.mass * desc.springConstant;
|
double initialVelocity
|
||||||
|
) {
|
||||||
if (cmk == 0.0) {
|
double cmk = desc.damping * desc.damping - 4 * desc.mass * desc.springConstant;
|
||||||
|
if (cmk == 0.0)
|
||||||
return new _CriticalSolution(desc, initialPosition, initialVelocity);
|
return new _CriticalSolution(desc, initialPosition, initialVelocity);
|
||||||
} else if (cmk > 0.0) {
|
if (cmk > 0.0)
|
||||||
return new _OverdampedSolution(desc, initialPosition, initialVelocity);
|
return new _OverdampedSolution(desc, initialPosition, initialVelocity);
|
||||||
} else {
|
return new _UnderdampedSolution(desc, initialPosition, initialVelocity);
|
||||||
return new _UnderdampedSolution(desc, initialPosition, initialVelocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double x(double time);
|
||||||
|
double dx(double time);
|
||||||
SpringType get type;
|
SpringType get type;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CriticalSolution implements _SpringSolution {
|
class _CriticalSolution implements _SpringSolution {
|
||||||
final double _r, _c1, _c2;
|
|
||||||
|
|
||||||
factory _CriticalSolution(
|
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 r = -desc.damping / (2.0 * desc.mass);
|
||||||
final double c1 = distance;
|
final double c1 = distance;
|
||||||
final double c2 = velocity / (r * distance);
|
final double c2 = velocity / (r * distance);
|
||||||
return new _CriticalSolution.withArgs(r, c1, c2);
|
return new _CriticalSolution.withArgs(r, c1, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpringType get type => SpringType.criticallyDamped;
|
|
||||||
|
|
||||||
_CriticalSolution.withArgs(double r, double c1, double c2)
|
_CriticalSolution.withArgs(double r, double c1, double c2)
|
||||||
: _r = r,
|
: _r = r,
|
||||||
_c1 = c1,
|
_c1 = c1,
|
||||||
_c2 = c2;
|
_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) {
|
double dx(double time) {
|
||||||
final double power = math.pow(math.E, _r * time);
|
final double power = math.pow(math.E, _r * time);
|
||||||
return _r * (_c1 + _c2 * time) * power + _c2 * power;
|
return _r * (_c1 + _c2 * time) * power + _c2 * power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpringType get type => SpringType.criticallyDamped;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OverdampedSolution implements _SpringSolution {
|
class _OverdampedSolution implements _SpringSolution {
|
||||||
final double _r1, _r2, _c1, _c2;
|
|
||||||
|
|
||||||
factory _OverdampedSolution(
|
factory _OverdampedSolution(
|
||||||
SpringDescription desc, double distance, double velocity) {
|
SpringDescription desc,
|
||||||
final double cmk =
|
double distance,
|
||||||
desc.damping * desc.damping - 4 * desc.mass * desc.springConstant;
|
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 r1 = (-desc.damping - math.sqrt(cmk)) / (2.0 * desc.mass);
|
||||||
final double r2 = (-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 c2 = (velocity - r1 * distance) / (r2 - r1);
|
||||||
final double c1 = distance - c2;
|
final double c1 = distance - c2;
|
||||||
|
|
||||||
return new _OverdampedSolution.withArgs(r1, r2, c1, c2);
|
return new _OverdampedSolution.withArgs(r1, r2, c1, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
_OverdampedSolution.withArgs(double r1, double r2, double c1, double c2)
|
_OverdampedSolution.withArgs(double r1, double r2, double c1, double c2)
|
||||||
: _r1 = r1,
|
: _r1 = r1,
|
||||||
_r2 = r2,
|
_r2 = r2,
|
||||||
_c1 = c1,
|
_c1 = c1,
|
||||||
_c2 = c2;
|
_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;
|
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 {
|
class _UnderdampedSolution implements _SpringSolution {
|
||||||
final double _w, _r, _c1, _c2;
|
|
||||||
|
|
||||||
factory _UnderdampedSolution(
|
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 -
|
final double w = math.sqrt(4.0 * desc.mass * desc.springConstant -
|
||||||
desc.damping * desc.damping) /
|
desc.damping * desc.damping) / (2.0 * desc.mass);
|
||||||
(2.0 * desc.mass);
|
|
||||||
final double r = -(desc.damping / 2.0 * desc.mass);
|
final double r = -(desc.damping / 2.0 * desc.mass);
|
||||||
final double c1 = distance;
|
final double c1 = distance;
|
||||||
final double c2 = (velocity - r * distance) / w;
|
final double c2 = (velocity - r * distance) / w;
|
||||||
|
|
||||||
return new _UnderdampedSolution.withArgs(w, r, c1, c2);
|
return new _UnderdampedSolution.withArgs(w, r, c1, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
_UnderdampedSolution.withArgs(double w, double r, double c1, double c2)
|
_UnderdampedSolution.withArgs(double w, double r, double c1, double c2)
|
||||||
: _w = w,
|
: _w = w,
|
||||||
_r = r,
|
_r = r,
|
||||||
_c1 = c1,
|
_c1 = c1,
|
||||||
_c2 = c2;
|
_c2 = c2;
|
||||||
|
|
||||||
SpringType get type => SpringType.underDamped;
|
final double _w, _r, _c1, _c2;
|
||||||
|
|
||||||
double x(double time) => math.pow(math.E, _r * time) *
|
double x(double time) {
|
||||||
(_c1 * math.cos(_w * time) + _c2 * math.sin(_w * time));
|
return math.pow(math.E, _r * time) *
|
||||||
|
(_c1 * math.cos(_w * time) + _c2 * math.sin(_w * time));
|
||||||
|
}
|
||||||
|
|
||||||
double dx(double time) {
|
double dx(double time) {
|
||||||
final double power = math.pow(math.E, _r * time);
|
final double power = math.pow(math.E, _r * time);
|
||||||
final double cosine = math.cos(_w * time);
|
final double cosine = math.cos(_w * time);
|
||||||
final double sine = math.sin(_w * time);
|
final double sine = math.sin(_w * time);
|
||||||
|
return power * (_c2 * _w * cosine - _c1 * _w * sine) +
|
||||||
return power * (_c2 * _w * cosine - _c1 * _w * sine) +
|
_r * power * (_c2 * sine + _c1 * cosine);
|
||||||
_r * power * (_c2 * sine + _c1 * cosine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpringType get type => SpringType.underDamped;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpringDescription {
|
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)
|
/// The mass of the spring (m)
|
||||||
final double mass;
|
final double mass;
|
||||||
|
|
||||||
@ -131,41 +165,23 @@ class SpringDescription {
|
|||||||
/// Not to be confused with the damping ratio. Use the separate
|
/// Not to be confused with the damping ratio. Use the separate
|
||||||
/// constructor provided for this purpose
|
/// constructor provided for this purpose
|
||||||
final double damping;
|
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
|
/// Creates a spring simulation. Depending on the spring description, a
|
||||||
/// critically, under or overdamped spring will be created.
|
/// critically, under or overdamped spring will be created.
|
||||||
class SpringSimulation extends Simulation {
|
class SpringSimulation extends Simulation {
|
||||||
final double _endPosition;
|
|
||||||
|
|
||||||
final _SpringSolution _solution;
|
|
||||||
|
|
||||||
/// A spring description with the provided spring description, start distance,
|
/// A spring description with the provided spring description, start distance,
|
||||||
/// end distance and velocity.
|
/// end distance and velocity.
|
||||||
SpringSimulation(
|
SpringSimulation(
|
||||||
SpringDescription desc, double start, double end, double velocity)
|
SpringDescription desc,
|
||||||
: this._endPosition = end,
|
double start,
|
||||||
_solution = new _SpringSolution(desc, start - end, velocity);
|
double end,
|
||||||
|
double velocity
|
||||||
|
) : _endPosition = end,
|
||||||
|
_solution = new _SpringSolution(desc, start - end, velocity);
|
||||||
|
|
||||||
|
final double _endPosition;
|
||||||
|
final _SpringSolution _solution;
|
||||||
|
|
||||||
SpringType get type => _solution.type;
|
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
|
/// A SpringSimulation where the value of x() is guaranteed to have exactly the
|
||||||
/// end value when the simulation isDone().
|
/// end value when the simulation isDone().
|
||||||
class ScrollSpringSimulation extends SpringSimulation {
|
class ScrollSpringSimulation extends SpringSimulation {
|
||||||
ScrollSpringSimulation(SpringDescription desc, double start, double end, double velocity)
|
ScrollSpringSimulation(
|
||||||
: super(desc, start, end, velocity);
|
SpringDescription desc,
|
||||||
|
double start,
|
||||||
|
double end,
|
||||||
|
double velocity
|
||||||
|
) : super(desc, start, end, velocity);
|
||||||
|
|
||||||
double x(double time) => isDone(time) ? _endPosition : super.x(time);
|
double x(double time) => isDone(time) ? _endPosition : super.x(time);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user