Initial Import
This commit is contained in:
commit
03d0978743
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.stl
|
||||||
|
*.xz
|
32
Bottle Clip/Clipholder.scad
Normal file
32
Bottle Clip/Clipholder.scad
Normal 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);
|
||||||
|
}
|
119
Bottle Clip/bottle-clip.scad
Normal file
119
Bottle Clip/bottle-clip.scad
Normal 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
16230
Bottle Clip/logos/logo.dxf
Normal file
File diff suppressed because it is too large
Load diff
15
Bottle Clip/usr_space.scad
Normal file
15
Bottle Clip/usr_space.scad
Normal 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="");
|
||||||
|
}
|
388
Bottle Clip/write/Write.scad
Normal file
388
Bottle Clip/write/Write.scad
Normal 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
16730
Bottle Clip/write/orbitron.dxf
Normal file
File diff suppressed because it is too large
Load diff
84
Bunny Cookie Cutter/bunny.scad
Normal file
84
Bunny Cookie Cutter/bunny.scad
Normal file
File diff suppressed because one or more lines are too long
39
Can Sleeve/Can Sleeve.scad
Normal file
39
Can Sleeve/Can Sleeve.scad
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
72
Cthulhu Keychain/Cthulhu Keychain.scad
Normal file
72
Cthulhu Keychain/Cthulhu Keychain.scad
Normal 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
141
D20 Net/icosahedron.scad
Normal 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
13
Gewindetest/Mutter.scad
Normal 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
50
Gewindetest/Mutter2.scad
Normal 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
123
Glider Cube/Glidercube.scad
Normal 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();
|
||||||
|
}
|
20
HDMI Halter/HDMI Halter.scad
Normal file
20
HDMI Halter/HDMI Halter.scad
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
33
Laptop Stand/Laptop Stand.scad
Normal file
33
Laptop Stand/Laptop Stand.scad
Normal 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]);
|
51
Overhang Test/overhang.scad
Normal file
51
Overhang Test/overhang.scad
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
Poster Clip/Poster Clip.scad
Normal file
22
Poster Clip/Poster Clip.scad
Normal 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
3
README.md
Normal 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
17
convertSTL/README.md
Normal 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
127
convertSTL/convertSTL.rb
Normal 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
23
lib/Icosahedron.scad
Normal 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
374
lib/threads.scad
Normal 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
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue