I keep designing physical parts for our robots. Motor mounts, sensor brackets, wheel hubs. Every time, the workflow is the same: open a GUI CAD program, click around for an hour, export an STL, realize the bolt pattern is 2mm off, repeat. I wanted to write my parts the way I write firmware. In Rust. With types. With version control. With the ability to change one number and regenerate everything. So I built vcad. cargo add vcad The idea A part is just geometry with a name. You create primitives, combine them with boolean operations, and export. That's it. use vcad::{centered_cube, centered_cylinder, bolt_pattern}; let plate = centered_cube("plate", 120.0, 80.0, 5.0); let bore = centered_cylinder("bore", 15.0, 10.0, 64); let bolts = bolt_pattern(6, 50.0, 4.5, 10.0, 32); let part = plate - bore - bolts; part.write_stl("plate.stl").unwrap(); That minus sign is a real boolean difference. + is union. & is intersection. Operator overloads make CSG feel like arithmetic. The plate above has a center bore, four corner mounting holes, and a six-bolt circle pattern. Twelve lines of code. One STL file. Done. What you can build The API is small on purpose. Primitives, booleans, transforms, patterns. That's the whole language. But it composes well. An L-bracket with mounting holes in both faces: let base = centered_cube("base", 60.0, 40.0, 4.0); let wall = centered_cube("wall", 60.0, 4.0, 36.0) .translate(0.0, -18.0, 20.0); let bracket = base + wall - base_holes - wall_holes; A flanged hub with a bolt circle: let hub = centered_cylinder("hub", 15.0, 20.0, 64); let flange = centered_cylinder("flange", 30.0, 4.0, 64) .translate(0.0, 0.0, -10.0); let part = hub + flange - bore - bolt_pattern(6, 45.0, 3.0, 8.0, 32); A radial vent pattern cut from a disc — one slot, repeated eight times: let slot = centered_cube("slot", 15.0, 2.0, 10.0); let vents = slot.circular_pattern(20.0, 8); let panel = centered_cylinder("panel", 35.0, 3.0, 64) - vents; Every part here is parametric. Change the ...
First seen: 2026-01-27 22:07
Last seen: 2026-01-28 11:26