The scad crate: Write openSCAD models using rust

I recently published scad, a crate I started
working on a couple of years ago which allows you to write OpenSCAD models
using the rust language.

The advantage here is that you get the power of the rust ecosystem and language
combined with the CAD features of openSCAD.

Usage

//"Import" the module along with the macros
#[macro_use]
extern crate scad_generator;

//Avoid having to write scad_generator:: everywhere
use scad_generator::*;

pub fn main() {
    //Create an scad file object for storing the scad objects. This
    //allows us to set things like the detail level ($fn) for the models.
    let mut scad_file = ScadFile::new();

    //Sets the $fn variable in scad which controls the detail level of things
    //like spheres. Look at the scad wiki for details
    scad_file.set_detail(50);

    //Create an scad object
    let mut cube = scad!(Translate(vec3(2.0, 2.0, 3.0)); {
        scad!(Cube(vec3(2.0,1.0,4.0)))
    });

    //Create a cylinder with a height of 10 and a diameter of 3 mm
    let cylinder = scad!(Cylinder(10., Diameter(3.)));

    //Add the cylinder to the cubes translation.
    cube.add_child(cylinder);

    //Add the cube object to the file
    scad_file.add_object(cube.clone());

    //Save the scad code to a file
    scad_file.write_to_file(String::from("out.scad"));

    //You can also print the code for the object manually since it's just a string
    println!("{}", scad!(Cube(vec3(5., 3.,  2.))).get_code());
}

The above code shows some basic usage of the library. The scad! macro allows
you to write code that is similar to the equivalent openSCAD code. You can also
do more advanced things by using the underlying ScadObject type.

When you run the code, you normally write the resulting SCAD code to a file
which you then open in OpenSCAD to see the results.

Why?

OpenSCAD is a great tool, but the language isn't a great programming language
and the tooling around it is lacking compared to rust. Being able
to easily import libraries using cargo, and having a good type system are
very good things.

However, what tipped me over the edge was the following scad code:

current_value = 5;

echo(current_value);

for( i = [0: 3])
{
    current_value = current_value + i;
    echo(current_value);
}

current_value = 10;
echo(current_value);

I think most of us would expect it to print

5
5
6
8
11
10

But because of the way SCAD works, it prints this:

ECHO: 10
ECHO: 10
ECHO: 11
ECHO: 12
ECHO: 13
ECHO: 10

Generally, this is not a problem but for some projects it made things way more tricky than they should have been.

Future plans

I wrote this library a couple of years ago before knowing a lot of the things
I do now which means that I have a plan in the back of my head to rewrite the
library without the ScadElement enum and replace it with traits. However,
for my own personal use, the current structure works well enough for me to
not bother.

The library also doesn't include all OpenSCAD primitives. I have included the ones
i've had a use for in my own projects, but adding more should be fairly simple
and I would love to get pull requests for additional primitives :slight_smile:

4 Likes