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}