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}