@essrt/physics 13.0.0 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,142 +0,0 @@
1
- /**
2
- * Planet orientation channel — THE shared implementation (Phase 8.3, L4):
3
- * invariable-plane inclination, ascending nodes, and the scene ecliptic
4
- * inclination (the balanced-year dot-product form canonicalized at S-P4).
5
- *
6
- * Time is EXPLICIT here (yearsSinceBalanced / calendar year). A finding
7
- * from extraction, preserved not fixed: the browser's
8
- * computePlanetInvPlaneInclinationDynamic(planet, currentYear) IGNORED its
9
- * currentYear parameter and read the live scene JD — the 8.3-0 fixtures
10
- * recorded identical values at every probed epoch. The browser wrapper
11
- * keeps that scene-coupling (visibly, at the wrapper); the Node engine
12
- * honors the year as before. Unifying them is a measured decision for the
13
- * factory layer, not a silent side effect.
14
- *
15
- * Two ascending-node conventions exist and BOTH are quantities (the S-P4
16
- * lesson): the year-2000-anchored linear node here
17
- * (ascendingNodeInvPlaneLinearAt — the node-integrator mirror)
18
- * and the balanced-year −8H/N node inside the scene tilt
19
- * (eclipticInclinationFromBalanced). Do not merge them.
20
- *
21
- * SCOPE SINCE v16.2 (owner-found audit): these record-based forms — the
22
- * planet record's linear lattice rates, the −8H/N node period, the
23
- * balanced-year inclination oscillation — are the RETIRED device. They serve
24
- * the structural record and the browser's no-chain bodies (Pluto, Halley,
25
- * Eros) only. The seven planets' elements of date on every published surface
26
- * (the simulator, the API's /v1/bodies, the MCP essrt_bodies) ride the N-body
27
- * Keplerian chain with the series handover (model.js planetChainElementsAt;
28
- * src/script.js _kcElementsOfDate).
29
- */
30
-
31
- 'use strict';
32
-
33
- /**
34
- * Invariable-plane inclination at explicit time (browser form): the ICRF
35
- * perihelion-linked oscillation i(t) = mean + s·A·cos(ϖ_ICRF(t) − anchor).
36
- * @param {{ key?: string, isEarth?: boolean,
37
- * invPlaneInclinationJ2000: number, invPlaneInclinationMean: number,
38
- * invPlaneInclinationAmplitude: number, inclinationCycleAnchor: number,
39
- * longitudePerihelion: number, perihelionEclipticYears: number,
40
- * antiPhase?: boolean }} body
41
- * @param {number} yearsSinceBalanced
42
- * @param {{ H: number, yearsFromBalancedToJ2000: number }} env
43
- * @returns {number} degrees */
44
- function invPlaneInclinationAt(body, yearsSinceBalanced, env) {
45
- const iJ2000 = body.invPlaneInclinationJ2000;
46
- const amplitude = body.invPlaneInclinationAmplitude;
47
- if (iJ2000 === undefined || amplitude === undefined) return iJ2000 || 0;
48
- if (amplitude === 0) return iJ2000;
49
-
50
- // ICRF period: Earth = H/3 directly; others = 1/(1/eclP − 1/(H/13)).
51
- const genPrecRate = 1 / (env.H / 13);
52
- const icrfPeriod = body.isEarth
53
- ? env.H / 3
54
- : 1 / (1 / body.perihelionEclipticYears - genPrecRate);
55
- const icrfRate = 360 / icrfPeriod;
56
-
57
- const periAtBalanced = body.longitudePerihelion - icrfRate * env.yearsFromBalancedToJ2000;
58
- const periCurrent = periAtBalanced + icrfRate * yearsSinceBalanced;
59
- const currentPhaseRad = (periCurrent - body.inclinationCycleAnchor) * Math.PI / 180;
60
- const antiPhaseSign = body.antiPhase ? -1 : 1;
61
- return body.invPlaneInclinationMean + antiPhaseSign * amplitude * Math.cos(currentPhaseRad);
62
- }
63
-
64
- /**
65
- * Ascending node on the invariable plane — the LINEAR year-2000-anchored
66
- * convention (node-integrator; see the header).
67
- * @param {{ ascendingNodeInvPlane?: number, ascendingNodePeriod?: number,
68
- * perihelionEclipticYears: number }} body
69
- * @param {number} year @returns {number} degrees 0–360 */
70
- function ascendingNodeInvPlaneLinearAt(body, year) {
71
- if (!body.ascendingNodeInvPlane) return 0;
72
- const period = body.ascendingNodePeriod || body.perihelionEclipticYears;
73
- const rate = 360 / period;
74
- return ((body.ascendingNodeInvPlane + rate * (year - 2000)) % 360 + 360) % 360;
75
- }
76
-
77
- /**
78
- * Scene ecliptic inclination — normal-vector dot product, balanced-year
79
- * anchoring, planet Ω on the −8H/N assignment (canonicalized at S-P4; the
80
- * mirror of src/script.js updateDynamicInclinations).
81
- * @param {{ perihelionEclipticYears: number, longitudePerihelion: number,
82
- * inclinationCycleAnchor: number, antiPhase?: boolean,
83
- * invPlaneInclinationMean: number, invPlaneInclinationAmplitude: number,
84
- * ascendingNodeInvPlane: number, ascendingNodeCyclesIn8H?: number }} body
85
- * @param {{ invPlanePrecessionYears: number, inclinationMean: number,
86
- * inclinationAmplitude: number, ascendingNodeInvPlane: number }} earth
87
- * @param {number} yearsSinceBalanced
88
- * @param {{ H: number, yearsFromBalancedToJ2000: number }} env
89
- * @returns {number} degrees */
90
- function eclipticInclinationFromBalanced(body, earth, yearsSinceBalanced, env) {
91
- const d2r = Math.PI / 180;
92
- const genPrecRate = 1 / (env.H / 13);
93
-
94
- // --- Earth's orbital plane ---
95
- const earthPhaseRad = (yearsSinceBalanced / earth.invPlanePrecessionYears) * 2 * Math.PI;
96
- const earthI = (earth.inclinationMean
97
- - earth.inclinationAmplitude * Math.cos(earthPhaseRad)) * d2r;
98
-
99
- // Earth Ω regresses at -H/5 (ecliptic precession rate), NOT at H/3.
100
- const earthAscNodePeriod = -env.H / 5;
101
- const earthOmegaRate = 360 / earthAscNodePeriod;
102
- const earthOmega = (earth.ascendingNodeInvPlane
103
- - earthOmegaRate * env.yearsFromBalancedToJ2000
104
- + earthOmegaRate * yearsSinceBalanced) * d2r;
105
-
106
- // --- Planet's orbital plane ---
107
- const eclRate = 1 / body.perihelionEclipticYears;
108
- const icrfRate = (eclRate - genPrecRate) * 360; // deg/yr
109
- const periICRFDeg = body.longitudePerihelion
110
- - icrfRate * env.yearsFromBalancedToJ2000
111
- + icrfRate * yearsSinceBalanced;
112
-
113
- const planetPhaseDeg = periICRFDeg - body.inclinationCycleAnchor;
114
- const antiPhaseSign = body.antiPhase ? -1 : 1;
115
- const planetI = (body.invPlaneInclinationMean
116
- + antiPhaseSign * body.invPlaneInclinationAmplitude * Math.cos(planetPhaseDeg * d2r)) * d2r;
117
-
118
- // Planet Ω advances at the asc-node period (-8H/N), NOT the ecliptic
119
- // perihelion period — they are different angles.
120
- const planetAscNodePeriod = body.ascendingNodeCyclesIn8H
121
- ? -(8 * env.H) / body.ascendingNodeCyclesIn8H
122
- : body.perihelionEclipticYears;
123
- const planetOmegaRate = 360 / planetAscNodePeriod;
124
- const planetOmegaDeg = body.ascendingNodeInvPlane
125
- - planetOmegaRate * env.yearsFromBalancedToJ2000
126
- + planetOmegaRate * yearsSinceBalanced;
127
- const planetOmega = planetOmegaDeg * d2r;
128
-
129
- // --- Dot product of normal vectors → angle between orbital planes ---
130
- const eNx = Math.sin(earthI) * Math.sin(earthOmega);
131
- const eNy = Math.sin(earthI) * Math.cos(earthOmega);
132
- const eNz = Math.cos(earthI);
133
-
134
- const pNx = Math.sin(planetI) * Math.sin(planetOmega);
135
- const pNy = Math.sin(planetI) * Math.cos(planetOmega);
136
- const pNz = Math.cos(planetI);
137
-
138
- const cosAngle = eNx * pNx + eNy * pNy + eNz * pNz;
139
- return Math.acos(Math.max(-1, Math.min(1, cosAngle))) * (180 / Math.PI);
140
- }
141
-
142
- module.exports = { invPlaneInclinationAt, ascendingNodeInvPlaneLinearAt, eclipticInclinationFromBalanced };
@@ -1,30 +0,0 @@
1
- /**
2
- * @param {{ ascendingNodeDeg: number, inclinationDeg: number }} tilt —
3
- * static node and inclination (engine-decomposed from its scene scheme)
4
- * @param {number} currentYear
5
- * @param {{
6
- * obliquityAt: (year: number) => number,
7
- * earthInclinationAt: (year: number) => number,
8
- * obliquityExtremaInRange: (yearMin: number, yearMax: number) => number[],
9
- * inclinationCrossingsInRange: (inclinationDeg: number, yearMin: number, yearMax: number) => number[],
10
- * eclipticInclinationAt: ((year: number) => number) | null,
11
- * earthInclinationMeanDeg: number,
12
- * earthInclinationAmplitudeDeg: number,
13
- * epochYear?: number,
14
- * }} deps — eclipticInclinationAt non-null enables the dynamic-inclination
15
- * crossover search and per-segment rates (the planetName path).
16
- * @returns {number} dynamic ascending node longitude, degrees 0–360
17
- */
18
- export function integrateAscendingNode(tilt: {
19
- ascendingNodeDeg: number;
20
- inclinationDeg: number;
21
- }, currentYear: number, deps: {
22
- obliquityAt: (year: number) => number;
23
- earthInclinationAt: (year: number) => number;
24
- obliquityExtremaInRange: (yearMin: number, yearMax: number) => number[];
25
- inclinationCrossingsInRange: (inclinationDeg: number, yearMin: number, yearMax: number) => number[];
26
- eclipticInclinationAt: ((year: number) => number) | null;
27
- earthInclinationMeanDeg: number;
28
- earthInclinationAmplitudeDeg: number;
29
- epochYear?: number;
30
- }): number;
@@ -1,27 +0,0 @@
1
- /**
2
- * ψ constant from Earth's calibration. @param {{
3
- * earthInvPlaneInclinationAmplitude: number,
4
- * massEarthAlone: number, massSun: number }} c @returns {number} */
5
- export function computePsiConstant(c: {
6
- earthInvPlaneInclinationAmplitude: number;
7
- massEarthAlone: number;
8
- massSun: number;
9
- }): number;
10
- /**
11
- * ψ law: invariable-plane inclination amplitude and mean.
12
- * @param {{ fibonacciD: number, massFrac: number,
13
- * invPlaneInclinationJ2000: number, longitudePerihelion: number,
14
- * inclinationCycleAnchor: number, antiPhase: boolean }} b
15
- * @param {number} psiConstant
16
- * @returns {{ amplitude: number, mean: number }} */
17
- export function computeInclinationLaw(b: {
18
- fibonacciD: number;
19
- massFrac: number;
20
- invPlaneInclinationJ2000: number;
21
- longitudePerihelion: number;
22
- inclinationCycleAnchor: number;
23
- antiPhase: boolean;
24
- }, psiConstant: number): {
25
- amplitude: number;
26
- mean: number;
27
- };
@@ -1,67 +0,0 @@
1
- /**
2
- * Invariable-plane inclination at explicit time (browser form): the ICRF
3
- * perihelion-linked oscillation i(t) = mean + s·A·cos(ϖ_ICRF(t) − anchor).
4
- * @param {{ key?: string, isEarth?: boolean,
5
- * invPlaneInclinationJ2000: number, invPlaneInclinationMean: number,
6
- * invPlaneInclinationAmplitude: number, inclinationCycleAnchor: number,
7
- * longitudePerihelion: number, perihelionEclipticYears: number,
8
- * antiPhase?: boolean }} body
9
- * @param {number} yearsSinceBalanced
10
- * @param {{ H: number, yearsFromBalancedToJ2000: number }} env
11
- * @returns {number} degrees */
12
- export function invPlaneInclinationAt(body: {
13
- key?: string;
14
- isEarth?: boolean;
15
- invPlaneInclinationJ2000: number;
16
- invPlaneInclinationMean: number;
17
- invPlaneInclinationAmplitude: number;
18
- inclinationCycleAnchor: number;
19
- longitudePerihelion: number;
20
- perihelionEclipticYears: number;
21
- antiPhase?: boolean;
22
- }, yearsSinceBalanced: number, env: {
23
- H: number;
24
- yearsFromBalancedToJ2000: number;
25
- }): number;
26
- /**
27
- * Ascending node on the invariable plane — the LINEAR year-2000-anchored
28
- * convention (node-integrator; see the header).
29
- * @param {{ ascendingNodeInvPlane?: number, ascendingNodePeriod?: number,
30
- * perihelionEclipticYears: number }} body
31
- * @param {number} year @returns {number} degrees 0–360 */
32
- export function ascendingNodeInvPlaneLinearAt(body: {
33
- ascendingNodeInvPlane?: number;
34
- ascendingNodePeriod?: number;
35
- perihelionEclipticYears: number;
36
- }, year: number): number;
37
- /**
38
- * Scene ecliptic inclination — normal-vector dot product, balanced-year
39
- * anchoring, planet Ω on the −8H/N assignment (canonicalized at S-P4; the
40
- * mirror of src/script.js updateDynamicInclinations).
41
- * @param {{ perihelionEclipticYears: number, longitudePerihelion: number,
42
- * inclinationCycleAnchor: number, antiPhase?: boolean,
43
- * invPlaneInclinationMean: number, invPlaneInclinationAmplitude: number,
44
- * ascendingNodeInvPlane: number, ascendingNodeCyclesIn8H?: number }} body
45
- * @param {{ invPlanePrecessionYears: number, inclinationMean: number,
46
- * inclinationAmplitude: number, ascendingNodeInvPlane: number }} earth
47
- * @param {number} yearsSinceBalanced
48
- * @param {{ H: number, yearsFromBalancedToJ2000: number }} env
49
- * @returns {number} degrees */
50
- export function eclipticInclinationFromBalanced(body: {
51
- perihelionEclipticYears: number;
52
- longitudePerihelion: number;
53
- inclinationCycleAnchor: number;
54
- antiPhase?: boolean;
55
- invPlaneInclinationMean: number;
56
- invPlaneInclinationAmplitude: number;
57
- ascendingNodeInvPlane: number;
58
- ascendingNodeCyclesIn8H?: number;
59
- }, earth: {
60
- invPlanePrecessionYears: number;
61
- inclinationMean: number;
62
- inclinationAmplitude: number;
63
- ascendingNodeInvPlane: number;
64
- }, yearsSinceBalanced: number, env: {
65
- H: number;
66
- yearsFromBalancedToJ2000: number;
67
- }): number;