for developers
Sign In
Join
Discussions
Documentation
Tutorials
Examples
Editor
Scene
Import Scene
Export Scene
Load Last Scene
Save Current Scene
Model
Save Model
Upload Model
Show Printability
Render
Preferences
Help
Reference Guide
Examples
Tutorials
Generate
Save Model
Reset Params
Check Model
// // Candy dish made using Polyhedra reflection to make one image into a cool pattern. // // Intended to be produced in WSF // // author Vladimir Bulatov // author Alan Hudson // var uiParams = [ { name: "image", desc: "Image", type: "uri", defaultVal: "https:\/\/static1.sw-cdn.net\/files\/cms\/shapejs\/images\/pedals4.png" }, { name: "xcoff", desc: "xcoff", type: "double", "rangeMin": -1, "rangeMax": 2, "step": 0.05, defaultVal: 1, onChange: "transformChanged" }, { name: "ycoff", desc: "ycoff", type: "double", "rangeMin": -1, "rangeMax": 2, "step": 0.05, defaultVal: 1, onChange: "transformChanged" }, { name: "zrot", desc: "zrot", type: "double", "rangeMin": -180, "rangeMax": 180, "step": 0.05, defaultVal: 0, onChange: "transformChanged" }, { name: "text", desc: "Text", type: "string", defaultVal:"Shapeways", onChange: "textChanged" } ]; var vs = 0.2*MM; var thickness = 1.0*MM; var radius = 31.1*MM - thickness / 2; var rimHeight = 2*MM; var TAU = (Math.sqrt(5)+1)/2; // golden ratio var PI = Math.PI; var overlap = 0.5*MM; var TORAD = PI/180; var imgTrans; var imgBox; var scene; function getIcosahedralSymmetry( ){ var v5 = new Vector3d(1,0,TAU); // vertex of icosahedron var v3 = new Vector3d(0,1/TAU,TAU); // vertex of dodecahedron var p35 = new Vector3d(); // normal to plane via (0, v3, v5) p35.cross(v3, v5); p35.normalize(); var splanes = new Array(); var count = 0; splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(-1,0,0), 0.0); splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(0,-1,0), 0.0); splanes[count++] = new ReflectionSymmetry.getPlane(p35, 0.0); return new ReflectionSymmetry(splanes); } function getSphereBend(fixedRadius, bendAmount, offset){ var center = fixedRadius*fixedRadius/bendAmount; var radius = Math.sqrt(center*center + fixedRadius*fixedRadius); var cp = new CompositeTransform(); cp.add(new PlaneReflection(new Vector3d(0,0,1), new Vector3d(0,0,offset))); cp.add(new SphereInversion(new Vector3d(0,0,-center + offset), radius)); return cp; } function getImageReflection(xsize, ysize){ var splanes = new Array(); var count = 0; splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(-1,0,0), xsize); splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(0,-1,0), ysize); splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(1,0,0), xsize); splanes[count++] = new ReflectionSymmetry.getPlane(new Vector3d(0,1,0), ysize); return new ReflectionSymmetry(splanes); } function getImage(radius, thickness, path){ var s = radius/Math.sqrt(1 + 1.0/(TAU*TAU)); var v5 = new Vector3d(s/TAU,0,s); // vertex of icosahedron var v3 = new Vector3d(0,s/(TAU*TAU),s); // vertex of dodecahedron var union = new Union(); var correction = 1.11; // correction to get var ypnt = v3.y*correction; var xpnt = v5.x*correction; var image = loadImage(path); var grid = image.getGrid(); var threshold = 0.5; var filled = getPercentFilled(grid,threshold); var thick = thickness; if (filled < 0.20) { // thicken by 20% for thin structures thick = 1.4 * thickness; } imgBox = new Image3D(grid, xpnt, ypnt, thick,0.1*MM); imgBox.setUseGrayscale(false); imgBox.setImagePlace(Image3D.IMAGE_PLACE_TOP); imgBox.setBaseThickness(0.0); imgBox.setBaseThreshold(threshold); imgBox.setBlurWidth(0.1*MM); union.add(imgBox); union.setTransform(getSphereBend(v5.x, radius - v5.z, v5.z)); return union; } /** * Analyse an image for structural issues. Change thickness based on how sparse the image is * * @param image * @return The */ function getPercentFilled(grid,threshold) { var w = grid.getWidth(); var h = grid.getHeight(); var filled = 0; var threshatt = 65636 /2 ; // not sure on this logic. for(var y=0; y < h; y++) { for (var x = 0; x < w; x++) { var att = grid.getAttribute(x,y); if (att < threshatt) { filled++; } } } return filled / (w * h); } function transformChanged(args) { var s = radius/Math.sqrt(1 + 1.0/(TAU*TAU)); var v5 = new Vector3d(s/TAU,0,s); // vertex of icosahedron var v3 = new Vector3d(0,s/(TAU*TAU),s); // vertex of dodecahedron var correction = 1.1; // correction to get var ypnt = v3.y*correction; var xpnt = v5.x; imgTrans = new CompositeTransform(); imgTrans.add(getImageReflection(xpnt/2, ypnt/2)); imgTrans.add(new Rotation(0,0,1,args.zrot*TORAD)); imgTrans.add(new Translation(args.xcoff*xpnt/2,args.ycoff*ypnt/2,v5.z)); imgBox.setTransform(imgTrans); } // Create a hole for the tea light to be placed through function getLightHole(hole,outside) { var cyl = new Cylinder(new Vector3d(0,0,0), new Vector3d(0,-outside,0), hole); return cyl; } // Create a rim around the light hole function getRim(hole,radius,thickness) { var cr = hole + thickness; // Calculate intersection location of cylinder with sphere var loc = -radius +(radius - Math.sqrt(radius * radius - cr * cr)) - thickness; var outer = new Cylinder(new Vector3d(0,loc,0), new Vector3d(0,loc-thickness,0), hole + thickness); var inner = new Cylinder(new Vector3d(0,loc+overlap,0), new Vector3d(0,loc-thickness-overlap,0), hole); var rim = new Subtraction(outer,inner); return rim; } function makeDefaultScene() { var dr = 5 * MM; var src = new Box(dr, dr, dr); var bounds = new Bounds(-dr, dr, -dr, dr, -dr, dr); scene = new Scene(src, bounds); var ef = 0.1; scene.setVoxelSize(vs); scene.setMeshErrorFactor(ef); scene.setMaxPartsCount(1); return scene; } function main(args){ var holeRadius = 20*MM; // a bit larger then a typical 1.5" / 38.1mm tea light var rimThickness = 1.25*MM; scene = makeDefaultScene(); var path = args.image; if (path === undefined) return scene; var a = radius + 2*thickness; var image = getImage(radius,thickness, path); transformChanged(args); var reflectedImage = new Union(); reflectedImage.add(image); reflectedImage.setTransform(getIcosahedralSymmetry( )); var subtract = new Subtraction(reflectedImage, getLightHole(holeRadius,a)); var rim = getRim(holeRadius,radius,rimThickness); var tealight = new Union(subtract, rim); var s = radius + 2*thickness; return new Scene(tealight,new Bounds(-s,s,-s,s,-s,s),vs); }
Preferences
Close
Printability Check
Region check
Voxel size
Number of regions
Largest region
Close