fuzzyworld

tower / cascadia / files / src / canon / motion.ts

Branch cascadia · default branch · all branches

motion.ts

2.8 KB · history · blame

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 */
14import { G0, OMEGA_RAD_S } from './constants.js'
15
16/** Terminal velocity of an ordinary raindrop, m/s. */
17export 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 */
26export 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. */
30export 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 */
36export 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 */
44export 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 */
60export const freeFallLeanRad = (heightM: number): number =>
61 Math.atan(OMEGA_RAD_S * freeFallTimeS(heightM))