µCAD: A declarative language for geometry processing

2024-11-25

In the past months, we have been working on a project called µCAD, a declarative language for geometry processing.

The goal

The goal of this project is to provide a high-level language for describing parametric geometries and operations. For example, we can describe parametric geometries using primitives like cylinders and circles and combine them with boolean operations. Moreover, we want to export the geometry to formats like SVG and STL in a way that is easy to understand and write. The language is designed to be simple but expressive, allowing users to quickly create reusable parametric modules without having to worry about the low-level details of geometry processing.

History

I did a lot of modeling with OpenSCAD, and while it is a powerful tool, I found that the language had several short-comings, which made it difficult to create complex models. I also wanted to learn Rust and more about compilers, so I decided to create a new language that would address these issues. The goal create a declarative, domain-specific language with a static type system that was more expressive and easier to use, so we set out to create µCAD.

The sample project

Winter is coming, and I needed a lid to close the openings of my water irrigation system. I decided to create a model of the lid in µCAD. The model consists of a cylinder with a closed cap, with an inner diameter of 16cm. Its height is supposed to be 20mm. For the thickness, I choose 1.6mm, because the model will be 3D printed with a 0.8mm wide nozzle. Moreover, I wanted to know the volume of the model to estimate the weight of the print.

This is the resulting STL model rendered by µCAD: Lid

The code in µCAD looks like this:

// Import everything from the standard library
use std::*;

// We have module called `lid` with three parameters
module lid(
    thickness = 1.6mm,
    inner_diameter = 16.0cm,
    height = 20.0mm,
) {
    // Calculate the outer diameter
    outer_diameter = 2.0 * thickness + inner_diameter;

    // Use the geo3d::cylinder module from the standard library
    use geo3d::cylinder;

    // Create two cylinders, one for the outer and one for the inner
    outer = cylinder(d = outer_diameter, h = height);
    inner = translate(z = thickness) cylinder(d = inner_diameter, h = height);

    // Calculate the difference between two translated cylinders and output them
    outer - inner;
}

// `l` is the instance of the lid model
l = lid();

// Print out the volume of the model instance
print("Volume: {l.volume() / 1000}cm³");

// Export the stl of the model instance
export("lid.stl") l;

The program above will print out the following text and export the model to STL.

Volume: 48.415571412489506cm³

We can now load the STL in Cura to generate G-Code and print it:

Lid

This is how the print looks like, printed with recycled transparent PETG:

Lid

Now, we can install the lid and my irrigation is winter-proof!

Lid Lid

µCAD is work in progress. The language is still in development, and there are many features that are not yet implemented. Right now, proper error handling is missing to make it usable for a wider audience. We hope to make the repository public in the upcoming months.