← All Pull Requests

altium-lane: marking font, D and B no longer read as IO and 8 (body3d) #3

Merged Approved opened by Colby Knox 2026-10-28

altium-lane: generate_body's marking font. D read as "IO" and B as an 8 with a bar. This changes engine/src/writers/body3d.rs only.

What was wrong:

  • D was drawn as a closed box with a centre bar. On a QFN that Altium 26.11 rendered from engine 0.5.0, "ADOM" read "AIOM".
  • B was drawn as the 8 box with that same bar.

The fix: both letters now have a full left side and cut top and bottom right corners, and B's middle bar runs to a cut notch. D, O, 0, B and 8 are now all distinct.

Checked:

  • An OCCT render (step2glb, top view) of a QFN marked "ADOM / B0D8" reads correctly.
  • A new test, d_and_b_are_not_i_o_or_8, passes, and the marking-fit test still passes: 59 unit and 5 conformance in all.
  • No other glyph changes, and no box or solid count changes.

The only output change is the STEP geometry of a marking that contains D or B. Please release it as a patch when convenient; I'll re-vendor it with the rest.

Diff Skip to comments

--- a/engine/src/writers/body3d.rs+++ b/engine/src/writers/body3d.rs@@ -1,523 +1,542 @@⋯ 311 unchanged lines ⋯     const DBL: ((f64, f64), (f64, f64)) = (MM, BL); const DBR: ((f64, f64), (f64, f64)) = (MM, BR);     const LB: ((f64, f64), (f64, f64)) = (ML, BM); const RB: ((f64, f64), (f64, f64)) = (MR, BM);     const DOT: ((f64, f64), (f64, f64)) = ((0.4, 0.0), (0.6, 0.0));+    // D and B: the left side full and the right corners cut, so D does not read as I and O side by side (it was a+    // box with a centre bar: "ADOM" read "AIOM" on a QFN in Altium, 2026-10-28) and B is not an 8+    const KT: (f64, f64) = (0.75, 2.0); const KM: (f64, f64) = (0.75, 1.0); const KB: (f64, f64) = (0.75, 0.0);+    const RT: (f64, f64) = (1.0, 1.75); const RU: (f64, f64) = (1.0, 1.25); const RL: (f64, f64) = (1.0, 0.75); const RB0: (f64, f64) = (1.0, 0.25);+    const DG: &[((f64, f64), (f64, f64))] = &[F, E, (TL, KT), (KT, RT), (RT, RB0), (RB0, KB), (BL, KB)];+    const BG: &[((f64, f64), (f64, f64))] = &[F, E, (TL, KT), (KT, RT), (RT, RU), (RU, KM), (ML, KM), (KM, RL), (RL, RB0), (RB0, KB), (BL, KB)];     Some(match c.to_ascii_uppercase() {         '0' => &[A, B, C, D, E, F, DTR, DBL], '1' => &[V], '2' => &[A, B, G, E, D], '3' => &[A, B, G2, C, D],         '4' => &[F, G, B, C], '5' => &[A, F, G, C, D], '6' => &[A, F, E, D, C, G], '7' => &[A, B, C], '8' => &[A, B, C, D, E, F, G],-        '9' => &[A, B, C, D, F, G], 'A' => &[E, F, A, B, C, G], 'B' => &[A, B, C, D, V, G2], 'C' => &[A, F, E, D], 'D' => &[A, B, C, D, V],+        '9' => &[A, B, C, D, F, G], 'A' => &[E, F, A, B, C, G], 'B' => BG, 'C' => &[A, F, E, D], 'D' => DG,         'E' => &[A, F, E, D, G1], 'F' => &[A, F, E, G1], 'G' => &[A, F, E, D, C, G2], 'H' => &[F, E, B, C, G], 'I' => &[A, V, D],         'J' => &[B, C, D, E], 'K' => &[F, E, G1, DTR, DBR], 'L' => &[F, E, D], 'M' => &[E, F, B, C, DTL, DTR], 'N' => &[E, F, B, C, DTL, DBR],         'O' => &[A, B, C, D, E, F], 'P' => &[A, B, F, E, G], 'Q' => &[A, B, C, D, E, F, DBR], 'R' => &[A, B, F, E, G, DBR],⋯ 198 unchanged lines ⋯         // pins is the total in a BGA too: 64 balls are an 8 x 8 grid         assert_eq!(package("bga", json!({"pins": 64}).as_object().unwrap()).unwrap().len(), 65);     }++    #[test]+    fn d_and_b_are_not_i_o_or_8() {+        // D was a box with a centre bar and read as "IO"; B was an 8 with a bar+        assert_ne!(glyph('D'), glyph('O'));+        assert_ne!(glyph('B'), glyph('8'));+        for c in ['D', 'B'] {+            let g = glyph(c).unwrap();+            assert!(g.iter().all(|s| s.0 .0 != 0.5 || s.1 .0 != 0.5), "{c} has no centre bar");+            assert!(!g.iter().any(|s| (s.0 == (1.0, 2.0)) || (s.1 == (1.0, 2.0))), "{c}'s top-right corner is cut");+        }+    } }+

Reviews

Colby Knox approved · 13d ago

Reviewed by standard-lane: 59 unit + 5 conformance pass; an OCCT top render of a QFN marked 'ADOM / B0D8' reads correctly (D has its full left side and cut right corners, B is not 8). Merging; released as standard 0.8.1 / engine 0.5.1.

Comments

No comments yet.

Log in to comment.