As initially uploaded to thingiverse

This commit is contained in:
Jeff Epler 2017-03-31 14:18:54 -05:00
commit 6e9dec8291

201
hexbrick.scad Normal file
View file

@ -0,0 +1,201 @@
// hex toy bricks based on designs described at
// http://tamivox.org/redbear/hex_toy_bricks/index2.html
// I follow the prose descriptions and formulas given there, but this
// implementation in openscad is original.
// configurable values
stud_height = 2;
base_height = 3;
base_width = 3.5;
outer_width = .8;
inner_width = .64;
ceiling_thickness = .4;
stud_inset = .05;
outer_wall_inset = .25;
corner_round = .05;
// Round or hex studs are both viable choices
use_round_stud = false;
// "the base height equals the sum of the socket depth and the ceiling
// thickness"
socket_depth = base_height - ceiling_thickness;
// "the stud height cannot be more than the socket depth"
if(socket_depth < stud_height) error();
// "If the stud width is denoted by S, the base width by B, and the inner width
// by I, then S = (B - I) / sqrt(3)" says tamivox.org, but this doesn't
// make a correct model in openscad even after accounting for the fact that
// a "hexagon" constructed with cylinder() is measured with the diameter across
// points instead of across flats.
hex_stud_width = base_width - inner_width / sqrt(3);
// "Some manufacturers might prefer a round stud. For a crisp fit in the
// hexagonal sockets, the diameter should be sqrt(3) times the stud width as
// given in figure F-1a"
round_stud_width = hex_stud_width * sqrt(3)/2;
// advance from point to point of hex
short_advance = base_width * sqrt(3);
// advance from to flat of hex
long_advance = 1.5 * base_width;
X = [1,0,0];
Y = [0,1,0]; XY = X+Y;
Z = [0,0,1]; XZ = X+Z; YZ = Y+Z; XYZ=X+Y+Z;
module cube_cc(sz, cc) {
translate([sz[0] * cc[0] * -.5, sz[1] * cc[1] * -.5, sz[2] * cc[2] *-.5])
cube(sz);
}
module cube_cx(sz) { cube_cc(sz, X); }
module cube_cy(sz) { cube_cc(sz, Y); }
module cube_cxy(sz) { cube_cc(sz, X+Y); }
module lambda_wall(width=inner_width) {
for(th=[0,120,240])
rotate([0,0,th])
cube_cy([base_width, width, base_height - ceiling_thickness/2]);
}
module hexgrid(x, y) {
yprime = y + .5 * x;
translate([x*long_advance, yprime*short_advance,0]) children();
}
// Output a hex grid of walls nx × ny
module inner_walls(nx, ny) {
translate([-base_width/2, -short_advance/2, -base_height])
for(x=[-1:1:nx]) {
for(y=[-1:1:ny]) {
hexgrid(x,y) lambda_wall();
}
}
}
module outline_single() {
rotate(Z*30)
circle(short_advance, $fn=6);
}
module round_stud() {
cylinder(r=round_stud_width-stud_inset, h=stud_height);
}
module hex_stud() {
difference() {
translate(-ceiling_thickness*Z/2)
cylinder(r=hex_stud_width-stud_inset, h=stud_height+ceiling_thickness/2, $fn=6);
translate(-ceiling_thickness*Z)
cylinder(r=(hex_stud_width-stud_inset)/2, h=stud_height+2*ceiling_thickness, $fn=24);
}
}
module stud() {
if(use_round_stud) round_stud(); else hex_stud();
}
function maxcoord_x(seq, best=0) = len(seq) == 0 ? best
: maxcoord_x(rest(seq), max(best, seq[0][0]));
function maxcoord_x(seq, best=0) = len(seq) == 0 ? best
: maxcoord_x(rest(seq), max(best, seq[0][0]));
module outline_coordlist(cc) {
offset(r=-corner_round)
offset(r=corner_round)
for(ii=[0:1:len(cc)-1]) {
ci = cc[ii];
hull() {
for(jj=[0:1:len(ci)-1]) {
cij = ci[jj];
x = cij[0];
y = cij[1];
hexgrid(x,y) outline_single();
}
}
}
}
module inner_volume_coordlist(cc) {
translate([0,0,-base_height-1])
linear_extrude(height=base_height+2)
offset(delta=-outer_wall_inset-outer_width/2)
outline_coordlist(cc);
}
module outer_walls_coordlist(cc) {
translate(-Z*base_height)
linear_extrude(height=base_height-ceiling_thickness/2)
difference() {
offset(delta=-outer_wall_inset)
outline_coordlist(cc);
offset(delta=-outer_width-outer_wall_inset)
outline_coordlist(cc);
}
}
module ceiling_coordlist(cc) {
translate((-ceiling_thickness+1e-3)*Z)
linear_extrude(height=ceiling_thickness)
offset(delta=-outer_wall_inset-1e-3)
outline_coordlist(cc);
}
// The structure of the "cc" parameter is complicated:
// It is a list of lists of nonnegative integer coords
// Each coord gets a stud
// The outer walls for each list of points get hulled together, which is useful
// for lateral bricks. The outermost lists are not hulled but common edges
// are eliminated, which is useful for punctal bricks. It seems possible that
// there are uses for bricks that combine punctal and lateral features.
module piece_coordlist(cc) {
maxx = max([for (i=cc) max([for(j=i) j[0]])]);
maxy = max([for (i=cc) max([for(j=i) j[1]])]);
color("red") outer_walls_coordlist(cc);
intersection() {
color("blue") inner_walls(maxx+1, maxy+1);
inner_volume_coordlist(cc);
}
color("orange") ceiling_coordlist(cc);
for(ii=[0:1:len(cc)-1]) {
ci = cc[ii];
for(jj=[0:1:len(ci)-1]) {
cij = ci[jj];
x = cij[0];
y = cij[1];
hexgrid(x,y) stud();
}
}
}
// A-1
hexgrid(-1,3)
piece_coordlist([[[0,0]]]);
piece_coordlist([
[[0,1]], [[2,0]]
]);
// A-3.1
hexgrid(1,3)
piece_coordlist([
[[0,2]], [[2,1]], [[4,0]]
]);
// A-3.2
hexgrid(4,0)
piece_coordlist([
[[0,2]], [[2,1]], [[3,2]]
]);
// A-3.3
hexgrid(1,1)
piece_coordlist([
[[0,1]], [[2,0]], [[1,2]]
]);
// D-1 (lateral brick)
hexgrid(4,-1)
piece_coordlist([[[0,0],[2,0]]]);