327 lines
10 KiB
OpenSCAD
327 lines
10 KiB
OpenSCAD
//
|
|
// Anybeam OpenSCAD Library
|
|
//
|
|
// This library provides an anybeam() module that can be used to create beams
|
|
// with a variaty of hole, axle and slot patterns using a simple declaritive syntax.
|
|
//
|
|
//
|
|
// Beam String
|
|
//
|
|
// A beam is speficied with a sequence of characters, each representing a hole
|
|
// type in the beam.
|
|
//
|
|
// O Pin hole
|
|
// X Axle hole
|
|
// ( Half hole with a slot on the right.
|
|
// ) Half hole with the slot on the left.
|
|
// - (dash) A full width slot, use with ( and ) to create long slots with half hole ends like "(--)" (4 span slot) or "()" (2 span slot)
|
|
// | (line) Pin hole at the edge (rotated 90 degree in respect to normal pin hole). Beam will be rotated 90 degree if at least one its end is "|", and none of its ends are "O".
|
|
// # (hash) Axle hole at the edge.
|
|
// . (period) Skip this hole.
|
|
//
|
|
// Use the above characters to represent the hole layout on the beam:
|
|
//
|
|
// XOOOOX - Size 6 beam with axle holes at the ends.
|
|
// OOXOO - Size 5 beam with an axle hole in the middle.
|
|
// (---)OOO - Size 8 beam with a size 5 slot and three holes at the end.
|
|
//
|
|
// Between each beam is a connection vector that defines how the beams connect.
|
|
//
|
|
// [ PREVIOUS_BEAM_HOLE, CURRENT_BEAM_HOLE, ANGLE ]
|
|
//
|
|
// * Holes are numbered from 1 to N (the length of the beam) from left to right.
|
|
// * Angles are in degrees.
|
|
//
|
|
// Here is a standard 4x2 90 degree lift arm:
|
|
//
|
|
// [ "XOOO", [ 4, 1, 90 ], "OO" ]
|
|
//
|
|
// The connection hole specifier may includ a fractional part.
|
|
//
|
|
//
|
|
// Fractional Hole Spacing
|
|
//
|
|
// Here is a 4x2 beam with the size 2 beam in the midde of the size 4 beam.
|
|
// The space prevents a hole from appearing at the start of the beam where
|
|
// the two overlap.
|
|
//
|
|
// Connecting hole 2.5 of the size 4 beam to hole 1 of the size 2 beam at 90 degrees.
|
|
//
|
|
// [ "OOOO", [ 2.5, 1, 90 ], ".O" ]
|
|
//
|
|
//
|
|
// Examples:
|
|
|
|
|
|
// Constants.
|
|
AB_HOLE_SPACING = 8.0;
|
|
AB_HOLE_INSIDE_DIAMETER = 5.4;
|
|
AB_STUD_DIAMETER = 4.8;
|
|
AB_HOLE_RING_DIAMETER = 6.28;
|
|
AB_HOLE_RING_DEPTH = 0.9;
|
|
AB_BEAM_WIDTH = 7.8; // originally 7.6, restore if you want slightly thinner beams like standard ones
|
|
AB_AXLE_GAP = 1.95;
|
|
AB_AXLE_LENGTH = 5.1;
|
|
|
|
AB_BEAM_HEIGHT = 7.8;
|
|
AB_THIN_BEAM_HEIGHT = AB_BEAM_HEIGHT/3;
|
|
|
|
// From roipoussiere's string functions - https://www.thingiverse.com/thing:202724
|
|
function ab_fill(car, nb_occ, out="") = (nb_occ == 0) ? out : str(ab_fill(car, nb_occ-1, out), car);
|
|
|
|
//anybeam( [ "XOOO", [ 4, 1, 53.13 ], "OOO()", [ 5, 1, -53.13 ], "(-)X" ], 1 );
|
|
|
|
//anybeam( [ "X##X", [ 4, 1, 90 ], "X|OO|X", [ 6, 1, 90 ], "X##X", [ 4, 1, 90 ], "X|OO|X" ], 1);
|
|
|
|
// Standard small frame
|
|
//anybeam( [ "O|||O", [ 5, 1, 90 ], "O|O|O|O", [ 7, 1, 90 ], "O|||O", [ 5, 1, 90 ], "O|O|O|O" ], 1);
|
|
|
|
// Standard big frame
|
|
//anybeam( [ "O|||O", [ 5, 3, 90 ], "||O|O|O|O||", [ 9, 1, 90 ], "O|||O", [ 5, 3, 90 ], "||O|O|O|O||" ], 1);
|
|
|
|
//anybeam( [ "|O|O|", [ 5, 1, 90 ], "_|O|O|O|_", [ 9, 1, 90 ], "|O|O|", [ 5, 1, 90 ], "_|O|O|O|_" ], 1);
|
|
|
|
//anybeam_tee(stem="|O|", top="_O|");
|
|
|
|
module anybeam( beams = [], height = 1 ) {
|
|
translate([0, 0, height/2]) {
|
|
difference() {
|
|
ab_beams( beams, height * AB_BEAM_HEIGHT );
|
|
ab_holes( beams, height * AB_BEAM_HEIGHT );
|
|
}
|
|
}
|
|
}
|
|
|
|
module anybeam_straight( holes = 10, height = 1 ) {
|
|
if( len(holes )) {
|
|
anybeam( [ holes ], height);
|
|
}
|
|
else {
|
|
anybeam( [ ab_fill("O", holes ) ], height);
|
|
}
|
|
}
|
|
|
|
module anybeam_tee( stem = "OOO", top = "OOO", height = 1 ) {
|
|
anybeam( [ stem, [ 2, 1, 90 ], top ], height );
|
|
}
|
|
|
|
module anybeam_143( left = "XOOO", right = "OOOOOX", height = 1 ) {
|
|
anybeam( [ left, [ len(left), 1, 53.13 ], right ], height );
|
|
}
|
|
|
|
module anybeam_90(left = "XOOO", right = "OO", height = 1) {
|
|
anybeam( [ left, [ len(left), 1, 90 ], right ], height );
|
|
}
|
|
|
|
module anybeam_135x2(left = "XOOOOOO", middle = " () ", right = "OOX", height = 1) {
|
|
anybeam( [ left, [ len(left), 1, 45 ], middle, [ len(middle), 1, 45], right ], height );
|
|
}
|
|
|
|
//
|
|
// Test beam that uses all features.
|
|
//
|
|
module anybeam_test(left = "XOOOOOO", middle = "O(-) ", right = 3, height = 1) {
|
|
anybeam( [ left, [ len(left), 3, 45 ], middle, [ len(middle), 1, 45], right ], height );
|
|
}
|
|
|
|
//
|
|
// Support Modules
|
|
//
|
|
|
|
//
|
|
// Layout beam holes.
|
|
//
|
|
module ab_holes( beams = [], height = AB_BEAM_HEIGHT, b = 0 ) {
|
|
beam = beams[b];
|
|
connection = beams[b-1];
|
|
next_beam = beams[b+2];
|
|
|
|
if( connection ) {
|
|
if( next_beam ) {
|
|
translate( [ (connection[0]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
rotate([0, 0, connection[2]])
|
|
translate( [ -(connection[1]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
ab_beam_holes( beam, height )
|
|
ab_holes( beams, height, b+2 );
|
|
}
|
|
else {
|
|
translate( [ (connection[0]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
rotate([0, 0, connection[2]])
|
|
translate( [ -(connection[1]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
ab_beam_holes( beam, height );
|
|
}
|
|
}
|
|
else {
|
|
if( next_beam ) {
|
|
ab_beam_holes( beam, height )
|
|
ab_holes( beams, height, b+2 );
|
|
}
|
|
else {
|
|
ab_beam_holes( beam, height );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Layout solid beams.
|
|
//
|
|
module ab_beams( beams = [], height = AB_BEAM_HEIGHT, b = 0 ) {
|
|
|
|
beam = beams[b];
|
|
connection = beams[b-1];
|
|
next_beam = beams[b+2];
|
|
|
|
if( connection ) {
|
|
if( next_beam ) {
|
|
translate( [ (connection[0]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
rotate([0, 0, connection[2]])
|
|
translate( [ -(connection[1]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
ab_solid_beam( beam, height )
|
|
ab_beams( beams, height, b+2 );
|
|
}
|
|
else {
|
|
translate( [ (connection[0]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
rotate([0, 0, connection[2]])
|
|
translate( [ -(connection[1]-1)*AB_HOLE_SPACING, 0, 0 ] )
|
|
ab_solid_beam( beam, height );
|
|
}
|
|
}
|
|
else {
|
|
if( next_beam ) {
|
|
ab_solid_beam( beam, height )
|
|
ab_beams( beams, height, b+2 );
|
|
}
|
|
else {
|
|
ab_solid_beam( beam, height );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// A single solid beam.
|
|
//
|
|
module ab_solid_beam( beam = "OOOO", beam_height = AB_BEAM_HEIGHT ) {
|
|
holes = len(beam) ? len(beam)-1 : beam-1;
|
|
beam_length = holes*AB_HOLE_SPACING;
|
|
rot = (beam[0] == "|" && beam[len(beam)-1] != "O" || beam[0] != "O" && beam[len(beam)-1] == "|" ? 90 : 0);
|
|
union() {
|
|
rotate([ rot, 0, 0 ])
|
|
translate( [beam_length/2,0,0] ) {
|
|
cube( [ beam_length, AB_BEAM_WIDTH, beam_height ], center=true );
|
|
|
|
translate( [-beam_length/2, 0, 0] )
|
|
cylinder( r = AB_BEAM_WIDTH/2, beam_height, center=true, $fn=100 );
|
|
translate( [beam_length/2, 0, 0] )
|
|
cylinder( r = AB_BEAM_WIDTH/2, beam_height, center=true, $fn=100 );
|
|
}
|
|
|
|
if( $children ) child(0);
|
|
}
|
|
}
|
|
|
|
module ab_beam_holes( beam = "OOOO", beam_height = AB_BEAM_HEIGHT ) {
|
|
holes = len(beam)-1;
|
|
beam_length = holes*AB_HOLE_SPACING;
|
|
layout = beam;
|
|
|
|
for (hole = [0:1:holes]) {
|
|
translate( [hole*AB_HOLE_SPACING,0,0] ) {
|
|
if( layout == "" ) {
|
|
ab_hole_pin( beam_height );
|
|
}
|
|
else {
|
|
if( layout[hole] == "O" ) {
|
|
ab_hole_pin( beam_height );
|
|
}
|
|
if( layout[hole] == "|" ) {
|
|
rotate([-90, 0, 0]) ab_hole_pin( beam_height );
|
|
}
|
|
if( layout[hole] == "(" ) {
|
|
ab_hole_left_slot( beam_height );
|
|
}
|
|
if( layout[hole] == ")" ) {
|
|
ab_hole_right_slot( beam_height );
|
|
}
|
|
if( layout[hole] == "-" ) {
|
|
ab_hole_slot( beam_height );
|
|
}
|
|
if( layout[hole] == "X" ) {
|
|
ab_hole_axle( beam_height, first = (hole==0), last = (hole==holes) );
|
|
}
|
|
if( layout[hole] == "#" ) {
|
|
rotate([-90, 0, 0]) ab_hole_axle( beam_height, first = (hole==0), last = (hole==holes) );
|
|
}
|
|
// Any other letter is a space.
|
|
}
|
|
}
|
|
}
|
|
if( $children ) child(0);
|
|
}
|
|
|
|
module ab_hole_pin( beam_height = AB_BEAM_HEIGHT ) {
|
|
cylinder(beam_height+2, AB_HOLE_INSIDE_DIAMETER/2, AB_HOLE_INSIDE_DIAMETER/2, center = true, $fn=100);
|
|
|
|
translate([0,0,beam_height/2-AB_HOLE_RING_DEPTH/2+.5])
|
|
cylinder(AB_HOLE_RING_DEPTH+1, AB_HOLE_RING_DIAMETER/2, AB_HOLE_RING_DIAMETER/2, center = true, $fn=100);
|
|
|
|
translate([0,0,-(beam_height/2-AB_HOLE_RING_DEPTH/2+.5)])
|
|
cylinder(AB_HOLE_RING_DEPTH+1, AB_HOLE_RING_DIAMETER/2, AB_HOLE_RING_DIAMETER/2, center = true, $fn=100);
|
|
}
|
|
|
|
module ab_hole_left_slot( beam_height = AB_BEAM_HEIGHT ) {
|
|
ab_hole_pin(beam_height);
|
|
|
|
translate([AB_HOLE_SPACING/4, 0, 0]) {
|
|
cube([AB_HOLE_SPACING/2+.05,AB_HOLE_INSIDE_DIAMETER,beam_height+2], center = true);
|
|
|
|
translate([0,0,beam_height/2-AB_HOLE_RING_DEPTH/2+.5])
|
|
cube([AB_HOLE_SPACING/2+0.05, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1,], center = true);
|
|
|
|
translate([0,0,-(beam_height/2-AB_HOLE_RING_DEPTH/2+.5)])
|
|
cube([AB_HOLE_SPACING/2+0.05, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1], center = true);
|
|
}
|
|
}
|
|
|
|
module ab_hole_right_slot( beam_height = AB_BEAM_HEIGHT ) {
|
|
ab_hole_pin(beam_height);
|
|
|
|
translate([-AB_HOLE_SPACING/4, 0, 0]) {
|
|
cube([AB_HOLE_SPACING/2+.05,AB_HOLE_INSIDE_DIAMETER,beam_height+2], center = true);
|
|
|
|
translate([0,0,beam_height/2-AB_HOLE_RING_DEPTH/2+.5])
|
|
cube([AB_HOLE_SPACING/2+0.05, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1,], center = true);
|
|
|
|
translate([0,0,-(beam_height/2-AB_HOLE_RING_DEPTH/2+.5)])
|
|
cube([AB_HOLE_SPACING/2+0.05, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1], center = true);
|
|
}
|
|
}
|
|
|
|
module ab_hole_slot( beam_height = AB_BEAM_HEIGHT ) {
|
|
cube([AB_HOLE_SPACING,AB_HOLE_INSIDE_DIAMETER,beam_height+2], center = true);
|
|
|
|
translate([0,0,beam_height/2-AB_HOLE_RING_DEPTH/2+.5])
|
|
cube([AB_HOLE_SPACING, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1,], center = true);
|
|
|
|
translate([0,0,-(beam_height/2-AB_HOLE_RING_DEPTH/2+.5)])
|
|
cube([AB_HOLE_SPACING, AB_HOLE_RING_DIAMETER, AB_HOLE_RING_DEPTH+1], center = true);
|
|
}
|
|
|
|
module ab_hole_axle( beam_height = AB_BEAM_HEIGHT , first = false, last = false) {
|
|
if( first == true ) {
|
|
cube([AB_AXLE_GAP,AB_AXLE_LENGTH,beam_height+2], center = true);
|
|
translate([+.5,0,0])
|
|
cube([AB_AXLE_LENGTH+1,AB_AXLE_GAP,beam_height+2], center = true);
|
|
}
|
|
if( last == true ) {
|
|
cube([AB_AXLE_GAP,AB_AXLE_LENGTH,beam_height+2], center = true);
|
|
translate([-.5,0,0])
|
|
cube([AB_AXLE_LENGTH+1,AB_AXLE_GAP,beam_height+2], center = true);
|
|
}
|
|
if( first == false && last == false ) {
|
|
cube([AB_AXLE_GAP,AB_AXLE_LENGTH,beam_height+2], center = true);
|
|
cube([AB_AXLE_LENGTH,AB_AXLE_GAP,beam_height+2], center = true);
|
|
}
|
|
}
|
|
|