Using OpenSCAD to produce drawings for 3D Printing

A place where discussions are about 3D printing.
User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Sat Apr 10, 2021 9:37 am

I thought I'd do a thread introducing OpenSCAD because I haven’t seen it discussed much on the forum. It's maybe not so much a tutorial as a journal of discovery as I’ve only just begun exploring it myself. Also it may get a little bit evangelical, because I really really love this program.

First of all, what is it? OpenSCAD is an application for drawing printable 3D models. It is open source and you download it to your computer – so you will never lose your work because it has stopped being available or started charging. And it is different from other 3D drawing programs like TinkerCAD, Blender, Fusion360 etc. in that it is entirely text driven. This may put some people off, but for me it makes it much easier to be precise... but that's only the beginning, there's a huge amount of power here that makes it much easier to adjust and amend your drawings even once they have become quite complex.

So I thought I would start by showing how I have been drawing a wheel. Despite this, fortunately I managed to restrain myself from calling this thread "Why OpenSCAD is wheely good"...

To keep things simple I’m going to start by drawing a wheel. A very basic wheel, a bit of a rubbish wheel to be honest, but I want to demonstrate why I think OpenSCAD is powerful.

This wheel is essentially one cylinder sat on top of another cylinder with a hole down the middle... so it may not make for great running, but it should roll. We start by drawing our first cylinder. We use OpenSCAD's cylinder command, which draws a cylinder centred on the Z-axis. In a couple of lines of code we have our two cylinders - each cylinder is defined by the height and the radius at the base and top of the cylinder (which are the same here - but you can see you can also use the cylinder command to create cones).

Code: Select all

cylinder(6,10,10);
cylinder(1,12,12);
It's a 20mm diameter wheel so the radius is 10mm (OpenSCAD works in mm) and the flange extends 2mm further. Hit F5 to preview it and you can see what it looks like...

Image

Now I want a 3mm hole down the middle for the axle - so I draw this in a similar way, but I'm going to subtract it from the cylinders I've drawn using the difference command:

Code: Select all

difference(){
	cylinder(6,10,10);
	cylinder(7,1.5,1.5);
}
difference(){
	cylinder(1,12,12);
	cylinder(2,1.5,1.5);
}
Image

Ok, now I have something that should just about roll, although the cylinders have so many faces that it won't be smooth. Increase the number of faces by adding this line:

Code: Select all

$fn=100;
This sets the 'facet number' for everything in the drawing, from the default of 25 I've increased it to 100. My wheel is a lot smoother:

Image

So far so fiddly. You could have done this a lot quicker in TinkerCAD, right? So here, then, is where I think the power lies: you've got a 20mm wheel and you want a 24mm wheel. Rather than starting from scratch, you reuse your old drawing. In TinkerCAD you can't just scale the entire drawing up (you still want a centre hole of 3mm and a flange depth of 2mm) so you have to adjust each of your cylinders separately. So, too, here, you have to edit the code in a couple of places... unless... you write your code using what OpenSCAD calls 'variables' (although programmers will recognise these as being more akin to constants). I'm going to call my variable 'radius' and set it to 10 at the start, but then whenever I want that value in the code I'll use the word rather than hard-coding in the specific value - something like this:

Code: Select all

radius=10;
difference(){
	cylinder(6,radius,radius);
	cylinder(7,1.5,1.5);
}
difference(){
	cylinder(1,radius+2,radius+2);
	cylinder(2,1.5,1.5);
}
$fn=100;
Image

Notice that my wheel hasn't changed at all. But... by changing one single line of code I can create a wheel that is 24mm in diameter (or any other diameter I choose!)

Code: Select all

radius=12;
difference(){
	cylinder(6,radius,radius);
	cylinder(7,1.5,1.5);
}
difference(){
	cylinder(1,radius+2,radius+2);
	cylinder(2,1.5,1.5);
}
$fn=100;
Image

Suddenly my drawing is a lot more reusable - and however complex it gets, changes can always be this easy!
Last edited by SimonWood on Sat Apr 10, 2021 10:23 am, edited 1 time in total.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

OpenSCAD Modules

Post by SimonWood » Sat Apr 10, 2021 10:20 am

The next really powerful aspect of OpenSCAD is creating little bits of reusable code... OpenSCAD calls these 'modules' (again, programmers will recognise these as being more akin to 'functions' but OpenSCAD's functions are more like functions in the mathematical sense).

I want to draw a more sophisticated wheel... and this will be much easier if I can use a hollow tube shape to build it up out of rather than a cylinder. So I'm going to create a module called... 'tube' to draw a tube with any height and radius.

Code: Select all

module tube(height,outer_radius,inner_radius) {
    difference(){
        cylinder(height,outer_radius,outer_radius);
        translate([0,0,-1])
            cylinder(height+2,inner_radius,inner_radius);
    }
}
Notice that I've drawn the 'hole' slightly longer than the cylinder it's making a hole in and shifted it down using the 'translate' command. This command takes what OpenSCAD calls a 'vector' as an argument (which, for programmers, is more like an array - although in this case it is actually a vector of length 1 direction down the z-axis...).

Notice that if I preview this, nothing happens...

Image

I need to call my module - but now, with a couple of lines of code, I can redraw my crummy wheel.

Code: Select all

tube(6,10,1.5);
tube(1,12,1.5);
Image

But more importantly, I can draw myself a much nicer wheel...

Code: Select all

radius=10;
tube(5.5,radius,radius-1.5);
tube(6,3,1.5);
tube(1,12,10);
tube(4,radius-1.5,3);
module tube(height,outer_radius,inner_radius) {
    difference(){
        cylinder(height,outer_radius,outer_radius);
        translate([0,0,-1])
            cylinder(height+2,inner_radius,inner_radius);
    }
}
$fn=100;
Image

Note that it doesn't matter if I call module before I have defined it... and I prefer to shift my module definitions to the end of the code.

And now, with a small tweak to my module, I can even add a bit of a taper to the wheel profile:

Code: Select all

radius=10;
tube(5.5,radius,radius-1.5,0.25);
tube(6,3,1.5);
tube(0.75,radius+2,radius);
translate([0,0,0.75])
    tube(0.25,Radius+1.75,Radius,1.75);
tube(4,radius-1.5,3);
module tube(height,outer_radius,inner_radius,taper=0) {
    difference(){
        cylinder(height,outer_radius,outer_radius);
        translate([0,0,-1])
            cylinder(height+2,inner_radius,inner_radius);
    }
}
$fn=100;
Note that I set a default value for the additional 'taper' argument for the module in such a way that if 'tube' is called without this parameter, nothing will change. But I can now call it with the parameter where I want a different profile.

Image

But despite this additional complexity, if I want to change the wheel diameter, it's still just a single edit:

Image

In fact, I don't even need to make an edit. OpenSCAD has something called the 'Customizer' where you can dynamically change the value of the variables in your code away from your default value - see the panel on the right...

Image

By the way, I've never drawn any wheels before so if anyone has any tips on making my actual drawings better, please give me your advice!
Last edited by SimonWood on Sat Apr 10, 2021 12:37 pm, edited 2 times in total.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
philipy
Moderator
Moderator
Posts: 5363
Joined: Sun Jan 30, 2011 3:00 pm
Location: South Northants

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by philipy » Sat Apr 10, 2021 11:15 am

Thanks Simon, very impressive.
I have looked at OpenSCAD in the past and I'm afraid that you've just confirmed what I thought, you need to enjoy computer programming to bother with it!
I'm sure it is a whiz if/when you can learn it and I have seen some really superb models produced with it, but rather like trying to learn Arduino, my brain fades after about the third set of your explanations above. If it takes that much effort to produce a simple wheel, I can't imagine how you would even think about a loco.
Philip

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Loops

Post by SimonWood » Sat Apr 10, 2021 11:25 am

Ok, last one for now, but I think this is really useful for elements of a model that repeat regularly... think rivets, for example, or in this case, spokes.

Suppose I want a wheel with spokes instead of a disc wheel...

Following on from the way I developed my original code, I'm going to start out by drawing a single spoke as a module. For a straight spoke, that's going to be pretty straightforward... something like this:

Code: Select all

module straight_spoke(wheel_radius) {
    translate([-0.75,1.75,0])
        cube([1.5,wheel_radius-2,4]);
}
But now I can use a 'for' loop to create as many spokes as I like, rotating them through an appropriate number of degrees each time:

Code: Select all

module spoke_set(wheel_radius,number) {
    for (i=[1:number])
           rotate(i*360/number) {
                if(Spoke_type=="Curly")
                    curly_spoke(wheel_radius,0.75*wheel_radius);
                if(Spoke_type=="Straight")
                    straight_spoke(wheel_radius);
            }
}
Notice that I can feed any number of spokes in as a parameter, and it will adjust the angle between spokes accordingly... So I could call it with something like:

Code: Select all

spoke_set(Radius,6);
So now my code looks like this

Code: Select all

// Radius of the wheel in mm
Radius=10; //[8:15]
tube(5.5,Radius,Radius-1.5,0.25);
tube(6,3,1.5,0);
tube(0.75,Radius+2,Radius-1,0.25);
translate([0,0,0.75])
    tube(0.25,Radius+1.75,Radius,1.75);
spoke_set(Radius,6);
module tube(height,outer_radius,inner_radius,taper) {
    difference(){
        cylinder(height,outer_radius,outer_radius-taper);
        translate([0,0,-1])
            cylinder(height+2,inner_radius,inner_radius);
    }
}
module straight_spoke(wheel_radius) {
    translate([-0.75,1.75,0])
        cube([1.5,wheel_radius-2,4]);
}
module spoke_set(wheel_radius,number) {
    for (i=[1:number])
           rotate(i*360/number) 
                    straight_spoke(wheel_radius);
}
$fn=100;
and I get this

Image

or if I wanted say 8 spokes, one edit and this

Image

But of course it's more powerful if we make the type and number of spokes variables that can be set in the Customizer

Code: Select all

// Radius of the wheel in mm
Radius=10; //[8:15]
//Type of wheel
Spoke_type="Disc"; // ["Disc","Straight"]
//If your wheel has spokes, how many
Number_of_spokes=6; // [4:8]
Note how the comments, which begin // become the description used in the customiser when they are on the preceding line, and the range of values when they are at the end of the line. So now we can quickly and easily change the number of spokes and the wheel types with a slider.

Image

And, just to finish, as you've probably guessed by my calling my module "straight_spoke" I want to add another option for "curly_spoke" so here's the full code with that option too:

Code: Select all

// Radius of the wheel in mm
Radius=10; //[8:15]
//Type of wheel
Spoke_type="Disc"; // ["Disc","Straight","Curly"]
//If your wheel has spokes, how many
Number_of_spokes=6; // [4:8]
tube(5.5,Radius,Radius-1.5,0.25);
tube(6,3,1.5,0);
tube(0.75,Radius+2,Radius-1,0.25);
translate([0,0,0.75])
    tube(0.25,Radius+1.75,Radius,1.75);
if(Spoke_type=="Disc")
    tube(4,Radius-1.5,3,0);
if(Spoke_type=="Straight"||Spoke_type=="Curly")
    spoke_set(Radius,Number_of_spokes);
module tube(height,outer_radius,inner_radius,taper) {
    difference(){
        cylinder(height,outer_radius,outer_radius-taper);
        translate([0,0,-1])
            cylinder(height+2,inner_radius,inner_radius);
    }
}
module straight_spoke(wheel_radius) {
    translate([-0.75,1.75,0])
        cube([1.5,wheel_radius-2,4]);
}
module curly_spoke(wheel_radius,spoke_radius) {
    translate([0,-spoke_radius,0])
        intersection(){
            tube(4,spoke_radius,spoke_radius-1.5,0);
            rotate(-angle_subtended_by_chord(2,spoke_radius))
                cube(spoke_radius);
            rotate(90-angle_subtended_by_chord(Radius-0.5,spoke_radius))
                cube(spoke_radius);
        }
}
module spoke_set(wheel_radius,number) {
    for (i=[1:number])
           rotate(i*360/number) {
                if(Spoke_type=="Curly")
                    curly_spoke(wheel_radius,0.75*wheel_radius);
                if(Spoke_type=="Straight")
                    straight_spoke(wheel_radius);
            }
}
function angle_subtended_by_chord(chord_length,circle_radius) = 2*asin(0.5*chord_length/circle_radius);
$fn=100;
Image

So now, in a single but customisable drawing, we have a wheel that can take a range of radii, with different styles and numbers of spokes, and to print all you have to do is dial in your chosen parameters and export as an STL files...
Last edited by SimonWood on Sat Apr 10, 2021 12:37 pm, edited 2 times in total.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Sat Apr 10, 2021 11:33 am

philipy wrote: Sat Apr 10, 2021 11:15 am If it takes that much effort to produce a simple wheel, I can't imagine how you would even think about a loco.
I'm not sure I'd necessarily draw a whole loco in OpenSCAD (although I'm drawn towards it for the precision it offers so easily in comparison to the effort needed in a graphical interface). But even if I might not want to draw the whole loco, I might want to draw some components in it. Or for wagons, say. For example, I'm thinking about strapping - you can imagine the parameters here - do you want corner strapping? How high? How many rivets? If you are just going to produce one piece for one wagon, of course it's a lot more effort. But if that's the kind of thing you're going to print regularly, put the up-front effort in and next time you need something slightly different you just dial in some new values and you're away. I can think of various things off the top of my head - wheels, couplings, strapping, springs etc. for which this might apply. But it could also be true of any model which includes a number of repetitive elements.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
-steves-
Administrator
Administrator
Posts: 2453
Joined: Thu Jul 28, 2011 1:50 pm
Location: Cambridge & Peterborough

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by -steves- » Sat Apr 10, 2021 11:55 am

Simon

This is absolutely amazing work, totally mind boggling for me as I am no programmer, but if i was I can certainly see some distant advantages to this, particularly for reusing the code.

A very well done. I assume you are a programmer or have done programming?
The buck stops here .......

Ditton Meadow Light Railway (DMLR)
Member of Peterborough and District Association
http://peterborough.16mm.org.uk/

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Sat Apr 10, 2021 12:15 pm

-steves- wrote: Sat Apr 10, 2021 11:55 am A very well done. I assume you are a programmer or have done programming?
Thanks Steve. I'd certainly not call myself a programmer but I did do a module on Java as part of my masters, most of which I've forgotten, but I still tinker around with PHP. I'm not honestly sure if this is helpful or not with OpenSCAD, I'm having to 'unlearn' some assumptions that come with expecting it to behave like a programming language but there are some familiar concepts.

I'd say that, like any of these 3D CAD packages, it's worth having a tinker around with, because while it all seems a bit impenetrable at first, it's amazing how much you can build by combining a few simple commands like cube() and cylinder() and translate() and difference().
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
-steves-
Administrator
Administrator
Posts: 2453
Joined: Thu Jul 28, 2011 1:50 pm
Location: Cambridge & Peterborough

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by -steves- » Sat Apr 10, 2021 12:26 pm

SimonWood wrote: Sat Apr 10, 2021 12:15 pm
-steves- wrote: Sat Apr 10, 2021 11:55 am A very well done. I assume you are a programmer or have done programming?
Thanks Steve. I'd certainly not call myself a programmer but I did do a module on Java as part of my masters, most of which I've forgotten, but I still tinker around with PHP. I'm not honestly sure if this is helpful or not with OpenSCAD, I'm having to 'unlearn' some assumptions that come with expecting it to behave like a programming language but there are some familiar concepts.

I'd say that, like any of these 3D CAD packages, it's worth having a tinker around with, because while it all seems a bit impenetrable at first, it's amazing how much you can build by combining a few simple commands like cube() and cylinder() and translate() and difference().
I may pinch your code to do wheels as they seem much simpler than trying to do it in TinkerCad, hope you don't mind? :D
The buck stops here .......

Ditton Meadow Light Railway (DMLR)
Member of Peterborough and District Association
http://peterborough.16mm.org.uk/

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Sat Apr 10, 2021 12:49 pm

-steves- wrote: Sat Apr 10, 2021 12:26 pm I may pinch your code to do wheels as they seem much simpler than trying to do it in TinkerCad, hope you don't mind? :D
Not at all - that's the beauty of it, you can just download OpenSCAD copy and paste the code into it and away you go. Note that I've corrected a couple of errors in the last few minutes so refresh and copy the latest version!

I'll also put the OpenSCAD file up on Thingiverse in due course as CC-BY-NC-SA. In theory you can access all the Customizer stuff on there as a web form and then download an STL directly - in practice I've always found this functionality is broken and you need to download the .scad file to a local copy of the program anyway so you might as well just copy and paste...

I should probably add a disclaimer - I haven't actually built any of these wheels into a functional piece of rolling stock yet, so I'm not sure how well they run. I haven't designed any wheels before so I'm just feeling my way with this... again, any suggestions for improvements I will gratefully received, and incorporate them into the code.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
ge_rik
Administrator
Administrator
Posts: 6934
Joined: Sun Oct 25, 2009 10:20 pm
Location: Cheshire
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by ge_rik » Sat Apr 10, 2021 5:15 pm

A really interesting variation on the 3D drawing theme.

Although I quite enjoy tinkering with programming, I think I'd eventually find this medium frustrating. I can see that it's a lot more precise and mathematical than TinkerCAD, but I somehow enjoy the rough and ready nature of drawing stuff freehand in TinkerCAD and then tweaking it to make it fit. I suppose TinkerCAD is more in tune with my bodgelling approach to the hobby.

Rik
------------------------
Peckforton Light Railway - Blog Facebook Youtube

Trevor Thompson
Driver
Driver
Posts: 1015
Joined: Fri Oct 05, 2018 6:30 pm
Location: South West Wales

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by Trevor Thompson » Sat May 22, 2021 10:05 am

I think it is an interesting variation on 3 D modelling software.

In some ways I can see it as an improvement - I do find it frustrating to place things accurately in a 3 D space represented on a flat screen.

However I was always put off Autocad by its parametric input requirements - which are similar.

I suppose that creating components for a model from a drawing would be quite easy this way - chassis side, boiler etc. I find the concept of trying to mentally visualise how this would all fit together a bit challenging though.

Of course I found Sketchup really difficult to begin with - even abandoning the attempt to get to grips with it at first. It was only Utube videos which got me to try again.

Of course if you haven't invested effort into learning to use a package already, then I cant see that this would be any more difficult to get to grips with than Sketchup.

Simon - I'd go for it. If you have got this far then the whole loco is not far away.

Trevor

User avatar
FWLR
Driver
Driver
Posts: 4445
Joined: Sat Aug 05, 2017 9:45 am
Location: Preston, Lancashire, UK

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by FWLR » Mon May 24, 2021 9:41 am

looks really good this Simon, but unfortunately I can't seem to open it on my MacBook. I can download it, but how the heck can it be opened. Still if you like it Simon and you can do brilliant things with, good on you and take it to the next level mate and enjoy yourself with it. You deserve it and maybe we can all see the brilliant builds to do with it.

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Tue Dec 28, 2021 10:44 am

I've updated my wheel.scad code. Been meaning to post up the file properly for people to download but in the meanwhile I'll paste the code here. There are a few refinements and a lot more customisable parameters!

Image

Code: Select all

// Diameter of the wheel in mm
Diameter=20; //[16:32]
radius=Diameter/2;
//Type of wheel
Spoke_type="Disc"; // ["Disc","Straight","Curly"]
//If your wheel has spokes, how many
Number_of_spokes=6; // [4:8]
//Diameter of axle to accomodate in mm
Axle_diameter=3; //[3:3mm,3.175:1/8th inch]
axle_radius=Axle_diameter/2;
//Increase for a more robust wheel
Hub_thickness=1.5; // [1.5:0.1:2.5]
//Increase for a more robust wheel
Rim_thickness=1.5; // [1.5:0.1:2.5]
//How far the flange extends beyond the wheel rim
Flange_depth=2; // [0:0.1:3]
//Increase for a more robust wheel
Flange_thickness=1; // [1:0.1:1.5]
//Increase for a more robust wheel
Spoke_thickness=1.5; // [1.5:0.1:2.5]
//The taper of the wheel profile, as a percentage
Taper=5; // [0:10]
tube(5.5,radius,radius-Rim_thickness,Taper); // The wheel rim
tube(6,axle_radius+Hub_thickness,axle_radius);  // The hub
tube(Flange_thickness,radius+Flange_depth,radius-Rim_thickness,Taper,Taper); // The flange
// The axles depend on spoke type:
if(Spoke_type=="Disc")
    tube(4,radius-Rim_thickness,axle_radius+Hub_thickness);
if(Spoke_type=="Straight"||Spoke_type=="Curly")
    spoke_set(radius,Number_of_spokes,Spoke_thickness);
module tube(height,outer_radius,inner_radius,side_taper=0,end_taper=0) {
    difference(){
        tapered_side_radius=outer_radius-side_taper*height/100;
        tapered_end_height=tapered_side_radius*end_taper/100;
        union(){
            cylinder(height,outer_radius,tapered_side_radius);
            translate([0,0,height])
                cylinder(tapered_end_height,tapered_side_radius,0);
        }
        translate([0,0,-1])
            cylinder(height+2+tapered_end_height,inner_radius,inner_radius);
    }
}
module straight_spoke(wheel_radius,thickness) {
    translate([-thickness/2,1.75,0])
        cube([thickness,wheel_radius-2.25,4]);
}
module curly_spoke(wheel_radius,thickness,spoke_radius) {
    translate([0,-spoke_radius,0])
        intersection(){
            tube(4,spoke_radius,spoke_radius-thickness,0);
            rotate(-angle_subtended_by_chord(2,spoke_radius))
                cube(spoke_radius);
            rotate(90-angle_subtended_by_chord(wheel_radius-0.5,spoke_radius))
                cube(spoke_radius);
        }
}
module spoke_set(wheel_radius,number,thickness) {
    for (i=[1:number])
           rotate(i*360/number) {
                if(Spoke_type=="Curly")
                    curly_spoke(wheel_radius,thickness,0.75*wheel_radius);
                if(Spoke_type=="Straight")
                    straight_spoke(wheel_radius,thickness);
            }
}
function angle_subtended_by_chord(chord_length,circle_radius) = 2*asin(0.5*chord_length/circle_radius);
$fn=100;
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
ge_rik
Administrator
Administrator
Posts: 6934
Joined: Sun Oct 25, 2009 10:20 pm
Location: Cheshire
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by ge_rik » Tue Dec 28, 2021 12:28 pm

Wow, that looks so cool (I believe that is the parlance these days ;) ). I hope it's easier than it looks to get to grips with the relationship between the coding and the drawing - it certainly looks versatile.

Rik
------------------------
Peckforton Light Railway - Blog Facebook Youtube

User avatar
ge_rik
Administrator
Administrator
Posts: 6934
Joined: Sun Oct 25, 2009 10:20 pm
Location: Cheshire
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by ge_rik » Tue Dec 28, 2021 12:37 pm

I was wondering if I could use this to produce wheels for my 0-16.5 models. Their wheel diameter is 10.5mm, but the minimum seems to be 16mm.

I think I can see how to alter the parameter settings but have you constrained the settings because you feel the geometry would become too fragile for a 3D printer to successfully produce?

Rik
------------------------
Peckforton Light Railway - Blog Facebook Youtube

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Tue Dec 28, 2021 12:48 pm

ge_rik wrote: Tue Dec 28, 2021 12:28 pm Wow, that looks so cool (I believe that is the parlance these days ;) ).
I am sure you must be right. After all, there can't be many who are as hip as those of us who build model trains in our gardens ;)
ge_rik wrote: Tue Dec 28, 2021 12:37 pm I was wondering if I could use this to produce wheels for my 0-16.5 models. Their wheel diameter is 10.5mm, but the minimum seems to be 16mm.
I don't see why you shouldn't - I've not done anything as fancy as tuning this to ensure the parameters make sensible wheels. I'm sure you could already set parameters that would produce wheel profiles that performed really badly without altering the constraints, and the robustness will depend on the printer anyway. It's more that I've tried to constrain it for the likely ranges for 16mm because that just makes it quicker and less fiddly to churn out a wheel. As long as it is in those ranges!

Code: Select all

// Diameter of the wheel in mm
Diameter=20; //[10:0.5:32]
As you've spotted, you can change the constraints. In this case if you set the minimum to 10mm and the step size to 0.5mm you'd allow the diameter you're after. There are probably other parameters to adjust for 0-16.5 besides that!
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
ge_rik
Administrator
Administrator
Posts: 6934
Joined: Sun Oct 25, 2009 10:20 pm
Location: Cheshire
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by ge_rik » Tue Dec 28, 2021 3:41 pm

Thanks. I'll have a play and see what develops...

Rik
------------------------
Peckforton Light Railway - Blog Facebook Youtube

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Fri Dec 31, 2021 5:59 pm

SimonWood wrote: Sat Apr 10, 2021 12:49 pm I'll also put the OpenSCAD file up on Thingiverse in due course as CC-BY-NC-SA. In theory you can access all the Customizer stuff on there as a web form and then download an STL directly - in practice I've always found this functionality is broken and you need to download the .scad file to a local copy of the program anyway so you might as well just copy and paste...
I have now posted the wheels code up on Thingiverse (and it's only taken me 8 months to get round to it). Alas the Customizer still seems to be broken as far as I can see, so for now you still need to download OpenSCAD to render an STL file.

So... where next? I mentioned strapping but I haven't had a play with that yet. Instead I turned my attention to headboards. I liked the idea of being able to knock out a headboard on the printer, it's a cheap and cheerful and fast way to run a named train, and it seems that if the lettering is big enough it works ok even on a filament printer - and the ABS withstands the heat on a live steamer (not sure if resin would?) My first effort - last Christmas - was in TinkerCAD and getting the curved lettering was something of a nightmare... there's no curved lettering function so each letter has to be created as an individual text item and to ensure all of the letters were positioned correctly copied pairs of letters diametrically opposite (with the notional centre of the circle around which the lettering was curved at the midpoint). This let me move and rotate the letters at the same time to get the orientation correct...

Image

Mind you it worked...

Image

But making any changes to the lettering to make a new headboard was a nightmare, with each letter needing to be created and positioned individually, and I didn't want to spend all that time recreating it from scratch. I had a look for a vector graphics package that could generate curved lettering as an SVG which I believe you can then extrude in TinkerCAD, but it was hard to tell which packages might offer that option - and I didn't particularly want to learn a new package just for this! So, of course, this is where OpenSCAD came it - as I figured since you can easily change the parameters, why not make the text one of those, along with the radius of the curvature and the width of the headboard, etc. etc.

So the first thing is getting some text - this is pretty easy - using text() with the text you want and the height of the letters in mm:

Code: Select all

text("SANTA SPECIAL",6);
Image

But of course to be properly 3D you also want to be able to control how thick the letters are, this is where linear_extrude() comes in:

Code: Select all

linear_extrude(3)
    text("SANTA SPECIAL",6);
The argument 3 is the how thick to make it, i.e. how far to extrude the 2D shape into the third dimension...

Image

Of course so far, this is just a more difficult way of doing something I could have done in TinkerCAD.

But now if I use a for loop like I did with the spokes, I can iterate through the letters, rotating them 10° each time and translating them out to a radius of 30mm. (I've also centred the text to make it symmetrical about the y-axis centred on the origin.)

Code: Select all

// The text itself
the_text="SANTA SPECIAL";
// The number of degrees to rotate each letter through
degrees_per_letter=10;
// The radius of the curve for the lettering
radius = 30;
number_of_letters=len(the_text);
for (i = [0:number_of_letters-1]) { 
  rotate(((number_of_letters-1)*degrees_per_letter/2-i*degrees_per_letter))
      translate([0,radius,0])
          linear_extrude(3)
                text(the_text[i],halign="center",6); 
}
Image

So now if I want to change the lettering, I just need to edit the text string right at the beginning

Image

So now I had my curved text, I just needed a headboard to put it on.
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
SimonWood
Trainee Driver
Trainee Driver
Posts: 703
Joined: Tue Apr 07, 2015 9:46 pm
Location: West Wales
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by SimonWood » Sat Jan 01, 2022 9:14 am

My headboard is a bit of a kludge and could do with some tidying up, but here it is.

Code: Select all

// Upper row text
Upper_row_text="SANTA";
//  Lower row text
Lower_row_text="SPECIAL";
//  The angle of the arc forming the headboard
angle=100; // [30:5:120]
//  How thick the board on which the lettering is placed should be
backboard_thickness=2; // [1:0.5:5]
//  How high the letters should be
font_size=6; // [4:12]
//  The thickness of the letters above the board
lettering_thickness=1; // [0.5:0.5:5]
//  The radius of arc forming the outer edge of the headboard
outer_radius=50;  // [30:100]
//  How big the border around the edge of the board should be
border_height=1; // [0.5:0.5:2]
//  The number of letters in the row with the most letters
max_letters=max(len(Upper_row_text),len(Lower_row_text));
//  The height of the headboard (i.e. the difference between the inner and outer radii)
board_height=font_size*3+border_height*2;
// Create the backboard
back_board(backboard_thickness,outer_radius,board_height,angle,lettering_thickness,border_height);
// Add the text
// Upper row
translate([0,0,backboard_thickness])
    text_arc(Upper_row_text,max_letters,font_size,lettering_thickness,outer_radius-board_height/2+font_size/2-2,0.75*angle);
// Lower row
translate([0,0,backboard_thickness])
    text_arc(Lower_row_text,max_letters,font_size,lettering_thickness,outer_radius-board_height+font_size/2,0.75*angle);
module text_arc(the_text,max_letters,font_size,lettering_thickness,radius,angle) {
    number_of_letters=len(the_text);
    letter_difference=max_letters-number_of_letters;
        for (i = [0:number_of_letters]) { 
        letter_angle=angle/2-((i+1+letter_difference/2)*(angle/(max_letters+1)));
        rotate(letter_angle)
            translate([0,radius,0])
                linear_extrude(lettering_thickness)
                    text(the_text[i],halign="center",font_size); 
    }
}
module back_board(thickness,radius,height,angle,border_thickness,border_width){
    difference() {
        union(){
        cylinder(thickness,radius,radius);
        circ(thickness+border_thickness,radius,border_width);
        circ(thickness+border_thickness,radius-height+border_width,border_width);
        rotate(90-angle/2)
            cube([radius,border_width,thickness+border_thickness]);
        rotate(-90+angle/2)
            translate([-radius,0,0])
                cube([radius,border_width,thickness+border_thickness]);
        offset_cylinder(thickness+border_thickness,height/2+border_width,radius,angle/2);
        offset_cylinder(thickness+border_thickness,height/2+border_width,radius,-angle/2);

    }
    translate([0,0,-1])
        cylinder(thickness+border_thickness+2,radius-height,radius-height);
                    translate([0,0,-1])
        circ(thickness+border_thickness+2,2*radius,radius);
            rotate(-angle/2)
        translate([0,0,-1])
            cube([radius,2*radius,thickness+border_thickness+2]);
                rotate(angle/2)
        translate([-radius,0,-1])
            cube([radius,2*radius,thickness+border_thickness+2]);
        translate([0,0,-1])
        offset_cylinder(thickness+border_thickness+2,height/2,radius,angle/2);
            translate([0,0,-1])
        offset_cylinder(thickness+border_thickness+2,height/2,radius,-angle/2);
                    translate([-radius,-radius,-1])
cube([radius*2,radius+2,thickness+border_thickness+2]);
    }
}
module circ(thickness,radius,width) {
    difference(){
        cylinder(thickness,radius,radius);
        translate([0,0,-1])
            cylinder(thickness+2,radius-width,radius-width);
    }
}
module offset_cylinder(height,radius,distance,angle){
    rotate(angle)
        translate([0,distance,0])
            cylinder(height,radius,radius);
}
module two_offset_cylinders(height,radius,distance,angle){
    offset_cylinder(height,radius,distance,angle);
    offset_cylinder(height,radius,distance,-angle);
}
module sector(thickness,radius,angle) {
    difference(){
        cylinder(thickness,radius,radius);
        translate([0,0,-1])
            two_offset_cubes(thickness+2,radius,radius,angle);
    }
}
module offset_cube(thickness,length,width,angle){
    rotate(45+angle)
       cube([length,width,thickness]);
}
module two_offset_cubes(thickness,length,width,height){
    offset_cube(thickness,length,width,angle);
    offset_cube(thickness,length,width,-angle);
}
module arc(thickness,radius,angle,width) {
    difference(){
        sector(thickness,radius+width,angle);
        translate([0,0,-1])
            sector(thickness+2,radius,angle+2);
    }
}
$fn=100;
Much like in TinkerCAD creating complex shapes is just a case of taking some simple shapes and combining them or subtracting one from another. For example a sector (or whatever the 3D equivalent of a sector is!) I made by taking a cylinder and then chopping off the bits I didn't want with some large cubes... crude, but exactly what I'd do in TinkerCAD. And arc (or 3D arc) is then just a sector with a sector subtending the same angle but a smaller radius subtracted from it.

I've used my curved text code from above but called it twice, once for each row. Rather than set the angle for each individual letter to rotate through I've set an angle for the arc of the whole headboard, and spaced the letters out within that. I'm not really sure whether this is a better approach. I also wanted the spacing for each row to be the same so I needed to base it on the number of letters in the longest row - OpenSCAD's max() makes it really easy to find the largest of the inputs you give it.

Image

As you can see you can change the text and various other parameters. Because it will use whatever space is available, if you try to cram too many letters in they will overlap, so you need to be careful when choosing your combination of text/angle/radius. It's currently set up more for fiddling than guaranteeing a good result every time - but it's still quicker than editing my headboard in TinkerCAD!

Here's a print from the code back in the summer for our first meet-up since 2019. It's a prototype for a headboard in memory of our friend in the South West Wales area group.

Image

Even after fiddling the parameters you can see the letter spacing is a problem more generally - since really having each letter spaced evenly never works. An 'I' is much narrower than a 'W'. I haven't found anything in OpenSCAD to solve this, although I think from Googling around there may be libraries other people have developed which I can use - I need to look into this more... So when I have a moment to refine this code I'm going to try to improve this - or at least make the various parameters 'interlock' a bit more so it's quicker to get something that just works, whatever the length of the text.

Oh and here's a bracket to glue to the back for mounting it on the lamp iron.

Code: Select all

difference(){
    cube([14,8,3]);
    translate([5,-1,-1])
        cube([4,10,2]);
    translate([-1,-1,1])
        cube([4,10,3]);
    translate([11,-1,1])
        cube([4,10,3]);
}
Image
Rheilffordd Moel Rhos: blog - photos - videos

User avatar
ge_rik
Administrator
Administrator
Posts: 6934
Joined: Sun Oct 25, 2009 10:20 pm
Location: Cheshire
Contact:

Re: Using OpenSCAD to produce drawings for 3D Printing

Post by ge_rik » Sat Jan 01, 2022 1:30 pm

Hi Simon
Have you figured out a way of getting the flare at the base of a loco dome or chimney with OpenSCAD? It's one of the trickiest things to do in TinkerCAD and I've still not yet mastered it.

Rik
------------------------
Peckforton Light Railway - Blog Facebook Youtube

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests