code wiki / _hdl_build / nx_explodelab_twinbake.nx

nx_explodelab_twinbake.nx source

↩ module page · 424 lines · 13593 B

1// nx_explodelab_twinbake.nx -- BAKE THE ENGINEERING TWIN into the /explodelab panel data. Runs the SAME gated 2// composed pipeline as nx_cadtwin_report_gate (step_parse -> cr_find_parts -> per-part tess2 planar + nurbs 3// round -> cr_weld -> meshthick min-wall + meshseg3d shells + partid shape class + unitconv dual-dimension + 4// assemseq teardown rank) on the real as1 STEP file, then EMITS every measured number as PRE-FORMATTED card 5// text to knowledge/explodelab_twin.txt. The viewer's JS only DISPLAYS these strings (physlab no-JS-logic 6// law): every value is computed by a sovereign gated organ at bake time, never by the browser. 7// Line grammar (pipe-delimited, '#' emitted as char 35 -- nx literals cannot carry it): 8// #TWIN|<part-name> starts a card 9// #F|<label>|<value> one field row of the current card 10// expect_exit: 0 license_tier: ORIGINAL 11import "nx_cadtwin_report.nx" 12import "nx_step_write.nx" 13const K_MAGIC_524288: i64 = 524288 14const K_MAGIC_8192: i64 = 8192 15const K_MAGIC_4096: i64 = 4096 16const K_MAGIC_1024: i64 = 1024 17const K_MAGIC_20480: i64 = 20480 18const K_MAGIC_2048: i64 = 2048 19const K_MAGIC_65536: i64 = 65536 20const K_MAGIC_262144: i64 = 262144 21const K_MAGIC_4194304: i64 = 4194304 22 23// fx256 -> "N.NN" appended to the string builder 24func tb_mm2(b: *i64, v: i64) -> i64 { 25 var a: i64 = v 26 if a < 0 { 27 swb_c(b, 45) 28 a = 0 - a 29 } 30 let cents: i64 = (a * 100 + 128) / 256 31 swb_n(b, cents / 100) 32 swb_c(b, 46) 33 let r: i64 = cents % 100 34 if r < 10 { swb_c(b, 48) } 35 swb_n(b, r) 36 return 0 37} 38 39// "#F|<label>|" -- opens a field row 40func tb_field(b: *i64, label: *u8) -> i64 { 41 swb_c(b, 35) 42 swb_s(b, "F|" as *u8) 43 swb_s(b, label) 44 swb_c(b, 124) 45 return 0 46} 47 48// append the PRODUCT name (arg-0 single-quoted string) to the builder 49func tb_pname(st: *i64, prodidx: i64, out2: *i64, b: *i64) -> i64 { 50 let ok: i64 = sp_arg_span(st, prodidx, 0, out2) 51 if ok == 0 { 52 swb_c(b, 63) 53 return 0 54 } 55 let buf: *u8 = st[0] as *u8 56 var v: i64 = out2[0] 57 let e: i64 = out2[0] + out2[1] 58 var sk: i64 = 1 59 while sk == 1 { 60 if v < e { 61 if sp_isspace(buf[v] as i64) == 1 { v = v + 1 } else { sk = 0 } 62 } else { sk = 0 } 63 } 64 if v >= e { return 0 } 65 if buf[v] != (39 as u8) { return 0 } 66 let s0: i64 = v + 1 67 var w: i64 = s0 68 var go: i64 = 1 69 while go == 1 { 70 if w < e { 71 if buf[w] == (39 as u8) { go = 0 } else { w = w + 1 } 72 } else { go = 0 } 73 } 74 var k: i64 = s0 75 while k < w { 76 swb_c(b, buf[k] as i64) 77 k = k + 1 78 } 79 return 0 80} 81 82func main() -> i64 { 83 sp_puts("=== nx_explodelab_twinbake -- bake measured engineering truth into the /explodelab card data ===\n" as *u8) 84 let buf: *u8 = sys_mmap(K_MAGIC_4194304) 85 let aid: *i64 = sys_mmap(K_MAGIC_524288) as *i64 86 let anm: *i64 = sys_mmap(K_MAGIC_524288) as *i64 87 let anl: *i64 = sys_mmap(K_MAGIC_524288) as *i64 88 let aao: *i64 = sys_mmap(K_MAGIC_524288) as *i64 89 let aal: *i64 = sys_mmap(K_MAGIC_524288) as *i64 90 let st: *i64 = sys_mmap(256) as *i64 91 let n: i64 = sp_read_file("knowledge/fetched/step_as1.stp" as *u8, buf, K_MAGIC_4194304) 92 if n <= 0 { 93 sp_puts("MISSING knowledge/fetched/step_as1.stp\nRED\n" as *u8) 94 return 1 95 } 96 sp_init(st, buf, n, aid, anm, anl, aao, aal) 97 let cnt: i64 = sp_scan(st) 98 let out2: *i64 = sys_mmap(16) as *i64 99 100 // ---- organ contexts (identical wiring to nx_cadtwin_report_gate) 101 let tt: *i64 = sys_mmap(128) as *i64 102 let cp: *i64 = sys_mmap(128) as *i64 103 var z: i64 = 0 104 while z < 16 { 105 cp[z] = 0 106 z = z + 1 107 } 108 tt[0] = st as i64 109 tt[2] = cp as i64 110 tt[3] = sys_mmap(768) as i64 111 tt[4] = 0 112 tt[5] = sys_mmap(K_MAGIC_8192) as i64 113 tt[6] = sys_mmap(K_MAGIC_4096) as i64 114 tt[7] = sys_mmap(128) as i64 115 tt[8] = sys_mmap(16) as i64 116 tt[9] = 0 117 let t2: *i64 = sys_mmap(128) as *i64 118 t2[0] = st as i64 119 t2[1] = cp as i64 120 t2[2] = sys_mmap(32) as i64 121 t2[3] = sys_mmap(960) as i64 122 t2[4] = sys_mmap(K_MAGIC_1024) as i64 123 t2[5] = sys_mmap(128) as i64 124 t2[6] = sys_mmap(512) as i64 125 t2[7] = sys_mmap(256) as i64 126 t2[8] = sys_mmap(K_MAGIC_8192) as i64 127 t2[9] = sys_mmap(128) as i64 128 t2[10] = sys_mmap(768) as i64 129 t2[11] = sys_mmap(128) as i64 130 t2[12] = sys_mmap(256) as i64 131 let slab: *i64 = sys_mmap(K_MAGIC_20480) as *i64 132 let nt: *i64 = sys_mmap(128) as *i64 133 let c2: *i64 = sys_mmap(128) as *i64 134 z = 0 135 while z < 16 { 136 c2[z] = 0 137 z = z + 1 138 } 139 nt[0] = st as i64 140 nt[2] = c2 as i64 141 nt[3] = sys_mmap(256) as i64 142 nt[4] = sys_mmap(64) as i64 143 nt[5] = sys_mmap(16) as i64 144 nt[6] = sys_mmap(128) as i64 145 nt[7] = sys_mmap(128) as i64 146 // units registry -- dual-dimensioning is the anti-JPL doctrine 147 let u: *i64 = sys_mmap(64) as *i64 148 ur_init(u, 64) 149 ur_std(u) 150 let iFX: i64 = ur_find(u, "fx256mm" as *u8) 151 let iTHOU: i64 = ur_find(u, "thou" as *u8) 152 let uout: *i64 = sys_mmap(16) as *i64 153 // teardown order (nx_assemseq) 154 let pe: *i64 = sys_mmap(K_MAGIC_2048) as *i64 155 let ce: *i64 = sys_mmap(K_MAGIC_2048) as *i64 156 let en: i64 = sp_nauo_collect(st, pe, ce, 256) 157 let apd: *i64 = sys_mmap(K_MAGIC_2048) as *i64 158 let npd: i64 = asq_collect_pds(pe, ce, en, apd) 159 let rootpd: i64 = asq_root(pe, ce, en) 160 let depth: *i64 = sys_mmap(K_MAGIC_2048) as *i64 161 asq_depths(apd, npd, pe, ce, en, rootpd, depth) 162 let order: *i64 = sys_mmap(K_MAGIC_2048) as *i64 163 let no: i64 = asq_order(depth, npd, order) 164 165 // ---- parts, attributed from the FILE's own semantics 166 let pdid: *i64 = sys_mmap(128) as *i64 167 let prodidx: *i64 = sys_mmap(128) as *i64 168 let shellidx: *i64 = sys_mmap(128) as *i64 169 let np: i64 = cr_find_parts(st, pdid, prodidx, shellidx) 170 sp_puts("entities=" as *u8) 171 sp_putn(cnt) 172 sp_puts(" parts=" as *u8) 173 sp_putn(np) 174 sp_puts(" teardown steps=" as *u8) 175 sp_putn(no) 176 sp_puts("\n" as *u8) 177 178 let b: *i64 = sys_mmap(64) as *i64 179 swb_init(b, K_MAGIC_262144) 180 let out4: *i64 = sys_mmap(32) as *i64 181 let labels: *i64 = sys_mmap(K_MAGIC_65536) as *i64 182 let desc: *i64 = sys_mmap(16) as *i64 183 var sumfaces: i64 = 0 184 var sumtess: i64 = 0 185 var sumtris: i64 = 0 186 var sumverts: i64 = 0 187 var thinnest: i64 = 0 - 1 188 var cards: i64 = 0 189 190 var pi: i64 = 0 191 while pi < np { 192 let mesh: i64 = sys_mmap(m3_bytes()) as i64 193 m3_init(mesh) 194 tt[1] = mesh 195 nt[1] = mesh 196 cr_tess_part(tt, nt, t2, slab, shellidx[pi], out4) 197 sumfaces = sumfaces + out4[0] 198 sumtess = sumtess + out4[1] 199 let h: *i64 = m3_hdr(mesh) 200 let weldv: i64 = cr_weld(mesh) 201 let tria: i64 = h[1] 202 sumverts = sumverts + weldv 203 sumtris = sumtris + tria 204 pid_descriptor(mesh, desc) 205 let segk: i64 = ms_segment(mesh, 0 - 300, labels) 206 // min wall over faces (ray-cast, Zeiss/GOM method); misses counted honestly 207 var minw: i64 = 0 - 1 208 var miss: i64 = 0 209 var f: i64 = 0 210 while f < h[1] { 211 let th: i64 = mtk_face_thickness(mesh, f) 212 if th > 0 { 213 if minw < 0 { minw = th } else { 214 if th < minw { minw = th } 215 } 216 } else { miss = miss + 1 } 217 f = f + 1 218 } 219 if minw > 0 { 220 if thinnest < 0 { thinnest = minw } else { 221 if minw < thinnest { thinnest = minw } 222 } 223 } 224 // bbox 225 var mnx: i64 = 0 226 var mxx: i64 = 0 227 var mny: i64 = 0 228 var mxy: i64 = 0 229 var mnz: i64 = 0 230 var mxz: i64 = 0 231 if h[0] > 0 { 232 let v0: *i64 = m3_vert(mesh, 0) 233 mnx = v0[0] 234 mxx = v0[0] 235 mny = v0[1] 236 mxy = v0[1] 237 mnz = v0[2] 238 mxz = v0[2] 239 var vi: i64 = 1 240 while vi < h[0] { 241 let v: *i64 = m3_vert(mesh, vi) 242 if v[0] < mnx { mnx = v[0] } 243 if v[0] > mxx { mxx = v[0] } 244 if v[1] < mny { mny = v[1] } 245 if v[1] > mxy { mxy = v[1] } 246 if v[2] < mnz { mnz = v[2] } 247 if v[2] > mxz { mxz = v[2] } 248 vi = vi + 1 249 } 250 } 251 var ext: i64 = mxx - mnx 252 if mxy - mny > ext { ext = mxy - mny } 253 if mxz - mnz > ext { ext = mxz - mnz } 254 ur_conv(u, ext, iFX, iTHOU, uout) 255 let extthou: i64 = uout[0] 256 var wallthou: i64 = 0 257 if minw > 0 { 258 ur_conv(u, minw, iFX, iTHOU, uout) 259 wallthou = uout[0] 260 } 261 // teardown rank, joined by PD id 262 var rank: i64 = 0 - 1 263 var oi: i64 = 0 264 while oi < no { 265 if apd[order[oi]] == pdid[pi] { rank = oi } 266 oi = oi + 1 267 } 268 269 // ---- emit the card 270 swb_c(b, 35) 271 swb_s(b, "TWIN|" as *u8) 272 tb_pname(st, prodidx[pi], out2, b) 273 swb_c(b, 10) 274 275 tb_field(b, "Bounding box" as *u8) 276 tb_mm2(b, mxx - mnx) 277 swb_s(b, " x " as *u8) 278 tb_mm2(b, mxy - mny) 279 swb_s(b, " x " as *u8) 280 tb_mm2(b, mxz - mnz) 281 swb_s(b, " mm" as *u8) 282 swb_c(b, 10) 283 284 tb_field(b, "Max extent" as *u8) 285 tb_mm2(b, ext) 286 swb_s(b, " mm / " as *u8) 287 swb_n(b, extthou) 288 swb_s(b, " thou" as *u8) 289 swb_c(b, 10) 290 291 tb_field(b, "Min wall" as *u8) 292 if minw > 0 { 293 tb_mm2(b, minw) 294 swb_s(b, " mm / " as *u8) 295 swb_n(b, wallthou) 296 swb_s(b, " thou" as *u8) 297 } else { 298 swb_s(b, "not measurable (open mesh)" as *u8) 299 } 300 swb_c(b, 10) 301 302 tb_field(b, "Tessellation" as *u8) 303 swb_n(b, out4[1]) 304 swb_s(b, " / " as *u8) 305 swb_n(b, out4[0]) 306 swb_s(b, " faces (" as *u8) 307 swb_n(b, out4[2]) 308 swb_s(b, " planar, " as *u8) 309 swb_n(b, out4[3]) 310 swb_s(b, " NURBS)" as *u8) 311 swb_c(b, 10) 312 313 tb_field(b, "Mesh" as *u8) 314 swb_n(b, weldv) 315 swb_s(b, " verts, " as *u8) 316 swb_n(b, tria) 317 swb_s(b, " tris, " as *u8) 318 swb_n(b, segk) 319 swb_s(b, " shells" as *u8) 320 swb_c(b, 10) 321 322 tb_field(b, "Thickness misses" as *u8) 323 swb_n(b, miss) 324 swb_s(b, " of " as *u8) 325 swb_n(b, tria) 326 swb_s(b, " triangles" as *u8) 327 swb_c(b, 10) 328 329 // reliable shape signal: extent ratio from the bbox (dimensional truth, no sampling bias) 330 var mnext: i64 = mxx - mnx 331 if mxy - mny < mnext { mnext = mxy - mny } 332 if mxz - mnz < mnext { mnext = mxz - mnz } 333 tb_field(b, "Extent ratio" as *u8) 334 swb_s(b, "min:max = " as *u8) 335 if ext > 0 { swb_n(b, (mnext * 1000) / ext) } else { swb_n(b, 0) } 336 swb_s(b, " : 1000" as *u8) 337 swb_c(b, 10) 338 339 // HONEST: the covariance descriptor is VERTEX-weighted, so on hole-rich parts it describes the 340 // vertex cloud (hole tubes carry most verts) rather than the outline -- the bbox above is the 341 // dimensional truth. Stated on every card so the number is never read as more than it is. 342 tb_field(b, "Shape descriptor" as *u8) 343 swb_n(b, desc[0]) 344 swb_s(b, ", " as *u8) 345 swb_n(b, desc[1]) 346 swb_s(b, " permille -- vertex-covariance, sampling-weighted" as *u8) 347 swb_c(b, 10) 348 349 tb_field(b, "Teardown" as *u8) 350 swb_s(b, "step " as *u8) 351 swb_n(b, rank + 1) 352 swb_s(b, " of " as *u8) 353 swb_n(b, no) 354 swb_c(b, 10) 355 356 tb_field(b, "Source" as *u8) 357 swb_s(b, "as1.stp ISO-10303-21 units mm declared in file" as *u8) 358 swb_c(b, 10) 359 360 cards = cards + 1 361 pi = pi + 1 362 } 363 364 // ---- assembly-level card 365 swb_c(b, 35) 366 swb_s(b, "TWIN|_assembly" as *u8) 367 swb_c(b, 10) 368 tb_field(b, "Solid parts" as *u8) 369 swb_n(b, np) 370 swb_s(b, " attributed from file semantics" as *u8) 371 swb_c(b, 10) 372 tb_field(b, "Face coverage" as *u8) 373 swb_n(b, sumtess) 374 swb_s(b, " / " as *u8) 375 swb_n(b, sumfaces) 376 swb_s(b, " tessellated" as *u8) 377 swb_c(b, 10) 378 tb_field(b, "Total mesh" as *u8) 379 swb_n(b, sumverts) 380 swb_s(b, " verts, " as *u8) 381 swb_n(b, sumtris) 382 swb_s(b, " tris" as *u8) 383 swb_c(b, 10) 384 tb_field(b, "Thinnest wall" as *u8) 385 tb_mm2(b, thinnest) 386 swb_s(b, " mm across all parts" as *u8) 387 swb_c(b, 10) 388 tb_field(b, "STEP entities" as *u8) 389 swb_n(b, cnt) 390 swb_c(b, 10) 391 cards = cards + 1 392 393 let fd: i64 = sys_openat_wr("knowledge/explodelab_twin.txt" as *u8, 420) 394 if fd < 0 { 395 sp_puts("open knowledge/explodelab_twin.txt failed\nRED\n" as *u8) 396 return 1 397 } 398 sys_write(fd, b[0] as *u8, b[1]) 399 sys_close(fd) 400 401 sp_puts("cards=" as *u8) 402 sp_putn(cards) 403 sp_puts(" coverage=" as *u8) 404 sp_putn(sumtess) 405 sp_puts("/" as *u8) 406 sp_putn(sumfaces) 407 sp_puts(" verts=" as *u8) 408 sp_putn(sumverts) 409 sp_puts(" tris=" as *u8) 410 sp_putn(sumtris) 411 sp_puts(" thinnest=" as *u8) 412 sp_putn(thinnest) 413 sp_puts("fx bytes=" as *u8) 414 sp_putn(b[1]) 415 sp_puts("\n" as *u8) 416 if cards == np + 1 { 417 if sumtess == sumfaces { 418 sp_puts("GREEN -- engineering twin baked to knowledge/explodelab_twin.txt\n" as *u8) 419 return 0 420 } 421 } 422 sp_puts("RED -- incomplete bake\n" as *u8) 423 return 1 424}