nx_body_anchors.nx source
↩ module page · 292 lines · 13032 B
1// nx_body_anchors.nx -- per-body anchor-feature data (Olympus Mons,
2// Hellas Basin, Caloris Basin, Maxwell Montes, Mt Everest, etc.).
3//
4// The "Olympus Mons pops out" data layer. Composes:
5// - nx_solar_system_catalog (body ids, body kinds)
6// - nx_anchor_feature (shape functions for DOME/BASIN/RIDGE)
7//
8// Reads per-body anchor lists and sums their height contributions at
9// any (px, py) query point. Consumed by per-body surface generators
10// (nx_terrestrial_surface in nishi-engine/nx) which add the anchor
11// sum to base FBM noise to produce signature landmarks.
12//
13// V1 ships anchors for the 4 terrestrial planets only. Future
14// slices extend to moons (Tycho crater on Luna; Pavonis on Mars
15// already in Mars list; Mons Huygens on Luna), dwarf planets, etc.
16//
17// Coordinate convention: world coords in arbitrary Q14 units. V1
18// uses "flat-projected metres at body-scale" -- a body's surface is
19// modelled as a 2D plane in Q14 metres. V2 will project from
20// (latitude, longitude) onto the sphere using nx_camera_q14 sin/cos.
21//
22// Anchor record layout (6 i64 per anchor; matches nx_anchor_feature
23// dispatch signature):
24// out[0] = kind (NX_ANCHOR_*)
25// out[1] = cx_q14 (world x of feature centre)
26// out[2] = cy_q14
27// out[3] = scale_q14 (characteristic radius / length)
28// out[4] = magnitude_q14_m (peak height or depression depth)
29// out[5] = orient (NX_ANCHOR_ORIENT_*; ignored for radial kinds)
30//
31// Real-world reference values from NASA JPL / USGS / Wikipedia
32// planetary topography. Per cardinal feedback-no-third-party-trust:
33// numbers absorbed from public-domain scientific data (NASA / USGS
34// are US federal civil-service work, TIER_0_UNENCUMBERED).
35//
36// genealogy_id: nasa_mars_global_surveyor_topography +
37// nasa_messenger_mercury_topography +
38// magellan_venus_radar_topography +
39// usgs_earth_dem_canon
40// lineage_id: nx_body_anchors_flat_q14_v1
41//
42// license_tier: INDEPENDENT_REDERIVE
43// genealogy_id: international-research-sources/nasa_contractor/holzmann_2006_power_of_10
44//
45
46// nx_safety_envelope:
47// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
48// sil_target: SIL1
49// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
50// verdict: NOT_YET_EVALUATED
51
52import "nx_syscalls.nx"
53import "nx_tier.nx"
54import "nx_solar_system_catalog.nx"
55import "nx_anchor_feature.nx"
56const NX_MAGIC_5000: i64 = 5000
57const NX_MAGIC_1550: i64 = 1550
58const NX_MAGIC_4000: i64 = 4000
59const NX_MAGIC_3000: i64 = 3000
60const NX_MAGIC_11000: i64 = 11000
61const NX_MAGIC_2500: i64 = 2500
62const NX_MAGIC_3500: i64 = 3500
63const NX_MAGIC_8849: i64 = 8849
64const NX_MAGIC_2400: i64 = 2400
65const NX_MAGIC_6000: i64 = 6000
66const NX_MAGIC_1800: i64 = 1800
67const NX_MAGIC_22000: i64 = 22000
68const NX_MAGIC_4500: i64 = 4500
69const NX_MAGIC_1500: i64 = 1500
70const NX_MAGIC_1150: i64 = 1150
71const NX_MAGIC_7000: i64 = 7000
72const NX_MAGIC_20000: i64 = 20000
73const NX_MAGIC_16000: i64 = 16000
74
75// ===== Q14 ==========================================================
76const NX_BA_Q: nx_int = 16384
77
78// Anchor record stride.
79const NX_BA_STRIDE: nx_int = 6
80
81// Field offsets.
82const NX_BA_OFF_KIND: nx_int = 0
83const NX_BA_OFF_CX: nx_int = 1
84const NX_BA_OFF_CY: nx_int = 2
85const NX_BA_OFF_SCALE: nx_int = 3
86const NX_BA_OFF_MAGNITUDE: nx_int = 4
87const NX_BA_OFF_ORIENT: nx_int = 5
88
89// ===== Anchor-list counts per body =================================
90// Returns 0 for any body without an anchor list yet (the queued ones
91// stay at 0 until their data ships).
92func nx_body_anchor_count(body_id: nx_int) -> nx_int {
93 if body_id == NX_BODY_MERCURY { return 1 } // Caloris Basin
94 if body_id == NX_BODY_VENUS { return 1 } // Maxwell Montes
95 if body_id == NX_BODY_EARTH { return 2 } // Everest + Himalayan ridge
96 if body_id == NX_BODY_MARS { return 2 } // Olympus Mons + Hellas Basin
97 return 0
98}
99
100// ===== Per-body anchor accessor ====================================
101// Writes the n-th anchor's 6-field record into out (6 i64). Reads
102// out-of-range entries as all-zero (caller pre-checks via
103// nx_body_anchor_count).
104func nx_body_anchor_at(body_id: nx_int, n: nx_int, out: *i64) {
105 let q: nx_int = NX_BA_Q
106
107 // Zero-init for any out-of-list query.
108 out[NX_BA_OFF_KIND] = 0
109 out[NX_BA_OFF_CX] = 0
110 out[NX_BA_OFF_CY] = 0
111 out[NX_BA_OFF_SCALE] = 0
112 out[NX_BA_OFF_MAGNITUDE] = 0
113 out[NX_BA_OFF_ORIENT] = 0
114
115 // Mercury -- Caloris Basin (1550 km diameter impact basin near
116 // 30 N, 162 W on real Mercury; ~ 4 km below datum). V1 places
117 // it at a flat (5000, 5000) km-projected coords.
118 if body_id == NX_BODY_MERCURY {
119 if n == 0 {
120 out[NX_BA_OFF_KIND] = NX_ANCHOR_IMPACT_BASIN
121 out[NX_BA_OFF_CX] = NX_MAGIC_5000 * q
122 out[NX_BA_OFF_CY] = NX_MAGIC_5000 * q
123 out[NX_BA_OFF_SCALE] = NX_MAGIC_1550 * q
124 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_4000
125 out[NX_BA_OFF_ORIENT] = 0
126 }
127 return
128 }
129
130 // Venus -- Maxwell Montes (highest peak on Venus, 11 km above
131 // datum, ~ 65 N 0 E on real Venus, part of Ishtar Terra).
132 if body_id == NX_BODY_VENUS {
133 if n == 0 {
134 out[NX_BA_OFF_KIND] = NX_ANCHOR_VOLCANIC_DOME
135 out[NX_BA_OFF_CX] = NX_MAGIC_3000 * q
136 out[NX_BA_OFF_CY] = NX_MAGIC_4000 * q
137 out[NX_BA_OFF_SCALE] = 350 * q
138 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_11000
139 out[NX_BA_OFF_ORIENT] = 0
140 }
141 return
142 }
143
144 // Earth -- Everest (8849 m volcanic-dome approximation) + the
145 // wider Himalayan ridge (8000 m linear, ~ 2500 km long).
146 if body_id == NX_BODY_EARTH {
147 if n == 0 {
148 // Everest: single peak.
149 out[NX_BA_OFF_KIND] = NX_ANCHOR_VOLCANIC_DOME
150 out[NX_BA_OFF_CX] = NX_MAGIC_2500 * q
151 out[NX_BA_OFF_CY] = NX_MAGIC_3500 * q
152 out[NX_BA_OFF_SCALE] = 80 * q
153 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_8849
154 out[NX_BA_OFF_ORIENT] = 0
155 }
156 if n == 1 {
157 // Himalayan ridge: E-W oriented.
158 out[NX_BA_OFF_KIND] = NX_ANCHOR_RIDGE
159 out[NX_BA_OFF_CX] = NX_MAGIC_2400 * q
160 out[NX_BA_OFF_CY] = NX_MAGIC_3500 * q
161 out[NX_BA_OFF_SCALE] = NX_MAGIC_2500 * q
162 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_6000
163 out[NX_BA_OFF_ORIENT] = NX_ANCHOR_ORIENT_EW
164 }
165 return
166 }
167
168 // Mars -- Olympus Mons (largest known volcano in solar system,
169 // 22 km tall shield, ~ 300 km radius, at 18 N 226 E on real Mars)
170 // + Hellas Planitia (largest visible impact basin in solar
171 // system, 2300 km across, 7 km below datum, at 43 S 70 E).
172 if body_id == NX_BODY_MARS {
173 if n == 0 {
174 out[NX_BA_OFF_KIND] = NX_ANCHOR_VOLCANIC_DOME
175 out[NX_BA_OFF_CX] = NX_MAGIC_1800 * q
176 out[NX_BA_OFF_CY] = NX_MAGIC_4000 * q
177 out[NX_BA_OFF_SCALE] = 300 * q
178 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_22000
179 out[NX_BA_OFF_ORIENT] = 0
180 }
181 if n == 1 {
182 out[NX_BA_OFF_KIND] = NX_ANCHOR_IMPACT_BASIN
183 out[NX_BA_OFF_CX] = NX_MAGIC_4500 * q
184 out[NX_BA_OFF_CY] = NX_MAGIC_1500 * q
185 out[NX_BA_OFF_SCALE] = NX_MAGIC_1150 * q
186 out[NX_BA_OFF_MAGNITUDE] = NX_MAGIC_7000
187 out[NX_BA_OFF_ORIENT] = 0
188 }
189 return
190 }
191}
192
193// ===== Sum contribution at a query point ===========================
194// Iterates body's anchor list, sums each anchor's height contribution
195// at (px, py). Used by surface generators that need the "Olympus
196// Mons pops out" addition on top of base FBM.
197func nx_body_anchor_sum_contribution(
198 body_id: nx_int,
199 px_q14: nx_int,
200 py_q14: nx_int
201) -> nx_int {
202 let n: nx_int = nx_body_anchor_count(body_id)
203 if n <= 0 { return 0 }
204
205 let rec: *i64 = (sys_mmap(NX_BA_STRIDE * NX_SIZEOF_NX_INT)) as *i64
206 var sum: nx_int = 0
207 var i: nx_int = 0
208 while i < n {
209 nx_body_anchor_at(body_id, i, rec)
210 let contrib: nx_int = nx_anchor_feature_contribution(
211 rec[NX_BA_OFF_KIND],
212 rec[NX_BA_OFF_CX],
213 rec[NX_BA_OFF_CY],
214 px_q14,
215 py_q14,
216 rec[NX_BA_OFF_SCALE],
217 rec[NX_BA_OFF_MAGNITUDE],
218 rec[NX_BA_OFF_ORIENT]
219 )
220 sum = sum + contrib
221 i = i + 1
222 }
223 return sum
224}
225
226// ===== Self-test ====================================================
227func main() -> i64 {
228 let q: nx_int = NX_BA_Q
229
230 // T1: Body anchor counts.
231 if nx_body_anchor_count(NX_BODY_MERCURY) != 1 { return __syscall(93, 1, 0, 0, 0, 0, 0) }
232 if nx_body_anchor_count(NX_BODY_VENUS) != 1 { return __syscall(93, 2, 0, 0, 0, 0, 0) }
233 if nx_body_anchor_count(NX_BODY_EARTH) != 2 { return __syscall(93, 3, 0, 0, 0, 0, 0) }
234 if nx_body_anchor_count(NX_BODY_MARS) != 2 { return __syscall(93, 4, 0, 0, 0, 0, 0) }
235 if nx_body_anchor_count(NX_BODY_SUN) != 0 { return __syscall(93, 5, 0, 0, 0, 0, 0) }
236 if nx_body_anchor_count(NX_BODY_JUPITER) != 0 { return __syscall(93, 6, 0, 0, 0, 0, 0) }
237
238 // T2: Mars anchor 0 is Olympus Mons (DOME, magnitude 22000).
239 let rec: *i64 = (sys_mmap(NX_BA_STRIDE * NX_SIZEOF_NX_INT)) as *i64
240 nx_body_anchor_at(NX_BODY_MARS, 0, rec)
241 if rec[NX_BA_OFF_KIND] != NX_ANCHOR_VOLCANIC_DOME { return __syscall(93, 10, 0, 0, 0, 0, 0) }
242 if rec[NX_BA_OFF_MAGNITUDE] != NX_MAGIC_22000 { return __syscall(93, 11, 0, 0, 0, 0, 0) }
243 if rec[NX_BA_OFF_SCALE] != 300 * q { return __syscall(93, 12, 0, 0, 0, 0, 0) }
244
245 // T3: Mars anchor 1 is Hellas Basin (BASIN, magnitude 7000).
246 nx_body_anchor_at(NX_BODY_MARS, 1, rec)
247 if rec[NX_BA_OFF_KIND] != NX_ANCHOR_IMPACT_BASIN { return __syscall(93, 20, 0, 0, 0, 0, 0) }
248 if rec[NX_BA_OFF_MAGNITUDE] != NX_MAGIC_7000 { return __syscall(93, 21, 0, 0, 0, 0, 0) }
249 if rec[NX_BA_OFF_SCALE] != NX_MAGIC_1150 * q { return __syscall(93, 22, 0, 0, 0, 0, 0) }
250
251 // T4: Earth anchor 0 is Everest (DOME), anchor 1 is Himalayan
252 // ridge (RIDGE, E-W).
253 nx_body_anchor_at(NX_BODY_EARTH, 0, rec)
254 if rec[NX_BA_OFF_KIND] != NX_ANCHOR_VOLCANIC_DOME { return __syscall(93, 30, 0, 0, 0, 0, 0) }
255 if rec[NX_BA_OFF_MAGNITUDE] != NX_MAGIC_8849 { return __syscall(93, 31, 0, 0, 0, 0, 0) }
256 nx_body_anchor_at(NX_BODY_EARTH, 1, rec)
257 if rec[NX_BA_OFF_KIND] != NX_ANCHOR_RIDGE { return __syscall(93, 32, 0, 0, 0, 0, 0) }
258 if rec[NX_BA_OFF_ORIENT] != NX_ANCHOR_ORIENT_EW { return __syscall(93, 33, 0, 0, 0, 0, 0) }
259
260 // T5: Mercury anchor 0 is Caloris Basin.
261 nx_body_anchor_at(NX_BODY_MERCURY, 0, rec)
262 if rec[NX_BA_OFF_KIND] != NX_ANCHOR_IMPACT_BASIN { return __syscall(93, 40, 0, 0, 0, 0, 0) }
263 if rec[NX_BA_OFF_MAGNITUDE] != NX_MAGIC_4000 { return __syscall(93, 41, 0, 0, 0, 0, 0) }
264 if rec[NX_BA_OFF_SCALE] != NX_MAGIC_1550 * q { return __syscall(93, 42, 0, 0, 0, 0, 0) }
265
266 // T6: Sum contribution -- at the exact centre of Olympus Mons
267 // (Mars anchor 0 at (1800q, 4000q)), the contribution = 22000.
268 // No other Mars anchor is within range at that point.
269 let s_olympus: nx_int = nx_body_anchor_sum_contribution(NX_BODY_MARS, NX_MAGIC_1800 * q, NX_MAGIC_4000 * q)
270 if s_olympus != NX_MAGIC_22000 { return __syscall(93, 50, 0, 0, 0, 0, 0) }
271
272 // T7: At Hellas centre (4500q, 1500q): contribution = -7000.
273 let s_hellas: nx_int = nx_body_anchor_sum_contribution(NX_BODY_MARS, NX_MAGIC_4500 * q, NX_MAGIC_1500 * q)
274 if s_hellas != (0 - NX_MAGIC_7000) { return __syscall(93, 60, 0, 0, 0, 0, 0) }
275
276 // T8: Far from any Mars anchor -> 0. Coords very far from both.
277 let s_far: nx_int = nx_body_anchor_sum_contribution(NX_BODY_MARS, NX_MAGIC_20000 * q, NX_MAGIC_20000 * q)
278 if s_far != 0 { return __syscall(93, 70, 0, 0, 0, 0, 0) }
279
280 // T9: Bodies with no anchors return 0 at any coord.
281 if nx_body_anchor_sum_contribution(NX_BODY_SUN, 0, 0) != 0 { return __syscall(93, 80, 0, 0, 0, 0, 0) }
282 if nx_body_anchor_sum_contribution(NX_BODY_JUPITER, 1000, 1000) != 0 { return __syscall(93, 81, 0, 0, 0, 0, 0) }
283
284 // T10: Earth at Everest centre -> 8849 (Everest only; Himalayan
285 // ridge is also nearby and may contribute). Verify >= 8849 and
286 // not significantly more than 8849 + 6000 = 14849.
287 let s_everest: nx_int = nx_body_anchor_sum_contribution(NX_BODY_EARTH, NX_MAGIC_2500 * q, NX_MAGIC_3500 * q)
288 if s_everest < NX_MAGIC_8849 { return __syscall(93, 90, 0, 0, 0, 0, 0) }
289 if s_everest > NX_MAGIC_16000 { return __syscall(93, 91, 0, 0, 0, 0, 0) }
290
291 return 0
292}