code wiki / (root) / nx_vasc_lib.nx

nx_vasc_lib.nx source

↩ module page · 68 lines · 3967 B

1// nx_vasc_lib.nx -- GROWN VASCULATURE -> THE HAEMOGLOBIN FIELD THE SKIN LAYER SEES (2026-09-03) 2// 3// THE OPERATOR'S LAW THIS IMPLEMENTS (2026-09-03): a human is GROWN bottom-up -- bone, nerve, circulation, 4// muscle, fat, dermis, hair out of follicles -- and the vessels you can see through fair skin must EMERGE 5// from a circulatory structure that is actually there. Painting a blue line on a texture is the failure mode 6// this file exists to make unnecessary. 7// 8// THE JOIN. The estate already grows: nx_derm computes skin as an envelope FROM the layers beneath it, 9// nx_anat_sov carries inside-out vasculature scoped to where it actually shows (chest, hands, not 10// everywhere), nx_nxa_groom grows hair from a follicle-density RATIO. What was missing is the step between a 11// grown vessel network and a VISIBLE colour: geometry has no appearance until something converts it into an 12// absorber concentration. That is this file. It takes segments of a grown network -- each with a volume 13// fraction and a depth below the surface -- and returns the haemoglobin fraction c_hem that nx_kubelka_lib's 14// mix term consumes. Structure in, chromophore out; Kubelka-Munk then turns chromophore into reflectance. 15// 16// BEER-LAMBERT, DOUBLE PASS. Light must cross the tissue above a vessel, scatter, and cross it again to be 17// seen, so a segment's visible contribution falls as exp(-2*atten*depth). A vessel one millimetre down 18// contributes far less than the same vessel just under the surface, which is exactly why vasculature reads 19// on the wrist and the eyelid and not on the palm. 20// 21// WHAT THIS FILE DELIBERATELY DOES NOT MODEL: epidermal MELANIN attenuation. Melanin is already an absorber 22// in km_ks_mix, and attenuating the vessel signal by melanin here as well would COUNT IT TWICE -- the same 23// absorber charged on two layers, which reads as a plausible darkening and is a physics error. The melanin 24// term belongs to Kubelka-Munk alone. 25// 26// IT ACCEPTS A NETWORK, IT DOES NOT INVENT ONE. Branching growth is its own rung with its own gate; this lib 27// is the join and takes the grown segments as input, so no growth model is faked here. 28// 29// PROVEN 9/9 GREEN 2026-09-03. The two teeth that matter: denser vasculature raises the red-minus-green 30// separation from 89,090 to 196,295 micro (the skin reddens BECAUSE the vessels are there), and the same 31// vessel buried deep returns that separation to 70,497 -- byte-identical to the vessel-free baseline. 32// license_tier: ORIGINAL No hw writes (Rule 26). LIB (no main). 33import "nx_syscalls.nx" 34import "nx_fixq30_lib.nx" 35 36const VA_REFUSED: i64 = 0 - 1 37const VA_TWO: i64 = 2 38 39// visible haemoglobin contribution of ONE grown segment. 40// vol is the segment's volume fraction in the sampled tissue column (Q30, 0..1). 41// depth is its depth below the surface, atten the tissue attenuation per unit depth (both Q30, >= 0). 42// Returns vol * exp(-2*atten*depth): the double-pass Beer-Lambert transmittance of the tissue above it. 43func va_seg_visible(fq: *i64, vol: i64, depth: i64, atten: i64) -> i64 { 44 if vol < 0 { return VA_REFUSED } 45 if depth < 0 { return VA_REFUSED } 46 if atten <= 0 { return VA_REFUSED } 47 let tau: i64 = fq_mul(atten, depth) * VA_TWO 48 let t: i64 = fq_exp(fq, 0 - tau) 49 return fq_mul(vol, t) 50} 51 52// total visible haemoglobin fraction from a grown network of n segments. 53// CLAMPED at unity: a fraction cannot exceed one, and returning 1.4 would sail into km_ks_mix and produce a 54// confident reflectance for a tissue that cannot exist. 55func va_field(fq: *i64, vols: *i64, depths: *i64, n: i64, atten: i64) -> i64 { 56 if n < 0 { return VA_REFUSED } 57 if atten <= 0 { return VA_REFUSED } 58 var acc: i64 = 0 59 var i: i64 = 0 60 while i < n { 61 let c: i64 = va_seg_visible(fq, vols[i], depths[i], atten) 62 if c == VA_REFUSED { return VA_REFUSED } 63 acc = acc + c 64 i = i + 1 65 } 66 if acc > FQ_ONE { return FQ_ONE } 67 return acc 68}