openjscad-aurora-webapp
141 строка · 5.0 Кб
1// title: S Hook
2// author: Joost Nieuwenhuijse
3// license: MIT License
4
5// Here we define the user editable parameters:
6function getParameterDefinitions() {7return [8{ name: 'topdiameter', caption: 'Inner diameter of top hook:', type: 'float', initial: 16.7 },9{ name: 'clampfactor', caption: 'Snugness of top hook (0 - 100):', type: 'float', initial: 25 },10{ name: 'cliplength', caption: 'Top hook clip length:', type: 'float', initial: 5 },11{ name: 'bottomdiameter', caption: 'Inner diameter of bottom hook:', type: 'float', initial: 20 },12{ name: 'height', caption: 'Outer height of the hook:', type: 'float', initial: 60 },13{ name: 'thickness', caption: 'Thickness:', type: 'float', initial: 5 },14{ name: 'width', caption: 'Width:', type: 'float', initial: 7 },15{16name: 'rounded',17type: 'choice',18caption: 'Rounded edges',19values: [0, 1],20captions: ["No", "Yes (rendering will take a long time!)"],21initial: 022},23{ name: 'roundness', caption: 'Diameter of rounded edges (if enabled):', type: 'float', initial: 1.5 },24{ name: 'buildwidth', caption: 'Width (x) of build area (to print multiple copies):', type: 'float', initial: 90 },25{ name: 'builddepth', caption: 'Depth (y) of build area (to print multiple copies):', type: 'float', initial: 90 }26];27}
28
29function main(params) {30if(OpenJsCad.log) OpenJsCad.log("start");31
32var pathresolution = 16;33var expandresolution = 6;34
35// construct the 2D path:36var topradius = params.topdiameter/2;37var bottomradius = params.bottomdiameter/2;38var halfthickness = params.thickness/2;39topradius += halfthickness;40bottomradius += halfthickness;41
42var roundness = params.roundness;43if(params.rounded != 1)44{45roundness = 0;46}47roundness = Math.min(roundness, halfthickness-0.1, params.width/2-0.1);48if(roundness < 0) roundness = 0;49
50var clampfactor = params.clampfactor / 100;51if(clampfactor < 0) clampfactor = 0;52if(clampfactor >= 1) clampfactor = 1;53clampfactor *= (topradius-halfthickness)/topradius;54
55var topstartangle = - 180 * Math.acos(1 - 2*clampfactor) / Math.PI;56var tophookcenter = new CSG.Vector2D(topradius, 0);57var tophookstart = tophookcenter.plus(CSG.Vector2D.fromAngleDegrees(topstartangle).times(topradius));58var circledistance = params.height - topradius - bottomradius - 2 * params.thickness;59if(circledistance < 0) circledistance = 0;60var bottomhookcenter = new CSG.Vector2D(-bottomradius, -circledistance);61var gravityangle = 90 - tophookcenter.minus(bottomhookcenter).angleDegrees();62
63var path = new CSG.Path2D();64
65// top hook curve:66if(params.cliplength > 0)67{68var clipstart = new CSG.Vector2D([0, -1]).times(params.cliplength).plus(tophookstart);69path = path.appendPoint(clipstart);70}71var topcurvepath = CSG.Path2D.arc({72center: tophookcenter,73radius: topradius,74startangle: topstartangle,75endangle: 180,76resolution: pathresolution,77maketangent: true78});79path = path.concat(topcurvepath);80
81// straight middle part:82if(circledistance > 0)83{84path = path.appendPoint([0, -circledistance]);85}86
87// bottom hook curve:88var bottomcurvepath = CSG.Path2D.arc({89center: bottomhookcenter,90radius: bottomradius,91startangle: 0,92endangle: -180-gravityangle,93resolution: pathresolution,94maketangent: true95});96path = path.concat(bottomcurvepath);97
98// center around origin, and rotate as it would hang under gravity:99var centerpoint = tophookcenter.plus(bottomhookcenter).times(0.5);100var matrix = CSG.Matrix4x4.translation(centerpoint.negated().toVector3D(0));101matrix = matrix.multiply(CSG.Matrix4x4.rotationZ(gravityangle));102path = path.transform(matrix);103
104// extrude the path to create a 3D solid105var hook = path.rectangularExtrude(2*(halfthickness-roundness), params.width-2*roundness, pathresolution, true);106hook = hook.translate([0, 0, -params.width/2+roundness]);107
108// expand to create rounded corners:109if(roundness > 0)110{111hook = hook.expand(roundness, expandresolution);112}113// hook = hook.toPointCloud(0.1);114
115// determine how many objects will fit in the build area:116var bounds = hook.getBounds();117var objsize = bounds[1].minus(bounds[0]);118var margin = 5; // distance between the copies119var numx = Math.floor((params.buildwidth + margin) / (objsize.x + margin));120var numy = Math.floor((params.builddepth + margin) / (objsize.y + margin));121if(numx < 1) numx = 1;122if(numy < 1) numy = 1;123
124// and make the copies:125var result = new CSG();126for(var x = 0; x < numx; x++)127{128var deltax = ((1-numx)/2+x) * (objsize.x + margin);129var colresult = new CSG();130for(var y = 0; y < numy; y++)131{132var deltay = ((1-numy)/2+y) * (objsize.y + margin);133var translated = hook.translate(new CSG.Vector3D(deltax, deltay, 0));134colresult = colresult.union(translated);135}136result = result.union(colresult);137}138
139if(OpenJsCad.log) OpenJsCad.log("finish");140return result;141}
142
143