您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

238 行
7.6 KiB

using System;
using UIWidgets.foundation;
namespace UIWidgets.physics {
public class SpringDescription {
public SpringDescription(
double mass,
double stiffness,
double damping
) {
this.mass = mass;
this.stiffness = stiffness;
this.damping = damping;
}
public static SpringDescription withDampingRatio(
double mass,
double stiffness,
double ratio = 1.0
) {
var damping = ratio * 2.0 * Math.Sqrt(mass * stiffness);
return new SpringDescription(mass, stiffness, damping);
}
public readonly double mass;
public readonly double stiffness;
public readonly double damping;
public override string ToString() {
return string.Format("{0}(mass {1:F1}, stiffness: {2:F1}, damping: {3:F1})",
this.GetType(), this.mass, this.stiffness, this.damping);
}
}
public enum SpringType {
criticallyDamped,
underDamped,
overDamped,
}
public class SpringSimulation : Simulation {
public SpringSimulation(
SpringDescription spring,
double start,
double end,
double velocity,
Tolerance tolerance = null
) : base(tolerance: tolerance) {
this._endPosition = end;
this._solution = _SpringSolution.create(spring, start - end, velocity);
}
protected readonly double _endPosition;
readonly _SpringSolution _solution;
public SpringType type {
get { return this._solution.type; }
}
public override double x(double time) {
return this._endPosition + this._solution.x(time);
}
public override double dx(double time) {
return this._solution.dx(time);
}
public override bool isDone(double time) {
return PhysicsUtils.nearZero(this._solution.x(time), this.tolerance.distance) &&
PhysicsUtils.nearZero(this._solution.dx(time), this.tolerance.velocity);
}
public override string ToString() {
return string.Format("{0}(end: {1}, {2}", this.GetType(), this._endPosition, this.type);
}
}
public class ScrollSpringSimulation : SpringSimulation {
public ScrollSpringSimulation(
SpringDescription spring,
double start,
double end,
double velocity,
Tolerance tolerance = null
) : base(spring, start, end, velocity, tolerance: tolerance) {
}
public override double x(double time) {
return this.isDone(time) ? this._endPosition : base.x(time);
}
}
abstract class _SpringSolution {
internal static _SpringSolution create(
SpringDescription spring,
double initialPosition,
double initialVelocity
) {
D.assert(spring != null);
double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness;
if (cmk == 0.0) {
return _CriticalSolution.create(spring, initialPosition, initialVelocity);
}
if (cmk > 0.0) {
return _OverdampedSolution.create(spring, initialPosition, initialVelocity);
}
return _UnderdampedSolution.create(spring, initialPosition, initialVelocity);
}
public abstract double x(double time);
public abstract double dx(double time);
public abstract SpringType type { get; }
}
class _CriticalSolution : _SpringSolution {
internal new static _CriticalSolution create(
SpringDescription spring,
double distance,
double velocity
) {
double r = -spring.damping / (2.0 * spring.mass);
double c1 = distance;
double c2 = velocity / (r * distance);
return new _CriticalSolution(r, c1, c2);
}
private _CriticalSolution(
double r, double c1, double c2
) {
this._r = r;
this._c1 = c1;
this._c2 = c2;
}
readonly double _r, _c1, _c2;
public override double x(double time) {
return (this._c1 + this._c2 * time) * Math.Pow(Math.E, this._r * time);
}
public override double dx(double time) {
double power = Math.Pow(Math.E, this._r * time);
return this._r * (this._c1 + this._c2 * time) * power + this._c2 * power;
}
public override SpringType type {
get { return SpringType.criticallyDamped; }
}
}
class _OverdampedSolution : _SpringSolution {
internal new static _OverdampedSolution create(
SpringDescription spring,
double distance,
double velocity
) {
double cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness;
double r1 = (-spring.damping - Math.Sqrt(cmk)) / (2.0 * spring.mass);
double r2 = (-spring.damping + Math.Sqrt(cmk)) / (2.0 * spring.mass);
double c2 = (velocity - r1 * distance) / (r2 - r1);
double c1 = distance - c2;
return new _OverdampedSolution(r1, r2, c1, c2);
}
private _OverdampedSolution(
double r1, double r2, double c1, double c2
) {
this._r1 = r1;
this._r2 = r2;
this._c1 = c1;
this._c2 = c2;
}
readonly double _r1, _r2, _c1, _c2;
public override double x(double time) {
return this._c1 * Math.Pow(Math.E, this._r1 * time) +
this._c2 * Math.Pow(Math.E, this._r2 * time);
}
public override double dx(double time) {
return this._c1 * this._r1 * Math.Pow(Math.E, this._r1 * time) +
this._c2 * this._r2 * Math.Pow(Math.E, this._r2 * time);
}
public override SpringType type {
get { return SpringType.overDamped; }
}
}
class _UnderdampedSolution : _SpringSolution {
internal new static _UnderdampedSolution create(
SpringDescription spring,
double distance,
double velocity
) {
double w = Math.Sqrt(4.0 * spring.mass * spring.stiffness -
spring.damping * spring.damping) / (2.0 * spring.mass);
double r = -(spring.damping / 2.0 * spring.mass);
double c1 = distance;
double c2 = (velocity - r * distance) / w;
return new _UnderdampedSolution(w, r, c1, c2);
}
private _UnderdampedSolution(
double w, double r, double c1, double c2
) {
this._w = w;
this._r = r;
this._c1 = c1;
this._c2 = c2;
}
readonly double _w, _r, _c1, _c2;
public override double x(double time) {
return Math.Pow(Math.E, this._r * time) *
(this._c1 * Math.Cos(this._w * time) + this._c2 * Math.Sin(this._w * time));
}
public override double dx(double time) {
double power = Math.Pow(Math.E, this._r * time);
double cosine = Math.Cos(this._w * time);
double sine = Math.Sin(this._w * time);
return power * (this._c2 * this._w * cosine - this._c1 * this._w * sine) +
this._r * power * (this._c2 * sine + this._c1 * cosine);
}
public override SpringType type {
get { return SpringType.underDamped; }
}
}
}