M.Eva – OpenSCAD Makes

First OpenSCAD Design

I made a pencil/pen holder.  I tried to start relatively simple to start out.  In order to make it I had did have to go back and follow the code used in the PolyBowl video because I still don’t completely remember how some pieces of code, like offset and if, work so I needed the video to refresh me and guide me through it.  So the code to create the hollow body comes heavily from that video.

I did want to do something a bit more challenging than just this, so I put a hexagon design on it and I know there may very well be a much easier way to do this, but I couldn’t figure it out so I just did what I found to make sense.  I made a hexagon log and repeated it over and over then differenced it out from the body of the form.

The final outcome is okay, I think.  The pattern looks weird on it, but I think that’s because it doesn’t follow the shape of the body.  And as I said before, there might be a way to have done that but I don’t know the program or code well enough to have figured it out yet.

Also I’m not sure why but when previewing the make it does this:

I don’t know whats happening and if it means I did something wrong but either way I find it kinda funny that it happens.  If you render it then it looks right and the file opens in Cura just fine but who knows.  I sure don’t.

OpenSCAD Code:

////base shape
Length = 40;
Width = 50;
edge = 2;
thickness = 4;
////body form guides
RimHeight = 3;
BodyHeight = 120;
BaseHeight = 6;
Opening = 1.5;
$fn = 100;
////hex pattern guides
HLlength = 200;
Patternbegin = 28;
hexSize = 11.5;

base();
difference(){
    body();
    HexPattern();
}
rim();

//////hex shape/////////////////////////////
*rotate(90,[0,1,0]){
    circle(hexSize,$fn=6);
}

////////////////////////////////////////////
////////////MODULES/////////////////////////
/////////////////////////

module BaseShape(solid){
    difference(){
        offset(20)
            minkowski(){
                square([40,50],true);
                circle(edge);
            }
        if (solid=="no"){
            offset(20-thickness){
                minkowski(){
                    square([Length,Width],true);
                    circle(edge);
                }
            }
        }
    }
}

module base(){
    translate([0,0,0]){
        linear_extrude(BaseHeight){
            BaseShape(solid="yea");
        }
    }
}

module rim(){
    translate([0,0,BodyHeight+BaseHeight]){
        linear_extrude(RimHeight){
            scale(Opening){
                BaseShape(solid="no");
            }
        }
    }
}

module body(){
    translate([0,0,BaseHeight]){
        linear_extrude(height=BodyHeight,scale=Opening){
            BaseShape(solid="no");
        }
    }
}

module hexlog(){
    translate([-HLlength/2,0,Patternbegin]){
        rotate(90,[0,1,0]){
            linear_extrude(HLlength){
                circle(hexSize,$fn=6);
            }
        }
    }
}

module hexPatternSingle(){
    hexlog();
    rotate(30,[0,0,1]){
        hexlog();
    }
    rotate(60,[0,0,1]){
        hexlog();
    }
    rotate(90,[0,0,1]){
        hexlog();
    }
    rotate(120,[0,0,1]){
        hexlog();
    }
    rotate(150,[0,0,1]){
        hexlog();
    }
}

module HexPattern(){
    hexPatternSingle();
    translate([0,0,hexSize*2]){
        rotate(15,[0,0,1]){
            hexPatternSingle();
        }
    }
    translate([0,0,hexSize*4]){
        rotate(30,[0,0,1]){
            hexPatternSingle();
        }
    }
    translate([0,0,hexSize*6]){
        rotate(45,[0,0,1]){
            hexPatternSingle();
        }
    }
}

 

 

Object Design no.2

This time, I focused on using the rotate extrude function as well as the for function.  For the for function, I used what we talked about in the last class meeting, as well as multiple tests in scrap files.  I also, like every time I use OpenSCAD, often refer to the quick guide and digital user manual.  That’s how I fixed some issues I had with the rotate extrude.  So there reading and may hours of just testing in OpenSCAD.

I stayed simple, mostly for my own sanity if for anything.  My idea for it is as a bowl holder (like a fruit bowl or something), but the more I looked at it the more it looks like a fire pit or like a pot holder.  Could be the leg height.

It’s just a fire pit no matter what I do.

Then, when I looked at it small, I realized that if you make it small enough, it becomes a holder for one single egg.  Which is really funny to me.  A fancy table for just one egg.

If you twist the legs too much they stick out through the top, but at some point you can keep twisting it out so it works again.  I’ve found the working twist ranges to be 0-35° & 235-360°.

35°
135°
235°

I spent a lot of time trying to make it adaptation-friendly.  A lot of time (a sad amount of time, probably too much time) went in to figuring out what each specific variable in the code does so I could give it a specific parameter that gives a proper output as well as condensing code.  On the upside, that helped me understand what each part of the code itself does so that’s a plus.

In general, there are a number of elements that can be changed now without a negative effect but I can’t get it to be completely scalable for all things without a lot of little 0.x changes to different parameters – it might take more time to get that all put into place, so one parameter change would scale the whole thing properly.

Also when you give it like 26 legs it’s just too many legs but funny looking.

OpenSCAD Code:

////////leg parameters////////
foot = 2;
leg_height = 20;
twist_degree = 35;
scale_up = 2;
leg_poly = 4;
number_of_legs = 3;
////////top parameters////////
doughnut_poly = 60;
top_width = 6.6;
top_height = 2;
round_edge = 0.15;
inside_slope = 3;
////////universal diameter parameters////////
distance_from_x = 20;


difference(){
    top();
    top_removed();
}

for(L=[0:360]){
    rotate(360/number_of_legs*L,[0,0,1]){
        Leg2();
    }
}


//////////////////////////////////////////////////////////
//////////////////modules/////////////////////////////////
//////////////////////////////////////////////////////////

module Leg2(){
    *square([1,distance_from_x]);
    translate([0,distance_from_x,0]){
        linear_extrude(height=leg_height,twist=twist_degree,scale=scale_up, $fn=leg_poly){
            square(foot);
        }
    }
}

module top(){
    rotate_extrude($fn=doughnut_poly){
        translate([distance_from_x,leg_height+top_height/2,0]){
            scale(scale_up/1.3){
                minkowski(){
                    square([top_width,top_height],true);
                    circle(round_edge);
                }
            }
        }
    }
}

module top_removed(){
    rotate_extrude($fn=doughnut_poly){
        translate([distance_from_x-top_width/1.4,leg_height+top_height+2,0]){
            scale(scale_up/1.3){
                circle(inside_slope);
            }
        }
    }
}

 

 

Pencil/Pen Holder Iteration

I chose to iterate my earlier pencil holder design.  I liked it the most and wanted to tackle patterning with for loops again.

Not much changed besides labeling stuff more, separating things into modules for organization, using the for function for the pattern, and using a star shape rather than a hexagon.

I also gave it a little foot bottom type thing.  Like you find on bowls and such.

I think I got it better than before – it definitely got easier and cleaner looking with the use of the for function, though I don’t think the pattern is quite perfect yet.  That, however, I think is more on the side of the angles and rotations being a difficult thing to grasp entirely, combined with it being subtracted off a shape that scales up.  It is fun to change the numbers and make the pattern different though.  It also still does that ghosty thing.

I’m not entirely sure where to section off the new code from old, since I sort of tweaked everything so I’m putting the entire code here.

OpenSCAD Code:

////BODY PARAMETERS////
Length = 80;
Width = 80;
holder_side_thickness = 3;
footheight = 2;
baseheight = 4;
holderheight = 150;
scale_up_value = 1.4;
rimheight = 4;
////STAR PARAMETERS////
star_size = 0.25;
loglength = 100;
A = 4;///distance between stars vertically
rotation = 50;///effects distance between stars horizontally, how many stars there are
B = 90;///rotation of 0-360, effects how high the star pattern goes
$fn = 100;



Rim();
difference(){
    Body();
    StarPattern();
}
Base();
Foot();



/////////////////////////////////////////////
////////modules//////////////////////////////
/////////////////////////////////////////////
module ShapeBase(solid){
    difference(){
        offset(10)
            minkowski(){
                square([Length,Width],true);
                circle(0.1);
            }
        if (solid=="no"){
            offset(10-holder_side_thickness){
                minkowski(){
                    square([Length,Width],true);
                    circle(0.1);
                }
            }
        }
    }
}

module Star(){
    rotate(90,[1,0,0]){
        linear_extrude([0,0,loglength]){
            scale(star_size){
                polygon([[0,40],[15,0],[60,0],[25,-25],[40,-70],[0,-45],[-40,-70],[-25,-25],[-60,0],[-15,0]]);
            }
        }
    }
}

module StarPattern(){
    for(a=[0:B]){
        rotate(rotation*a,[0,0,1]){
            translate([0,0,A*a]){
                Star();
            }
        }
    }
}

module Rim(){
    translate([0,0,footheight+baseheight+holderheight]){
        linear_extrude(rimheight){
            scale(scale_up_value){
                ShapeBase("no");
            }
        }
    }
}
            
module Body(){
    translate([0,0,footheight+baseheight]){
        linear_extrude(holderheight,scale=scale_up_value){
            ShapeBase("no");
        }
    }
}

module Base(){
    translate([0,0,footheight]){
        linear_extrude(baseheight){
            ShapeBase("radish");
        }
    }
}

module Foot(){
    linear_extrude(footheight){
        ShapeBase("no");
    }
    linear_extrude(footheight){
        minkowski(){
            square([Length,Width],true);
            circle(3);
        }
    }
}

 

 

Randomization

I just like storage containers, so I made a box.  With a lid that has a pattern.

I used the random code given to us, but I didn’t find a use for the subrandom bits so I didn’t use them.  Also they confused me too much.  For the pattern I used this source to get the for looping code right.  I ended up combining two and messing around until I got it to work.

The shapes aren’t exactly like I was imagining, and I think they could get better, but for right now I think they’re fine.

OpenSCAD Code:

custom_seed = 0;
custom_seedPATTERN = 0;

////BODY PARAMETERS////
base_thickness = 3;
holder_height = 14;
wall_thickness = 1.5;
lid_height = 3;
lid_float = 2;
////PATTERN PARAMETERS////
sizePATTERN = 0.5;
rows = 10;
columns = 10;
vertical_spacing = 24*sizePATTERN;
horizontal_spacing = 24*sizePATTERN;
////SEED:COLOR NOTATIONS////
colorBody = "plum";
colorPattern = "mediumaquamarine";
show_seed = "yes"; //[yes:Yes,no:No]
show_seedPATTERN = "yes"; //[yes:Yes,no:No]


///RENDERS////

color(colorBody)
    linear_extrude(base_thickness){
        RandomizedOval(solid="turnip");
    }

color(colorBody)
    translate([0,0,base_thickness]){
        linear_extrude(holder_height){
            RandomizedOval(solid="no");
        }
    }
    
color(colorPattern)
    Lid();



/////////////////////////////////////////////////
////BODY CODE////////////////////////////////////
/////////////////////////////////////////////////
module RandomizedOval(solid){
    difference(){
        offset(10){
            resize([random[1]*2.5,random[2]*1.5])circle(random[3]);
            }
        if (solid=="no"){
            offset(10-wall_thickness){
                resize([random[1]*2.5,random[2]*1.5])circle(random[3]);
            }
        }
    }
}
module Lid(){
    translate([0,0,base_thickness+holder_height+lid_float]){
        linear_extrude(lid_height){
            RandomizedOval(solid="no");
        }
    }
    translate([0,0,base_thickness+holder_height-1+lid_float]){
        linear_extrude(lid_height){
            difference(){
                RandomizedOval(solid="turnip");
                RandomizedOval(solid="no");
                PatternBlock();
            }
        }
    }
}

//////////////////////////////////
////RANDOMIZER CODE BITS, BODY////
//////////////////////////////////
random_seed = floor(rands(1,9999999,1)[0]);

seed = (custom_seed==0) ? random_seed : custom_seed;

echo(labelString);

maxSteps=30*1;
random = rands(0,30,maxSteps,seed);
echo(random);

////////////////////////////////////////
////SEED LABELING, BODY////
////////////////////////////////////////
labelString=str(floor(seed/1000000)%10, floor(seed/100000)%10, 
                floor(seed/10000)%10, floor(seed/1000)%10, 
                floor(seed/100)%10, floor(seed/10)%10, 
                floor(seed/1)%10);

if(show_seed=="yes"){
    translate([0,-54,0]) 
        color(colorBody)
        %linear_extrude(height=1)
            text(labelString,size=4,halign="center");
}

/////////////////////////////////////////////////
////////PATTERN CODE/////////////////////////////
/////////////////////////////////////////////////
module Pattern(){
    scale(sizePATTERN){
        polygon([
        [randomPATTERN[0],randomPATTERN[1]],
        [randomPATTERN[2],randomPATTERN[3]],
        [randomPATTERN[4],randomPATTERN[5]],
        [randomPATTERN[6],randomPATTERN[7]],
        [randomPATTERN[8],randomPATTERN[9]]
        ]);
    }
}
module lineup(num,space){
    for (i = [0:num-1]){
        translate([space*i,0,0])children();
    }
}
module PatternBlock(){
    for(b=[0:rows-1]){
        translate([(-horizontal_spacing*columns)/2,b*vertical_spacing-((vertical_spacing*rows)/2),0]){
            lineup(columns,horizontal_spacing)Pattern();
        }
    }
}

/////////////////////////////////////
////RANDOMIZER CODE BITS, PATTERN////
/////////////////////////////////////
random_seedPATTERN = floor(rands(1,9999999,1)[0]);

seedPATTERN = (custom_seedPATTERN==0) ? random_seedPATTERN : custom_seedPATTERN;

echo(labelStringPATTERN);

maxStepsPATTERN=42*1;
randomPATTERN = rands(1,36,maxStepsPATTERN,seedPATTERN);
echo(randomPATTERN);

//////////////////////////////
////SEED LABELING, PATTERN////
//////////////////////////////
labelStringPATTERN=str(floor(seedPATTERN/1000000)%10, floor(seedPATTERN/100000)%10, 
                floor(seedPATTERN/10000)%10, floor(seedPATTERN/1000)%10, 
                floor(seedPATTERN/100)%10, floor(seedPATTERN/10)%10, 
                floor(seedPATTERN/1)%10);

if(show_seedPATTERN=="yes"){
    translate([0,-60,0]) 
        color(colorPattern)
        %linear_extrude(height=1)
            text(labelStringPATTERN,size=4,halign="center");
}

 

 

Final Projects with Randomization

At first I thought to continue what I had been doing, container or table sorts, but then I realized I could sort of recreate the idea of my original final project – the base pedestal piece with something on top.  Now while it isn’t the exact same shapes and forms, the idea is there so I thought that would be a really cool way to both tie in my original final puzzle design theme and this project.  Also, my original final project idea did hold an element of randomness (the object inside the puzzle was a random unknown outcome) so even that ties in!  Way better way to go than a funky table.  So, using the now easier randomizing code, I made this application-crashing monstrosity.

There’s a lot happening in each render, so OpenSCAD sort of threatens to crash every now and again (it did once while I was writing the code, wound of losing what I had written but it was okay I was able to redo and simplify it).

 

Also, compared to my last randomized piece, where I had two seeds, I was able to figure out how to make every element work within only one seed.  It took a couple times and a few practice codes for some functions I wound up not using to realize how to make the twist varied and dramatic.

My original fear was that with one seed, either the twist would only be a max of around 20 or every other size element would just be way too big.  After spending time trying to learn sine and cosine (I couldn’t really figure it out in a way that would work in this project so I didn’t use it), the example code from the OpenSCAD user manual had something like sin(360/x) and I realized that I should just make the twist 360/random.  Took me way to many days to realize that.  Whoops.

I really like the randomization, and I wish I knew how to use OpenSCAD a little more or at least could understand what the videos I watch are talking about to have been able to use some of the more complex elements (at least to me) like sine and cosine in this project.  But all the same, I still like what I got and I think it still holds the spirit of my original final project, so that’s a bonus.

OpenSCAD Code:

/////RANDOM #S USED :
    ///  1 2 3 4 5 6
//// random no.s used:
    //// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

$fn = 5;


translate([0,0,1+random[3]+10+random[4]+5+random[6]+4+1.4+10]){
    scale(0.4)
        color("powderblue")
        Topper();
    mirror([0,1,0]){
        scale(0.4)
            color("aqua")
            Topper();
        }
    mirror([1,0,0]){
        scale(0.4)
            color("turquoise")
            Topper();
        }
    rotate(180,[0,0,1]){
        scale(0.4)
            color("deepskyblue")
            Topper();
        }
}

color("royalblue")
translate([0,0,1+random[3]+10+random[4]+5+random[6]+4+1.4+11]){
    sphere(d=10,true,$fn=20);
}

color("ivory"){
    Stand();
}



//////////////////////////////////////////
/////////////////MODULES//////////////////
//////////////////////////////////////////
module Stand(){

    linear_extrude(2){
        circle(random[1]+6,$fn=random[2]);
    }

    translate([0,0,1]){
        linear_extrude(random[3]+10,scale=0.5){
            circle(random[1]+6,$fn=random[2]);
        }
    }

    translate([0,0,1+random[3]+10]){
        linear_extrude(random[4]+5,twist=350/random[5]){
            scale(0.5)
                circle(random[1]+6,$fn=random[2]);
        }
    }

    translate([0,0,1+random[3]+10+random[4]+5]){
        linear_extrude(random[6]+4,scale=2){
            scale(0.5)
                circle(random[1]+6,$fn=random[2]);
        }
    }

    translate([0,0,1+random[3]+10+random[4]+5+random[6]+4]){
        linear_extrude(1.4){
            minkowski(){
                square((random[1]+6)*2.5,true);
                circle(2);
            }
        }
    }

}

module Topper(){
    
    for(A=[0:random[23]],B=[0:random[24]],C=[0:random[25]]){
        
        //////A
        angle_rotateA = A*360/random[22];
        
        rotate(angle_rotateA*random[23],[0, 0, 1]){
            linear_extrude(height=10+random[20]*10,twist=360/random[21]){
                polygon([
                [random[0],random[1]], //1
                [random[2],random[3]], //2
                [random[4],random[5]], //3
                [random[6],random[7]], //4
                [random[8],random[9]], //5
                [random[10],random[11]], //6
                [random[12],random[13]], //7
                [random[14],random[15]], //8
                [random[16],random[17]], //9
                [random[18],random[19]] //10
                ]);
            }
        }
        
        //////B
        angle_rotateB = B*360/random[26];
        
        rotate(angle_rotateB*random[28],[0, 1, 1]){
            linear_extrude(height=10+random[20]*20,twist=360/random[21]){
                polygon([
                [random[0],random[1]], //1
                [random[2],random[3]], //2
                [random[4],random[5]], //3
                [random[6],random[7]], //4
                [random[8],random[9]], //5
                [random[10],random[11]], //6
                [random[12],random[13]], //7
                [random[14],random[15]], //8
                [random[16],random[17]], //9
                [random[18],random[19]] //10
                ]);
            }
        }    
        
        //////C
        angle_rotateC = C*360/random[27];
        
        rotate(angle_rotateC*random[29],[1, 0, 1]){
            linear_extrude(height=10+random[20]*20,twist=360/random[21]){
                polygon([
                [random[0],random[1]], //1
                [random[2],random[3]], //2
                [random[4],random[5]], //3
                [random[6],random[7]], //4
                [random[8],random[9]], //5
                [random[10],random[11]], //6
                [random[12],random[13]], //7
                [random[14],random[15]], //8
                [random[16],random[17]], //9
                [random[18],random[19]] //10
                ]);
            }
        }    

    }
    
}


////////////////////////////////////////
//////////RANDOMIZATION CODE////////////
////////////////////////////////////////
random_seed = floor(rands(1,9999999,1)[0]);
custom_seed = 0;
seed = (custom_seed==0) ? random_seed : custom_seed;
maxSteps=30;
random = rands(0,18,maxSteps,seed);
show_seed = "yes"; //[yes:Yes,no:No]
labelString=str(floor(seed/1000000)%10, floor(seed/100000)%10, 
                floor(seed/10000)%10, floor(seed/1000)%10, 
                floor(seed/100)%10, floor(seed/10)%10, 
                floor(seed/1)%10);
if(show_seed=="yes"){
    translate([0,-50,0]) 
        color("deeppink")
        %linear_extrude(height=1)
            text(labelString,size=4,halign="center");
}
echo(labelString);
echo(random);