CAD WITH CODE

Introduction

What’s OpenScad ?

OpenScad Features

CSG geometry engine

Constructive solid geometry (CSG) (formerly called computational binary solid geometry) is a technique used in solid modeling. Constructive solid geometry allows a modeler to create a complex surface or object by using Boolean operators to combine simpler objects. Potentially generating visually complex objects by combining a few primitive ones. Wikipedia

OpenSCAD GUI

More Information about User Interface

OpenScad support external editors

Yes, you can use your favourite text editor to code CAD objects.

OpenScad is able to check for changes of files and automatically recompile if a file change occurs. To use this feature enable “Design->Automatic Reload and Compile”.

Then, hide OpenScad editor ( View -> Hide Editor) and open the file (.scad) in both softwares: OpenScand and your external editor.

References

Learning by Coding: How to design a Lego brick

Inch = 25.4
Foot = (12 * Inch)

1. Measure your object or think about it

2. Create a cube

FYI : OpenScad Language Reference

cube([3,8,9],center=false);
// Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cube([brick_width, brick_length,brick_height],center=false);

Note how to comment code // Play with the parameters Finish a “command” with ;

// Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

color("red")
cube([brick_width, brick_length,brick_height],center=false);

To change the color use: color(“name_of_the_color”) or RGB color([1,0.5,0]) More Info Note color command doesn’t finis with ;

3. Create the top cylinders of the brick

// Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// End parameters

// 3D Model

color("red")
cube([brick_width, brick_length,brick_height],center=false);

for (a =[0:number_cyl-1]){

                // Step 2
                translate([3.9,(3.9+(8*a)),brick_height])
                cylinder( h = cyl_height, d=cyl_diameter, center = true);

                  // Step 4
                translate([3.9+8,(3.9+(8*a)),brick_height])
                cylinder( h = cyl_height, d=cyl_diameter, center = true);
         }

Don’t forget to parametrize the model Let’s talk about transform objects Let’s talk about loops

// OpenScad special variables
$fn = 50;

//Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// End parameters

// 3D Model

color("red")
cube([brick_width, brick_length,brick_height],center=false);

for (a =[0:number_cyl-1]){

                // Step 2
                translate([3.9,(3.9+(8*a)),brick_height])
                cylinder( h = cyl_height, d=cyl_diameter, center = true);

                  // Step 4
                translate([3.9+8,(3.9+(8*a)),brick_height])
                cylinder( h = cyl_height, d=cyl_diameter, center = true);
         }

4. Boolean operantions: union, difference, intersection of objects

// OpenScad special variables
$fn = 50;

//Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// End parameters

// 3D Model

union(){ // Lego Piece
    color("red")
    cube([brick_width, brick_length,brick_height],center=false);

    for (a =[0:number_cyl-1]){

                    // Step 2
                    translate([3.9,(3.9+(8*a)),brick_height])
                    cylinder( h = cyl_height, d=cyl_diameter, center = true);

                      // Step 4
                    translate([3.9+8,(3.9+(8*a)),brick_height])
                    cylinder( h = cyl_height, d=cyl_diameter, center = true);
     }
}

Play with difference boolean operators

5. Functions and Module

// OpenScad special variables
$fn = 50;

//Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// End parameters

module lego_brick(){

    // 3D Model
    // Boolean Operator
    union(){ // Lego Piece
        color("red")
        cube([brick_width, brick_length,brick_height],center=false);

        for (a =[0:number_cyl-1]){

                        // Step 2
                        translate([3.9,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);

                          // Step 4
                        translate([3.9+8,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);
                 }
    }
}

lego_brick();
use<module_example_1.scad>
lego_brick();

6. Internal Walls

// OpenScad special variables
$fn = 50;

//Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// Step 3
brick_wall = 1.2;

// Step 4
number_cyl = 4;
// Step 6
minicyl_diameter = 2.6;

// Step 10 - Int cyl
intcyl_diameter = 6.5;
intcyl_diameter2 = 4.8;
// End parameters

module lego_brick(){

    // 3D Model
    // Boolean Operator
    union(){ // Lego Piece
        color("red")
         difference(){ // Cube walls

                cube([brick_width, brick_length,brick_height],center=false);


                translate([brick_wall,brick_wall,-brick_wall])
                cube([brick_width-brick_wall*2, brick_length-brick_wall*2,brick_height-brick_wall],center=false);
            }
        for (a =[0:number_cyl-1]){

                        // Step 2
                        translate([3.9,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);

                          // Step 4
                        translate([3.9+8,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);
                 }
    }
}

lego_brick();

7. Internal cylinders

// OpenScad special variables
$fn = 50;

//Lego brick parameters

brick_width = 15.8;
brick_length = 31.8;
brick_height = 9.6;

cyl_diameter = 4.8;
cyl_height = 1.8;
number_cyl = 4;

// Step 3
brick_wall = 1.2;

// Step 4
number_cyl = 4;
// Step 6
minicyl_diameter = 2.6;

// Step 10 - Int cyl
intcyl_diameter = 6.5;
intcyl_diameter2 = 4.8;
// End parameters

module lego_brick(){

    // 3D Model
    // Boolean Operator
    union(){ // Lego Piece
        color("red")
         difference(){ // Cube walls

                cube([brick_width, brick_length,brick_height],center=false);


                translate([brick_wall,brick_wall,-brick_wall])
                cube([brick_width-brick_wall*2, brick_length-brick_wall*2,brick_height-brick_wall],center=false);
            }

            // Top Cyl
        for (a =[0:number_cyl-1]){

                        // Step 2
                        translate([3.9,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);

                          // Step 4
                        translate([3.9+8,(3.9+(8*a)),brick_height])
                        cylinder( h = cyl_height, d=cyl_diameter, center = true);
                 }

          // Internal Cyl
           color("yellow")
         for (a =[0:number_cyl-2]){
            translate([brick_width/2,8+8*a,-0.2])
                difference(){

                    cylinder( h = brick_height, d=intcyl_diameter, center = false);
                    translate([0,0,-brick_wall])
                    cylinder( h = brick_height-brick_wall, d=intcyl_diameter2, center = false);

                }
        }
    }
}

lego_brick();

8. Export 3D Model

OpenScad Tips and Tricks

1. Example of use parametric with Lego or re-use scripts: LEGO.scad

2. Modifier characters

3. Export to .dxf . From 3D to 2D -> Projection

Use projection() before define the 3D model.

Press F6

File -> Export -> Export to .dxf

4. Living Hinges for laser cut in Openscad

//////////////////////////// Parameters /////////////////////////////////////
//The y dimension of the hinge, parallel to the laser cuts
length=30;
//The x dimension of the hinge, transverse to laser cuts
width=200;
//The distance between parallel laser cuts
d=2;
//The distance between 2 collinear laser cuts
hinge_length=1;
//The number of hinges across the length of the hinge
hinges_across_length=1;
//How thick do you want the hinge to be
height=5;
///////////////////////////////// Main() //////////////////////////////////////
//preview[view:north, tilt:top]
projection(cut=false) linear_extrude(height) hinge(length=length,width=width,d=d,minimum_thinness=.01,hinge_length=hinge_length,hinges_across_length=hinges_across_length);
////Uncomment lines to see samples (all flat for DXF exporting)
//hinge();
//hinge(d=6);
//hinge(length=20, width=39,d=6,hinge_length=2.5,hinges_across_length=2,minimum_thinness=3);
//hinge(length=30, width=20,d=2,hinge_length=2.5,hinges_across_length=2,minimum_thinness=3,center=true);
//hinge(length=20, width=40,d=3,hinge_length=4,hinges_across_length=0,minimum_thinness=1);
//linear_extrude(height=5) hinge(length=20, width=40,d=6,hinge_length=2.5,hinges_across_length=2,minimum_thinness=3);
//add_hinge(width=20,length=length,center=true) square([3*length,length-1],center=true);
//add_hinge(width=20,length=90) translate([5,0]) circle(d=90);
//add_hinge(width=30,length=90,hinges_across_length=3) circle(d=90);
//add_hinge(width=30,length=90,hinges_across_length=3,center=false) circle(d=90);
//add_hinge(width=30,length=90,hinges_across_length=3,minimum_thinness=.1) circle(d=90);

/////////////////////////////// Functions /////////////////////////////////////
module hinge(length=30,width=20,d=3,minimum_thinness=3,hinge_length=3,hinges_across_length=2,center=false){
    //length = the y dimension of the hinge, parallel to the laser cuts
    //width = the x dimension of the hinge, transverse to laser cuts
    //d=the distance between parallel laser cuts
    //What is the minimum distance that two parallel lines can be apart before the laser does something catastrophic? E.g. setting uncontrollable fire to the work piece. This is "minimum_thinness"
    //hinge_length=the distance between 2 colinear laser cuts
    //hinges_across_length=the number of hinges across the length of the hinge
    //center is a boolean value, if true, place the center of the rectangle at the origin, if false, put the bottom left corner at the origin (just like square() and cube())
    ep=.00101;//epsilon, a small number,=1.01 micron, a hack (for OpenSCAD 2015.03) used to make square()'s which look like lines (which OpenSCAD doesn't support). Hopefully, your laser has a function which says something like "ignore cuts less than THRESHOLD apart", set that to anything greater than ep.
    adjust=center?-[width,length]/2:[0,0];//a vector for adjusting the center position
    th=d/2<minimum_thinness?ep:d/2;//If the distance between lines is less than the minimum thickness, just make linear cuts, specifically, set the width=th=thickness of the squares to ep, which is just above 1 micron (for 1=1mm slicers)
    n=floor(width/d);
    m=floor(abs(hinges_across_length)); echo(str("Number of hinges (m)=",m)); //input cleaning, ensures m ϵ {non-negative integers}
    echo(str("Suggested filename: Living Hinge-",length,"x",width,"mm-h=",m,"x",hinge_length,"-th=",th));
    echo(str("The distance between parallel laser cuts (d) is: ",d," mm."));
    //the length of the short lines
    short=(length-m*hinge_length)/(m+1);
    //the length of the long lines
    long=(length-(m+1)*hinge_length)/(m);
    echo(str("There should be n=",n," links in the hinge."));
    translate(adjust) difference(){ 
        square([width,length],center=false);
        if(m==0) 
            //In the special case where |hinges_across_length|<1, the hinge should look like:
            // |  --------------------------------------|
            // |--------------------------------------  |
            // |  --------------------------------------|
            // |--------------------------------------  |
                for(i=[0:n])
                    translate([i*d,(pow(-1,i))*hinge_length]) // (-1)^i,{iϵZ} = {-1,+1,-1,+1,...}
                        square([th,length]);                
        else
            //A hinge with hinges_across_length=2 should look like:
            // |------------  ------------  ------------|
            // |  -----------------  -----------------  |
            // |------------  ------------  ------------|
            // |  -----------------  -----------------  |
            for(i=[0:n]){ //Iterating across x
                translate([i*d*1,0]){ //Do the x translation seperate from the y translations
                    if(i%2==1) //For odd columns
                        for(j=[0:m-1]){
                            translate([0,hinge_length+j*(long+hinge_length)]) 
                                square([th,long]);
                            }
                    if(i%2==0) //For even columns
                        for(j=[0:m]){
                            translate([0,j*(short+hinge_length)]) 
                                square([th,short]);
                        }
                    }
                }
            }
    }

module add_hinge(length=30,width=20,d=3,minimum_thinness=3,hinge_length=3,hinges_across_length=2,center=true){
    //add_hinge() modifies another 2D object, by adding a hinge which is centered on the origin (by default, this can be changed to false, so that the bottom left corner of the hinge is at the origin. It uses the same parameters as hinge(). 
    //First, difference() a rectangle the size of the hinge from the child object (makes a hole for the hinge
    //Second, union() a hinge with First (puts the hinge in the hole)
    //Third, intersection() the child object with Second (cuts off any extra hinge that sticks out past the child object)
    intersection(){
        children();
        union(){
            hinge(length=length,width=width,d=d,minimum_thinness=minimum_thinness,hinge_length=hinge_length,hinges_across_length=hinges_across_length,center=center);
            difference(){
                children();
                square([width,length],center=center);
                }
            }
        }
    }    

Visual Programming: BlocksCAD

BlocksCAD is a cloud-based 3D modeling tool that encourages users to learn math, computational thinking and coding concepts through visualization and designing models to be 3D printed.

From Inkscape to OpenScad (2D - 3D)

- Select object -> Path -> Object to Path

- Path -> Difference

Python to generate .scad : a speech recognition example

import pyaudio
import speech_recognition as sr

#for index, name in enumerate(sr.Microphone.list_microphone_names()):
#    print("Microphone with name \"{1}\" found for `Microphone(device_index={0})`".format(index, name))

def text2int(textnum, numwords={}):
    if not numwords:
      units = [
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen",
      ]

      tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

      scales = ["hundred", "thousand", "million", "billion", "trillion"]

      numwords["and"] = (1, 0)
      for idx, word in enumerate(units):    numwords[word] = (1, idx)
      for idx, word in enumerate(tens):     numwords[word] = (1, idx * 10)
      for idx, word in enumerate(scales):   numwords[word] = (10 ** (idx * 3 or 2), 0)

    current = result = 0
    for word in textnum.split():
        if word not in numwords:
          raise Exception("Illegal word: " + word)

        scale, increment = numwords[word]
        current = current * scale + increment
        if scale > 100:
            result += current
            current = 0

    return result + current

r = sr.Recognizer()
r.pause_threshold = 1.0
r.phrase_threshold = 1.0
r.non_speaking_duration = 1.0

f= open("speech_to_cad.scad","w+")
with sr.Microphone() as source:
    print("STAR TO DESIGN...")
    r.adjust_for_ambient_noise(source)
    audio = r.listen(source)
    print("TIME OVER, THANKS")
try:
    primitiva = r.recognize_google(audio).lower()
    data = primitiva.split()
    for temp in data:
        print temp

    #primitiva = primitiva.split(' ':,1)
    print(data[0]+"(\""+data[1]+"\")"+data[2]+"(h="+data[3]+"$fn=100);");
    #color("blue") cylinder(h=10,$fn=100);
    #print(text2int(primitiva, numwords=1))
    f.write(data[0]+"(\""+data[1]+"\")"+data[2]+"(h="+data[3]+",$fn=100);")
    f.close()
except:
    pass;
  1. Open .scad in OpenScad -> File should be defined in python code ( speech_to_cad.scad )
  2. Run python code
  3. Speak ( color green shape height)
  4. Be patient…is not perfect…yet :-)