Commit 09099a17 authored by Hans Muller's avatar Hans Muller

Added FrictionSimulation.through() constructor

parent eaa72f6e
......@@ -16,8 +16,28 @@ class FrictionSimulation extends Simulation {
_x = position,
_v = velocity;
double x(double time) =>
_x + _v * math.pow(_drag, time) / _dragLog - _v / _dragLog;
// Return the drag value for a FrictionSimulation whose x() and dx() values pass
// through the specified start and end position/velocity values.
//
// Total time to reach endVelocity is just: (log(endVelocity) / log(startVelocity)) / log(_drag)
// or (log(v1) - log(v0)) / log(D), given v = v0 * D^t per the dx() function below.
// Solving for D given x(time) is trickier. Algebra courtesy of Wolfram Alpha:
// x1 = x0 + (v0 * D^((log(v1) - log(v0)) / log(D))) / log(D) - v0 / log(D), find D
static double _dragFor(double startPosition, double endPosition, double startVelocity, double endVelocity) {
return math.pow(math.E, (startVelocity - endVelocity) / (startPosition - endPosition));
}
// A friction simulation that starts and ends at the specified positions
// and velocities.
factory FrictionSimulation.through(double startPosition, double endPosition, double startVelocity, double endVelocity) {
return new FrictionSimulation(
_dragFor(startPosition, endPosition, startVelocity, endVelocity),
startPosition,
startVelocity)
.. tolerance = new Tolerance(velocity: endVelocity.abs());
}
double x(double time) => _x + _v * math.pow(_drag, time) / _dragLog - _v / _dragLog;
double dx(double time) => _v * math.pow(_drag, time);
......
......@@ -29,6 +29,48 @@ void main() {
expect(friction.x(5.0) > 431 && friction.x(5.0) < 432, true);
});
test('test_friction_through', () {
// Use a normal FrictionSimulation to generate start and end
// velocity and positions with drag = 0.025.
var startPosition = 10.0;
var startVelocity = 600.0;
var f = new FrictionSimulation(0.025, startPosition, startVelocity);
var endPosition = f.x(1.0);
var endVelocity = f.dx(1.0);
expect(endPosition, greaterThan(startPosition));
expect(endVelocity, lessThan(startVelocity));
// Verify that that the "through" FrictionSimulation ends up at
// endPosition and endVelocity; implies that it computed the right
// value for _drag.
var friction = new FrictionSimulation.through(
startPosition, endPosition, startVelocity, endVelocity);
expect(friction.isDone(0.0), false);
expect(friction.x(0.0), 10.0);
expect(friction.dx(0.0), 600.0);
double epsilon = 1e-4;
expect(friction.isDone(1.0 + epsilon), true);
expect(friction.x(1.0), closeTo(endPosition, epsilon));
expect(friction.dx(1.0), closeTo(endVelocity, epsilon));
// Same scenario as above except that the velocities are
// are negative.
startPosition = 1000.0;
startVelocity = -500.0;
f = new FrictionSimulation(0.025, 1000.0, -500.0);
endPosition = f.x(1.0);
endVelocity = f.dx(1.0);
expect(endPosition, lessThan(startPosition));
expect(endVelocity, greaterThan(startVelocity));
friction = new FrictionSimulation.through(
startPosition, endPosition, startVelocity, endVelocity);
expect(friction.isDone(1.0 + epsilon), true);
expect(friction.x(1.0), closeTo(endPosition, epsilon));
expect(friction.dx(1.0), closeTo(endVelocity, epsilon));
});
test('test_gravity', () {
var gravity = new GravitySimulation(200.0, 100.0, 600.0, 0.0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment