code wiki / _hdl_build / nx_biotwin_morpho.nx

nx_biotwin_morpho.nx source

↩ module page · 255 lines · 10179 B

1// nx_biotwin_morpho.nx -- BIOTWIN rung-1 LIBRARY: the MORPHOMETRIC-DERIVATION engine (board axis 8, COU-1). 2// 3// The biotwin board's computed gap_queue ranks morphometric-derivation #1 (it blocks 4 QOIs). This is the 4// DERIVATION TRANSFORM: geometry -> numbers. It COMPOSES with the visualise-body substrate (nx_bodyatlas 5// ba_sdf -- the same sovereign integer SDF being that the Gx north star ships and that QOI[0] visualise- 6// own-body scores 833 on) and does NOT duplicate it. From the SDF it extracts geometric landmarks, then 7// derives standard anthropometric morphometric axes -- and CARRIES PROVENANCE ON EVERY AXIS (which input 8// landmarks, which transform, the input measurement resolution). Integer/fixed-point only (the no-float 9// doctrine holds for derivation; the FEM/UQ float collision is a SEPARATE, still-unratified question). 10// 11// RULER (not ours): the banked anthropometric canon in knowledge/anthropometry_banked.txt -- 7.5-heads, 12// leg/stature, arm/stature, shoulder/hip, fingertip-drop. The same external canon nx_anthro_gate grades 13// the being against; this engine turns that gate's ad-hoc measurements into first-class, provenanced axes. 14// 15// THE FENCE (rule-26 never-brick applied to bodies): bm_fence_blocked() carries a PERMANENT PLANTED LIE -- 16// a caller claim that a morphometric measurement is "genomic/clinical ready" -- and a CLAMP that forces it 17// back to measurement-only every run. A morphometric MEASUREMENT can never be silently promoted to a 18// clinical or genomic CLAIM: fence_blocked>=1 proves the clamp fires, mechanically, on every invocation. 19// This composes with the board's axis-21 fence; it does not replace it. 20// 21// license_tier: ORIGINAL 22import "nx_syscalls.nx" 23import "nx_bodyatlas.nx" 24const N_MAGIC_100000: i64 = 100000 25const N_MAGIC_1200: i64 = 1200 26const N_MAGIC_99999: i64 = 99999 27const N_MAGIC_1469598103: i64 = 1469598103 28 29// ---- landmark slot layout (all in SDF units; y is vertical, +up) ---- 30const N_LM: i64 = 8 31const LM_CROWN: i64 = 0 32const LM_SOLE: i64 = 1 33const LM_CHIN: i64 = 2 34const LM_CROTCH: i64 = 3 35const LM_SHW: i64 = 4 36const LM_HIPW: i64 = 5 37const LM_ACRO: i64 = 6 38const LM_FTIP: i64 = 7 39 40// ---- derived-axis table layout: N_AX axes x AX_STRIDE i64 slots ---- 41const N_AX: i64 = 5 42const AX_STRIDE: i64 = 7 43const AX_VAL: i64 = 0 // derived value (fixed-point per axis) 44const AX_LO: i64 = 1 // canon band low (banked) 45const AX_HI: i64 = 2 // canon band high (banked) 46const AX_RES: i64 = 3 // coarsest input landmark resolution (+- SDF units) 47const AX_NM: i64 = 4 // axis name (str ptr as i64) 48const AX_TF: i64 = 5 // transform formula (str ptr as i64) 49const AX_IN: i64 = 6 // input landmarks (str ptr as i64) 50 51const N_PROMO: i64 = 3 // promotion-fence claim slots 52const NECK_RATIO_PCT: i64 = 60 // chin/neck = where head width collapses below this fraction of head max width 53 54// ===== landmark scanners (composed with the substrate SDF; proven by nx_anthro_gate) ===== 55func mo_scan_down(x: i64, z: i64, yhi: i64, ylo: i64) -> i64 { 56 var y: i64 = yhi 57 while y >= ylo { 58 if ba_sdf(x, y, z, 1) < 0 { return y } 59 y = y - 2 60 } 61 return 0-N_MAGIC_100000 62} 63func mo_scan_up(x: i64, z: i64, ylo: i64, yhi: i64) -> i64 { 64 var y: i64 = ylo 65 while y <= yhi { 66 if ba_sdf(x, y, z, 1) < 0 { return y } 67 y = y + 2 68 } 69 return 0-N_MAGIC_100000 70} 71func mo_halfwidth_at(y: i64, lim: i64) -> i64 { 72 var best: i64 = 0 73 var x: i64 = 0 74 while x <= lim { 75 if ba_sdf(x, y, 20, 1) < 0 { best = x } 76 x = x + 4 77 } 78 return best 79} 80 81// ===== bm_measure: build the being for a preset and extract geometric landmarks from its SDF ===== 82func bm_measure(preset: i64, LM: *i64) -> i64 { 83 atlas_hand_curl(0) 84 atlas_build(preset) 85 atlas_pose(0) 86 let crown: i64 = mo_scan_down(0, 20, N_MAGIC_1200, 400) // top of head 87 let sole: i64 = mo_scan_up(90, 20, 0-N_MAGIC_1200, 0-400) // bottom of a foot (feet at x ~ +-90) 88 // head widest halfwidth (skip the narrow dome top), then chin = first y BELOW it where the width 89 // collapses toward the neck. The threshold is RELATIVE to the head's own width so it generalises across 90 // body girths -- an absolute plateau value only fits one preset (a lean body misfires it at the dome top). 91 var headmax: i64 = 0 92 var ymax: i64 = crown 93 var yy: i64 = crown - 8 94 while yy > crown - 320 { 95 let hwd: i64 = mo_halfwidth_at(yy, 240) 96 if hwd > headmax { 97 headmax = hwd 98 ymax = yy 99 } 100 yy = yy - 4 101 } 102 let neckthr: i64 = headmax*NECK_RATIO_PCT/100 103 var chin: i64 = 0-N_MAGIC_100000 104 var y: i64 = ymax - 8 105 while y > crown - 460 { 106 if chin < 0-N_MAGIC_99999 { if mo_halfwidth_at(y, 240) < neckthr { chin = y } } 107 y = y - 4 108 } 109 // crotch: highest y where the centre column is OUTSIDE while both thighs are INSIDE 110 var crotch: i64 = 0-N_MAGIC_100000 111 y = 0 112 while y > 0-560 { 113 if crotch < 0-N_MAGIC_99999 { if ba_sdf(0, y, 20, 1) > 0 { if ba_sdf(0-95, y, 20, 1) < 0 { if ba_sdf(95, y, 20, 1) < 0 { crotch = y } } } } 114 y = y - 4 115 } 116 // shoulders: widest halfwidth in the shoulder band 117 var shw: i64 = 0 118 y = 560 119 while y > 380 { 120 let w: i64 = mo_halfwidth_at(y, 400) 121 if w > shw { shw = w } 122 y = y - 8 123 } 124 // hips: widest halfwidth in the hip band (lim 200: hanging arms/hands are NOT hips) 125 var hipw: i64 = 0 126 y = 0 127 while y > 0-200 { 128 let w2: i64 = mo_halfwidth_at(y, 200) 129 if w2 > hipw { hipw = w2 } 130 y = y - 8 131 } 132 // fingertip: lowest inside y on the hand columns 133 var ftip: i64 = 0-N_MAGIC_100000 134 var cx: i64 = 220 135 while cx <= 280 { 136 let t: i64 = mo_scan_up(cx, 20, 0-300, 100) 137 if t > 0-N_MAGIC_99999 { if ftip < 0-N_MAGIC_99999 { ftip = t } else { if t < ftip { ftip = t } } } 138 cx = cx + 10 139 } 140 let acro: i64 = mo_scan_down(240, 20, 700, 300) // acromion (shoulder top at the arm column) 141 LM[LM_CROWN] = crown 142 LM[LM_SOLE] = sole 143 LM[LM_CHIN] = chin 144 LM[LM_CROTCH] = crotch 145 LM[LM_SHW] = shw 146 LM[LM_HIPW] = hipw 147 LM[LM_ACRO] = acro 148 LM[LM_FTIP] = ftip 149 return 0 150} 151 152// ===== bm_derive: derive the morphometric axes WITH PROVENANCE into OUT[N_AX*AX_STRIDE] ===== 153// Canon bands are the BANKED anthropometric canon (knowledge/anthropometry_banked.txt), not invented here. 154func bm_derive(preset: i64, OUT: *i64) -> i64 { 155 let LM: *i64 = sys_mmap(N_LM*8) as *i64 156 bm_measure(preset, LM) 157 let crown: i64 = LM[LM_CROWN] 158 let sole: i64 = LM[LM_SOLE] 159 let chin: i64 = LM[LM_CHIN] 160 let crotch: i64 = LM[LM_CROTCH] 161 let shw: i64 = LM[LM_SHW] 162 let hipw: i64 = LM[LM_HIPW] 163 let acro: i64 = LM[LM_ACRO] 164 let ftip: i64 = LM[LM_FTIP] 165 let stature: i64 = crown - sole 166 let headh: i64 = crown - chin 167 let legs: i64 = crotch - sole 168 let arm: i64 = acro - ftip 169 // axis 0: heads-tall (x10). transform stature*10/head_height. canon 69..81 (7.5 heads +-8%). 170 var v0: i64 = 0 171 if headh != 0 { v0 = stature*10/headh } 172 OUT[0] = v0 173 OUT[1] = 69 174 OUT[2] = 81 175 OUT[3] = 2 176 OUT[4] = "heads_tall_x10" as i64 177 OUT[5] = "stature*10/head_height" as i64 178 OUT[6] = "crown_y,chin_y,sole_y" as i64 179 // axis 1: leg fraction (x1000). transform (crotch-sole)*1000/stature. canon 470..530. 180 var v1: i64 = 0 181 if stature != 0 { v1 = legs*1000/stature } 182 OUT[7] = v1 183 OUT[8] = 470 184 OUT[9] = 530 185 OUT[10] = 2 186 OUT[11] = "leg_fraction_x1000" as i64 187 OUT[12] = "(crotch_y-sole_y)*1000/stature" as i64 188 OUT[13] = "crotch_y,sole_y,crown_y" as i64 189 // axis 2: arm fraction (x1000). transform (acromion-fingertip)*1000/stature. canon 358..442. 190 var v2: i64 = 0 191 if stature != 0 { v2 = arm*1000/stature } 192 OUT[14] = v2 193 OUT[15] = 358 194 OUT[16] = 442 195 OUT[17] = 2 196 OUT[18] = "arm_fraction_x1000" as i64 197 OUT[19] = "(acromion_y-fingertip_y)*1000/stature" as i64 198 OUT[20] = "acromion_y,fingertip_y,crown_y,sole_y" as i64 199 // axis 3: shoulder/hip ratio (x100). transform shoulder_hw*100/hip_hw. canon 108..130 (men ~118). 200 var v3: i64 = 0 201 if hipw != 0 { v3 = shw*100/hipw } 202 OUT[21] = v3 203 OUT[22] = 108 204 OUT[23] = 130 205 OUT[24] = 4 206 OUT[25] = "shoulder_hip_ratio_x100" as i64 207 OUT[26] = "shoulder_hw*100/hip_hw" as i64 208 OUT[27] = "shoulder_hw,hip_hw" as i64 209 // axis 4: fingertip-to-mid-thigh drop (abs offset). transform |fingertip-(crotch-leg_length/4)|. canon 0..90. 210 let midthigh: i64 = crotch - legs/4 211 var ftoff: i64 = ftip - midthigh 212 if ftoff < 0 { ftoff = 0 - ftoff } 213 OUT[28] = ftoff 214 OUT[29] = 0 215 OUT[30] = 90 216 OUT[31] = 2 217 OUT[32] = "fingertip_midthigh_offset" as i64 218 OUT[33] = "abs(fingertip_y-(crotch_y-leg_length/4))" as i64 219 OUT[34] = "fingertip_y,crotch_y,sole_y" as i64 220 return N_AX 221} 222 223// ===== bm_fence_blocked: rule-26 PROMOTION CLAMP with a PERMANENT PLANTED LIE (runtime neg-control) ===== 224// promotion tiers: 0 measurement-only, 1 visualise-ok, 2 clinical/genomic-ready (FORBIDDEN for a measurement). 225// The clamp forces any claim>=2 back to 0. The planted lie claim[0]=2 must be caught -> return >=1 every run. 226func bm_fence_blocked() -> i64 { 227 let claim: *i64 = sys_mmap(N_PROMO*8) as *i64 228 let comp: *i64 = sys_mmap(N_PROMO*8) as *i64 229 claim[0] = 2 // <-- PERMANENT PLANTED LIE: a caller claims morphometrics are clinical/genomic-ready 230 claim[1] = 1 231 claim[2] = 0 232 var blocked: i64 = 0 233 var i: i64 = 0 234 while i < N_PROMO { 235 comp[i] = claim[i] 236 if claim[i] >= 2 { comp[i] = 0 237 blocked = blocked + 1 } 238 i = i + 1 239 } 240 return blocked 241} 242 243// ===== bm_checksum: order-sensitive rolling hash over the derived values (determinism witness) ===== 244func bm_checksum(preset: i64) -> i64 { 245 let OUT: *i64 = sys_mmap(N_AX*AX_STRIDE*8) as *i64 246 bm_derive(preset, OUT) 247 var h: i64 = N_MAGIC_1469598103 248 var i: i64 = 0 249 while i < N_AX { 250 let v: i64 = OUT[i*AX_STRIDE] 251 h = h*31 + v*(i+7) 252 i = i + 1 253 } 254 return h 255}