code wiki / (root) / nx_body_anchors.nx

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}