Skip to content

Instantly share code, notes, and snippets.

@apla
Last active February 14, 2017 09:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apla/9cd440e45d4154a2177e081ba904b996 to your computer and use it in GitHub Desktop.
Save apla/9cd440e45d4154a2177e081ba904b996 to your computer and use it in GitHub Desktop.
cnc

Preview:

  1. Copy jscad file contents to the OpenJSCad.org

Prepare and edit:

  1. Download and install Atom editor
  2. Launch Atom, then go to the plugins, search and install atom-jscad package
  3. Save all the files from this gist to the folder on your computer
  4. Open folder with Atom editor
  5. Open file y-axis.jscad
  6. Press Control+Y (or Cmd+Y on )
  7. To update preview with file changes, just save jscad file
var outerShell = 3;
var bearings = {
'6': {
od: 12, // outer diameter
id: 6, // inner diameter
l: 19 // length
},
'6long': {
od: 12, id: 6, l: 35
},
'8': {
od: 15, id: 8, l: 24
},
'8dual': {
od: 15, id: 8, l: 24*2
},
}
var pulleys = {
'f695zz-dual': {
h: 8, // height with flange
id: 5, // inner diameter
od: 13, // outer diameter wihout flange
fr: 1, // flange radius
fh: 1 // flange height on one side
}
};
// 608
var ballBearing = {
h: 7,
r: 11
};
var linearBearing = {
h: "xx",
r: 7.5
}
var stepperWidth = 42;
var holesPushUp = 4;
var holder = {
h: 34,
w: + stepperWidth/2 + ballBearing.r + outerShell*2,
d: 15
};
var sHolder = {
h: 34,
w: + stepperWidth/2 + ballBearing.r + outerShell*2,
d: 7
};
var shaftCenterX = - (stepperWidth/2 - ballBearing.r)/2
var sidePin = {
// shift
up: 12.5,
side: 10,
w: 5,
h: 5,
w2: 3,
h2: 11
};
var bearing = bearings['8'];
var caretExtra = 5;
var caretHalfDepth = bearing.od/2 + outerShell;
var caretWidth = bearing.l*2 + outerShell*2;
var caretHeight = 20 + outerShell * 2 + bearing.od;
var caretDepth = caretHalfDepth + caretExtra;
// profile width: 29 + 1.5*2() + 4.5*2
// profile depth: 25, inner profile depth: 22
function topPin () {
var h = 22;
var d = 10;
topPin.w = 29 + 1.5*2 + 4.5*2;
return union (
cube ({size: [4.5, d, h], center: [true, true, false]}).translate ([29/2 + 1.5 + 4.5/2, 0, 0]),
cube ({size: [4.5, d, h], center: [true, true, false]}).translate ([-(29/2 + 1.5 + 4.5/2), 0, 0]),
difference (
cube ({size: [29, d, h], center: [true, true, false]}),
union (
cylinder ({r: 5, h: d}),
cube ({size: [10, 20, d], center: [true, false, false]}).rotateZ (-30)
).rotateX (90).translate([29/2 - 2, d/2, h/2]),
union (
cylinder ({r: 5, h: d}),
cube ({size: [10, 20, d], center: [true, false, false]}).rotateZ (30)
).rotateX (90).translate([-29/2 + 2, d/2, h/2])
)
)
}
var bearingShaftR = bearing.id/2 + outerShell/4;
function bearingsHolder () {
return union (
cylinder ({r: bearingShaftR, h: caretWidth}).translate ([0, 0, 0]),
cube ({size: [bearingShaftR*2, bearingShaftR*2, caretWidth]}).translate ([-bearingShaftR*2, -bearingShaftR]),
cylinder ({r: bearing.od/2, h: bearing.l*2}).translate ([0, 0, outerShell]),
cube ({size: [bearing.od, bearing.od, bearing.l*2]}).translate ([-bearing.od, -bearing.od/2, outerShell])
).rotateY (90).rotateX (-30)
}
var tieW = 4, tieH = 2;
function tie () {
return cube ({size: [tieW, tieH, caretDepth]});
}
function tieSet () {
return union (
tie ().translate ([outerShell*2 - 2, 0, 0]),
tie ().translate ([caretWidth/2 - outerShell*1.5 - 1, 0, 0]),
tie ().translate ([caretWidth/2 + outerShell*1.5 - 3, 0, 0]),
tie ().translate ([caretWidth - outerShell*2 - 2, 0, 0])
)
}
function tieBack () {
return cube ({size: [tieW, bearing.od + outerShell, 2]});
}
function tieBackSet () {
return union (
tieBack ().translate ([outerShell*2 - 2, outerShell/2, 0]),
tieBack ().translate ([caretWidth/2 - outerShell*1.5 - 1, outerShell/2, 0]),
tieBack ().translate ([caretWidth/2 + outerShell*1.5 - 3, outerShell/2, 0]),
tieBack ().translate ([caretWidth - outerShell*2 - 2, outerShell/2, 0])
);
}
function cubeRoundEdgesZ (cubeParams, roundRadius) {
var width = cubeParams.size[0];
var height = cubeParams.size[1];
var thickness = cubeParams.size[2];
return difference (
cube (cubeParams),
difference (
cube (cubeParams),
cube (Object.assign ({}, cubeParams, {
size: [width - roundRadius * 2, height, thickness]
})).translate ([roundRadius, 0, 0]),
cube (Object.assign ({}, cubeParams, {
size: [width, height - roundRadius * 2, thickness]
})).translate ([0, roundRadius, 0]),
cylinder ({
r: roundRadius, h: thickness
}).translate ([roundRadius, roundRadius, 0]),
cylinder ({
r: roundRadius, h: thickness
}).translate ([width - roundRadius, roundRadius, 0]),
cylinder ({
r: roundRadius, h: thickness
}).translate ([width - roundRadius, height - roundRadius, 0]),
cylinder ({
r: roundRadius, h: thickness
}).translate ([roundRadius, height - roundRadius, 0])
)
)
}
// non-standard aluminum extrusion profile
function pinAlu (holder) {
return difference (
union (
// inside profile
cube ({
size: [sidePin.w, holder.d + sidePin.side, sidePin.h],
center: true
}),
// profile hole
cube ({
size: [sidePin.w2, holder.d + sidePin.side, sidePin.h2],
center: true
}).translate ([(sidePin.w - sidePin.w2)/2, 0, 0]),
// outside profile
cube ({
size: [sidePin.w2, holder.d + sidePin.side, sidePin.h2],
center: true
}).translate ([-(sidePin.w + sidePin.w2)/2, 0, 0])//,
).translate ([holder.w/2 + sidePin.w/2, -(sidePin.side/2), sidePin.up + sidePin.h/2]),
union (
// hole for the holding fastener
printableHole (2, holder.w + sidePin.w).rotateZ (-90).rotateY (90).translate ([-sidePin.w2, 0, sidePin.up + sidePin.h/2]),
//printableHole (4.1, holder.w + sidePin.w).rotateZ (-90).rotateY (90).translate ([-25, 0, sidePin.up + sidePin.h/2]),
nutM4().rotateY (90).translate ([holder.w/2 + sidePin.w/2, 0, sidePin.up + sidePin.h/2]),
nutM4().rotateY (90).translate ([holder.w/2 + sidePin.w/2 + 1.6, 0, sidePin.up + sidePin.h/2])
).translate ([0, -(sidePin.side + holder.d)/2, 0])
)
}
var shaftPushUp = linearBearing.r + outerShell + holesPushUp;
var ballBearingPushUp = linearBearing.r*2 + ballBearing.r + outerShell + holesPushUp;
function printableHole (r, h) {
return union (
cylinder ({r: 1.1*r, h: h}),
cube ({size: [r*1.25, r*1.25, h], center: [true, true, false]}).rotateZ (45).translate ([0.66*r, 0, 0])
)
}
function nutM4 () {
return union (
//cylinder ({r: 2.1, h: 1.5}).translate ([0, 0, -(exruderMount.d - 0.7)]),
cylinder ({r: 3.2, h: 2.5}).translate ([0, 0, -1.25]),
torus ({fni: 4,
fno: 6,
roti: 45,
ro: 2.85, //Math.sqrt (Math.pow (12, 2)/2),
ri: 2,
center: true})
).setColor ([0, 0.6, 0.4])
}
function endstop (pos) {
return union (
cube ({size: [7, 11, 20], center: true}),
cylinder ({r: 1, h: 15}).rotateY (90).translate ([-7.5, 3, 4.25]),
cylinder ({r: 1, h: 15}).rotateY (90).translate ([-7.5, 3, -4.25]),
cylinder ({r: 1.75, h: 10}).rotateX (-90).translate ([0, 0, 20/2 - 1.5]),
cylinder ({r: 1.75, h: 10}).rotateX (-90).translate ([0, 0, - (20/2 - 1.5)]),
cylinder ({r: 1.75, h: 10}).rotateX (-90).translate ([0, 0, - 1.5]),
cylinder ({r: 1.75, h: 10}).rotateX (-90).translate ([0, 0, + 1.5])
).rotateX (pos === 'front' ? 180 : 0)
}
function shaftHolder (haveEndstopMount) {
return union (
difference (
union (
// main
cube ({size: [holder.w, holder.d, holder.h], center: [true, true, false]}),
// side pin
pinAlu (holder),
cylinder ({r: 11 + outerShell, h: holder.d}).rotateX (90).translate ([shaftCenterX, holder.d/2, ballBearingPushUp])
),
union (
// split slice
cube ({size: [1, holder.d, holder.h], center: [true, true, false]}),
// hole for the m8 screw ball bearing
cylinder ({r: 11, h: holder.d}).rotateX (90).translate ([0, holder.d/2, ballBearingPushUp]),
// hole for the m8 linear shaft
cylinder ({r: 4, h: holder.d}).rotateX (90).translate ([0, holder.d/2, shaftPushUp])
).translate ([shaftCenterX, 0, 0]),
// hole for the tightening fastener
// printableHole (1.7, holder.w + sidePin.w).rotateZ (-90).rotateY (90).translate ([-15, 0, 5]),
printableHole (2.2, outerShell - shaftCenterX).rotateZ (-90).rotateY (-90).translate ([(outerShell/2 - shaftCenterX)/2, 1, 6]),
printableHole (2.2, outerShell - shaftCenterX).rotateZ (-90).rotateY (-90).translate ([-(outerShell*2 - shaftCenterX)/2, 1, 6]),
printableHole (4.1, ballBearing.r + outerShell).rotateZ (-90).rotateY (90).translate ([-holder.w/2 - (outerShell - shaftCenterX), 1, 6]),
// nut hole from bottom
union (
nutM4().rotateY (90).translate ([-0.25, 0, 0]),
nutM4().rotateY (90).translate ([0.25, 0, 0]),
cube ({size: [3.3, 7.4, 8], center: [true, true, false]}).rotateX (180).translate ([0, 0, 2])
).translate ([+outerShell, 1, 6]),
// nut hole at the end
// nutM4().rotateY (90).translate ([holder.w/2 - 1.4, 0, 5])
// cutout for the endstop or holder side
haveEndstopMount
? endstop (haveEndstopMount).translate ([
12.5,
(haveEndstopMount === 'front' ? 1 : -1) * (holder.d/2 - 11/2),
11 + holder.h/2
])
: cylinder ({r: 10, h: holder.d}).rotateX (90).translate ([holder.w/2, holder.d/2, ballBearingPushUp-2.5]),
// exterior cutout
cylinder ({r: 6, h: holder.d}).rotateX (90).translate ([-holder.w/2, holder.d/2, linearBearing.r + outerShell*2 + holesPushUp])
) // difference
) // union
}
function stepperHolder () {
return union (
difference (
union (
// main
cube ({size: [sHolder.w, sHolder.d, sHolder.h], center: [true, true, false]}),
linear_extrude({height: sidePin.w2, center: [true, true, false]}, polygon([ [0,sHolder.h/2 + 3.5],[sHolder.w - 6, sHolder.h/2 + 3.5],[0,sHolder.h + 9.5] ])).rotateX (90).rotateZ (-90).translate ([sHolder.w/2, sHolder.d/2, 0]),
// side pin
pinAlu ({h: sHolder.h, w: sHolder.w, d: sHolder.d + 15}).translate ([0, -7.5, 0]),
cylinder ({r: 11 + outerShell, h: sHolder.d}).rotateX (90).translate ([shaftCenterX, sHolder.d/2, ballBearingPushUp]),
// for the stepper
cylinder ({r: 12, h: sHolder.d}).rotateX (90).translate ([-15.5, sHolder.d/2, ballBearingPushUp - 15.5]).translate ([shaftCenterX + 7, 0, 3]),
cylinder ({r: 12, h: sHolder.d}).rotateX (90).translate ([15.5, sHolder.d/2, ballBearingPushUp + 15.5]).translate ([shaftCenterX - 3, 0, -8])
),
union (
// hole for the stepper shaft
cylinder ({r: 11.5, h: sHolder.d}).rotateX (90).translate ([0, sHolder.d/2, ballBearingPushUp]),
// holes for the stepper fasteners
cylinder ({r: 2, h: sHolder.d}).rotateX (90).translate ([15.5, sHolder.d/2, ballBearingPushUp - 15.5]),
cylinder ({r: 2, h: sHolder.d}).rotateX (90).translate ([-15.5, sHolder.d/2, ballBearingPushUp - 15.5]),
cylinder ({r: 2, h: sHolder.d}).rotateX (90).translate ([15.5, sHolder.d/2, ballBearingPushUp + 15.5]),
cylinder ({r: 2, h: sHolder.d}).rotateX (90).translate ([-15.5, sHolder.d/2, ballBearingPushUp + 15.5]),
// hole for the m8 linear shaft
cylinder ({r: 4, h: sHolder.d}).rotateX (90).translate ([0, sHolder.d/2, shaftPushUp])
).translate ([shaftCenterX, 0, 0])
// holder side cutout
// cylinder ({r: 10, h: holder.d}).rotateX (90).translate ([holder.w/2, holder.d/2, ballBearingPushUp-2.5])
// exterior cutout
//cylinder ({r: 6, h: holder.d}).rotateX (90).translate ([-holder.w/2, holder.d/2, linearBearing.r + outerShell*2 + holesPushUp])
), // difference
difference (
cube ({size: [sHolder.w, 30, ballBearingPushUp - 21], center: [true, true, false]}),
cube ({size: 42, center: true}).translate ([0, holder.d/2, ballBearingPushUp]).translate ([-outerShell*2, 0, 0]),
cylinder ({r: 4, h: sHolder.w}).rotateY (90).translate ([0, sHolder.d/2 - 13.5, ballBearingPushUp - 19])
).translate ([0, - (20 + sHolder.d)/2, 0])
) // union
}
function caret () {
return union (
difference (
union (
cubeRoundEdgesZ ({size: [caretWidth, caretHeight, caretDepth]}, outerShell),
cubeRoundEdgesZ ({size: [caretWidth, 12, 22]}, outerShell)
),
// nylon ties: top-outside
tieSet().translate ([0, caretHeight - outerShell/3 - tieH, 0]),
cylinder ({r: 1.4, h: caretDepth}).translate ([outerShell*2, caretHeight - outerShell/2 - 1.4/2]),
cylinder ({r: 1.4, h: caretDepth}).translate ([caretWidth - outerShell*2, caretHeight - outerShell/2 - 1.4/2]),
// nylon ties: top-inside
tieSet().translate ([0, caretHeight - (bearing.od + outerShell*2 - outerShell/3), 0]),
// nylon ties: top connections
tieBackSet ().translate ([0, caretHeight - (bearing.od + outerShell*2), 0]),
// hole for the m8 linear shaft
union (
cylinder ({r: 5, h: caretWidth}),
cube ({size: [10, 10, caretWidth], center: [true, false, false]}),
union (
cylinder ({r: nuts.M8.W/2, fn: 6, h: nuts.M8.h*1.75}).rotateZ (30),
cube ({size: [nuts.M8.W/2*Math.sqrt (3), nuts.M8.W/2*Math.sqrt (3), nuts.M8.h*1.75], center: [true, false, false]})
).translate ([0, 0, outerShell + bearing.l/2 - nuts.M8.h]),
union (
cylinder ({r: nuts.M8.W/2, fn: 6, h: nuts.M8.h}).rotateZ (30),
cube ({size: [nuts.M8.W/2*Math.sqrt (3), nuts.M8.W/2*Math.sqrt (3), nuts.M8.h], center: [true, false, false]})
).translate ([0, 0, caretWidth - (outerShell + bearing.l/2 + nuts.M8.h/2)])
).rotateY (90).rotateX (60).translate ([
0, caretHeight - (outerShell + bearing.od/2) - (ballBearingPushUp - shaftPushUp), caretHalfDepth
]),
// top bearings holder
bearingsHolder ().translate([0, caretHeight - (outerShell + bearing.od/2), caretHalfDepth])
), // difference
topPin ().translate ([caretWidth/2, -5, 0])
) // union;
}
function getParameterDefinitions() {
/*
{name: 'topdiameter', type: 'float', initial: 160, caption: "Top diameter:"},
{name: 'bottomdiameter', type: 'float', initial: 300, caption: "Bottom diameter:"},
{name: 'height', type: 'float', initial: 170, caption: "Height:"},
{name: 'numfaces', type: 'int', initial: 5, caption: "Number of faces:"},
{name: 'thickness', type: 'float', initial: 4, caption: "Thickness of stock material:"},
{name: 'topholediameter', type: 'float', initial: 42, caption: "Diameter of top hole:"},
{name: 'cutterdiameter', type: 'float', initial: 3.2, caption: "Diameter of CNC cutter / laser beam:"},
*/
return [{
name: 'part',
type: 'choice',
values: [
"SHAFT-HOLDER",
"STEPPER-MOUNT",
"CARRIAGE"
],
captions: [
"Y shaft holder",
"Y stepper mount",
"Y carriage"
],
caption: 'Show:',
initial: "CARRIAGE",
}, {
name: 'version',
caption: 'Version:',
type: 'text',
initial: '3'
}];
}
function nut(params, num) {
var thread = CSG.Polygon.createFromPoints([
[(params.D2-params.H)/2 + (params.H-params.D2+params.D1)/2, (params.H-params.D +params.D2)/4, 0],
[(params.D2-params.H)/2 + (params.H+params.D -params.D2)/2, (params.H+params.D2-params.D1)/4, 0],
[(params.D2-params.H)/2 + (params.H+params.D -params.D2)/2, -(params.H+params.D2-params.D1)/4, 0],
[(params.D2-params.H)/2 + (params.H-params.D2+params.D1)/2, -(params.H-params.D +params.D2)/4, 0]
]).rotateX(90);
var angle = 10;
var helical = thread.solidFromSlices({
numslices: num * 360 / angle + 1,
callback: function (t, slice) {
return this
.translate([0, 0, params.P * t * num])
.rotateZ(slice*angle);
}
});
var body =
cylinder({fn:6, r: params.D1/2+params.H*3, h:params.P*num})
.setColor(0,1,0)
.subtract(
cylinder({r: params.D/2, h:params.P*num})
).union(helical);
return body
.cutByPlane(CSG.Plane.fromNormalAndPoint([0, 0, 1], [0, 0, params.P*num]))
.cutByPlane(CSG.Plane.fromNormalAndPoint([0, 0, -1], [0, 0, 0]))
/*.scale(1.175)*/;
}
nut.metric = {
4: {
P: 0.7, D: 7.75, D1: 4, D2: 7, H: 3.2
}
}
var nuts = {
M1: {d: 1, pitch: 0.25, h: 0.8, W: 2.71, w: 2.5},
"M1.2": {d: 1.2, pitch: 0.25, h: 1, W: 3.28, w: 3},
"M1.4": {d: 1.4, pitch: 0.3, h: 1.2, W: 3.28, w: 3},
"M1.6": {d: 1.6, pitch: 0.35, h: 1.3, W: 3.48, w: 3.2},
"M1.8": {d: 1.8, pitch: 0.35, h: 1.4, W: 4.21, w: 3.5},
"M2": {d: 2, pitch: 0.4, h: 1.6, W: 4.32, w: 4},
"M2.3": {d: 2.3, pitch: 0.4, h: 1.8, W: 4.88, w: 4.5},
"M2.5": {d: 2.5, pitch: 0.45, h: 2, W: 5.45, w: 5},
"M2.6": {d: 2.6, pitch: 0.45, h: 2, W: 5.45, w: 5},
M3: {d: 3, pitch: 0.5, h: 2.4, W: 6.01, w: 5.5},
"M3.5": {d: 3.5, pitch: 0.6, h: 2.8, W: 6.58, w: 6},
M4: {d: 4, pitch: 0.7, h: 3.2, W: 7.66, w: 7},
M5: {d: 5, pitch: 0.8, h: 4, W: 8.79, w: 8},
M6: {d: 6, pitch: 1, h: 5, W: 11.05, w: 10},
M7: {d: 7, pitch: 1, h: 5.5, W: 12.12, w: 11},
M8: {d: 8, pitch: 1.25, h: 6.5, W: 14.38, w: 13},
M10: {d: 10, pitch: 1.5, h: 8, W: 18.9, w: 17},
M12: {d: 12, pitch: 1.75, h: 10, W: 21.1, w: 19},
M14: {d: 14, pitch: 2, h: 11, W: 24.49, w: 22},
M16: {d: 16, pitch: 2, h: 13, W: 26.75, w: 24},
M18: {d: 18, pitch: 2.5, h: 15, W: 29.56, w: 27},
M20: {d: 20, pitch: 2.5, h: 16, W: 32.95, w: 30},
M22: {d: 22, pitch: 2.5, h: 18, W: 35.03, w: 32},
M24: {d: 24, pitch: 3, h: 19, W: 39.55, w: 36},
M27: {d: 27, pitch: 3, h: 22, W: 45.2, w: 41},
M30: {d: 30, pitch: 3.5, h: 2.4, W: 50.85, w: 46},
M33: {d: 33, pitch: 3.5, h: 28, W: 55.37, w: 50},
M36: {d: 36, pitch: 4, h: 29, W: 60.79, w: 55},
M39: {d: 39, pitch: 4, h: 31, W: 66.44, w: 60},
M42: {d: 42, pitch: 4.5, h: 34, W: 71.3, w: 65},
M45: {d: 45, pitch: 4.5, h: 36, W: 76.95, w: 70},
M48: {d: 48, pitch: 5, h: 38, W: 82.6, w: 75},
M52: {d: 52, pitch: 5, h: 42, W: 88.25, w: 80},
// M56: {d: 56, h: 48, W: 90},
// M60: {d: 60, h: 48, W: 90},
// M64: {d: 64, h: 51, W: 95},
// M68: {d: 68, h: 54, W: 100}
};
function bolt(params, num) {
var thread = CSG.Polygon.createFromPoints([
[(params.D2-params.H)/2 + (params.H-params.D2+params.D1)/2, (params.H+params.D2-params.D1)/4, 0],
[(params.D2-params.H)/2 + (params.H+params.D -params.D2)/2, (params.H-params.D +params.D2)/4, 0],
[(params.D2-params.H)/2 + (params.H+params.D -params.D2)/2, -(params.H-params.D +params.D2)/4, 0],
[(params.D2-params.H)/2 + (params.H-params.D2+params.D1)/2, -(params.H+params.D2-params.D1)/4, 0]
]).rotateX(90);
var angle = 10;
var helical = thread.solidFromSlices({
numslices: num*360 / angle + 1,
callback: function (t, slice) {
return this
.translate([0, 0, params.P * t * num])
.rotateZ(slice*angle);
}
});
var tube = [];
for (var i = 0; i < num+1; ++i) {
tube.push(
cylinder({r:params.D1/2,h:params.P})
.translate([0,0,i*params.P])
.setColor(i/num*0.2,0,i/num)
);
}
var boltHead =
cylinder({r:params.D1/2+params.H*5, h:params.P*3, fn:6})
.translate([0,0,-params.P*2])
.setColor(0,1,0);
return helical.union(tube).union(boltHead).translate([0,0,params.P*2]);
}
function main (params) {
if (params.part === 'STEPPER-MOUNT') {
return stepperHolder ();
} else if (params.part === 'SHAFT-HOLDER') {
return shaftHolder (
/*have endstop cutout in front/back*/ "back"
);
} else if (params.part === 'CARRIAGE') {
var params = {
P: 1*2, //pitch
D: 9.5*2, // major diameter
D1: 8.5*2, // minor daimeter
D2: 9*2 // picth diameter
};
params.H = params.P / 2 * Math.sqrt(3);
//var nut1 = nut(params, 4);
//var nut2 = nut(nut.metric[4], 4);
return union (
caret ()
// cylinder ({r: nuts.M4.W, fn: 6, h: nuts.M4.h}).translate ([0, 0, nuts.M4.h]),
// cylinder ({r: nuts.M4.w, h: nuts.M4.h}).translate ([0, 0, 2*nuts.M4.h]),
// cylinder ({r: nuts.M4.W, h: nuts.M4.h}).translate ([0, 0, 0])
//nut1.translate ([-20, -20, 0]),
//nut2.translate ([-40, -40, 0])
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment