/// title : Basic Sleeved Rubber Bushing // author : Tim Farrell // license : MIT License // revision : 3 // tags : TPU // file : bushing.jscad const { polygon, cylinder, torus } = require('@jscad/modeling').primitives; const { extrudeLinear } = require('@jscad/modeling').extrusions; const { translate, rotateZ } = require('@jscad/modeling').transforms; const { subtract, union } = require('@jscad/modeling').booleans function getParameterDefinitions () { return [ {name: 'overhang', type: 'float', initial: 7, min: 1, max: 40, step: 1, caption: 'Overhang'}, {name: 'host_hole_diameter', type: 'float', initial: 13, min: 1, max: 40, step: 1, caption: 'Host hole diameter'}, {name: 'host_hole_height', type: 'float', initial: 0.8, caption: 'Host hole height'}, {name: 'bushing_height', type: 'float', initial: 4, min: 1, max: 40, step: 1, caption: 'Bushing height'}, {name: 'bushing_diameter', type: 'float', initial: 10, min: 1, max: 40, step: 1, caption: 'Bushing diameter'}, {name: 'taper', type: 'checkbox', checked: true, caption: 'Taper Edges?'}, {name: 'knurling', type: 'checkbox', checked: false, caption: 'Add knurling?'} ]; } function knurling(p) { const knurls = []; const bushing_radius = p.bushing_diameter / 2; const thread_radius = bushing_radius * 0.72 const twist_angle = 45; const overlap = 1; const twist = twist_angle * p.bushing_height / thread_radius; const threads = 360 / twist_angle * overlap; const square = polygon({points: [ [thread_radius, thread_radius], [0, thread_radius], [0, 0], [thread_radius, 0] ]}); for (let i=0; i < threads; ++i) { knurls.push( translate( [0, 0, -p.bushing_height/2], rotateZ( 2 * Math.PI * i / threads, [extrudeLinear({height: p.bushing_height, twistAngle: twist, twistSteps: 120}, square)] ) ) ); knurls.push( translate( [0, 0, -p.bushing_height/2], rotateZ( 2 * Math.PI * i / threads, [extrudeLinear({height: p.bushing_height, twistAngle: -twist, twistSteps: 120}, square)] ) ) ); } return union(...knurls); } function donut(p) { const inner_radius = (p.bushing_height - p.host_hole_height) / 2; const outer_radius = p.overhang + p.host_hole_diameter/2 - inner_radius; const z_offset = p.bushing_height/2 - (p.bushing_height/2 - p.host_hole_height/2); return union( translate([0, 0, z_offset], torus({ innerRadius: inner_radius, outerRadius: outer_radius })), translate([0, 0, -z_offset], torus({ innerRadius: inner_radius, outerRadius: outer_radius })) ); } function bushing_main(p) { const outer_radius = p.overhang + p.host_hole_diameter/2; const main_cylinder = cylinder({ radius: outer_radius - (p.taper ? (p.bushing_height - p.host_hole_height) / 2 : 1), height: p.bushing_height, center: [0, 0, 0] }); if (p.taper) { return union( main_cylinder, donut(p) ); } return main_cylinder; } function host_hole(p) { const inner_radius = p.host_hole_diameter/2; const outer_radius = p.overhang + inner_radius; return subtract( cylinder({radius: outer_radius, height: p.host_hole_height, center: [0, 0, 0]}), cylinder({radius: inner_radius, height: p.host_hole_height, center: [0, 0, 0]}) ); } function bushing_sleeve(p) { const sleeve = cylinder({radius: p.bushing_diameter/2, height: p.bushing_height, center: [0, 0, 0]}); if (p.knurling) { return union(sleeve, knurling(p)); } return sleeve; } function main(p) { return subtract( bushing_main(p), host_hole(p), bushing_sleeve(p) ); } module.exports = { main, getParameterDefinitions }