Commit 5a439792 authored by Chinmay Garde's avatar Chinmay Garde

Non composite simulations: Friction, gravity, spring

parents
# Newton
Simple Physics Simulations for Dart. Springs, friction, gravity, etc.
// 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.
library newton;
import 'dart:math' as Math;
part 'src/simulation.dart';
part 'src/utils.dart';
part 'src/fall.dart';
part 'src/friction.dart';
part 'src/gravity.dart';
part 'src/scroll.dart';
part 'src/spring.dart';
part 'src/spring_solution.dart';
// 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;
// TODO(csg): Composite simulation
class Fall {}
// 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 Friction extends Simulation {
final double _drag;
final double _dragNaturalLog;
final double _x;
final double _v;
Friction(double drag, double position, double velocity)
: _drag = drag,
_dragNaturalLog = Math.log(drag),
_x = position,
_v = velocity;
double x(double time) =>
_x + _v + Math.pow(_drag, time) / _dragNaturalLog - _v / _dragNaturalLog;
double dx(double time) => _v * Math.pow(_drag, time);
@override
bool isDone(double time) => dx(time).abs() < 1.0;
}
// 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 Gravity extends Simulation {
final double _x;
final double _v;
final double _a;
final double _end;
Gravity(
double acceleration, double distance, double endDistance, double velocity)
: _a = acceleration,
_x = distance,
_v = velocity,
_end = endDistance;
double x(double time) => _x + _v * time + 0.5 * _a * time * time;
double dx(double time) => _v + time * _a;
@override
bool isDone(double time) => x(time).abs() >= _end;
}
// 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;
// TODO(csg): Composite simulation
class Scroll {}
// 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;
abstract class Simulatable {
/// 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.
///
/// Note: All operation on subclasses of Simulation are idempotent. Composite
/// simulations are not guaranteed to be idempotent however. FIXME(csg): How do
/// I make this apparent?
abstract class Simulation implements Simulatable {
/// Returns if the simulation is done at a given time
bool isDone(double time);
}
// 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 SpringDesc {
/// 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 (zeta). Use the separate
/// constructor provided for this purpose
final double damping;
SpringDesc(this.mass, this.springConstant, this.damping);
SpringDesc.withDampingRatio(double mass, double springConstant, double zeta)
: this.mass = mass,
this.springConstant = springConstant,
this.damping = zeta * 2.0 * Math.sqrt(mass * springConstant);
}
/// Creates a spring simulation. Depending on the spring description, a
/// critically, under or overdamped spring will be created.
class Spring extends Simulation {
final double _endPosition;
final _SpringSolution _solution;
/// A spring description with the provided spring description, start distance,
/// end distance and velocity.
Spring(SpringDesc desc, double start, double end, double velocity)
: this._endPosition = end,
_solution = new _SpringSolution(desc, start - end, velocity);
double x(double time) => _endPosition + _solution.x(time);
double dx(double time) => _solution.dx(time);
@override
bool isDone(double time) =>
_nearEqual(x(time), _endPosition) && _nearZero(dx(time));
}
// 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;
abstract class _SpringSolution implements Simulatable {
factory _SpringSolution(
SpringDesc 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) {
return new _OverdampedSolution(desc, initialPosition, initialVelocity);
} else {
return new _UnderdampedSolution(desc, initialPosition, initialVelocity);
}
return null;
}
}
class _CriticalSolution implements _SpringSolution {
double r, c1, c2;
_CriticalSolution(SpringDesc desc, double distance, double velocity) {
r = -desc.damping / (2.0 * desc.mass);
c1 = distance;
c2 = velocity / (r * distance);
}
double x(double time) => (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;
}
}
class _OverdampedSolution implements _SpringSolution {
double r1, r2, c1, c2;
_OverdampedSolution(SpringDesc desc, double distance, double velocity) {
double cmk =
desc.damping * desc.damping - 4 * desc.mass * desc.springConstant;
r1 = (-desc.damping - Math.sqrt(cmk)) / (2.0 * desc.mass);
r2 = (-desc.damping + Math.sqrt(cmk)) / (2.0 * desc.mass);
c2 = (velocity - r1 * distance) / (r2 - r1);
c1 = distance - c2;
}
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 {
double w, r, c1, c2;
_UnderdampedSolution(SpringDesc desc, double distance, double velocity) {
w = Math.sqrt(4.0 * desc.mass * desc.springConstant -
desc.damping * desc.damping) /
(2.0 * desc.mass);
r = -(desc.damping / 2.0 * desc.mass);
c1 = distance;
c2 = (velocity - r * distance) / w;
}
double x(double time) => 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);
}
}
// 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;
const double _simulationEpsilon = 0.01;
bool _nearEqual(double a, double b) =>
(a > (b - _simulationEpsilon)) && (a < (b + _simulationEpsilon));
bool _nearZero(double a) => _nearEqual(a, 0.0);
// 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.
library simple_physics.test;
import 'package:test/test.dart';
import 'package:newton/newton.dart';
void main() {}
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