code wiki / (root) / nx_devpaint_lib.nx

nx_devpaint_lib.nx

buildroot/runtime/nx_devpaint_lib.nx

10693 B228 linesdepth 4pulls 6 transitivereach 2 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_devpaint_lib.nx -- THE DERIVED-SCALE DEVIATION HEATMAP (2026-08-26). WHY, MEASURED: /exceed/vrm/seed-san.html has been telling visitors that /exceed/vrm/nishi_seedsan_heatmap.glb is "the INTERACTIVE deviation heatmap (drag-rotate the painted gap itself)". That file was BYTE-IDENTICAL to nishi_fitted_seedsan.glb (sha256 1ef8ec04..., 9,435,856 B each): a copy of the unpainted mesh with no deviation on it anywhere. Rule 25 says rewrite it better rather than filter it out, so this lib is the emitter that makes the claim true. WHAT IS NEW HERE, versus nx_meshdist's incumbent `paint` verb, which is otherwise a working heatmap: 1. THE SCALE IS DERIVED FROM THE MEASURED DISTRIBUTION, NOT PASSED IN. md_paint takes `band_um` as an argument and defaults it to 5000 -- a number the caller has to guess, and the published run guessed 10000. A guessed band is a magic number wearing an argument's clothes: pick it too small and every triangle saturates magenta, too large and the whole body is green, and BOTH pictures look authoritative. Here the ramp ceiling is the measured p95 rounded up to the next whole millimetre, and dp_provenance names that rule so the number travels with the picture. 2. IT MEASURES PER VERTEX, NOT PER CENTROID. md_paint takes the distance from each triangle's centroid. A centroid can sit on the reference surface while a corner is far off it, so the incumbent can hide deviation at exactly the sharp features you built a heatmap to find. 3. THE RAMP IS CONTINUOUS, not five hard bands, so a 39 mm and a 41 mm triangle no longer land in different colours because of where a band edge happened to fall. COMPOSED, NEVER RE-IMPLEMENTED: the distance itself is nx_mmdev_lib's exact point-to-triangle ruler (Ericson 5.1.5 + its uniform grid, integer, no sampling). The colour codec is nx_nxmesh_lib's. This file adds the derivation and the ramp and nothing else -- there is no second distance ruler here. DECLARED IMPRECISIONS, all three: (a) NXMSH2 carries ONE colour per TRIANGLE. Three measured corner deviations are therefore reduced to one colour by MAX -- a triangle is as bad as its worst corner. That is wrong in the direction of SHOWING deviation rather than hiding it, which is the safe direction for an inspection tool. Measured on the shipping subject, a triangle spans about 10 mm on a 1.6 m body and renders about 2 px at showcase size, so per-corner interpolation would change little that a viewer can see; the reduction is a format limit, not a shortcut, and lifting it needs a per-vertex colour source in nx_mesh2glb, which is named here rather than silently wished for. (b) Percentiles come from a histogram of MD_HIST_BINS one-tenth-millimetre bins, so they are exact to the bin. Deviations past the last bin land in it and are counted, so p95 can never be reported BELOW a deviation that fell off the end. (c) The scale is per-subject by construction. Two heatmaps are only comparable by reading the printed bounds, which is exactly why dp_provenance exists and why the CLI prints them. license_tier: ORIGINAL

dependencies 4 imports · 2 importers

nx_syscalls.nx nx_vecmath.nx nx_nxmesh_lib.nx nx_mmdev_lib.nx nx_devpaint_lib.nx nx_devpaint.nx nx_devpaint_gate.nx

imports: nx_syscalls.nxnx_vecmath.nxnx_nxmesh_lib.nxnx_mmdev_lib.nx

imported by: nx_devpaint.nxnx_devpaint_gate.nx

structs

none

consts

47const DP_R_CORNERS: i64 = 0 // triangle-corners measured: the FULL population, never a sample
48const DP_R_TRIS: i64 = 1
49const DP_R_LO: i64 = 2 // ramp floor, ruler units (tenths of a millimetre)
50const DP_R_HI: i64 = 3 // ramp ceiling, DERIVED -- see dp_scale
51const DP_R_P50: i64 = 4
52const DP_R_P95: i64 = 5
53const DP_R_MAX: i64 = 6
54const DP_R_MEAN: i64 = 7
55const DP_R_SATURATED: i64 = 8 // corners at or above HI: they clamp to the top stop
56const DP_R_OVERFLOW: i64 = 9 // corners past the last histogram bin
57const DP_R_REFUSED: i64 = 10 // 0 ok, 1 extent bound, 3 empty
58const DP_R_N: i64 = 11
65const DP_STOPS: i64 = 5
66const DP_SEGS: i64 = 4 // DERIVED: DP_STOPS - 1 segments between five stops
67const DP_PCT_DEN: i64 = 100
68const DP_P50_NUM: i64 = 50
69const DP_P95_NUM: i64 = 95

functions

71func dp_stop_r(i: i64) -> i64
called by 1: dp_ramp
78func dp_stop_g(i: i64) -> i64
called by 1: dp_ramp
85func dp_stop_b(i: i64) -> i64
called by 1: dp_ramp
96func dp_ramp(d: i64, lo: i64, hi: i64, out3: *i64) -> i64
112func dp_res() -> *i64
called by 2: mainmain calls 1: sys_mmap
120func dp_pct(hist: *i64, cnt: i64, num: i64, den: i64) -> i64
called by 1: dp_measure
139func dp_measure(ca: *u8, ref: *u8, dev: *i64, res: *i64) -> i64
189func dp_scale(res: *i64) -> i64
called by 2: mainmain
200func dp_saturated(dev: *i64, ncorners: i64, hi: i64) -> i64
called by 2: mainmain
211func dp_tri_dev(dev: *i64, t: i64) -> i64
called by 2: maindp_paint
219func dp_paint(buf: *u8, tri_base: i64, nt: i64, dev: *i64, lo: i64, hi: i64) -> i64