Skip to content

Instantly share code, notes, and snippets.

@ryansturmer
Last active August 17, 2016 16:33
Show Gist options
  • Save ryansturmer/94549b2c4e766a15a1e353522ca9cdd4 to your computer and use it in GitHub Desktop.
Save ryansturmer/94549b2c4e766a15a1e353522ca9cdd4 to your computer and use it in GitHub Desktop.
Parametric Baby Chair
// Walter's Chair
var woodColor = [0.93,0.83,0.67];
function getParameterDefinitions() {
return [
{ name: 'seatDepth', type: 'float', initial: 12, caption: "Seat Depth" },
{ name: 'seatWidth', type: 'float', initial: 12, caption: "Seat Width" },
{ name: 'chairHeight', type: 'float', initial: 12, caption: "Chair Height" },
{ name: 'seatHeight', type: 'float', initial: 7, caption: "Seat Height" },
{ name: 'sideRadius', type: 'float', initial: 1.75, caption: "Side Radius" },
{ name: 'sideTabSize', type: 'float', initial:2.0, caption: "Tab Size"},
{ name: 'materialThickness', type: 'float', initial: 0.5, caption: "Material Thickness" },
{ name: 'slotFitAllowance', type: 'float', initial:0.015, caption: "Fit Allowance"},
{ name: 'boltCount', type: 'int', initial:2, caption: "Screws per Side"},
{ name: 'handles',
type : 'choice',
values : [0,1,2],
caption : "Handles",
captions: ['No Handles', 'Top Only', 'Top and Bottom'],
initial : 2
} ,
{ name: 'part',
caption: 'Display Part',
type : 'choice',
values : ['assembled', 'all', 'left', 'right', 'seat', 'back'],
captions: ['Assembled', 'All', 'Left', 'Right', 'Seat', 'Back'],
initial : 'assembled'
}
];
}
function main(params) {
parts = makeStaticSeatParts(params);
switch(params.part) {
case 'assembled':
return parts.parts;
break;
case 'all':
var pieces = [
{name:'seat'},
{name:'back'},
{name:'left',flip:true},
{name:'right'}
]
t = 0;
retval = [];
pieces.forEach(function(piece) {
// Flatten Part
var movedPart =
parts[piece.name].
lieFlat().center(true);
// Flip it over if desired
if(piece.flip) {
movedPart = movedPart
.rotateY(180)
.lieFlat().center(true);
}
movedPart = movedPart.translate([t,0])
retval.push(movedPart);
t = t + 14;
});
return retval;
break;
default:
return parts[params.part].lieFlat();
break;
}
return parts.parts;
}
function makeStaticSeatParts(params) {
var seatWidth = params.seatWidth;
var seatDepth = params.seatDepth;
var chairHeight = params.chairHeight;
var seatHeight = params.seatHeight;
var seatOffset = -chairHeight/2.0+seatHeight;
var thickness = params.materialThickness;
var sideRadius = params.sideRadius;
var handles = parseInt(params.handles);
console.log(handles)
// Create the seat
var seat = makeSeat({
width : seatWidth,
depth : seatDepth,
thickness : thickness,
fitAllowance : params.slotFitAllowance,
tabDepth : thickness*0.333,
boltCount : params.boltCount
});
// Move the seat (and joints) to the appropriate height
seat = seat.translate([0,0,seatOffset]);
// Make side panel
var left = makeSide({
depth : seatDepth,
height : chairHeight,
thickness : thickness,
radius : sideRadius,
handles : handles,
fitAllowance : params.slotFitAllowance,
tabSize : params.sideTabSize
}).rotateX(90)
.rotateZ(90)
.translate([-seatWidth/2.0-thickness/2.0,0,0]);
// Make second side panel from the first one
var right = left.translate([seatWidth+thickness, 0,0]);
// Cut tab slots in side panel
left = difference(left, seat.properties.slot, seat.properties.bolts)
right = difference(right, seat.properties.slot, seat.properties.bolts)
// Make back panel
var back = makeBack({
width : seatWidth,
height : chairHeight,
thickness : thickness,
handles : handles
});
// Move back panel into position
back = back.rotateX(90).translate(
[0,seatDepth/2.0 + thickness/2.0,0]
);
// Cut slots in back panel to mate with side panels and seat
back = difference(
back,
seat.properties.slot,
left.properties.slots,
left.properties.bolts,
right.properties.slots,
right.properties.bolts,
seat.properties.bolts
);
// Build final list of parts
parts = [];
// Panels
var panels = [ color(darken(woodColor, 0.7), seat),
left,
right,
color(darken(woodColor, 0.85), back)
];
panels.forEach(function(panel) {parts.push(panel)});
return {
left : left,
right : right,
back : back,
seat : seat,
panels : panels,
parts : parts
}
}
function darken(c, factor) {
factor = factor || 0.8;
return [c[0]*factor, c[1]*factor, c[2]*factor];
}
function makeRoundedCube(options) {
options = options || {};
var size = options.size || [1,1,1];
var radius = options.radius || 0.25;
var thickness = size[2] || 0.5;
var width = size[0];
var height = size[1];
return difference(
cube({
size: [width, height, thickness],
center: true
}),
makeFillet(radius, thickness).rotateZ(0).translate([width/2,height/2]),
makeFillet(radius, thickness).rotateZ(90).translate([-width/2,height/2]),
makeFillet(radius, thickness).rotateZ(-90).translate([width/2,-height/2]),
makeFillet(radius, thickness).rotateZ(180).translate([-width/2,-height/2])
);
}
function makeHandle(options) {
options = options || {};
var majorDiameter = options.majorDiameter || 1.0;
var minorDiameter = options.minorDiameter || majorDiameter/2.0;
var majorRadius = majorDiameter/2.0;
var minorRadius = minorDiameter/2.0;
var thickness = options.thickness || 0.5;
var count = options.count || 4;
// "Majors" (places where fingers go)
majors = [];
major = cylinder({
d : majorDiameter,
h : thickness,
center : true
});
for(var i=0; i<count; i++) {
majors.push(major.translate([(-(count-1)*majorDiameter/2)+(i*majorDiameter),0]));
}
var b = sqrt(pow(majorRadius+minorRadius,2)-pow(majorRadius,2));
var theta = atan(b/majorRadius);
// "Minors" (arcs between places where fingers go)
minors = []
var minor = cylinder({
d : minorDiameter,
h : 0.5,
center : true
}).translate([0,b]);
for(var i=0; i<count-1; i++) {
minors.push(minor.translate([(-(count-2)*majorDiameter/2)+(i*majorDiameter),0]));
}
// The hole is the bulk of the handle
hole = union(
cube({
size:[(count-1)*majorDiameter, 2*majorRadius*sin(theta), thickness],
center: true
}),
cube({
size:[count*majorDiameter, majorRadius*2, thickness],
center : true
}).translate([0,-majorRadius*2/2])
);
fillet = makeFillet(minorDiameter, thickness);
hole = difference(
hole,
fillet.rotateZ(180).translate([-count*majorDiameter/2,-majorRadius*2]),
fillet.rotateZ(-90).translate([count*majorDiameter/2,-majorRadius*2]),
union(minors)
)
return union(union(majors), hole);
}
function makeFillet(radius, thickness) {
var round = cylinder({
r : radius,
h : 2*thickness,
center : true
});
var corner = cube({
size : [radius, radius, thickness]
}).translate([0,0,-thickness/2]);
return difference(corner, round).translate([-radius,-radius])
}
function makeSeat(options) {
var width = options.width;
var depth = options.depth;
var thickness = options.thickness;
var fitAllowance = options.fitAllowance || 0.010;
var setBack = options.setBack || 0.5;
var tabDepth = options.tabDepth || thickness*0.3333333;
var boltCount = options.boltCount || 3;
var panel = cube({
size: [width+tabDepth*2,depth+tabDepth-setBack,thickness],
center: true
});
panel = panel.translate([0,tabDepth/2 + setBack/2])
var slot = cube({
size: [width+tabDepth*2+fitAllowance,depth-setBack+tabDepth+fitAllowance,thickness+fitAllowance],
center: true
});
slot = slot.translate([0,tabDepth/2 + setBack/2])
bounds = panel.getBounds();
var inset = 1.5
depth = (bounds[1].y - bounds[0].y)-2*inset;
var bolt = cylinder({
d : 0.125,
h : 2*thickness
}).rotateY(90).translate([0,bounds[1].y-inset]);
var bolts = bolt;
var spacing = -depth/(boltCount-1);
for(var i=0; i<boltCount; i++) {
bolts = union(bolts, bolt);
panel = union(panel, bolt)
bolt = bolt.translate([0,spacing]);
}
bolts = union(
bolts.translate([bounds[1].x,0]),
bolts.rotateZ(90).translate([0,bounds[1].y]),
bolts.rotateZ(180).translate([bounds[0].x,0])
);
panel.properties.slot = slot;
panel.properties.bolts = bolts;
return color(woodColor, panel);
}
function makeSide(options) {
options = options || {}
var depth = options.depth;
var height = options.height;
var thickness = options.thickness;
var filletRadius = options.radius || height/3;
var handles = options.handles || 0;
var fitAllowance = options.fitAllowance || 0.010;
var tabSize = options.tabSize || 2.0;
var panel = union(
cube({
size: [depth, height, thickness],
center: true
}),
cube({
size: [depth + thickness, tabSize, thickness],
center: true
}).translate([thickness/2, height/4.0, 0]),
cube({
size: [depth + thickness, tabSize, thickness],
center: true
}).translate([thickness/2, -height/4.0, 0])
);
panel.properties.slots = union(
cube({
size: [depth + thickness, tabSize+fitAllowance, thickness],
center: true
}).translate([thickness/2, height/4.0, 0]),
cube({
size: [depth + thickness, tabSize+fitAllowance, thickness],
center: true
}).translate([thickness/2, -height/4.0, 0])
)
var inset = 1.0
var bolt = cylinder({
d : 0.125,
h : thickness*2
}).rotateY(90).translate([depth/2,0]);
bolts = union(
bolt.translate([0,height/2 - inset]),
bolt.translate([0,-height/2 + inset])
);
panel.properties.bolts = bolts;
var handleLength = min(depth/3.2, 3.75);
var handleDepth = handleLength/2.5;
var handle1 = makeRoundedCube({
size:[handleLength,handleDepth,handleLength/1.875],
radius: handleDepth/2.5
}).translate([0,height/2.0-handleDepth*1.1]);
var handle2 = handle1.rotateZ(180);
switch(handles) {
case 0:
handles = [];
break;
case 1:
handles = [handle1];
break;
case 2:
handles = [handle1, handle2];
break;
default:
handles = [];
break;
}
largeFillet = makeFillet(filletRadius, thickness)
.rotateZ(90)
.translate([-depth/2, height/2]);
smallFillet = makeFillet(filletRadius, thickness)
.translate([depth/2, height/2])
.rotateZ(180);
handles.forEach(function(handle) {
panel = difference(panel, handle);
});
panel = difference(panel, largeFillet, smallFillet);
return color(woodColor, panel);
}
function makeBack(options) {
options = options || {};
var width = options.width;
var height = options.height;
var thickness = options.thickness;
var handles = options.handles || 0;
var panel = cube({
size : [width + 2*thickness, height, thickness],
center : true
});
handleDiameter = min(width/12.0,1.0);
var handle1 = makeHandle({
majorDiameter : handleDiameter
}).translate([0,height/2.0-(handleDiameter*1.25)]);
var handle2 = handle1.rotateZ(180);
var handleList = [];
switch(handles) {
case 1:
handleList = [handle1];
break;
case 2:
handleList = [handle1,handle2];
break;
default:
break
}
handleList.forEach(function(handle) {
panel = difference(panel, handle);
});
return color(woodColor,panel);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment