Last active
December 23, 2022 01:18
-
-
Save BrianRossmajer/e6d0a3a7d679d97f2530321cb1c7657f to your computer and use it in GitHub Desktop.
experimenting with openjscad.xyz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const jscad = require('@jscad/modeling') | |
const { torus, cuboid, roundedCuboid, cylinder } = jscad.primitives | |
const { translate, translateX, scale, rotate, rotateY, rotateZ } = jscad.transforms | |
const { measureDimensions, measureCenter } = jscad.measurements | |
const { union, intersect, subtract } = jscad.booleans | |
const { hull } = require('@jscad/modeling').hulls | |
const getParameterDefinitions = () => [ | |
{ name: 'body', type: 'group', caption: 'Visible Body' }, | |
{ name: 'bulkHeight', type: 'float', initial: 14, min: 10, max: 100.0, step: 1, caption: 'Visible body height:' }, | |
{ name: 'bulkRadius', type: 'float', initial: 2, min: 0, max: 5, step: .1, caption: 'Radius of ouside rounding:' }, | |
{ name: 'arm', type: 'group', caption: 'Arm' }, | |
{ name: 'armLength', type: 'float', initial: 60, min: 0, max: 170.0, step: 1, caption: 'Length:' }, | |
{ name: 'armRadius', type: 'float', initial: 40, min: 10, max: 170.0, step: 1, caption: 'Torus radius:' }, | |
{ name: 'armThickness', type:'float', initial: 6, min: 1, max:20, step:0.25, caption:'Thickness'}, | |
{ name: 'armSegmentsInner', type: 'int', initial: 18, min: 6, max: 170.0, step: 6, caption: 'Inner segments:' }, | |
{ name: 'armSegmentsOuter', type: 'int', initial: 18, min: 6, max: 170.0, step: 6, caption: 'Outer segments:' }, | |
{ name: 'insert', type: 'group', caption: 'In-post support' }, | |
{ name: 'postInset', type: 'float', initial: 1.5, min: 0, max: 10.0, step: .1, caption: 'Support inset:' } | |
]; | |
const main = (params) => { | |
const fullWidth = 57; | |
const poleWidth = fullWidth-params.postInset*2; | |
const radiusBig = params.armRadius; | |
const radiusSmall = 7.5; | |
const poleDepth = 23; | |
const poleCornerIndent=10; | |
const bulkRadius = params.bulkRadius; | |
const armOverlap = bulkRadius; | |
// smaller for speed, larger to print, multiples of 6 | |
const innerSegments = params.armSegmentsInner; | |
const outerSegments = params.armSegmentsOuter; | |
let fullTorus = torus({ innerRadius: params.armThickness, innerSegments: innerSegments, outerRadius: radiusBig, outerSegments: outerSegments*2, startAngle: 0 }); | |
let fullTorusHeight = measureDimensions(fullTorus)[2]; | |
let bigTorus = scale([1,1,fullWidth/fullTorusHeight],fullTorus); | |
let ama = torus({ innerRadius: 2.25, innerSegments: innerSegments, outerRadius: radiusSmall, outerSegments: outerSegments, startAngle: 0 }); | |
let amaHeight = measureDimensions(ama)[2]; | |
let halfBigTorus = intersect( bigTorus, | |
cuboid({size: [(radiusBig+radiusSmall)*2,radiusBig+radiusSmall,fullWidth], | |
center: [0,0-(radiusBig+radiusSmall)/2,0]}) ); | |
// the offset of 3 in the center calculation above lets the arm extend into the support | |
// torus (the "ama") so when we attach them we're going to subtract out the antiAma which is | |
// the shape of the hole in the middle | |
let amaInPlace = translate([radiusBig,radiusSmall,0],scale([1,1,fullWidth/amaHeight],ama)); | |
let filledAma = cylinder({radius:radiusSmall,height:fullWidth, center: measureCenter(amaInPlace)}); | |
let antiAma = subtract(filledAma,amaInPlace); | |
let support = subtract(union(halfBigTorus,amaInPlace),antiAma); | |
// the -bulkRadius is to allow the arm edge to extend past the radius of the | |
let supportInPlace = intersect( rotateZ(params.armLength/params.armRadius,support), | |
cuboid({size: [radiusBig*3,radiusBig*2,fullWidth], | |
center: [0,radiusBig-bulkRadius,0]})); | |
// centers are 45.5mm apart | |
let capInsertOffset = 45.5 / 2; | |
let capInsertDepth = 14; | |
let capInsert = translateX( (params.bulkHeight-capInsertDepth)/2, rotateY( Math.PI / 2, union( | |
cuboid( {size: [ 8, 14, capInsertDepth ], center: [ -capInsertOffset, 0, 0 ] } ), | |
cuboid( {size: [ 14, 8, capInsertDepth ], center: [ 0, -capInsertOffset, 0 ] } ), | |
cuboid( {size: [ 8, 14, capInsertDepth ], center: [ capInsertOffset, 0, 0 ] } ), | |
cuboid( {size: [ 14, 8, capInsertDepth ], center: [ 0, capInsertOffset, 0 ] } ) | |
)) ); | |
// bulk is the visible part over the post; it's a rounded cuboid with the rounding | |
// on the top and bottom removed so it transitions relatively seamlessly into the | |
// post and cap | |
let bulk = intersect( | |
roundedCuboid({size: [params.bulkHeight+bulkRadius*2,fullWidth,fullWidth], | |
roundRadius: bulkRadius, center: [radiusBig,-fullWidth/2,0]}) , | |
cuboid({size: [params.bulkHeight,fullWidth,fullWidth], | |
center: [radiusBig,-fullWidth/2,0]}) | |
); | |
let bulkBottomX = radiusBig - params.bulkHeight/2; | |
let bulkTopX = radiusBig + params.bulkHeight/2; | |
let bulkCenter = measureCenter(bulk); | |
let inPolePart = rotateY(Math.PI / 2, subtract( | |
cuboid({size:[poleWidth,poleWidth,poleDepth]}), | |
cylinder({radius: poleCornerIndent, height: poleDepth, center:[-poleWidth/2,-poleWidth/2,0]}), | |
cylinder({radius: poleCornerIndent, height: poleDepth, center:[-poleWidth/2, poleWidth/2,0]}), | |
cylinder({radius: poleCornerIndent, height: poleDepth, center:[ poleWidth/2,-poleWidth/2,0]}), | |
cylinder({radius: poleCornerIndent, height: poleDepth, center:[ poleWidth/2, poleWidth/2,0]}) | |
)); | |
let inPole = translate([bulkBottomX-(poleDepth/2),-fullWidth/2+((fullWidth-poleWidth)*0),0],inPolePart); | |
return rotate([-Math.PI/2,-Math.PI/2,Math.PI/2],translate([-bulkCenter[0],-bulkCenter[1],0], | |
subtract(union(supportInPlace, bulk, inPole ), translate(bulkCenter, capInsert)) ) ); | |
}; | |
module.exports = { main, getParameterDefinitions }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment