{"id":15363,"date":"2019-02-24T16:43:37","date_gmt":"2019-02-24T21:43:37","guid":{"rendered":"http:\/\/scruss.com\/blog\/?p=15363"},"modified":"2019-02-24T16:43:42","modified_gmt":"2019-02-24T21:43:42","slug":"symmetric-chamfered-extrusion-in-openscad","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2019\/02\/24\/symmetric-chamfered-extrusion-in-openscad\/","title":{"rendered":"Symmetric chamfered extrusion in OpenSCAD"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"480\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Screenshot-from-2019-02-24-15-07-39.jpg\" alt=\"\" class=\"wp-image-15364\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Screenshot-from-2019-02-24-15-07-39.jpg 960w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Screenshot-from-2019-02-24-15-07-39-160x80.jpg 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Screenshot-from-2019-02-24-15-07-39-320x160.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Screenshot-from-2019-02-24-15-07-39-768x384.jpg 768w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><figcaption>enjoy the quality of the smooth, smooth taper<\/figcaption><\/figure>\n\n\n\n<p>I like using <a href=\"https:\/\/www.openscad.org\/\">OpenSCAD<\/a>, but it has some limitations. While you can <em>linear_extrude()<\/em> 2D paths into 3D shapes, you can&#8217;t get a proper tapered\/chamfered extrusion of anything but simple shapes that are symmetric about the origin:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2.png\" alt=\"\" class=\"wp-image-15365\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>\/\/ this is symmetrical \u00e2\u20ac\u00a6<br> linear_extrude(height=20, scale=2)square(10, center=true);<br><br> \/\/ but shift the same square off the origin and <em>this<\/em> happens \u00e2\u20ac\u00a6<br> linear_extrude(height=20, scale=2)translate([20, 20])square(10, center=true);<\/figcaption><\/figure>\n\n\n\n<p>There are lots of partial attempts at fixing this, many of which end up with ugly results. Some of them even mess up the top surface, which is precisely what I wanted to avoid. My code uses the computationally-intensive <em>minkowski()<\/em> sum function to replace every vertex of a 2D shape with a many-sided pyramid.<\/p>\n\n\n\n<p>Minkowski sums effectively replace every vertex with another shape, here making a rounded cube from a cube and a sphere:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2a.png\" alt=\"\" class=\"wp-image-15366\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2a.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2a-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2a-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>minkowski() {<br>     cube(10);<br>     sphere(4);<br> }<\/figcaption><\/figure>\n\n\n\n<p>One feature of OpenSCAD&#8217;s implementation of the Minkowski sum is that the operator takes into account the second shape&#8217;s position relative to the origin. So if I take the same cube and apply the <em>minkowski()<\/em> operator with the same sphere moved away from the origin, I get:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2b.png\" alt=\"\" class=\"wp-image-15367\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2b.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2b-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2b-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>\/\/ the same cube, but shifted by the power of minkowski()!<br>minkowski() {<br>     cube(10);<br>     translate([-15,-15,-15])sphere(4);<br> }<\/figcaption><\/figure>\n\n\n\n<p>So I can approximate a tapered extrusion by turning a 2d path into a very thin 3d plate (OpenSCAD&#8217;s 2D and 3D subsystems can never meet in the same output) and using a pyramid as the second argument to the operator:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2c.png\" alt=\"\" class=\"wp-image-15368\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2c.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2c-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2c-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>\/\/ the component parts, before minkowski()<br><br>\/\/ thin extrusion of 2D path<br>linear_extrude(height=0.001)text(&#8220;S&#8221;, size=24, font=&#8221;EB Garamond:style=12 Italic&#8221;);<br><br>\/\/ a 30 degree pyramid with its apex at the origin<br>rotate_extrude()polygon([ [0,0] , [4, -8], [0, -8] ]);<\/figcaption><\/figure>\n\n\n\n<p>You get:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2d.png\" alt=\"\" class=\"wp-image-15369\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2d.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2d-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2d-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>minkowski() {<br>     \/\/ thin extrusion of 2D path<br>     linear_extrude(height=0.001)text(&#8220;S&#8221;, size=24, font=&#8221;EB Garamond:style=12 Italic&#8221;);<br> <code>\/\/ a 30 degree pyramid with its apex at the origin <\/code><br><code>  rotate_extrude()polygon([ [0,0] , [4, -8], [0, -8] ]);<\/code><br> }<\/figcaption><\/figure>\n\n\n\n<p>In reality, you&#8217;d probably use a smaller taper angle, but the example is short rather than pretty. If you&#8217;re really picky about correctness, the process leaves the thin extrusion as parallel walls at the bottom of the shape, shown grossly exaggerated here for effect:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2e.png\" alt=\"\" class=\"wp-image-15370\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2e.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2e-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2e-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>hugely exaggerated vertical profile<\/figcaption><\/figure>\n\n\n\n<p>If you&#8217;re working in consumer-grade 3D printing and are using the standard 1 unit = 1 mm scale, the residual parallel section would only be 1 \u00c2\u00b5m thick and <em>way<\/em> below any realistic layer height. Feel free to remove it, but be warned that this process creates so many facets that the <em>difference()<\/em> required to remove it will be very time-consuming for no visible difference.<\/p>\n\n\n\n<p>Here&#8217;s the code: <a href=\"http:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/chamfer_extrude_scad.txt\">chamfer_extrude.scad<\/a> &#8211; make sure to rename the txt extension to scad. Or, if you&#8217;d prefer, here&#8217;s a link to a gist: <a href=\"https:\/\/gist.github.com\/scruss\/09600e55e140e0d394cf815d028b752d\">scruss\/chamfer_extrude.scad<\/a><\/p>\n\n\n\n<p>Put it in your OpenSCAD library folder, then you can use it like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">include &lt;chamfer_extrude.scad>; <br><br>chamfer_extrude(height=4, angle=15, $fn=16)text(\"S\", size=24, font=\"EB Garamond:style=12 Italic\", $fn=64);<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"503\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2f.png\" alt=\"\" class=\"wp-image-15373\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2f.png 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2f-160x118.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2019\/02\/Untitled2f-320x237.png 320w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>way smooth s<\/figcaption><\/figure>\n\n\n\n<p>The library just adds some expected utility and tidiness to the above process. The source includes documentation and examples.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I like using OpenSCAD, but it has some limitations. While you can linear_extrude() 2D paths into 3D shapes, you can&#8217;t get a proper tapered\/chamfered extrusion of anything but simple shapes that are symmetric about the origin: There are lots of partial attempts at fixing this, many of which end up with ugly results. Some of [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7],"tags":[],"class_list":["post-15363","post","type-post","status-publish","format-standard","hentry","category-computers-suck"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-3ZN","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/15363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=15363"}],"version-history":[{"count":4,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/15363\/revisions"}],"predecessor-version":[{"id":15376,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/15363\/revisions\/15376"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=15363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=15363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=15363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}