code wiki / _hdl_build / nx_partid_gate.nx
nx_partid_gate.nx source
↩ module page · 118 lines · 6047 B
1// nx_partid_gate.nx -- benchmark geometric part identification (cadtwin P5). A catalog of distinct shape classes
2// (rod / plate / cube) gets rotation+scale-invariant descriptors; then prove (a) the classes are DISTINCT, (b)
3// ROTATING a part leaves its descriptor unchanged, (c) SCALING leaves it unchanged, (d) a rotated+scaled query
4// part is correctly IDENTIFIED against the catalog. This is coarse shape-class recognition for the flip chain
5// (segment -> identify -> NHTSA/thickness lookup). expect_exit: 0 license_tier: ORIGINAL
6import "nx_partid.nx"
7
8func dg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
9func dg_putn(v: i64) -> i64 {
10 let bb: *u8 = sys_mmap(28)
11 var m: i64 = v
12 if m < 0 { dg_puts("-" as *u8); m = 0 - m }
13 let t: *u8 = sys_mmap(28)
14 var k: i64 = 0
15 if m == 0 { t[0] = 48 as u8; k = 1 }
16 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
17 var i: i64 = 0
18 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
19 sys_write(1, bb, k)
20 return 0
21}
22func dg_tooth(name: *u8, pass: i64, fails: *i64) -> i64 {
23 dg_puts(" " as *u8); dg_puts(name); dg_puts(" -> " as *u8)
24 if pass == 1 { dg_puts("PASS\n" as *u8); return 0 }
25 dg_puts("FAIL\n" as *u8)
26 fails[0] = fails[0] + 1
27 return 0
28}
29func dg_dist(a: *i64, b: *i64) -> i64 {
30 var e0: i64 = a[0] - b[0]
31 if e0 < 0 { e0 = 0 - e0 }
32 var e1: i64 = a[1] - b[1]
33 if e1 < 0 { e1 = 0 - e1 }
34 return e0 + e1
35}
36
37func main() -> i64 {
38 dg_puts("=== nx_partid_gate -- rotation/scale-invariant geometric part identification ===\n" as *u8)
39 let fails: *i64 = sys_mmap(8) as *i64
40 fails[0] = 0
41
42 // catalog shapes
43 let rod: i64 = sys_mmap(m3_bytes()) as i64
44 m3_init(rod); m3_box(rod, 0, 0, 0, 150, 150, 1500) // long thin -> one dominant axis
45 let plate: i64 = sys_mmap(m3_bytes()) as i64
46 m3_init(plate); m3_box(plate, 0, 0, 0, 1500, 1500, 120) // flat -> two dominant axes
47 let cube: i64 = sys_mmap(m3_bytes()) as i64
48 m3_init(cube); m3_box(cube, 0, 0, 0, 800, 800, 800) // equal -> three equal
49
50 let cat: *i64 = sys_mmap(64) as *i64 // catalog descriptors: 0=rod 1=plate 2=cube
51 let dr: *i64 = sys_mmap(16) as *i64
52 let dp: *i64 = sys_mmap(16) as *i64
53 let dc: *i64 = sys_mmap(16) as *i64
54 pid_descriptor(rod, dr); cat[0] = dr[0]; cat[1] = dr[1]
55 pid_descriptor(plate, dp); cat[2] = dp[0]; cat[3] = dp[1]
56 pid_descriptor(cube, dc); cat[4] = dc[0]; cat[5] = dc[1]
57 dg_puts(" rod desc=(" as *u8); dg_putn(dr[0]); dg_puts("," as *u8); dg_putn(dr[1]); dg_puts(") plate=(" as *u8)
58 dg_putn(dp[0]); dg_puts("," as *u8); dg_putn(dp[1]); dg_puts(") cube=(" as *u8)
59 dg_putn(dc[0]); dg_puts("," as *u8); dg_putn(dc[1]); dg_puts(")\n" as *u8)
60
61 // T1 classes distinct
62 var t1: i64 = 0
63 if dg_dist(dr, dp) > 200 { if dg_dist(dr, dc) > 200 { if dg_dist(dp, dc) > 200 { t1 = 1 } } }
64 let ig1: i64 = dg_tooth("T1 rod/plate/cube descriptors are DISTINCT" as *u8, t1, fails)
65
66 // T2 rotation invariance: rotate the rod by a compound rotation
67 let R: *i64 = sys_mmap(128) as *i64 // Ry(30): tilts the rod's long axis off-z
68 R[0] = 14189; R[1] = 0; R[2] = 8192
69 R[3] = 0; R[4] = 16384; R[5] = 0
70 R[6] = 0 - 8192; R[7] = 0; R[8] = 14189
71 let rodR: i64 = sys_mmap(m3_bytes()) as i64
72 pid_rotate_mesh(rod, rodR, R)
73 let drR: *i64 = sys_mmap(16) as *i64
74 pid_descriptor(rodR, drR)
75 dg_puts(" rod rotated desc=(" as *u8); dg_putn(drR[0]); dg_puts("," as *u8); dg_putn(drR[1]); dg_puts(")\n" as *u8)
76 var t2: i64 = 0
77 if dg_dist(drR, dr) < 60 { t2 = 1 }
78 let ig2: i64 = dg_tooth("T2 ROTATION invariant (rotated rod desc == rod desc)" as *u8, t2, fails)
79
80 // T3 scale invariance: a 2x-bigger rod (same aspect ratios)
81 let rod2: i64 = sys_mmap(m3_bytes()) as i64
82 m3_init(rod2); m3_box(rod2, 0, 0, 0, 300, 300, 3000)
83 let dr2: *i64 = sys_mmap(16) as *i64
84 pid_descriptor(rod2, dr2)
85 dg_puts(" rod 2x desc=(" as *u8); dg_putn(dr2[0]); dg_puts("," as *u8); dg_putn(dr2[1]); dg_puts(")\n" as *u8)
86 var t3: i64 = 0
87 if dg_dist(dr2, dr) < 60 { t3 = 1 }
88 let ig3: i64 = dg_tooth("T3 SCALE invariant (2x rod desc == rod desc)" as *u8, t3, fails)
89
90 // T4 IDENTIFY a rotated+scaled query as the rod
91 let q: i64 = sys_mmap(m3_bytes()) as i64
92 pid_rotate_mesh(rod2, q, R) // scaled (rod2) then rotated
93 let dq: *i64 = sys_mmap(16) as *i64
94 pid_descriptor(q, dq)
95 let odist: *i64 = sys_mmap(8) as *i64
96 let id: i64 = pid_match(dq, cat, 3, odist)
97 dg_puts(" query(rotated+scaled rod) desc=(" as *u8); dg_putn(dq[0]); dg_puts("," as *u8); dg_putn(dq[1])
98 dg_puts(") -> matched catalog #" as *u8); dg_putn(id); dg_puts(" (0=rod 1=plate 2=cube) dist=" as *u8); dg_putn(odist[0]); dg_puts("\n" as *u8)
99 var t4: i64 = 0
100 if id == 0 { t4 = 1 }
101 let ig4: i64 = dg_tooth("T4 rotated+scaled query IDENTIFIED as rod" as *u8, t4, fails)
102
103 // T5 determinism
104 let dq2: *i64 = sys_mmap(16) as *i64
105 pid_descriptor(q, dq2)
106 var t5: i64 = 0
107 if dq2[0] == dq[0] { if dq2[1] == dq[1] { t5 = 1 } }
108 let ig5: i64 = dg_tooth("T5 deterministic" as *u8, t5, fails)
109
110 dg_puts("\nP5: coarse rotation/scale-invariant part-CLASS ID (principal-moment signature) for the flip chain --\n" as *u8)
111 dg_puts("segment (nx_meshseg3d) -> identify class -> look up NHTSA (nx_underbuilt_board) + thickness. HONEST:\n" as *u8)
112 dg_puts("this is shape CATEGORY, not fine OEM part-number ID -- that needs the EPC catalog corpus + finer/neural\n" as *u8)
113 dg_puts("matching (the fuller P5 rung). Invariance holds BY CONSTRUCTION (covariance eigenvalues).\n" as *u8)
114 dg_puts("\nfails=" as *u8); dg_putn(fails[0]); dg_puts("\n" as *u8)
115 if fails[0] == 0 { dg_puts("GREEN -- geometric part identification 5/5 (invariant descriptor + catalog match)\n" as *u8); return 0 }
116 dg_puts("RED\n" as *u8)
117 return 1
118}