OpenSCAD Modules

What is it?

A module in OpenSCAD is similar to a macro or function in other languages. Creating a module allows you to easily reuse code and to create parametric models. To define a module:
module Name_of_module(param1,param2,...){
//statements...
}

You can specify default values in your definition like this:
module house(roof="flat", paint=[1,0,0]){
    color(paint)
    if(roof=="flat"){
        translate([0,-1,0])
        cube();
    }else if( roof=="pitched"){
       rotate([90,0,0])
       linear_extrude(height=1)
       polygon(points=[[0,0],[0,1],[0.5,1.5],[1,1],[1,0]],paths=[ [0,1,2,3,4] ]);
    }else if(roof=="domical"){
       translate([0,-1,0])
        union(){
            translate([0.5,0.5,1]) 
            sphere(r=0.5,$fn=20);
            cube();
        }
    }
}


To use the module:
house();
translate([1,0,0])
house("pitched", [0,1,0]);
example_house.png



Creating a Module

  1. Open OpenSCAD


  2. In the editor add code to define the name of a module. The module should be called join_two_points. This module will take the following parameters:
    • x1
    • y1
    • z1
    • x2
    • y2
    • z2
    • diameter



  3. You will use the distance formula to create the value for a variable called length.
    Inside the module, create a variable called length and set it to
    sqrt( pow(x1 - x2, 2) + pow(y1 - y2, 2) + pow(z1 - z2, 2) );
    

  4. Tertiary syntax allows you to test a conditional and assign a value based on the evaluation in one line:
    //if a is less than b then set the string to "hello"
    //if a is not less than b then set the string to "good bye"
     ((a<b) ? string="hello": string="good bye");
     
    You want to determine if the difference between the y1 and y2 is not 0. If this condition is met than you want to set alpha to the inverse tangent (arctangent) of (z2 - z1) / (y2 - y1).

    The arctangent is used to calculate the angles of a right triangle. It will return the angle of the given ratio.

    To illustrate arctangent, start with a right triangle with sides a and b. The typical way to use the tangent function is to calculate the ratio of the two non-hypotenuse sides of a right triangle, such as a and b, from the angle (θ) between b and the hypotenuse. This is indicated as tan(θ) = b / a.

    arctangent works in the opposite direction; you can use the ratio b / a to find the angle θ, such that θ = atan(b / a).
    atnp.gifatnp2.gif
    Create a variable named beta and if x2- x1 does not equal 0 than set beta to 90-atan( (z2 - z1) / (x2 - x1) ) otherwise set it to 90- 0.


  5. Create a variable named gamma and if x2- x1 does not equal 0 than
    set gamma to atan( (y2 - y1) / (x2 - x1)

    Otherwise
    set gamma to ( (y2 - y1 >= 0) ? 90 : -90 ) ) + ( (x2 - x1 >= 0) ? 0 : -180 )


  6. To display values of variables, you use the keyword echo
    	echo(Length = length, Alpha = alpha, Beta = beta, Gamma = gamma);	
    



  7. Call translate() and translate the object by x1, y1, z1


  8. Call rotate() and rotate the object by 0, beta, gamma


  9. Create a cylinder where the height = length and radius = diameter/2


  10. To use the module you specify the starting x, y and z and the ending x, y and z:
    join_two_points(0, 0, 0, 50, 0, 0, 5 ); // +X
    join_two_points( 50, 0, 0, 50, 50, 0, 5 ); // -X
    join_two_points(  50, 50, 0, 0, 50, 0, 5 ); // +Y
    join_two_points( 0, 50, 0, 0, 0, 0, 5 ); // -Y
    join_two_points( 0, 0, 0, -50, -50,0, 5 ); // -X -Y
    join_two_points( 0, 0, 0, 50, 50, 50, 5 ); // +XYZ
    



  11. Here is the module to add rounded corners:
    module corner(x, y, z, diameter){
    	translate([x, y, z])
    	sphere( r = diameter/2 );
    }



  12. This code:
    diameter=2;
    cubeHeight=10;
    width=50;
    length=50;
    innerWidth=20;
    innerLength=10;
    translate([-25,-25,-10]){
    	cube([width,length,cubeHeight]);
    		for(z=[0:2]){
    			perimeter(width,length,cubeHeight+z*diameter,diameter);
    		}
    		translate([(width-innerWidth)/2,(length-innerLength)/2,0]){
    			for(z=[0:2]){
    			perimeter(innerWidth,innerLength,cubeHeight+z*diameter,diameter);
    		}
    	}
    }
    produces this:



  13. Complete the program by creating the module perimeter.


  14. View the model by pressing F5.


  15. Render and Compile by pressing F6. Then select Design>Export as STL






Using Variables

You could rewrite the module so that it would be parametric:
module house(roof="flat", paint=[1,0,0], s=20){
    color(paint)
    if(roof=="flat"){
        translate([0,-s,0])
         cube(s);
    }else if( roof=="pitched"){
       rotate([90,0,0])
       linear_extrude(height=s)
       polygon(points=[[0,0],[0,s],[s/2,3*s/2],[s,s],[s,0]],paths=[ [0,1,2,3,4] ]);
    }else if(roof=="domical"){
       translate([0,-s,0])
    	   union(){
       	translate([s/2,s/2,s]) 
		sphere(r=s/2,$fn=20);
      	cube(s);
       }
    }
}

  house();
  translate([40,0,0]) house("pitched");
  translate([80,0,0]) house("domical",[0,1,1]);
  translate([0,40,0]) house(roof="pitched",paint=[0,0,1]);
  translate([20,20,0]) house(paint=[0,0,0],roof="pitched");
  translate([60,40,0]) house(roof="domical");
  translate([80,60,0]) house(paint=[0,.5,.2]);