The slides for James' tutorial are here: [pdf]. His event page is here: [link].

A video recording is here: [skillsmatter].

### Why 3D Printing

The ever onward march of technology brings with it not just new innovations, but also makes them ever more affordable and practical.Printing 3-dimensional physical objects has seen a growth in popularity and accessibility in recent years. Practical applications are plenty, but so are creative ones too.

Suddenly, imagining 3-dimensional objects and making them reality is no longer the realm of magical fantasy or science fiction.

Here is an example of James' experiments - an interesting landscape made of hexagonal rock forms.

In algorithmic art, we can use computers to create art forms that no human hand could ever create. Extending this to 3-dimensional forms is exciting!

### OpenJSCAD

We're very fond of tools that work entirely in a browser, with no additional software needing to be installed. Not only does it make the tools independent of your computer brand, it also reduces technical complexity making them ideal for beginners. We love**openprocessing**, which is a

**p5js**environment entirely on the web.

James introduced OpenJSCAD, which allows us to use code to create 3-dimensional forms, which can then be exported in a form suitable for 3D printers.

James then led us through the basic concepts for coding in OpenJSCAD, together with some interesting challenges for us to tackle. You can see them being discussed on the video.

Here I'll try my own introductory tutorial to create simple 3D forms.

### Basic OpenJSCAD Ideas

OpenJSCAD will create 3-dimensional forms defined by computer program we write. That program is written in code which looks very much like**javascript**(tutorial).

OpenJSCAD expects to run a

**main()**function, and expects it to return a single object. That single object can be a single sphere or cube, or a collection of shapes which together form an interesting form.

Let's try creating the simplest of objects. Try replacing the

**main()**function with just the following simple code:

function main () {

return cube({size: 10, center: true});

}

**main()**is a

**cube**. The data inside the

**cube()**function sets the size to

**10**, and locates the centre of the object at the centre of the virtual world. Let's have a look at the result:

You can use your pointer to drag the view around and confirm it is indeed a 3-dimensional object:

If we want to compose a more interesting form, we need to use several basic shapes. Remember that the

**main()**function can only return one single thing, so that thing needs to be a group of other objects. That's called a

**union**here, which reflects the mathematical term, a

**union**of sets.

Here's how we use

**union**:

Let's try joining a

**cube**and a

**sphere**together:

function main () {

return union(

cube({size: 20, center: true}),

sphere({r: 12, center: true})

);

}

The sphere() function needs its

**radius**set, which we can see is set to

**12**here. Here's the result:

If we kept adding more shapes, they'd all be overcrowding the same origin of this 3-d world. We need a way to move them around. We can do this by using a

**translate()**function:

The

**translate()**function takes an object and translates it by

**[x, y, z]**along these axes. A translation of

**[1, 0, 0]**would translate an object only along the x-axis by

**1**.

Let's try it:

function main () {

return union(

cube({size: 10, center: true}),

translate([10, 0, 0], sphere({r: 6, center: true}))

);

}

The result is a

**cube**at the centre of the world, and a

**sphere**which has been shifted along the x-axis by

**10**units.

Let's chain a few of these shapes together. Here's some code which has a series of spheres and cubes all shifted along so that they form a nice line:

function main () {

return union(

translate([-30, 0, 0], sphere({r: 6, center: true})),

translate([-20, 0, 0], cube({size: 10, center: true})),

translate([-10, 0, 0], sphere({r: 6, center: true})),

translate([0, 0, 0], cube({size: 10, center: true})),

translate([10, 0, 0], sphere({r: 6, center: true})),

translate([20, 0, 0], cube({size: 10, center: true})),

translate([30, 0, 0], sphere({r: 6, center: true}))

);

}

Cool!

We can see how we could create quite sophisticated forms just by using a

**union**of simple objects. I you look at the OpenJSCAD reference, you'll see that other simple shapes like a cylinder, torus and a polyhedron, as well as flat shapes like a circle and a rectangle.You can use any of these in a union, and you can translate any of them too.

Let's look at one more shape modifier -

**scale**- which you can guess scales a shape. We use it in a similar way to translate where we pass it the object we want to scale.

The following code is the same as that above, but has the spheres scaled by

**1.7**.

function main () {

return union(

translate([-30, 0, 0],

**scale(1.7, sphere({r: 6, center: true}))**),

translate([-20, 0, 0], cube({size: 10, center: true})),

translate([-10, 0, 0],

**scale(1.7, sphere({r: 6, center: true}))**),

translate([0, 0, 0], cube({size: 10, center: true})),

translate([10, 0, 0],

**scale(1.7, sphere({r: 6, center: true}))**),

translate([20, 0, 0], cube({size: 10, center: true})),

translate([30, 0, 0],

**scale(1.7, sphere({r: 6, center: true}))**)

);

}

Here's the result.

We can see that only the spheres have been scaled, and that's because we only applied

**scale()**to the spheres.

We have an interesting shape that we could now bring to life with a 3D printer. We can use the export options to save a file accepted by many printers. The STL format is more or less the standard for 3D printing.

### More Interesting Ideas

We can do more than just join objects together. One really interesting idea is to subtract one object from another, a bit like carving out one shape from another.Let's go back to our example which had a simple union of a cube and a sphere. Let's change the union to a difference:

function main () {

return

**difference**(

cube({size: 10, center: true}),

translate([10, 0, 0], sphere({r: 6, center: true}))

);

}

Comparing the results, we can see that the difference takes the first object and craves out the second object.

We can combine several objects into a union, and use that union to crave out a shape from another object. Have a look at this code:

function main () {

return

**difference**(

cube({size: 10, center: true}),

**union**(

translate([10, 0, 0], sphere({r: 6, center: true})),

translate([-10, 0, 0], sphere({r: 6, center: true})),

translate([0, 10, 0], sphere({r: 6, center: true})),

translate([0, -10, 0], sphere({r: 6, center: true})),

translate([0, 0, 10], sphere({r: 6, center: true})),

translate([0, 0, -10], sphere({r: 6, center: true}))

)

);

}

We can see that we've constructed a union of six spheres, and that union is taken from a cube.

You can explore more ways of combining and transforming objects on the OpenSCAD reference pages.

### JavaScript Power

We also have the full power of javascript at our disposal. That means we can use loops, functions, and lasts to help construct sophisticated shapes more efficiently.Let's use a loop to construct a circle of spheres.

function main () {

// list of sheres

**var spheres = [];**

// loop

for (let angle = 0; angle < 360; angle += 40) {

let x = 10 * cos(angle);

let y = 10 * sin(angle);

**spheres.push**( translate([x, y, 0], sphere({r: 3, center: true})) );

}

return

**union(spheres)**;

}

You can see we create an empty list called

**spheres**, and then using a loop, we add lots of spheres to it, each translated according to a bit of trigonometry to follow the edge of a larger circle. Finally the

**main()**function returns the

**union**of the list of spheres.

We can extend this idea into the z-axis, and vary the size of the spheres too.

function main () {

// list of sheres

var spheres = [];

var z = 0;

var distance = 10;

var size = 1;

// loop

for (let angle = 0; angle < 720; angle += 10) {

let x = (0.1 + distance) * cos(angle);

let y = (0.1 + distance) * sin(angle);

spheres.push( translate([x, y, z], sphere({r: 0.1+size, center: true})) );

z += 0.2;

distance *= 0.99;

size *= 0.95;

}

return union (spheres);

}

The result is interesting, although not printable as it isn't a fully connected object.

A more printable composition can be made by carving out spheres from a block:

function main () {

// list of sheres

var spheres = [];

// loop

for (let angle = 0; angle < 360; angle += 40) {

let x = 10 * cos(angle);

let y = 10 * sin(angle);

spheres.push( translate([x, y, 0], sphere({r: 3, center: true})) );

}

var block = translate([0, 0, -3], scale( [3, 3, 0.3], cube({size: 10, center: true}) ) );

return difference(block, union(spheres));

}

The results are rather nice. In fact the union would make a nice physical object itself.

In the meetup itself, we were encouraged to explore using simple maths to calculate vertical blocks which form a landscape when places regularly on a grid.

James provides many more examples to explore on his GitHub repository.

### Physical Objects

James also brought along examples of 3D printed forms for us to experience for real.He did discuss some of the limitations of 3D printers that are priced to appeal to home enthusiasts.

- there is a limit to the fine detail and intricacy that cheaper printers can reproduce
- some objects bend and distort during the printing process
- some shapes are either impossible, or barely constructible
- the time taken to print objects is long, many minutes or hours even at medium quality settings

### Conclusion

James succeeded in showing how easily and accessibly we can create objects ready for 3D printing, and not just any object but objects created algorithmically through code.I was really pleased that the class was inspired by James, with some wanting to go on to try 3D printing themselves.

### References

- 3D and 3D printer file formats - https://all3dp.com/3d-printing-file-formats/
- James' GitHub repository of OpenJSCAD examples - https://github.com/jamesporter/learning-openjscad

## No comments:

## Post a Comment