All Products
Shops
Designers
My Shapeways
Messages
0
Public Profile
Orders
Settings
My 3D Models
3D Design Apps
My Products
View Shop
Shop Settings
Shop Sales
e-Commerce Integrations
Manufacturing
Industries
Materials
About
Investors
Marketplace
Get a Quote
SIGN IN
Help Center
Contact Us
Log Out
Manufacturing
Additive Manufacturing
3D Printing
Rapid Prototyping
Design Services
Traditional Manufacturing
Injection Molding
Urethane Casting
CNC Machining
Vacuum Casting
Sheet Metal
Machine Tooling
Industries
Medical
Consumer
Robotics
Architecture
Aerospace
Gaming
Drones
Education
Jewelry
Materials
Selective Laser Sintering (SLS)
Nylon 12 [Versatile Plastic]
Nylon 11 [PA11 (SLS)]
Polypropylene [PP]
Thermoplastic Elastomer [TPE]
Thermoplastic Polyurethane [TPU]
Binder Jetting
Stainless Steel 17-4 PH
Stainless Steel 316L
Steel [60% Steel / 40% Bronze]
Sandstone
Multi Jet Fusion (MJF)
Full Color Nylon 12
Nylon 12 [MJF Plastic PA12]
Nylon 12 Glass Beads [MJF Plastic PA12GB]
Polypropylene [PP]
Thermoplastic Polyurethane [TPU]
Stereolithography (SLA)
Accura 60 [Clear]
Accura Xtreme [Gray]
Accura Xtreme White 200
Wax Casting
Copper
Platinum
Gold
Silver
Bronze
Brass
Rhodium Plated Brass
Gold Plated Brass
Selective Laser Melting (SLM)
Aluminum
Material Jetting
Fine Detail Plastic
High Definition Full Color
Not sure what material to choose?
View 3D Materials Guide
About Us
About
Who We Are
Press
Careers
Contact Us
Resources
Blog
Events & Webinars
Case Studies
Testimonials
API
e-Commerce Integrations
Newsletter Signup
0
0
You haven't added any 3D printed products yet.
Search our Marketplace
All Products
Shops
Designers
Manufacturing
Additive Manufacturing
3D Printing
Rapid Prototyping
Design Services
Traditional Manufacturing
Injection Molding
Urethane Casting
CNC Machining
Vacuum Casting
Sheet Metal
Machine Tooling
Industries
Medical
Consumer
Robotics
Architecture
Aerospace
Gaming
Drones
Education
Jewelry
Materials
Selective Laser Sintering (SLS)
Nylon 12 [Versatile Plastic]
Nylon 11 [PA11 (SLS)]
Polypropylene [PP]
Thermoplastic Elastomer [TPE]
Thermoplastic Polyurethane [TPU]
Binder Jetting
Stainless Steel 17-4 PH
Stainless Steel 316L
Steel [60% Steel / 40% Bronze]
Sandstone
Multi Jet Fusion (MJF)
Full Color Nylon 12
Nylon 12 [MJF Plastic PA12]
Nylon 12 Glass Beads [MJF Plastic PA12GB]
Polypropylene [PP]
Thermoplastic Polyurethane [TPU]
Stereolithography (SLA)
Accura 60 [Clear]
Accura Xtreme [Gray]
Accura Xtreme White 200
Selective Laser Melting (SLM)
Aluminum
Material Jetting
Fine Detail Plastic
High Definition Full Color
Wax Casting
Copper
Platinum
Gold
Silver
Bronze
Brass
Rhodium Plated Brass
Gold Plated Brass
Not sure what material to choose?
View 3D Materials Guide
ABOUT
About
Who We Are
Press
Careers
Contact Us
Resources
Blog
Events & Webinars
Case Studies
Testimonials
API
e-Commerce Integrations
Newsletter Signup
Investors
Marketplace
Get a Quote
0
My Shapeways
My 3D Models
Upload
3D Design Apps
My Products
View Shop
Shop Settings
Shop Sales
e-Commerce Integrations
Public Profile
Favorites & Lists
Settings
Messages
0
Orders
Help Center
Contact Us
Forum
Logout
Sign In
0
You haven't added any 3D printed products yet.
Ornament Creator
Turn a 2D Design into a 3D Printed Ornament
Start by choosing a design:
Customize Your Ornament
Text:
+ Advanced settings
Upload a Design
Kaleidoscope Effect 1:
Kaleidoscope Effect 2:
Check Printability
// // Ornament example using polyhedra reflection // // // Notes: vary thickness based on number of non white pixels as a proxy for strength? // // First printing notes: // // One bail broken, increase thickness // Sparse model fairly strong but increase some more // Increase text height for better legibility // Rim is too thick // // author Vladimir Bulatov // author Alan Hudson // var uiParams = [ { name: "image", desc: "Image", type: "uri" //onChange: "imageChanged" }, { 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: "xrot", desc: "xrot", type: "double", "rangeMin": -180, "rangeMax": 180, "step": 0.05, defaultVal: 0, onChange: "transformChanged" }, { name: "yrot", desc: "yrot", type: "double", "rangeMin": -180, "rangeMax": 180, "step": 0.05, defaultVal: 0, 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" }, { name: "material", desc: "Material", type: "enum", values: Materials.getAllNames(), defaultVal: "SingleColor", group: "Model" } ]; var vs = 0.15 * MM; var thickness = 1.3 * MM; // last version was 1.1 up a bit for more strength var radius = 76.2 * MM / 2 - thickness / 2; var rimHeight = 8 * MM; var bailPadRadius = 7 * MM; var bailHoleSize = 5.5 * MM; var bailThickness = thickness * 1.6; var TAU = (Math.sqrt(5) + 1) / 2; // golden ratio var PI = Math.PI; var TORAD = PI / 180; var embossText = true; var imgTrans; var imgBox; var scene; var textBox; var text2d; 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.1; // correction to get var ypnt = v3.y * correction; var xpnt = v5.x; var image = loadImage(path); var threshold = 0.5; var filled = getPercentFilled(image, threshold); var thick = thickness; print("filled: " + (filled * 100)); if (filled < 0.20) { // thickne by 20% for thin structures thick = 1.4 * thickness; print("Thicknening sparse structure"); } imgBox = new Image3D(image, 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(image, threshold) { var w = image.getWidth(); var h = image.getHeight(); var filled = 0; var threshatt = 65636 / 2; // not sure on this logic. var grid = image.getGrid(); // Reduced the resolution of this check to speed it up for (var y = 0; y < h / 2; y++) { for (var x = 0; x < w / 2; x++) { var att = grid.getAttribute(x*2, y*2); if (att < threshatt) { filled++; } } } return filled*4 / (w * h); } // Create a safe attachment point by intersection sphere and cylinder. Then attach torus as bail function getBail(sphereRadius, cylinderRadius, thickness, torusInner, bailThickness) { // Create attachment patch var sphere = new Sphere(sphereRadius + thickness / 3); var cylinder = new Cylinder(new Vector3d(0, sphereRadius + thickness, 0), new Vector3d(0, sphereRadius - 1.25 * thickness, 0), cylinderRadius); var patch = new Intersection(sphere, cylinder); patch.setTransform(new Translation(0, thickness / 2, 0)); var x0 = 0; var y0 = sphereRadius; var z0 = 0; // Create bail var R = torusInner / 2 + bailThickness / 2; var r = bailThickness / 2; var torus = new Torus(x0, y0 + torusInner / 2, z0, R, r); var s = 2 * R; var plane = new Plane(new Vector3d(0, 1, 0), new Vector3d(x0, y0 - r, z0)); var subtract = new Subtraction(torus, plane); /* if(rotateBail) torus.setTransform(new Rotation(Vector3d(0,1,0),Math.PI/2)); */ var bail = new Union(patch, subtract); bail.setBlend(0.2 * MM); //var bail = new Union(patch, torus); return bail; } 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 Rotation(1, 0, 0, args.xrot * TORAD)); imgTrans.add(new Rotation(0, 1, 0, args.yrot * 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); scene.setLightingRig(Scene.LightingRig.THREE_POINT); return scene; } function getRim(loc, sphereRadius, height, thickness) { var overlap = 0.25 * MM; overlap = vs; 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; } function getText(text, loc, sphereRadius, rimHeight, height, thickness, embossed) { var tby = height; var tbx = (sphereRadius + 2 * thickness) * 2 * Math.PI; // text2d.getPreferredWidth(); var tbz = thickness; text2d = new Text2D(text); text2d.setFontName("HelveticaRounded LT Std Bd"); text2d.setFontStyle(Text2D.BOLD); var spacing = 0 * MM; text2d.set("spacing", spacing); // additional spacing between characters var tvs = 0.05 * MM; // text voxel size text2d.setInset(2 * tvs); text2d.setVoxelSize(tvs); text2d.setFit("vertical"); // vertical, horizontal, both text2d.setHorizAlign("CENTER"); // left, right, center text2d.setHeight(tby); text2d.setWidth(tbx); //textBox = new Image3D(text2d.getImage(), tbx, tby, tbz, 0.1 * MM); // Not optimal, change to this after release textBox = new Image3D(text2d, tbx, tby, tbz, 0.1 * MM); textBox.setUseGrayscale(true); textBox.setImagePlace(Image3D.IMAGE_PLACE_TOP); textBox.setBaseThickness(0.0); textBox.setBaseThreshold(0.1); textBox.setBlurWidth(0.1*MM); // Add some blur to improve rendering and round edges var trans = new CompositeTransform(); trans.add(new Translation(new Vector3d(0, loc - rimHeight / 2, 0))); if (embossed) { trans.add(new RingWrap(sphereRadius + thickness)); } else { trans.add(new RingWrap(sphereRadius)); } textBox.setTransform(trans); return textBox; } function textChanged(args) { text2d.setText(args.text); textBox.setImage(text2d.getImage()); scene.setName(args.text + "_" + embossText); } // 150 stroke = 4mm function main(args) { scene = makeDefaultScene(); // Set background color of scene var bg = new Background(); bg.setSkyColor(new Color(237 / 255, 239 / 255, 240 / 255)); // #edeff0 bg.setMode(Background.Mode.SINGLE_COLOR); scene.setBackground(bg); var path = args.image; if (path === undefined) return scene; var a = radius + thickness + 2 * bailHoleSize + vs; var image = getImage(radius, thickness, path); transformChanged(args); var reflectedImage = new Union(); reflectedImage.add(image); reflectedImage.setTransform(getIcosahedralSymmetry()); var rim_loc = -radius / 1.2; var rim_radius = radius / 1.84; var rim_height = rimHeight; var clip = new Plane(new Vector3d(0, 1, 0), new Vector3d(0, rim_loc, 0)); var qsphere = new Subtraction(reflectedImage, clip); var rim_geom = getRim(rim_loc, rim_radius, rim_height, thickness * 1.2); var bail = getBail(radius, bailPadRadius, thickness, bailHoleSize, bailThickness); var object = new Union(); object.add(qsphere); object.add(rim_geom); if (embossText) { var up_text = getText(args.text, rim_loc, rim_radius, rim_height, rim_height * 0.8, 1.5 * MM, true); object.add(up_text); } object.add(bail); object.setBlend(0.25 * MM); if (!embossText) { var through_text = getText(args.text, rim_loc, rim_radius, rim_height, rim_height * 0.8, 3 * MM, false); object = new Subtraction(object, through_text); } var shape = new Shape(object, Materials.get(args.material)); var bounds = new Bounds(-a, a, -a, a, -a, a); var scene = new Scene(shape, bounds); var ef = 0.1; scene.setVoxelSize(vs); scene.setMeshErrorFactor(ef); scene.setMaxPartsCount(1); scene.setLightingRig(Scene.LightingRig.THREE_POINT); return scene; }
Create my Ornament
Click and drag to rotate
Need some help?
How to use the Ornament Creator