tower / cascadia / files / src / canon / motion.ts
Branch cascadia · default branch · all branches
motion.ts
| 1 | /** |
| 2 | * How things fall in Tower's rotating frame. See design.md §1.9.2. |
| 3 | * |
| 4 | * Coriolis never pushes surface water sideways (§1.9.1), so the spin is invisible |
| 5 | * in every static thing. The hull is sealed, so there are no stars to wheel |
| 6 | * overhead either. That leaves what falls as the only evidence in the sky that |
| 7 | * Tower turns at all, which makes these two angles load-bearing for the interior |
| 8 | * view rather than decoration. |
| 9 | * |
| 10 | * Constant-g plus Coriolis is the standard approximation and is what these use. |
| 11 | * It is exact only for drops small against the radius: gravity is 2% weaker 1 km |
| 12 | * up, and the true inertial-frame path is a straight line, not a parabola. |
| 13 | */ |
| 14 | import { G0, OMEGA_RAD_S } from './constants.js' |
| 15 | |
| 16 | /** Terminal velocity of an ordinary raindrop, m/s. */ |
| 17 | export const RAINDROP_TERMINAL_M_S = 9 |
| 18 | |
| 19 | /** |
| 20 | * Lean of something already falling at a steady speed, in radians, antispinward. |
| 21 | * |
| 22 | * Coriolis gives 2ωv antispinward against g outward, and at terminal velocity drag |
| 23 | * holds both constant — so rain leans by a *fixed* angle rather than curving. That |
| 24 | * angle is small: 1.5° for an ordinary raindrop. Rain is a poor compass here. |
| 25 | */ |
| 26 | export const steadyFallLeanRad = (speedMS: number): number => |
| 27 | Math.atan((2 * OMEGA_RAD_S * speedMS) / G0) |
| 28 | |
| 29 | /** Time for something dropped from `heightM` to reach the floor. */ |
| 30 | export const freeFallTimeS = (heightM: number): number => Math.sqrt((2 * heightM) / G0) |
| 31 | |
| 32 | /** |
| 33 | * Antispinward drift of something in free fall from `heightM`. Integrating the |
| 34 | * Coriolis acceleration 2ω(gt) twice gives ωgt³/3. |
| 35 | */ |
| 36 | export const freeFallDriftM = (heightM: number): number => |
| 37 | (OMEGA_RAD_S * G0 * freeFallTimeS(heightM) ** 3) / 3 |
| 38 | |
| 39 | /** |
| 40 | * Lean of the *path* of a free fall from `heightM` — where it lands, against how |
| 41 | * far it dropped. This is the tilt of a waterfall's plume seen whole, and it is |
| 42 | * the column design.md §1.9.2 tabulates: 7.6° over a kilometre. |
| 43 | */ |
| 44 | export const freeFallPathLeanRad = (heightM: number): number => |
| 45 | Math.atan(freeFallDriftM(heightM) / heightM) |
| 46 | |
| 47 | /** |
| 48 | * Lean of the *velocity* at the bottom of the same fall — the direction a streak |
| 49 | * of it is moving as it arrives, and so the angle rain and spray are drawn at. |
| 50 | * |
| 51 | * It reduces to atan(ωt), independent of g, and it is exactly half again the path |
| 52 | * lean in tangent: the drift integrates to ωgt³/3 over a drop of gt²/2, giving |
| 53 | * (2/3)ωt, while the sideways speed reaches ωgt² against a fall speed of gt. |
| 54 | * Both numbers are real and they describe different things, which is why |
| 55 | * §1.9.2 says 7.6° for a kilometre drop and the interior view's readout says 11.3°. |
| 56 | * |
| 57 | * Unlike rain this keeps growing with the drop, so a tall waterfall *is* a compass |
| 58 | * where a shower is not. |
| 59 | */ |
| 60 | export const freeFallLeanRad = (heightM: number): number => |
| 61 | Math.atan(OMEGA_RAD_S * freeFallTimeS(heightM)) |