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\/icosa_sphere_part_thin20.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 = 2.1*MM; var radius = 77.5*MM - thickness / 2; var rimHeight = 2*MM; var footHeight = 2.5*MM; var footThickness = 2*MM; var footRatio = 1/3; 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); } // Create a rim around the bowl function getRim(loc,sphereRadius,height,thickness) { var outer = new Cylinder(new Vector3d(0,loc,0), new Vector3d(0,loc-height,0), sphereRadius + thickness / 2); var inner = new Cylinder(new Vector3d(0,loc+overlap,0), new Vector3d(0,loc-height-overlap,0), sphereRadius - thickness / 2); var rim = new Subtraction(outer,inner); rim.setBlend(0.1*MM); return rim; } // Create a foot for stability function getFoot(loc,sphereRadius,height,thickness) { var outer = new Cylinder(new Vector3d(0,loc,0), new Vector3d(0,loc-height,0), sphereRadius + thickness / 2); var inner = new Cylinder(new Vector3d(0,loc+overlap,0), new Vector3d(0,loc-height-overlap,0), sphereRadius - thickness / 2); var foot = new Subtraction(outer,inner); foot.setBlend(0.1*MM); return foot; } 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); } 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){ scene = makeDefaultScene(); var path = args.image; if (path === undefined) return scene; var a = 2*radius + 2*thickness; var image = getImage(radius,thickness, path); transformChanged(args); var reflectedImage = new Union(); reflectedImage.add(image); reflectedImage.setTransform(getIcosahedralSymmetry( )); var cut_loc = -radius / 1.5; var plane = new Plane(new Vector3d(0,-1,0), new Vector3d(0,cut_loc,0)); var bowl = new Subtraction(reflectedImage, plane); var rim_loc = cut_loc + rimHeight; var rim_radius = radius * 0.75; // TODO: get real value var rim = getRim(rim_loc,rim_radius,rimHeight,thickness); var foot_loc = -radius + 3.25*MM; // TODO: get real calc var foot = getFoot(foot_loc, radius * footRatio, footHeight, footThickness); var combined = new Union(bowl,rim); combined.add(foot); return new Scene(combined,new Bounds(-a,a,-a,a,-a,a),vs); }
Preferences
Close
Printability Check
Region check
Voxel size
Number of regions
Largest region
Close