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}