| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:math' as math; | 5 import 'dart:math' as math; |
| 6 | 6 |
| 7 const double kGravity = -0.980; // m^s-2 | 7 const double kGravity = -0.980; // m^s-2 |
| 8 | 8 |
| 9 abstract class System { | 9 abstract class System { |
| 10 void update(double deltaT); | 10 void update(double deltaT); |
| 11 } | 11 } |
| 12 | 12 |
| 13 class Particle extends System { | 13 class Particle extends System { |
| 14 final double mass; | 14 final double mass; |
| 15 double velocity; | 15 double velocity; |
| 16 double position; | 16 double position; |
| 17 | 17 |
| 18 Particle({this.mass: 1.0, this.velocity: 0.0, this.position: 0.0}); | 18 Particle({this.mass: 1.0, this.velocity: 0.0, this.position: 0.0}); |
| 19 | 19 |
| 20 void applyImpulse(double impulse) { | 20 void applyImpulse(double impulse) { |
| 21 velocity += impulse / mass; | 21 velocity += impulse / mass; |
| 22 } | 22 } |
| 23 | 23 |
| 24 @override |
| 24 void update(double deltaT) { | 25 void update(double deltaT) { |
| 25 position += velocity * deltaT; | 26 position += velocity * deltaT; |
| 26 } | 27 } |
| 27 | 28 |
| 28 void setVelocityFromEnergy({double energy, double direction}) { | 29 void setVelocityFromEnergy({double energy, double direction}) { |
| 29 assert(direction == -1.0 || direction == 1.0); | 30 assert(direction == -1.0 || direction == 1.0); |
| 30 assert(energy >= 0.0); | 31 assert(energy >= 0.0); |
| 31 velocity = math.sqrt(2.0 * energy / mass) * direction; | 32 velocity = math.sqrt(2.0 * energy / mass) * direction; |
| 32 } | 33 } |
| 33 } | 34 } |
| 34 | 35 |
| 35 abstract class Box { | 36 abstract class Box { |
| 36 void confine(Particle p); | 37 void confine(Particle p); |
| 37 } | 38 } |
| 38 | 39 |
| 39 class ClosedBox extends Box { | 40 class ClosedBox extends Box { |
| 40 final double min; // m | 41 final double min; // m |
| 41 final double max; // m | 42 final double max; // m |
| 42 | 43 |
| 43 ClosedBox({this.min, this.max}) { | 44 ClosedBox({this.min, this.max}) { |
| 44 assert(min == null || max == null || min <= max); | 45 assert(min == null || max == null || min <= max); |
| 45 } | 46 } |
| 46 | 47 |
| 48 @override |
| 47 void confine(Particle p) { | 49 void confine(Particle p) { |
| 48 if (min != null) { | 50 if (min != null) { |
| 49 p.position = math.max(min, p.position); | 51 p.position = math.max(min, p.position); |
| 50 if (p.position == min) | 52 if (p.position == min) |
| 51 p.velocity = math.max(0.0, p.velocity); | 53 p.velocity = math.max(0.0, p.velocity); |
| 52 } | 54 } |
| 53 if (max != null) { | 55 if (max != null) { |
| 54 p.position = math.min(max, p.position); | 56 p.position = math.min(max, p.position); |
| 55 if (p.position == max) | 57 if (p.position == max) |
| 56 p.velocity = math.min(0.0, p.velocity); | 58 p.velocity = math.min(0.0, p.velocity); |
| 57 } | 59 } |
| 58 } | 60 } |
| 59 } | 61 } |
| 60 | 62 |
| 61 class GeofenceBox extends Box { | 63 class GeofenceBox extends Box { |
| 62 final double min; // m | 64 final double min; // m |
| 63 final double max; // m | 65 final double max; // m |
| 64 | 66 |
| 65 final Function onEscape; | 67 final Function onEscape; |
| 66 | 68 |
| 67 GeofenceBox({this.min, this.max, this.onEscape}) { | 69 GeofenceBox({this.min, this.max, this.onEscape}) { |
| 68 assert(min == null || max == null || min <= max); | 70 assert(min == null || max == null || min <= max); |
| 69 assert(onEscape != null); | 71 assert(onEscape != null); |
| 70 } | 72 } |
| 71 | 73 |
| 74 @override |
| 72 void confine(Particle p) { | 75 void confine(Particle p) { |
| 73 if (((min != null) && (p.position < min)) || | 76 if (((min != null) && (p.position < min)) || |
| 74 ((max != null) && (p.position > max))) | 77 ((max != null) && (p.position > max))) |
| 75 onEscape(); | 78 onEscape(); |
| 76 } | 79 } |
| 77 } | 80 } |
| 78 | 81 |
| 79 class ParticleInBox extends System { | 82 class ParticleInBox extends System { |
| 80 final Particle particle; | 83 final Particle particle; |
| 81 final Box box; | 84 final Box box; |
| 82 | 85 |
| 83 ParticleInBox({this.particle, this.box}) { | 86 ParticleInBox({this.particle, this.box}) { |
| 84 box.confine(particle); | 87 box.confine(particle); |
| 85 } | 88 } |
| 86 | 89 |
| 90 @override |
| 87 void update(double deltaT) { | 91 void update(double deltaT) { |
| 88 particle.update(deltaT); | 92 particle.update(deltaT); |
| 89 box.confine(particle); | 93 box.confine(particle); |
| 90 } | 94 } |
| 91 } | 95 } |
| 92 | 96 |
| 93 class ParticleInBoxWithFriction extends ParticleInBox { | 97 class ParticleInBoxWithFriction extends ParticleInBox { |
| 94 final double friction; // unitless | 98 final double friction; // unitless |
| 95 final double _sign; | 99 final double _sign; |
| 96 | 100 |
| 97 final Function onStop; | 101 final Function onStop; |
| 98 | 102 |
| 99 ParticleInBoxWithFriction({Particle particle, Box box, this.friction, this.onS
top}) | 103 ParticleInBoxWithFriction({Particle particle, Box box, this.friction, this.onS
top}) |
| 100 : super(particle: particle, box: box), | 104 : super(particle: particle, box: box), |
| 101 _sign = particle.velocity.sign; | 105 _sign = particle.velocity.sign; |
| 102 | 106 |
| 107 @override |
| 103 void update(double deltaT) { | 108 void update(double deltaT) { |
| 104 double force = -_sign * friction * particle.mass * -kGravity; | 109 double force = -_sign * friction * particle.mass * -kGravity; |
| 105 particle.applyImpulse(force * deltaT); | 110 particle.applyImpulse(force * deltaT); |
| 106 if (particle.velocity.sign != _sign) { | 111 if (particle.velocity.sign != _sign) { |
| 107 particle.velocity = 0.0; | 112 particle.velocity = 0.0; |
| 108 } | 113 } |
| 109 super.update(deltaT); | 114 super.update(deltaT); |
| 110 if ((particle.velocity == 0.0) && (onStop != null)) | 115 if ((particle.velocity == 0.0) && (onStop != null)) |
| 111 onStop(); | 116 onStop(); |
| 112 } | 117 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 123 | 128 |
| 124 class ParticleAndSpringInBox extends System { | 129 class ParticleAndSpringInBox extends System { |
| 125 final Particle particle; | 130 final Particle particle; |
| 126 final Spring spring; | 131 final Spring spring; |
| 127 final Box box; | 132 final Box box; |
| 128 | 133 |
| 129 ParticleAndSpringInBox({this.particle, this.spring, this.box}) { | 134 ParticleAndSpringInBox({this.particle, this.spring, this.box}) { |
| 130 _applyInvariants(); | 135 _applyInvariants(); |
| 131 } | 136 } |
| 132 | 137 |
| 138 @override |
| 133 void update(double deltaT) { | 139 void update(double deltaT) { |
| 134 particle.applyImpulse(spring.force * deltaT); | 140 particle.applyImpulse(spring.force * deltaT); |
| 135 particle.update(deltaT); | 141 particle.update(deltaT); |
| 136 _applyInvariants(); | 142 _applyInvariants(); |
| 137 } | 143 } |
| 138 | 144 |
| 139 void _applyInvariants() { | 145 void _applyInvariants() { |
| 140 box.confine(particle); | 146 box.confine(particle); |
| 141 spring.displacement = particle.position; | 147 spring.displacement = particle.position; |
| 142 } | 148 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 // potential energy at the top of the slope, which is g*h*m. | 180 // potential energy at the top of the slope, which is g*h*m. |
| 175 // If the slope's horizontal component is delta P long, then | 181 // If the slope's horizontal component is delta P long, then |
| 176 // the height is delta P times tan theta. | 182 // the height is delta P times tan theta. |
| 177 particle.setVelocityFromEnergy( | 183 particle.setVelocityFromEnergy( |
| 178 energy: (kGravity * (deltaPosition * tanTheta) * particle.mass).abs(), | 184 energy: (kGravity * (deltaPosition * tanTheta) * particle.mass).abs(), |
| 179 direction: deltaPosition > 0.0 ? 1.0 : -1.0 | 185 direction: deltaPosition > 0.0 ? 1.0 : -1.0 |
| 180 ); | 186 ); |
| 181 box.confine(particle); | 187 box.confine(particle); |
| 182 } | 188 } |
| 183 | 189 |
| 190 @override |
| 184 void update(double deltaT) { | 191 void update(double deltaT) { |
| 185 particle.update(deltaT); | 192 particle.update(deltaT); |
| 186 // Note that we apply the impulse from gravity after updating the particle's | 193 // Note that we apply the impulse from gravity after updating the particle's |
| 187 // position so that we overestimate the distance traveled by the particle. | 194 // position so that we overestimate the distance traveled by the particle. |
| 188 // That ensures that we actually hit the edge of the box and don't wind up | 195 // That ensures that we actually hit the edge of the box and don't wind up |
| 189 // reversing course. | 196 // reversing course. |
| 190 particle.applyImpulse(particle.mass * kGravity * _sinTheta * deltaT); | 197 particle.applyImpulse(particle.mass * kGravity * _sinTheta * deltaT); |
| 191 box.confine(particle); | 198 box.confine(particle); |
| 192 } | 199 } |
| 193 } | 200 } |
| 194 | 201 |
| 195 class Multisystem extends System { | 202 class Multisystem extends System { |
| 196 final Particle particle; | 203 final Particle particle; |
| 197 | 204 |
| 198 System _currentSystem; | 205 System _currentSystem; |
| 199 | 206 |
| 200 Multisystem({ this.particle, System system }) { | 207 Multisystem({ this.particle, System system }) { |
| 201 assert(system != null); | 208 assert(system != null); |
| 202 _currentSystem = system; | 209 _currentSystem = system; |
| 203 } | 210 } |
| 204 | 211 |
| 212 @override |
| 205 void update(double deltaT) { | 213 void update(double deltaT) { |
| 206 _currentSystem.update(deltaT); | 214 _currentSystem.update(deltaT); |
| 207 } | 215 } |
| 208 | 216 |
| 209 void transitionToSystem(System system) { | 217 void transitionToSystem(System system) { |
| 210 assert(system != null); | 218 assert(system != null); |
| 211 _currentSystem = system; | 219 _currentSystem = system; |
| 212 } | 220 } |
| 213 } | 221 } |
| OLD | NEW |