Initial Import

This commit is contained in:
Peter 2024-06-24 13:56:57 +00:00
commit 03d0978743
23 changed files with 34708 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.stl
*.xz

View file

@ -0,0 +1,32 @@
$fn=100;
union(){
difference(){
union(){
linear_extrude(height=5, scale=0)
circle(d=70);
translate([0,0,50])
linear_extrude(height=5, scale=0)
circle(d=30);
translate([0,0,100])
linear_extrude(height=5, scale=0)
circle(d=30);
translate([0,0,150])
linear_extrude(height=5, scale=0)
circle(d=30);
}
rotate([0,0,120])
translate([0,0,-5])
linear_extrude(height=180)
polygon(points=[[2.5*cos(60),2.5*sin(60)],[2.5*cos(60)+80,2.5*sin(60)],[2.5*cos(60)+80*cos(120),2.5*sin(60)+80*sin(120)],[2.5*cos(60),2.5*sin(60)]]);
rotate([0,0,240])
translate([0,0,-5])
linear_extrude(height=180)
polygon(points=[[2.5*cos(60),2.5*sin(60)],[2.5*cos(60)+80,2.5*sin(60)],[2.5*cos(60)+80*cos(120),2.5*sin(60)+80*sin(120)],[2.5*cos(60),2.5*sin(60)]]);
rotate([0,0,360])
translate([0,0,-5])
linear_extrude(height=180)
polygon(points=[[2.5*cos(60),2.5*sin(60)],[2.5*cos(60)+80,2.5*sin(60)],[2.5*cos(60)+80*cos(120),2.5*sin(60)+80*sin(120)],[2.5*cos(60),2.5*sin(60)]]);
}
cylinder(d=5,h=151);
}

View file

@ -0,0 +1,119 @@
/**
* A name tag that can easily be clipped to the neck of your bottle.
* Copyright (C) 2013 Roland Hieber <rohieb+bottleclip@rohieb.name>
*
* See examples.scad for examples on how to use this module.
*
* The contents of this file are licenced under CC-BY-SA 3.0 Unported.
* See https://creativecommons.org/licenses/by-sa/3.0/deed for the
* licensing terms.
*/
include <write/Write.scad>
/**
* Creates one instance of a bottle clip name tag. The default values are
* suitable for 0.5l Club Mate bottles (and similar bottles). By default, logo
* and text are placed on the name tag so they both share half the height. If
* there is no logo, the text uses the total height instead.
* Parameters:
* ru: the radius on the upper side of the clip
* rl: the radius on the lower side of the clip
* ht: the height of the clip
* width: the thickness of the wall. Values near 2.5 usually result in a good
* clippiness for PLA prints.
* name: the name that is printed on your name tag. For the default ru/rt/ht
* values, this string should not exceed 18 characters to fit on the name tag.
* gap: width of the opening gap, in degrees. For rigid materials this value
* usually needs to be near 180 (but if you set it to >= 180, you won't have
* anything left for holding the clip on the bottle). For flexible materials
* like Ninjaflex, choose something near 0. For springy materials like PLA or
* ABS, 90 has proven to be a good value.
* logo: the path to a DXF file representing a logo that should be put above
* the name. Logo files should be no larger than 50 units in height and should
* be centered on the point (25,25). Also all units in the DXF file should be
* in mm. This parameter can be empty; in this case, the text uses the total
* height of the name tag.
* font: the path to a font for Write.scad.
*/
module bottle_clip(ru=13, rl=17.5, ht=26, width=2.5, name="", gap=90,
logo="thing-logos/stratum0-lowres.dxf", font="write/orbitron.dxf") {
e=100; // should be big enough, used for the outer boundary of the text/logo
difference() {
rotate([0,0,-45]) union() {
// main cylinder
cylinder(r1=rl+width, r2=ru+width, h=ht);
// text and logo
if(logo == "") {
writecylinder(name, [0,0,3], rl+0.5, ht/13*7, h=ht/13*8, t=max(rl,ru),
font=font);
} else {
writecylinder(name, [0,0,0], rl+0.5, ht/13*7, h=ht/13*4, t=max(rl,ru),
font=font);
translate([0,0,ht*3/4-0.1])
rotate([90,0,0])
scale([ht/100,ht/100,1])
translate([-25,-25,0.5])
linear_extrude(height=max(ru,rl)*2)
import(logo);
}
}
// inner cylinder which is substracted
translate([0,0,-1])
cylinder(r1=rl, r2=ru, h=ht+2);
// outer cylinder which is substracted, so the text and the logo end
// somewhere on the outside ;-)
difference () {
cylinder(r1=rl+e, r2=ru+e, h=ht);
translate([0,0,-1])
// Note: bottom edges of characters are hard to print when character
// depth is > 0.7
cylinder(r1=rl+width+0.7, r2=ru+width+0.7, h=ht+2);
}
// finally, substract an equilateral triangle as a gap so we can clip it to
// the bottle
gap_x=50*sin(45-gap/2);
gap_y=50*cos(45-gap/2);
translate([0,0,-1])
linear_extrude(height=50)
polygon(points=[[0,0], [gap_x, gap_y], [50,50], [gap_y, gap_x]]);
}
}
/**
* Creates one instance of a bottle clip name tag suitable for 0.33l longneck
* bottles (like fritz cola, etc.). All parameters are passed to the module
* bottle_clip(), see there for their documentation.
*/
module bottle_clip_longneck(name="", width=2.5, gap=90,
logo="thing-logos/stratum0-lowres.dxf", font="write/orbitron.dxf") {
bottle_clip(name=name, ru=13, rl=15, ht=26, width=width, logo=logo, gap=gap,
font=font);
}
/**
* Creates one instance of a bottle clip name tag suitable for 0.33l DIN 6199
* beer bottles (also known as "Steinie", "Stubbi", "Knolle", etc.). Because of
* reasons, there is no logo, but all other parameters are passed to the module
* bottle_clip(), see there for their documentation.
*/
module bottle_clip_steinie(name="", width=2.5, gap=90, font="write/orbitron.dxf") {
bottle_clip(name=name, ru=13, rl=17.5, ht=13, width=width, logo="", gap=gap,
font=font);
}
/*
* Create one instance of a bottle clip name tag suitable for 0.5l DIN 6198
* bottle (also known as "Euroflasche" or "Euroform 2"). All parameters are
* passed to the module bottle_clip(), see there for their documentation.
*/
module bottle_clip_euro2(name="", width=2.5, gap=90,
logo="thing-logos/stratum0-lowres.dxf", font="write/orbitron.dxf") {
bottle_clip(name=name, ru=13, rl=22.5, ht=26, width=width, logo=logo, gap=gap,
font=font);
}
// vim: set noet ts=2 sw=2 tw=80:

16230
Bottle Clip/logos/logo.dxf Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
name="Peter";
beer=false;
nozzle=0.4;
layer=0.2;
$fa = $preview ? 12 : 0.01;
$fs = $preview ? 2 : min(layer, nozzle/2);
use <bottle-clip.scad>
rotate([0,0,.1])
if (beer) {
bottle_clip(name="Peter", logo="",ru=52.5/2,rl=65.5/2,ht=12,gap=90);
} else {
bottle_clip(name="Peter", logo="");
}

View file

@ -0,0 +1,388 @@
/* Version 4
Added bold property bold=0 (not bold) bold=1(bolder by 1.1) bold=2(bolder by 1.2)
Added support for font selection (default is Letters.dxf)
Added WriteCube module
Added Rotate for text (rotates on the plane of the text)
Added writesphere
Added space= (spacing between characters in char widths) def=1
Added writecylinder()
By Harlan Martin
harlan@sutlog.com
January 2012
(The file TestWrite.scad gives More usage examples)
(This module requires the file Letters.dxf to reside in the same folder)
(The file Letters.dfx was created with inkscape..Each letter is in its own layer)
(This module seperates each letter in the string and imports it from Letters.dfx)
*/
pi=3.1415926535897932384626433832795028841971693993751058209;
pi2=pi*2;
// These control the default values for write() writesphere() writecube()
// if the parameters are not included in the call. Feel free to set your own
// defaults.
//default settings
bold=0;
center=false;
h = 4; //mm letter height
t = 1; //mm letter thickness
space =1; //extra space between characters in (character widths)
rotate=0; // text rotation (clockwise)
font = "Letters.dxf"; //default for aditional fonts
// write cube defaults
face = "front"; // default face (top,bottom,left,right,back,front)
up =0; //mm up from center on face of cube
down=0;
right =0; //mm left from center on face of cube
left=0;
// write sphere defaults
rounded=false; //default for rounded letters on writesphere
north=0; // intial text position (I suggest leave these 0 defaults)
south=0;
east=0;
west=0;
spin=0;
// writecylinder defaults
middle=0; //(mm toward middle of circle)
ccw=false; //write on top or bottom in a ccw direction
r1=0; //(not implimented yet)
r2=0; //(not implimented yet)
// Contact me if your interested in how to make your own font files
// Its tedious and time consuming, but not very hard
module writecylinder(text,where,radius,height){
wid=(.125* h *5.5 * space);
widall=wid*(len(text)-1)/2;
//angle that measures width of letters on sphere
function NAngle(radius)=(wid/(pi2*radius))*360;
//angle of half width of text
function mmangle(radius)=(widall/(pi2*radius)*360);
if ((face=="top")||(face=="bottom") ){
if (face=="top" ){
if (center==true){
writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
}else{
writecircle(text,where+[0,0,height],radius-h,rotate=rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
}
}else{
rotate(180,[1,0,0])
if (center==true){
writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
}else{
writecircle(text,where+[0,0,0],radius-h,rotate=rotate,font=font,h=h,t=t,
space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
}
}
}else{
// if (radius>0){
if (center==true) {
rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
translate(where)
writethecylinder(text,where,radius,height,r1=radius,r2=radius,h=h,
rotate=rotate,t=t,font=font,face=face,up=up,down=down,
east=east,west=west,center=center,space=space,rounded=rounded,bold=bold);
} else{
rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
translate(where+[0,0,height/2])
writethecylinder(text,where,radius,height,r1=radius,r2=radius,h=h,
rotate=rotate,t=t,font=font,face=face,up=up,down=down,
east=east,west=west,center=center,space=space,rounded=rounded,bold=bold);
}
// the remarked out code is for cone shaped cylinders (not complete)
// }else{
// if (center==true) {
// rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
// translate(where)
// writethecylinder(text,where,radius,height,r1=r1,r2=r2,h=h,
// rotate=rotate,t=t,font=font,face=face,up=up,down=down,
// east=east,west=west,center=center,space=space,rounded=rounded);
// } else{
// rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
// translate(where+[0,0,height/2])
// writethecylinder(text,where,radius,height,r1=r1,r2=r2,h=h,
// rotate=rotate,t=t,font=font,face=face,up=up,down=down,
// east=east,west=west,center=center,space=space,rounded=rounded);
// }
// }
}
}
module writecircle(text,where,radius){
wid=(.125* h *5.5 * space);
widall=wid*(len(text)-1)/2;
//angle that measures width of letters on sphere
function NAngle(radius)=(wid/(pi2*radius))*360;
//angle of half width of text
function mmangle(radius)=(widall/(pi2*radius)*360);
if (ccw==true){
rotate(-rotate+east-west,[0,0,1]){
rotate(-mmangle(radius-middle),[0,0,1]){
translate(where)
for (r=[0:len(text)-1]){
rotate(-90+r*NAngle(radius-middle),[0,0,1]) // bottom out=-270+r
translate([radius-middle,0,0])
//rotate(90,[1,0,0])
//rotate(90,[0,1,0])
rotate(-270,[0,0,1]) // flip text (botom out = -270)
write(text[r],center=true,h=h,t=t,font=font,bold=bold);
}
}
}
}else{
rotate(-rotate-east+west,[0,0,1]){
rotate(mmangle(radius-middle),[0,0,1]){
translate(where)
for (r=[0:len(text)-1]){
rotate(90-r*NAngle(radius-middle),[0,0,1]) // bottom out=-270+r
translate([radius-middle,0,0])
//rotate(90,[1,0,0])
//rotate(90,[0,1,0])
rotate(270,[0,0,1]) // flip text (botom out = -270)
write(text[r],center=true,h=h,t=t,font=font,bold=bold);
}
}
}
}
}
module writethecylinder(text,where,radius,height,r1,r2){
wid=(.125* h *5.5 * space);
widall=wid*(len(text)-1)/2;
//angle that measures width of letters on sphere
function NAngle(radius)=(wid/(pi2*radius))*360*(1-abs(rotate)/90);
//angle of half width of text
function mmangle(radius)=(widall/(pi2*radius)*360);
translate([0,0,up-down])
rotate(east-west,[0,0,1])
for (r=[0:len(text)-1]){
rotate(-90+(r*NAngle(radius)),[0,0,1])
translate([radius,0,-r*((rotate)/90*wid)+(len(text)-1)/2*((rotate)/90*wid)])
rotate(90,[1,0,0])
rotate(90,[0,1,0])
write(text[r],center=true,h=h,rotate=rotate,t=t,font=font,bold=bold);
//echo("zloc=",height/2-r*((rotate)/90*wid)+(len(text)-1)/2*((rotate)/90*wid));
}
}
module writesphere(text,where,radius){
wid=(.125* h *5.5 * space);
widall=wid*(len(text)-1)/2;
echo("-----------------",widall,wid,mmangle(radius));
//angle that measures width of letters on sphere
function NAngle(radius)=(wid/(pi2*radius))*360;
//angle of half width of text
function mmangle(radius)=(widall/(pi2*radius)*360);
rotate(east-west,[0,0,1]){
rotate(south-north,[1,0,0]){
rotate(spin,[0,1,0]){
rotate(-mmangle(radius),[0,0,1]){
if ( rounded== false ){
translate(where)
for (r=[0:len(text)-1]){
rotate(-90+r*NAngle(radius),[0,0,1])
translate([radius,0,0])
rotate(90,[1,0,0])
rotate(90,[0,1,0])
write(text[r],center=true,h=h,rotate=rotate,t=t,font=font,bold=bold);
}
}else{
difference(){
translate(where)
for (r=[0:len(text)-1]){
rotate(-90+r*NAngle(radius),[0,0,1])
translate([radius,0,0])
rotate(90,[1,0,0])
rotate(90,[0,1,0])
write(text[r],center=true,h=h,rotate=rotate,t=t*2+h,font=font,bold=bold);
}
difference(){ //rounded outside
sphere(radius+(t*2+h)*2);
sphere(radius+t/2);
}
sphere(radius-t/2); // rounded inside for indented text
}
}
}
}}}
}
module writecube(text,where,size){
if (str(size)[0] != "["){
// its a square cube (size was not a matrix so make it one)
writethecube(text,where,[size,size,size],h=h,rotate=rotate,space=space,
t=t,font=font,face=face,up=up,down=down,right=right,left=left,bold=bold);
}else{
// its not square
writethecube(text,where,size,h=h,rotate=rotate,space=space,
t=t,font=font,face=face,up=up,down=down,right=right,left=left,bold=bold);
}
}
// I split the writecube module into 2 pieces.. easier to add features later
module writethecube(text,where,size){
if (face=="front") {
translate([where[0]+right-left,where[1]-size[1]/2,where[2]+up-down])
rotate(90,[1,0,0])
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
if (face=="back") {
translate([where[0]+right-left,where[1]+size[1]/2,where[2]+up-down])
rotate(90,[1,0,0]) // rotate around the x axis
rotate(180,[0,1,0]) // rotate around the y axis (z before rotation)
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
if (face=="left") {
translate([where[0]-size[0]/2,where[1]-right+left,where[2]+up-down ])
rotate(90,[1,0,0]) // rotate around the x axis
rotate(90,[0,-1,0]) // rotate around the y axis (z before rotation)
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
if (face=="right") {
translate([where[0]+size[0]/2,where[1]+right-left,where[2] +up-down])
rotate(90,[1,0,0]) // rotate around the x axis
rotate(90,[0,1,0]) // rotate around the y axis (z before rotation)
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
if (face=="top") {
translate([where[0]+right-left,where[1]+up-down,where[2]+size[2]/2 ])
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
if (face=="bottom") {
translate([where[0]+right-left,where[1]-up+down,where[2]-size[2]/2 ])
rotate(180,[1,0,0])
write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
}
}
module write(word){
echo (h);
echo (word);
echo ("There are " ,len(word) ," letters in this string");
// echo ("The second letter is ",word[1]);
// echo (str(word[0],"_"));
minkowski() {
rotate(rotate,[0,0,-1]){
for (r = [0:len(word)]){ // count off each character
// if the letter is lower case, add an underscore to the end for file lookup
if ((word[r] == "a" ) || (word[r]== "b") || (word[r]== "c")
|| (word[r]== "d") || (word[r]== "e") || (word[r]== "f")
|| (word[r]== "g") || (word[r]== "h") || (word[r]== "i")
|| (word[r]== "j") || (word[r]== "k") || (word[r]== "l")
|| (word[r]== "m") || (word[r]== "n") || (word[r]== "o")
|| (word[r]== "p") || (word[r]== "q") || (word[r]== "r")
|| (word[r]== "s") || (word[r]== "t") || (word[r]== "u")
|| (word[r]== "v") || (word[r]== "w") || (word[r]== "x")
|| (word[r]== "y" )|| (word[r]== "z")){
if (center == true) {
translate([0,-h/2,0]){
scale([.125*h,.125*h,t]){
translate([ (-len(word)*5.5*space/2) + (r*5.5*space),0,0])
//offset(delta = 20, join_type = "round") {
linear_extrude(height=1,convexity=10,center=true){
import(file = font,layer=str(word[r],"_"));
}//}
}
}
}else{
translate([0,0,t/2]){
scale([.125*h,.125*h,t]){
translate([r*5.5*space,0,0])
//offset(delta = 20, join_type = "round") {
linear_extrude(height=1,convexity=10,center=true){
import(file = font,layer=str(word[r],"_"));
}//}
}
}
}
}else{
if (center == true) {
translate([0,-h/2,0]){
scale([.125*h,.125*h,t]){
translate([ (-len(word)*5.5*space/2) + (r*5.5*space),0,0])
//offset(delta = 20, join_type = "round") {
linear_extrude(height=1,convexity=10,center=true){
import(file = font,layer=str(word[r]));
}//}
}
}
}else{
translate([0,0,t/2]){
scale([.125*h,.125*h,t]){
translate([r*5.5*space,0,0])
//offset(delta = 20, join_type = "round") {
linear_extrude(height=1,convexity=10,center=true){
import(file = font,layer=str(word[r]));
}//}
}
}
}
}
}
}
cube([bold*.1*h,bold*.1*h,.00001]);
}
}
/*writecylinder test
translate([0,0,0])
%cylinder(r=20,h=40,center=true);
color([1,0,0])
writecylinder("rotate=90",[0,0,0],20,40,center=true,down=0,rotate=90);
writecylinder("rotate = 30,east = 90",[0,0,0],20,40,center=true,down=0,rotate=30,east=90);
writecylinder("ccw = true",[0,0,0],20,40,center=true,down=0,face="top",ccw=true);
writecylinder("middle = 8",[0,0,0],20,40,h=3,center=true,down=0,face="top",middle=8);
writecylinder("face = top",[0,0,0],20,40,center=true,down=0,face="top");
writecylinder("east=90",[0,0,0],20,40,h=3,center=true,down=0,face="top",east=90);
writecylinder("west=90",[0,0,0],20,40,h=3,center=true,down=0,face="top",ccw=true,west=90);
writecylinder("face = bottom",[0,0,0],20,40,center=true,down=0,face="bottom");
*/
/*writesphere test
sphere(20);
color([1,0,0])
writesphere("Hello World",[0,0,0],20,t=1,h=6);
*/
/* writecube test
translate([30,30,30])
cube([10,15,30],center=true);
write("hello",center=true,rotate =30);
color([1,0,0])
writecube( "front",[30,30,30],[10,15,30],h=5,rotate=-90);
color([0,1,0])
writecube( "back",[30,30,30],size=[10,15,30],h=5,face="back",rotate=90,t=4);
color([0,0,1])
writecube( "left",[30,30,30],[10,15,30],h=5,face="left",up=5);
color([1,1,0])
writecube( "right",where=[30,30,30],size=[10,15,30],h=5,face="right",rotate=55);
color([1,0,1])
writecube( "top",where=[30,30,30],size=[10,15,30],h=5,face="top");
color([1,1,1])
writecube( "bttm",where=[30,30,30],size=[10,15,30],h=5,face="bottom",rotate=90);
*/

16730
Bottle Clip/write/orbitron.dxf Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,39 @@
$fa = $preview ? 12 : 1;
$fs = $preview ? 1 : 0.2;
height=168;
diameter=67;
thickness=2.5;
intersection(){
union(){
difference(){
cylinder(h=(height+thickness-15),r=diameter/2+thickness,center=true);
translate([0,0,thickness/2+.1])
cylinder(h=(height-15+.1),r=diameter/2,center=true);
translate([0,0,.6])
difference(){
cylinder(h=(height-15-1.2),r=diameter/2+thickness-.6,center=true);
cylinder(h=(height-15-1.0),r=diameter/2+.6,center=true);
}
}
for(i=[-4:1:4]){
translate([0,0,i*15])
union(){
difference(){
cylinder(h=2, r=diameter/2+thickness,center=true);
cylinder(h=2.1, r=diameter/2, center=true);
}
rotate_extrude()
translate([diameter/2,0,0])
scale([.5,1,1])
circle(r=1);
}
}
}
if($preview){
translate([0,20,0])
cube([80,40,200], center=true);
}
}

View file

@ -0,0 +1,72 @@
/*
* This work is licensed under the Creative Commons
* Attribution-ShareAlike 4.0 International License. To view a copy of
* this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
*/
/*
* Font "Rock Salt" licensed under APL 2.0
* https://fonts.google.com/specimen/Rock+Salt
*/
$fn=50;
module fhtagn() {
linear_extrude(height=1)
rotate([0,0,90])
translate([55/2,0,0])
resize([55,0,0],auto=true)
union(){
translate([0,60,0])
text(text="Iä! Iä! Cthulhu", font="Rock Salt",halign="center");
translate([0,45,0])
text(text="fhtagn! Ph'nglui", font="Rock Salt",halign="center");
translate([0,30,0])
text(text="mglw'nafh Cthulhu", font="Rock Salt",halign="center");
translate([0,15,0])
text(text="R'lyeh wgah-nagl", font="Rock Salt",halign="center");
text(text="fhtagn—", font="Rock Salt",halign="center");
}
}
module box() {
translate([1,1,1])
minkowski(){
cube([38,58,1]);
sphere(1,center=true);
}
}
union(){
difference(){
difference(){
box();
translate([20,30,1])
rotate([0,-180,-90])
scale([30/180,30/180,1/100])
surface(file="/home/pelu/Downloads/Elder-Rune2_verysmall.png", center=true);
}
translate([32.5,2.5,2])
fhtagn();
}
translate([39,58,1])
difference(){
minkowski(){
translate([-19,2,0])
union() {
resize([38,6,0])
intersection(){
cylinder(h=1,d=1);
translate([-.5,0,0])
cube([1,1,1]);
}
translate([-19,-2,0])
cube([38,2,1]);
}
sphere(1,center=true);
}
translate([-19,4,-1.5])
cylinder(d=5,h=4);
}
}

141
D20 Net/icosahedron.scad Normal file
View file

@ -0,0 +1,141 @@
module Tetrahedon(side=5) {
h = (side/4)*sqrt(6);
linear_extrude(height=h,scale=0)
translate([-side/2,-(sqrt(3)/6)*side,0])
polygon([
[0,0],
[side,0],
[side/2,sqrt(pow(side,2)-pow(side/2,2))],
[0,0]
]);
}
module Icosahedron_side(side=5){
translate([side/2,(sqrt(3)/6)*side,0])
difference(){
Tetrahedon(side);
translate([0,0,side/2])
cube([side+1,side+1,side-2],center=true);
}
}
module Icosahedron(side=5) {
translate([-2.75*side,-sqrt(pow(side,2)-pow(side/2,2))/2,0])
union(){
for(a=[0:4]){
translate([a*side,0,0])
Icosahedron_side(side);
translate([a*side+3/2*side,sqrt(pow(side,2)-pow(side/2,2)),0])
rotate([0,0,180])
Icosahedron_side(side);
translate([a*side+1/2*side,sqrt(pow(side,2)-pow(side/2,2)),0])
Icosahedron_side(side);
translate([(1+a)*side,0,0])
rotate([0,0,180])
Icosahedron_side(side);
}
}
}
module Icosahedron_map(side=10){
textsize=(sqrt(3)/6)*side;
textdepth=.3;
fontstring="Liberation Sans";
xoff=1/4*(sqrt(3)*side - side);
difference(){
Icosahedron(side);
translate([-2.25*side,-xoff,.3])
rotate([180,0,180])
linear_extrude(height=.3)
text(text="1",size=textsize,font=fontstring,halign="center",valign="center");
translate([.75*side,-xoff,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="2",size=textsize,font=fontstring,halign="center",valign="center");
translate([-1.75*side,2/3*side,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="3",size=textsize,font=fontstring,halign="center",valign="center");
translate([-.25*side,-2/3*side,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="4",size=textsize,font=fontstring,halign="center",valign="center");
translate([1.75*side,-2/3*side,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="5",size=textsize,font=fontstring,halign="center",valign="center");
translate([-.75*side,xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="6",size=textsize,font=fontstring,halign="center",valign="center");
translate([-.75*side,1.75*xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="_",size=textsize,font=fontstring,halign="center",valign="center");
translate([2.25*side,xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="7",size=textsize,font=fontstring,halign="center",valign="center");
translate([.25*side,2/3*side,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="8",size=textsize,font=fontstring,halign="center",valign="center");
translate([-1.25*side,-xoff,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="9",size=textsize,font=fontstring,halign="center",valign="center");
translate([-1.25*side,-1.75*xoff,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="_",size=textsize,font=fontstring,halign="center",valign="center");
translate([1.25*side,2/3*side,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="10",size=textsize,font=fontstring,halign="center",valign="center");
translate([-1.25*side,-2/3*side,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="11",size=textsize,font=fontstring,halign="center",valign="center");
translate([1.25*side,xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="12",size=textsize,font=fontstring,halign="center",valign="center");
translate([-2.25*side,-2/3*side,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="13",size=textsize,font=fontstring,halign="center",valign="center");
translate([-.25*side,-xoff,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="14",size=textsize,font=fontstring,halign="center",valign="center");
translate([1.75*side,-xoff,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="15",size=textsize,font=fontstring,halign="center",valign="center");
translate([-.75*side,2/3*side,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="16",size=textsize,font=fontstring,halign="center",valign="center");
translate([2.25*side,2/3*side,textdepth])
rotate([180,0,180])
linear_extrude(height=textdepth)
text(text="17",size=textsize,font=fontstring,halign="center",valign="center");
translate([.75*side,-2/3*side,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="18",size=textsize,font=fontstring,halign="center",valign="center");//*/
translate([-1.75*side,xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="19",size=textsize,font=fontstring,halign="center",valign="center");
translate([.25*side,xoff,textdepth])
rotate([180,0,0])
linear_extrude(height=textdepth)
text(text="20",size=textsize,font=fontstring,halign="center",valign="center");//*/
}
}
Icosahedron_map(side=10);

13
Gewindetest/Mutter.scad Normal file
View file

@ -0,0 +1,13 @@
//$fn=100;
use </home/pelu/Nextcloud/oc.ludikovsky.name/Privat/3D Druck/lib/threads.scad>;
/*
difference() {
cylinder(r=10, h=25, center=true);
cylinder(r=8, h=25, center=true);
}
*/
difference(){
cylinder(r=10, h=3);
metric_thread(diameter=16, length=3, pitch=3, thread_size=1, internal=true);
}

50
Gewindetest/Mutter2.scad Normal file
View file

@ -0,0 +1,50 @@
$fn=360;
use </home/pelu/Nextcloud/oc.ludikovsky.name/Privat/3D Druck/lib/threads.scad>;
difference(){
union(){
cylinder(d=18,h=17,center=true);
translate([0,0,8.5])
resize([34,34,4])
linear_extrude(h=4, center=false, scale=0)
circle(d=34,center=true);
}
cylinder(d=14,h=30,center=true);
}
translate([0,12,8.5])
minkowski(){
linear_extrude(2)
square([0.5,6],center=true);
cylinder(h=2,d=0.5);
}
translate([0,-12,8.5])
minkowski(){
linear_extrude(2)
square([0.5,6],center=true);
cylinder(h=2,d=0.5);
}
translate([12,0,8.5])
rotate([0,0,90])
minkowski(){
linear_extrude(2)
square([0.5,6],center=true);
cylinder(h=2,d=0.5);
}
translate([-12,0,8.5])
rotate([0,0,90])
minkowski(){
linear_extrude(2)
square([0.5,6],center=true);
cylinder(h=2,d=0.5);
}
translate([0,0,-7.5])
difference(){
cylinder(d=14, h=6);
metric_thread(diameter=14, length=6, pitch=3, thread_size=3, internal=true);
}

123
Glider Cube/Glidercube.scad Normal file
View file

@ -0,0 +1,123 @@
// Glider Cube with Stand
// © 2022 by Peter Ludikovsky
// Licensed under CC BY-SA 4.0
// http://creativecommons.org/licenses/by-sa/4.0/
// Pin Connectors V2 by tbuser
// https://www.thingiverse.com/thing:10541
use <pins/pins.scad>
// What to print
part="both"; //[cube:Glider Cube,stand:Stand,both:Cube and Stand]
// Size sans rounded edges
size=100; // [30:1:150]
// Inset depth
depth=5; // [1:.5:5]
// Border width around the inset
border=6; // [1:1:6]
// Extruder size or pixel size of LCD
filament=.1;
elementsize=(size-border)/4;
elementdistance=(size-border)/28;
$fa= $preview ? 6 : 2;
$fs= $preview ? .4/2 : filament/2;
module glidercube(){
translate([0,0,(size/2)+(size/30)])
difference(){
union(){
difference(){
minkowski(){
cube([size,size,size],center=true);
sphere(d=(size/15));
}
translate([0,-size/2-(size/15),0])
cube([size-border,2*depth+(size/15),size-border],center=true);
translate([0,size/2+(size/15),0])
cube([size-border,2*depth+(size/15),size-border],center=true);
translate([-size/2-(size/15),0,0])
cube([2*depth+(size/15),size-border,size-border],center=true);
translate([size/2+(size/15),0,0])
cube([2*depth+(size/15),size-border,size-border],center=true);
}
translate([0, -size/2+depth-(size/30), (elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([(elementsize+elementdistance), -size/2+depth-(size/30), 0])
cube([elementsize,depth*2,elementsize], center=true);
translate([-(elementsize+elementdistance), -size/2+depth-(size/30), -(elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([0, -size/2+depth-(size/30), -(elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([(elementsize+elementdistance), -size/2+depth-(size/30), -(elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([size/2-depth+(size/30), (elementsize+elementdistance), (elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
translate([size/2-depth+(size/30), -(elementsize+elementdistance), (elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
translate([size/2-depth+(size/30), 0, 0])
cube([depth*2,elementsize,elementsize], center=true);
translate([size/2-depth+(size/30), (elementsize+elementdistance), 0])
cube([depth*2,elementsize,elementsize], center=true);
translate([size/2-depth+(size/30), 0, -(elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
translate([-(elementsize+elementdistance), size/2-depth+(size/30), (elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([(elementsize+elementdistance), size/2-depth+(size/30), 0])
cube([elementsize,depth*2,elementsize], center=true);
translate([-(elementsize+elementdistance), size/2-depth+(size/30), 0])
cube([elementsize,depth*2,elementsize], center=true);
translate([0, size/2-depth+(size/30), -(elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([-(elementsize+elementdistance), size/2-depth+(size/30), -(elementsize+elementdistance)])
cube([elementsize,depth*2,elementsize], center=true);
translate([-size/2+depth-(size/30), (elementsize+elementdistance), (elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
translate([-size/2+depth-(size/30), 0, 0])
cube([depth*2,elementsize,elementsize], center=true);
translate([-size/2+depth-(size/30), -(elementsize+elementdistance), 0])
cube([depth*2,elementsize,elementsize], center=true);
translate([-size/2+depth-(size/30), (elementsize+elementdistance), -(elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
translate([-size/2+depth-(size/30), 0, -(elementsize+elementdistance)])
cube([depth*2,elementsize,elementsize], center=true);
}
translate([0,0,-size/2-(size/30)])
pinhole(h=size/3, r=4*size/30, lh=size/10, lt=size/30, tight=false);
}
}
module stand(){
union(){
rotate_extrude()
difference(){
square([size/2,size/3]);
translate([size/2+7*size/60,size/2])
circle(size/2);
}
translate([0,0,size/3])
pintack(h=size/3, r=4*size/30, lh=size/10, lt=size/30,bh=0,br=0);
}
}
if(part=="cube"){
glidercube();
}else if(part=="stand"){
stand();
} else {
translate([-size/1.5,0,0])
glidercube();
translate([size/1.5,0,0])
stand();
}

View file

@ -0,0 +1,20 @@
$fn = $preview ? 40 : 360;
union(){
translate([0,25,29/2+2.5])
cube([20,50,5], center=true);
translate([0,25,-(29/2+2.5)])
cube([20,50,5], center=true);
translate([0,-2.5,0])
cube([20,5,39],center=true);
translate([0,-20,-14.5])
difference(){
rotate([0,90,0])
difference(){
cylinder(h=20,r=20,center=true);
cylinder(h=21,r=15,center=true);
}
translate([0,20.5,10.5])
cube([21,41,21],center=true);
}
}

View file

@ -0,0 +1,33 @@
length=203;
lift=20;
width=10;
nozzle = .4;
$fa = 6;
$fs = nozzle/2;
rotate([asin(lift/length),0,0])
union(){
translate([0,0,-2])
cube([width,length,2]);
rotate([-asin(10/14),0,0])
translate([0,-14,-2])
cube([10,14,2]);
intersection(){
rotate([0,90,0])
cylinder(r=2,h=width);
translate([0,-3,-2])
cube([width,3,2]);
}
translate([0,length,-2])
rotate([0,90,0])
cylinder(r=2,h=width);
}
translate([0,2*sin(lift/length*(180/PI))+sqrt(pow(length,2)-pow(lift,2)),2-2*cos(lift/length*(180/PI))])
cube([width,2,lift-2]);
translate([0,2*sin(lift/length*(180/PI))+sqrt(pow(length,2)-pow(lift,2)),0])
rotate([0,90,0])
cylinder(r=2,h=width);
translate([0,0,-2])
cube([width,2*sin(lift/length*(180/PI))+sqrt(pow(length,2)-pow(lift,2)),2]);

View file

@ -0,0 +1,51 @@
//$fn=100;
module BlockWithText(txt="a"){
difference(){
cube([10,5,5]);
translate([.5,.5,4.5])
cube([9,4,1]);
}
translate([5,1,4.5])
linear_extrude(0.5)
text(txt,size=3,font="Hack",halign="center");
}
rotate([0,-90,0])
translate([0,0,-5])
union(){
BlockWithText("00");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
union(){
BlockWithText("10");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
union(){
BlockWithText("20");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
union(){
BlockWithText("30");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
union(){
BlockWithText("40");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
union(){
BlockWithText("50");
translate([10,0,5])
rotate([0,10,0])
translate([0,0,-5])
BlockWithText("60");
}
}
}
}
}
}

View file

@ -0,0 +1,22 @@
$fn=200;
diameter=50;
width=10;
height=10;
difference(){
cylinder(d=(diameter+width),h=height);
translate([0,0,-1])
cylinder(d=diameter,h=(height+2));
}
translate([cos(30)*(diameter+(width/2)),sin(30)*(diameter+(width/2)),0])
difference(){
cylinder(d=(diameter+width),h=height);
translate([0,0,-1])
cylinder(d=diameter,h=(height+2));
}
translate([cos(30)*(diameter+(width/2)),-sin(30)*(diameter+(width/2)),0])
difference(){
cylinder(d=(diameter+width),h=height);
translate([0,0,-1])
cylinder(d=diameter,h=(height+2));
}

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# scad - Diverse OpenSCAD Projekte
Eine Sammlung von diversen OpenSCAD-Projekten, nicht alle sind fertig oder brauchbar.

17
convertSTL/README.md Normal file
View file

@ -0,0 +1,17 @@
convertSTL
==========
A utility for converting STL files between ASCII and binary encoding.
I wrote this to save disk space and bandwidth when handling STL files. Some modeling programs include this functionality, but it is nice to have something that is more lightweight and can be called from a command line.
USAGE
---------
$ ruby convertSTL.rb [filename of .stl to be converted]
or 'chmod +x' the script and run as:
$ ./convertSTL.rb [filename of .stl to be converted]
The script will then translate the STL to the opposite encoding and save it as either `-ascii.stl` or `-binary.stl`
AUTHOR
-----------
Created by Chris Polis([@ChrisPolis](http://twitter.com/chrispolis)) under the MIT License

127
convertSTL/convertSTL.rb Normal file
View file

@ -0,0 +1,127 @@
#!/usr/bin/env ruby
# convertSTL.rb - Converts STL files between binary and ASCII encoding
# by Chris Polis
#
# This script detects which encoding the stl file is in and converts it to
# the opposite encoding and saves the file as *-ascii.stl or *-binary.stl.
# I wrote this script to save disk space and bandwidth when using stl files.
#
# USAGE:
# $ ruby convertSTL.rb [filename of .stl to be converted]
# or 'chmod +x' and run as ./convertSTL.rb
#
# Helper methods
class Float
def to_sn # to scientific notation
"%E" % self
end
def self.from_sn str # generate a float from scientific notation
("%f" % str).to_f
end
end
# Pass in filename as only argument
if ARGV.size != 1
puts "Usage: ./converSTL.rb [stl filename]"
exit
end
# Read file
begin
original = File.new(ARGV[0], "r")
# Read first line - check binary or ASCII
tempLine = original.gets
if tempLine.include? "solid"
outFilename = ARGV[0].sub(/\.stl/i, '-binary.stl')
puts "#{ARGV[0]} is in ASCII format, converting to BINARY: #{outFilename}"
outFile = File.new(outFilename, "w")
outFile.write("\0" * 80) # 80 bit header - ignored
outFile.write("FFFF") # 4 bit integer # of triangles - filled later
triCount = 0
# ASCII STL format (from Wikipedia):
# solid name(optional)
#
# [foreach triangle]
# facet normal ni nj nk
# outer loop
# vertex v1x v1y v1z
# vertex v2x v2y v2z
# vertex v3x v3y v3z
# endloop
# endfacet
# endsolid name(optional)
while temp = original.gets
next if temp =~ /^\s*$/ or temp.include? 'endsolid' # ignore whitespace
temp.sub! /facet normal/, ''
normal = temp.split(' ').map{ |num| Float.from_sn num }
triCount += 1
temp = original.gets # 'outer loop'
temp = original.gets
vertexA = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets
vertexB = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets
vertexC = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets # 'endsolid'
temp = original.gets # 'endfacet'
outFile.write(normal.pack("FFF"))
outFile.write(vertexA.pack("FFF"))
outFile.write(vertexB.pack("FFF"))
outFile.write(vertexC.pack("FFF"))
outFile.write("\0\0")
end
outFile.seek(80, IO::SEEK_SET)
outFile.write([ triCount ].pack("V"))
outFile.close
else
outFilename = ARGV[0].sub(/\.stl/i, '-ascii.stl')
puts "#{ARGV[0]} is in BINARY format, converting to ASCII: #{outFilename}"
outFile = File.new(outFilename, "w")
outFile.write("solid \n")
# Binary STL format (from Wikipedia):
# UINT8[80] Header
# UINT32 Number of triangles
#
# foreach triangle
# REAL32[3] Normal vector
# REAL32[3] Vertex 1
# REAL32[3] Vertex 2
# REAL32[3] Vertex 3
# UINT16 Attribute byte count
# end
original.seek(80, IO::SEEK_SET)
triCount = original.read(4).unpack('V')[0]
triCount.times do |triNdx|
normal = original.read(12).unpack('FFF')
vertexA = original.read(12).unpack('FFF')
vertexB = original.read(12).unpack('FFF')
vertexC = original.read(12).unpack('FFF')
original.seek(2, IO::SEEK_CUR)
outFile.write(" facet normal #{normal[0].to_sn} #{normal[1].to_sn} #{normal[2].to_sn}\n")
outFile.write(" outer loop\n")
outFile.write(" vertex #{vertexA[0].to_sn} #{vertexA[1].to_sn} #{vertexA[2].to_sn}\n")
outFile.write(" vertex #{vertexB[0].to_sn} #{vertexB[1].to_sn} #{vertexB[2].to_sn}\n")
outFile.write(" vertex #{vertexC[0].to_sn} #{vertexC[1].to_sn} #{vertexC[2].to_sn}\n")
outFile.write(" endloop\n")
outFile.write(" endfacet\n")
end
outFile.write("endsolid \n")
outFile.close
end
original.close
rescue => error
puts "Error: #{error}"
end

23
lib/Icosahedron.scad Normal file
View file

@ -0,0 +1,23 @@
/*****************************************************************
* Icosahedron By Adam Anderson
*
* This module allows for the creation of an icosahedron scaled up
* by a factor determined by the module parameter.
* The coordinates for the vertices were taken from
* http://www.sacred-geometry.es/?q=en/content/phi-sacred-solids
*************************************************************/
module icosahedron(a = 2) {
phi = a * ((1 + sqrt(5)) / 2);
polyhedron(
points = [
[0,-phi, a], [0, phi, a], [0, phi, -a], [0, -phi, -a], [a, 0, phi], [-a, 0, phi], [-a, 0, -phi],
[a, 0, -phi], [phi, a, 0], [-phi, a, 0], [-phi, -a, 0], [phi, -a, 0]
],
faces = [
[0,5,4], [0,4,11], [11,4,8], [11,8,7], [4,5,1], [4,1,8], [8,1,2], [8,2,7], [1,5,9], [1,9,2], [2,9,6], [2,6,7], [9,5,10], [9,10,6], [6,10,3], [6,3,7], [10,5,0], [10,0,3], [3,0,11], [3,11,7]
]
);
}

374
lib/threads.scad Normal file
View file

@ -0,0 +1,374 @@
/*
* ISO-standard metric threads, following this specification:
* http://en.wikipedia.org/wiki/ISO_metric_screw_thread
*
* Copyright 2017 Dan Kirshner - dan_kirshner@yahoo.com
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* See <http://www.gnu.org/licenses/>.
*
* Version 2.3. 2017-08-31 Default for leadin: 0 (best for internal threads).
* Version 2.2. 2017-01-01 Correction for angle; leadfac option. (Thanks to
* Andrew Allen <a2intl@gmail.com>.)
* Version 2.1. 2016-12-04 Chamfer bottom end (low-z); leadin option.
* Version 2.0. 2016-11-05 Backwards compatibility (earlier OpenSCAD) fixes.
* Version 1.9. 2016-07-03 Option: tapered.
* Version 1.8. 2016-01-08 Option: (non-standard) angle.
* Version 1.7. 2015-11-28 Larger x-increment - for small-diameters.
* Version 1.6. 2015-09-01 Options: square threads, rectangular threads.
* Version 1.5. 2015-06-12 Options: thread_size, groove.
* Version 1.4. 2014-10-17 Use "faces" instead of "triangles" for polyhedron
* Version 1.3. 2013-12-01 Correct loop over turns -- don't have early cut-off
* Version 1.2. 2012-09-09 Use discrete polyhedra rather than linear_extrude ()
* Version 1.1. 2012-09-07 Corrected to right-hand threads!
*/
// Examples.
//
// Standard M8 x 1.
// metric_thread (diameter=8, pitch=1, length=4);
// Square thread.
// metric_thread (diameter=8, pitch=1, length=4, square=true);
// Non-standard: long pitch, same thread size.
//metric_thread (diameter=8, pitch=4, length=4, thread_size=1, groove=true);
// Non-standard: 20 mm diameter, long pitch, square "trough" width 3 mm,
// depth 1 mm.
//metric_thread (diameter=20, pitch=8, length=16, square=true, thread_size=6,
// groove=true, rectangle=0.333);
// English: 1/4 x 20.
//english_thread (diameter=1/4, threads_per_inch=20, length=1);
// Tapered. Example -- pipe size 3/4" -- per:
// http://www.engineeringtoolbox.com/npt-national-pipe-taper-threads-d_750.html
// english_thread (diameter=1.05, threads_per_inch=14, length=3/4, taper=1/16);
// Thread for mounting on Rohloff hub.
//difference () {
// cylinder (r=20, h=10, $fn=100);
//
// metric_thread (diameter=34, pitch=1, length=10, internal=true, n_starts=6);
//}
// ----------------------------------------------------------------------------
function segments (diameter) = min (50, ceil (diameter*6));
// ----------------------------------------------------------------------------
// diameter - outside diameter of threads in mm. Default: 8.
// pitch - thread axial "travel" per turn in mm. Default: 1.
// length - overall axial length of thread in mm. Default: 1.
// internal - true = clearances for internal thread (e.g., a nut).
// false = clearances for external thread (e.g., a bolt).
// (Internal threads should be "cut out" from a solid using
// difference ()).
// n_starts - Number of thread starts (e.g., DNA, a "double helix," has
// n_starts=2). See wikipedia Screw_thread.
// thread_size - (non-standard) axial width of a single thread "V" - independent
// of pitch. Default: same as pitch.
// groove - (non-standard) subtract inverted "V" from cylinder (rather than
// add protruding "V" to cylinder).
// square - Square threads (per
// https://en.wikipedia.org/wiki/Square_thread_form).
// rectangle - (non-standard) "Rectangular" thread - ratio depth/(axial) width
// Default: 1 (square).
// angle - (non-standard) angle (deg) of thread side from perpendicular to
// axis (default = standard = 30 degrees).
// taper - diameter change per length (National Pipe Thread/ANSI B1.20.1
// is 1" diameter per 16" length). Taper decreases from 'diameter'
// as z increases.
// leadin - 0 (default): no chamfer; 1: chamfer (45 degree) at max-z end;
// 2: chamfer at both ends, 3: chamfer at z=0 end.
// leadfac - scale of leadin chamfer (default: 1.0 = 1/2 thread).
module metric_thread (diameter=8, pitch=1, length=1, internal=false, n_starts=1,
thread_size=-1, groove=false, square=false, rectangle=0,
angle=30, taper=0, leadin=0, leadfac=1.0)
{
// thread_size: size of thread "V" different than travel per turn (pitch).
// Default: same as pitch.
local_thread_size = thread_size == -1 ? pitch : thread_size;
local_rectangle = rectangle ? rectangle : 1;
n_segments = segments (diameter);
h = (square || rectangle) ? local_thread_size*local_rectangle/2 : local_thread_size / (2 * tan(angle));
h_fac1 = (square || rectangle) ? 0.90 : 0.625;
// External thread includes additional relief.
h_fac2 = (square || rectangle) ? 0.95 : 5.3/8;
tapered_diameter = diameter - length*taper;
difference () {
union () {
if (! groove) {
metric_thread_turns (diameter, pitch, length, internal, n_starts,
local_thread_size, groove, square, rectangle, angle,
taper);
}
difference () {
// Solid center, including Dmin truncation.
if (groove) {
cylinder (r1=diameter/2, r2=tapered_diameter/2,
h=length, $fn=n_segments);
} else if (internal) {
cylinder (r1=diameter/2 - h*h_fac1, r2=tapered_diameter/2 - h*h_fac1,
h=length, $fn=n_segments);
} else {
// External thread.
cylinder (r1=diameter/2 - h*h_fac2, r2=tapered_diameter/2 - h*h_fac2,
h=length, $fn=n_segments);
}
if (groove) {
metric_thread_turns (diameter, pitch, length, internal, n_starts,
local_thread_size, groove, square, rectangle,
angle, taper);
}
}
}
// chamfer z=0 end if leadin is 2 or 3
if (leadin == 2 || leadin == 3) {
difference () {
cylinder (r=diameter/2 + 1, h=h*h_fac1*leadfac, $fn=n_segments);
cylinder (r2=diameter/2, r1=diameter/2 - h*h_fac1*leadfac, h=h*h_fac1*leadfac,
$fn=n_segments);
}
}
// chamfer z-max end if leadin is 1 or 2.
if (leadin == 1 || leadin == 2) {
translate ([0, 0, length + 0.05 - h*h_fac1*leadfac]) {
difference () {
cylinder (r=diameter/2 + 1, h=h*h_fac1*leadfac, $fn=n_segments);
cylinder (r1=tapered_diameter/2, r2=tapered_diameter/2 - h*h_fac1*leadfac, h=h*h_fac1*leadfac,
$fn=n_segments);
}
}
}
}
}
// ----------------------------------------------------------------------------
// Input units in inches.
// Note: units of measure in drawing are mm!
module english_thread (diameter=0.25, threads_per_inch=20, length=1,
internal=false, n_starts=1, thread_size=-1, groove=false,
square=false, rectangle=0, angle=30, taper=0, leadin=0,
leadfac=1.0)
{
// Convert to mm.
mm_diameter = diameter*25.4;
mm_pitch = (1.0/threads_per_inch)*25.4;
mm_length = length*25.4;
echo (str ("mm_diameter: ", mm_diameter));
echo (str ("mm_pitch: ", mm_pitch));
echo (str ("mm_length: ", mm_length));
metric_thread (mm_diameter, mm_pitch, mm_length, internal, n_starts,
thread_size, groove, square, rectangle, angle, taper, leadin,
leadfac);
}
// ----------------------------------------------------------------------------
module metric_thread_turns (diameter, pitch, length, internal, n_starts,
thread_size, groove, square, rectangle, angle,
taper)
{
// Number of turns needed.
n_turns = floor (length/pitch);
intersection () {
// Start one below z = 0. Gives an extra turn at each end.
for (i=[-1*n_starts : n_turns+1]) {
translate ([0, 0, i*pitch]) {
metric_thread_turn (diameter, pitch, internal, n_starts,
thread_size, groove, square, rectangle, angle,
taper, i*pitch);
}
}
// Cut to length.
translate ([0, 0, length/2]) {
cube ([diameter*3, diameter*3, length], center=true);
}
}
}
// ----------------------------------------------------------------------------
module metric_thread_turn (diameter, pitch, internal, n_starts, thread_size,
groove, square, rectangle, angle, taper, z)
{
n_segments = segments (diameter);
fraction_circle = 1.0/n_segments;
for (i=[0 : n_segments-1]) {
rotate ([0, 0, i*360*fraction_circle]) {
translate ([0, 0, i*n_starts*pitch*fraction_circle]) {
//current_diameter = diameter - taper*(z + i*n_starts*pitch*fraction_circle);
thread_polyhedron ((diameter - taper*(z + i*n_starts*pitch*fraction_circle))/2,
pitch, internal, n_starts, thread_size, groove,
square, rectangle, angle);
}
}
}
}
// ----------------------------------------------------------------------------
module thread_polyhedron (radius, pitch, internal, n_starts, thread_size,
groove, square, rectangle, angle)
{
n_segments = segments (radius*2);
fraction_circle = 1.0/n_segments;
local_rectangle = rectangle ? rectangle : 1;
h = (square || rectangle) ? thread_size*local_rectangle/2 : thread_size / (2 * tan(angle));
outer_r = radius + (internal ? h/20 : 0); // Adds internal relief.
//echo (str ("outer_r: ", outer_r));
// A little extra on square thread -- make sure overlaps cylinder.
h_fac1 = (square || rectangle) ? 1.1 : 0.875;
inner_r = radius - h*h_fac1; // Does NOT do Dmin_truncation - do later with
// cylinder.
translate_y = groove ? outer_r + inner_r : 0;
reflect_x = groove ? 1 : 0;
// Make these just slightly bigger (keep in proportion) so polyhedra will
// overlap.
x_incr_outer = (! groove ? outer_r : inner_r) * fraction_circle * 2 * PI * 1.02;
x_incr_inner = (! groove ? inner_r : outer_r) * fraction_circle * 2 * PI * 1.02;
z_incr = n_starts * pitch * fraction_circle * 1.005;
/*
(angles x0 and x3 inner are actually 60 deg)
/\ (x2_inner, z2_inner) [2]
/ \
(x3_inner, z3_inner) / \
[3] \ \
|\ \ (x2_outer, z2_outer) [6]
| \ /
| \ /|
z |[7]\/ / (x1_outer, z1_outer) [5]
| | | /
| x | |/
| / | / (x0_outer, z0_outer) [4]
| / | / (behind: (x1_inner, z1_inner) [1]
|/ | /
y________| |/
(r) / (x0_inner, z0_inner) [0]
*/
x1_outer = outer_r * fraction_circle * 2 * PI;
z0_outer = (outer_r - inner_r) * tan(angle);
//echo (str ("z0_outer: ", z0_outer));
//polygon ([[inner_r, 0], [outer_r, z0_outer],
// [outer_r, 0.5*pitch], [inner_r, 0.5*pitch]]);
z1_outer = z0_outer + z_incr;
// Give internal square threads some clearance in the z direction, too.
bottom = internal ? 0.235 : 0.25;
top = internal ? 0.765 : 0.75;
translate ([0, translate_y, 0]) {
mirror ([reflect_x, 0, 0]) {
if (square || rectangle) {
// Rule for face ordering: look at polyhedron from outside: points must
// be in clockwise order.
polyhedron (
points = [
[-x_incr_inner/2, -inner_r, bottom*thread_size], // [0]
[x_incr_inner/2, -inner_r, bottom*thread_size + z_incr], // [1]
[x_incr_inner/2, -inner_r, top*thread_size + z_incr], // [2]
[-x_incr_inner/2, -inner_r, top*thread_size], // [3]
[-x_incr_outer/2, -outer_r, bottom*thread_size], // [4]
[x_incr_outer/2, -outer_r, bottom*thread_size + z_incr], // [5]
[x_incr_outer/2, -outer_r, top*thread_size + z_incr], // [6]
[-x_incr_outer/2, -outer_r, top*thread_size] // [7]
],
faces = [
[0, 3, 7, 4], // This-side trapezoid
[1, 5, 6, 2], // Back-side trapezoid
[0, 1, 2, 3], // Inner rectangle
[4, 7, 6, 5], // Outer rectangle
// These are not planar, so do with separate triangles.
[7, 2, 6], // Upper rectangle, bottom
[7, 3, 2], // Upper rectangle, top
[0, 5, 1], // Lower rectangle, bottom
[0, 4, 5] // Lower rectangle, top
]
);
} else {
// Rule for face ordering: look at polyhedron from outside: points must
// be in clockwise order.
polyhedron (
points = [
[-x_incr_inner/2, -inner_r, 0], // [0]
[x_incr_inner/2, -inner_r, z_incr], // [1]
[x_incr_inner/2, -inner_r, thread_size + z_incr], // [2]
[-x_incr_inner/2, -inner_r, thread_size], // [3]
[-x_incr_outer/2, -outer_r, z0_outer], // [4]
[x_incr_outer/2, -outer_r, z0_outer + z_incr], // [5]
[x_incr_outer/2, -outer_r, thread_size - z0_outer + z_incr], // [6]
[-x_incr_outer/2, -outer_r, thread_size - z0_outer] // [7]
],
faces = [
[0, 3, 7, 4], // This-side trapezoid
[1, 5, 6, 2], // Back-side trapezoid
[0, 1, 2, 3], // Inner rectangle
[4, 7, 6, 5], // Outer rectangle
// These are not planar, so do with separate triangles.
[7, 2, 6], // Upper rectangle, bottom
[7, 3, 2], // Upper rectangle, top
[0, 5, 1], // Lower rectangle, bottom
[0, 4, 5] // Lower rectangle, top
]
);
}
}
}
}