| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 import 'dart:math' as math; |
| 6 |
| 7 const double kGravity = -0.980; |
| 8 const double _kMinVelocity = 0.1; |
| 9 |
| 10 abstract class System { |
| 11 void update(double deltaT); |
| 12 } |
| 13 |
| 14 class Particle extends System { |
| 15 final double mass; |
| 16 double velocity; |
| 17 double position; |
| 18 |
| 19 Particle({this.mass: 1.0, this.velocity: 0.0, this.position: 0.0}); |
| 20 |
| 21 void applyImpluse(double impluse) { |
| 22 velocity += impluse / mass; |
| 23 } |
| 24 |
| 25 void update(double deltaT) { |
| 26 position += velocity * deltaT; |
| 27 } |
| 28 |
| 29 double get energy => 0.5 * mass * velocity * velocity; |
| 30 set energy(double e) { |
| 31 assert(e >= 0.0); |
| 32 velocity = math.sqrt(2 * e / mass); |
| 33 } |
| 34 } |
| 35 |
| 36 class Box { |
| 37 final double min; |
| 38 final double max; |
| 39 |
| 40 Box({this.min, this.max}) { |
| 41 assert(min == null || max == null || min <= max); |
| 42 } |
| 43 |
| 44 void confine(Particle p) { |
| 45 if (min != null) { |
| 46 p.position = math.max(min, p.position); |
| 47 if (p.position == min) |
| 48 p.velocity = math.max(0.0, p.velocity); |
| 49 } |
| 50 if (max != null) { |
| 51 p.position = math.min(max, p.position); |
| 52 if (p.position == max) |
| 53 p.velocity = math.min(0.0, p.velocity); |
| 54 } |
| 55 } |
| 56 } |
| 57 |
| 58 class ParticleInBox extends System { |
| 59 final Particle particle; |
| 60 final Box box; |
| 61 |
| 62 ParticleInBox({this.particle, this.box}) { |
| 63 box.confine(particle); |
| 64 } |
| 65 |
| 66 void update(double deltaT) { |
| 67 particle.update(deltaT); |
| 68 box.confine(particle); |
| 69 } |
| 70 } |
| 71 |
| 72 class Spring { |
| 73 final double k; |
| 74 double displacement; |
| 75 |
| 76 Spring(this.k, {this.displacement: 0.0}); |
| 77 |
| 78 double get force => -k * displacement; |
| 79 } |
| 80 |
| 81 class ParticleAndSpringInBox extends System { |
| 82 final Particle particle; |
| 83 final Spring spring; |
| 84 final Box box; |
| 85 |
| 86 ParticleAndSpringInBox({this.particle, this.spring, this.box}) { |
| 87 _applyInvariants(); |
| 88 } |
| 89 |
| 90 void update(double deltaT) { |
| 91 particle.applyImpluse(spring.force * deltaT); |
| 92 particle.update(deltaT); |
| 93 _applyInvariants(); |
| 94 } |
| 95 |
| 96 void _applyInvariants() { |
| 97 box.confine(particle); |
| 98 spring.displacement = particle.position; |
| 99 } |
| 100 } |
| 101 |
| 102 class ParticleClimbingHill extends System { |
| 103 final Particle particle; |
| 104 final Box box; |
| 105 final double slope; |
| 106 |
| 107 ParticleClimbingHill({ |
| 108 this.particle, |
| 109 this.box, |
| 110 this.slope, |
| 111 double targetPosition}) { |
| 112 double deltaPosition = targetPosition - particle.position; |
| 113 particle.energy = -kGravity * slope * deltaPosition * particle.mass; |
| 114 box.confine(particle); |
| 115 } |
| 116 |
| 117 void update(double deltaT) { |
| 118 particle.applyImpluse(kGravity * slope * deltaT); |
| 119 // If we don't apply a min velocity, error terms in the simulation can |
| 120 // prevent us from reaching the targetPosition before gravity overtakes our |
| 121 // initial velocity and we start rolling down the hill. |
| 122 particle.velocity = math.max(_kMinVelocity, particle.velocity); |
| 123 particle.update(deltaT); |
| 124 box.confine(particle); |
| 125 } |
| 126 } |
| OLD | NEW |