diff --git a/lego_compatibility.scad b/lego_compatibility.scad new file mode 100644 index 0000000..d47b567 --- /dev/null +++ b/lego_compatibility.scad @@ -0,0 +1,157 @@ +// This file is placed under the public domain + +// from: http://www.thingiverse.com/thing:9512 + + +// EXAMPLES: +// standard LEGO 2x1 tile has no pin +// block(1,2,1/3,reinforcement=false,flat_top=true); +// standard LEGO 2x1 flat has pin +// block(1,2,1/3,reinforcement=true); +// standard LEGO 2x1 brick has pin +// block(1,2,1,reinforcement=true); +// standard LEGO 2x1 brick without pin +// block(1,2,1,reinforcement=false); +// standard LEGO 2x1x5 brick has no pin and has hollow knobs +// block(1,2,5,reinforcement=false,hollow_knob=true); + + +knob_diameter=4.8; //knobs on top of blocks +knob_height=2; +knob_spacing=8.0; +wall_thickness=1.45; +roof_thickness=1.05; +block_height=9.5; +pin_diameter=3; //pin for bottom blocks with width or length of 1 +post_diameter=6.5; +reinforcing_width=1.5; +axle_spline_width=2.0; +axle_diameter=5; +cylinder_precision=0.5; + +/* EXAMPLES: + +block(2,1,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=true); + +translate([50,-10,0]) + block(1,2,1/3,axle_hole=false,circular_hole=true,reinforcement=false,hollow_knob=true,flat_top=true); + +translate([10,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=true); +translate([30,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=false,flat_top=false); +translate([50,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=false); +translate([0,20,0]) + block(3,2,2/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=false); +translate([20,20,0]) + block(3,2,1,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=false,flat_top=false); +translate([40,20,0]) + block(3,2,1/3,axle_hole=false,circular_hole=false,reinforcement=false,hollow_knob=false,flat_top=false); +translate([0,-10,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=false,flat_top=false); +translate([0,-20,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=true,flat_top=false); +translate([0,-30,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=true,flat_top=true); +//*/ + +module block(width,length,height,axle_hole=false,reinforcement=false, hollow_knob=false, flat_top=false, circular_hole=false, solid_bottom=true, center=false) { + overall_length=(length-1)*knob_spacing+knob_diameter+wall_thickness*2; + overall_width=(width-1)*knob_spacing+knob_diameter+wall_thickness*2; + center= center==true ? 1 : 0; + translate(center*[-overall_length/2, -overall_width/2, 0]) + union() { + difference() { + union() { + // body: + cube([overall_length,overall_width,height*block_height]); + // knobs: + if (flat_top != true) + translate([knob_diameter/2+wall_thickness,knob_diameter/2+wall_thickness,0]) + for (ycount=[0:width-1]) + for (xcount=[0:length-1]) { + translate([xcount*knob_spacing,ycount*knob_spacing,0]) + difference() { + cylinder(r=knob_diameter/2,h=block_height*height+knob_height,$fs=cylinder_precision); + if (hollow_knob==true) + translate([0,0,-roof_thickness]) + cylinder(r=pin_diameter/2,h=block_height*height+knob_height+2*roof_thickness,$fs=cylinder_precision); + } + } + } + // hollow bottom: + if (solid_bottom == false) + translate([wall_thickness,wall_thickness,-roof_thickness]) cube([overall_length-wall_thickness*2,overall_width-wall_thickness*2,block_height*height]); + // flat_top -> groove around bottom + if (flat_top == true) { + translate([-wall_thickness/2,-wall_thickness*2/3,-wall_thickness/2]) + cube([overall_length+wall_thickness,wall_thickness,wall_thickness]); + translate([-wall_thickness/2,overall_width-wall_thickness/3,-wall_thickness/2]) + cube([overall_length+wall_thickness,wall_thickness,wall_thickness]); + + translate([-wall_thickness*2/3,-wall_thickness/2,-wall_thickness/2]) + cube([wall_thickness,overall_width+wall_thickness,wall_thickness]); + translate([overall_length-wall_thickness/3,0,-wall_thickness/2]) + cube([wall_thickness,overall_width+wall_thickness,wall_thickness]); + } + if (axle_hole==true) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,roof_thickness]) axle(height); + if (circular_hole==true) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,roof_thickness]) + cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness/4,$fs=cylinder_precision); + } + + if (reinforcement==true && width>1 && length>1) + difference() { + for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,0]) reinforcement(height); + for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,-roof_thickness/2]) cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness, $fs=cylinder_precision); + } + // posts: + if (solid_bottom == false) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,0]) post(height); + + if (reinforcement == true && width==1 && length!=1) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,overall_width/2,0]) cylinder(r=pin_diameter/2,h=block_height*height,$fs=cylinder_precision); + + if (reinforcement == true && length==1 && width!=1) + for (ycount=[1:width-1]) + translate([overall_length/2,ycount*knob_spacing,0]) cylinder(r=pin_diameter/2,h=block_height*height,$fs=cylinder_precision); + } +} + +module post(height) { + difference() { + cylinder(r=post_diameter/2, h=height*block_height-roof_thickness/2,$fs=cylinder_precision); + translate([0,0,-roof_thickness/2]) + cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness/4,$fs=cylinder_precision); + } +} + +module reinforcement(height) { + union() { + translate([0,0,height*block_height/2]) union() { + cube([reinforcing_width,knob_spacing+knob_diameter+wall_thickness/2,height*block_height],center=true); + rotate(v=[0,0,1],a=90) cube([reinforcing_width,knob_spacing+knob_diameter+wall_thickness/2,height*block_height], center=true); + } + } +} + +module axle(height) { + translate([0,0,height*block_height/2]) union() { + cube([axle_diameter,axle_spline_width,height*block_height],center=true); + cube([axle_spline_width,axle_diameter,height*block_height],center=true); + } +} + diff --git a/multiply.scad b/multiply.scad new file mode 100644 index 0000000..bca12c3 --- /dev/null +++ b/multiply.scad @@ -0,0 +1,29 @@ +/* + * Multiplication along certain curves + * + * Copyright by Elmo Mäntynen, 2012. + * Licenced under LGPL2 or later + */ + +include + +use + +// TODO check that the axis parameter works as intended +// Duplicate everything $no of times around an $axis, for $angle/360 rounds +module spin(no, angle=360, axis=Z){ + for (i = [1:no]){ + rotate(normalized_axis(axis)*angle*no/i) union(){ + for (i = [0 : $children-1]) child(i); + } + } +} + +//Doesn't work currently +module duplicate(axis=Z) spin(no=2, axis=axis) child(0); + +module linear_multiply(no, separation, axis=Z){ + for (i = [0:no-1]){ + translate(i*separation*axis) child(0); + } +} diff --git a/regular_shapes.scad b/regular_shapes.scad index 2818983..acba0bc 100644 --- a/regular_shapes.scad +++ b/regular_shapes.scad @@ -76,6 +76,13 @@ module dodecagon(radius) reg_polygon(12,radius); } +module ring(inside_diameter, thickness){ + difference(){ + circle(r=(inside_diameter+thickness*2)/2); + circle(r=inside_diameter/2); + } +} + module ellipse(width, height) { scale([1, height/width, 1]) circle(r=width/2); } @@ -93,17 +100,17 @@ module egg_outline(width, length){ //3D regular shapes -module cone(height, radius, center = false) +module cone(height, radius, center = false) { cylinder(height, radius, 0, center); } -module oval_prism(height, rx, ry, center = false) +module oval_prism(height, rx, ry, center = false) { scale([1, rx/ry, 1]) cylinder(h=height, r=ry, center=center); } -module oval_tube(height, rx, ry, wall, center = false) +module oval_tube(height, rx, ry, wall, center = false) { difference() { scale([1, ry/rx, 1]) cylinder(h=height, r=rx, center=center); @@ -111,7 +118,7 @@ module oval_tube(height, rx, ry, wall, center = false) } } -module cylinder_tube(height, radius, wall, center = false) +module cylinder_tube(height, radius, wall, center = false) { tubify(radius,wall) cylinder(h=height, r=radius, center=center); @@ -144,10 +151,10 @@ module pentagon_prism(height,radius) module pentagon_tube(height,radius,wall) { - tubify(radius,wall) pentagon_prism(height,radius); + tubify(radius,wall) pentagon_prism(height,radius); } -module hexagon_prism(height,radius) +module hexagon_prism(height,radius) { linear_extrude(height=height) hexagon(radius); } @@ -157,7 +164,7 @@ module hexagon_tube(height,radius,wall) tubify(radius,wall) hexagon_prism(height,radius); } -module heptagon_prism(height,radius) +module heptagon_prism(height,radius) { linear_extrude(height=height) heptagon(radius); } @@ -167,9 +174,9 @@ module heptagon_tube(height,radius,wall) tubify(radius,wall) heptagon_prism(height,radius); } -module octagon_prism(height,radius) +module octagon_prism(height,radius) { - linear_extrude(height=height) octagon(radius); + linear_extrude(height=height) octagon(radius); } module octagon_tube(height,radius,wall) @@ -179,28 +186,28 @@ module octagon_tube(height,radius,wall) module nonagon_prism(height,radius) { - linear_extrude(height=height) nonagon(radius); + linear_extrude(height=height) nonagon(radius); } module decagon_prism(height,radius) { - linear_extrude(height=height) decagon(radius); + linear_extrude(height=height) decagon(radius); } module hendecagon_prism(height,radius) { - linear_extrude(height=height) hendecagon(radius); + linear_extrude(height=height) hendecagon(radius); } module dodecagon_prism(height,radius) { - linear_extrude(height=height) dodecagon(radius); + linear_extrude(height=height) dodecagon(radius); } module torus(outerRadius, innerRadius) { r=(outerRadius-innerRadius)/2; - rotate_extrude() translate([innerRadius+r,0,0]) circle(r); + rotate_extrude() translate([innerRadius+r,0,0]) circle(r); } module torus2(r1, r2) diff --git a/units.scad b/units.scad index 62662a9..61d0d7f 100644 --- a/units.scad +++ b/units.scad @@ -10,8 +10,13 @@ mm = 1; cm = 10 * mm; dm = 100 * mm; m = 1000 * mm; + inch = 25.4 * mm; +X = [1, 0, 0]; +Y = [0, 1, 0]; +Z = [0, 0, 1]; + M3 = 3*mm; M4 = 4*mm; M5 = 5*mm; diff --git a/utilities.scad b/utilities.scad index 6d6468d..01e4511 100644 --- a/utilities.scad +++ b/utilities.scad @@ -15,7 +15,9 @@ function length2(a) = sqrt( a[0]*a[0] + a[1]*a[1] ); function normalized(a) = a / (max(distance([0,0,0], a), 0.00001)); - +function normalized_axis(a) = a == "x" ? [1, 0, 0]: + a == "y" ? [0, 1, 0]: + a == "z" ? [0, 0, 1]: normalized(a); function angleOfNormalizedVector(n) = [0, -atan2(n[2], length2([n[0], n[1]])), atan2(n[1], n[0]) ]; @@ -23,16 +25,6 @@ function angle(v) = angleOfNormalizedVector(normalized(v)); function angleBetweenTwoPoints(a, b) = angle(normalized(b-a)); -// TODO check that the axis parameter works as intended -// Duplicate everything $no of times around an $axis, for $angle/360 rounds -module spin(no, angle=360, axis=[0, 0, 1]){ - for (i = [0:no]){ - rotate(normalized(axis)*angle*i/no) union(){ - for (i = [0 : $children-1]) child(i); - } - } -} - CENTER = 0; LEFT = -0.5;