From fe788f56b5139b25e9f5a898e871ed0ba408c50c Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Sat, 17 Apr 2021 19:17:44 -0700 Subject: [PATCH] Updated tutorials. --- scripts/make_tutorials.sh | 2 +- scripts/tutorial_gen.py | 20 +- tutorials/Mutators.md | 142 +++++++------- tutorials/Paths.md | 400 +++++++++++++++++++------------------- tutorials/Shapes2d.md | 230 +++++++++++----------- tutorials/Shapes3d.md | 116 +++++------ tutorials/Transforms.md | 118 +++++------ 7 files changed, 513 insertions(+), 515 deletions(-) diff --git a/scripts/make_tutorials.sh b/scripts/make_tutorials.sh index b99fb65..c092db5 100755 --- a/scripts/make_tutorials.sh +++ b/scripts/make_tutorials.sh @@ -15,7 +15,7 @@ done if [[ "$FILES" != "" ]]; then PREVIEW_LIBS="$FILES" else - PREVIEW_LIBS="Shapes2d Shapes3d Transforms Distributors Mutators Paths FractalTree" + PREVIEW_LIBS="Shapes2d Shapes3d Transforms Distributors Mutators Attachments Paths FractalTree" fi dir="$(basename $PWD)" diff --git a/scripts/tutorial_gen.py b/scripts/tutorial_gen.py index c2a57f8..24d4a28 100755 --- a/scripts/tutorial_gen.py +++ b/scripts/tutorial_gen.py @@ -14,7 +14,7 @@ imgmgr = ImageManager() def img_started(req): - print(" {}... ".format(os.path.basename(req.src_file)), end='') + print(" {}... ".format(os.path.basename(req.image_file)), end='') sys.stdout.flush() @@ -52,7 +52,7 @@ def processFile(infile, outfile=None, imgroot=""): outdata = [] with open(infile, "r") as f: - script = [] + script = ["include "] extyp = "" in_script = False imgnum = 0 @@ -67,26 +67,24 @@ def processFile(infile, outfile=None, imgroot=""): extyp = line.split("-")[1] else: extyp = "" - line = "```openscad" - script = [] show_script = "ImgOnly" not in extyp + script = ["include "] imgnum = imgnum + 1 - if show_script: - outdata.append(line) elif in_script: - if show_script: - outdata.append(line) if line == "```": in_script = False - imgfile = "{}_{}.png".format(fileroot, imgnum) + imgfile = os.path.join(imgroot, "{}_{}.png".format(fileroot, imgnum)) imgmgr.new_request( fileroot+".md", linenum, imgfile, script, extyp, starting_cb=img_started, completion_cb=img_completed ) - outdata.append("![Figure {}]({})".format(imgnum, imgroot + imgfile)) - script = [] + if show_script: + outdata.append("```openscad") + outdata.extend(script) + outdata.append("```") + outdata.append("![Figure {}]({})".format(imgnum, imgfile)) show_script = True extyp = "" else: diff --git a/tutorials/Mutators.md b/tutorials/Mutators.md index 3ad3eb1..299fc1e 100644 --- a/tutorials/Mutators.md +++ b/tutorials/Mutators.md @@ -7,51 +7,51 @@ Sometimes you want to take a 3D shape like a sphere, and cut it in half. The BOSL2 library provides a number of ways to do this: ```openscad - left_half() sphere(d=100); +left_half() sphere(d=100); ``` ```openscad - right_half() sphere(d=100); +right_half() sphere(d=100); ``` ```openscad - front_half() sphere(d=100); +front_half() sphere(d=100); ``` ```openscad - back_half() sphere(d=100); +back_half() sphere(d=100); ``` ```openscad - bottom_half() sphere(d=100); +bottom_half() sphere(d=100); ``` ```openscad - top_half() sphere(d=100); +top_half() sphere(d=100); ``` You can use the `half_of()` module if you want to split space in a way not aligned with an axis: ```openscad - half_of([-1,0,-1]) sphere(d=100); +half_of([-1,0,-1]) sphere(d=100); ``` The plane of dissection can be shifted along the axis of any of these operators: ```openscad - left_half(x=20) sphere(d=100); +left_half(x=20) sphere(d=100); ``` ```openscad - back_half(y=-20) sphere(d=100); +back_half(y=-20) sphere(d=100); ``` ```openscad - bottom_half(z=20) sphere(d=100); +bottom_half(z=20) sphere(d=100); ``` ```openscad - half_of([-1,0,-1], cp=[20,0,20]) sphere(d=100); +half_of([-1,0,-1], cp=[20,0,20]) sphere(d=100); ``` By default, these operators can be applied to objects that fit in a cube 1000 on a side. If you need @@ -59,59 +59,59 @@ to apply these halving operators to objects larger than this, you can give the s argument: ```openscad - bottom_half(s=2000) sphere(d=1500); +bottom_half(s=2000) sphere(d=1500); ``` ## 2D Plane Halving To cut 2D shapes in half, you will need to add the `planar=true` argument: ```openscad - left_half(planar=true) circle(d=100); +left_half(planar=true) circle(d=100); ``` ```openscad - right_half(planar=true) circle(d=100); +right_half(planar=true) circle(d=100); ``` ```openscad - front_half(planar=true) circle(d=100); +front_half(planar=true) circle(d=100); ``` ```openscad - back_half(planar=true) circle(d=100); +back_half(planar=true) circle(d=100); ``` ## Chained Mutators If you have a set of shapes that you want to do pair-wise hulling of, you can use `chain_hull()`: ```openscad - chain_hull() { - cube(5, center=true); - translate([30, 0, 0]) sphere(d=15); - translate([60, 30, 0]) cylinder(d=10, h=20); - translate([60, 60, 0]) cube([10,1,20], center=false); - } +chain_hull() { + cube(5, center=true); + translate([30, 0, 0]) sphere(d=15); + translate([60, 30, 0]) cylinder(d=10, h=20); + translate([60, 60, 0]) cube([10,1,20], center=false); +} ``` ## Extrusion Mutators The OpenSCAD `linear_extrude()` module can take a 2D shape and extrude it vertically in a line: ```openscad - linear_extrude(height=30) zrot(45) square(40,center=true); +linear_extrude(height=30) zrot(45) square(40,center=true); ``` The `rotate_extrude()` module can take a 2D shape and rotate it around the Z axis. ```openscad - linear_extrude(height=30) left(30) zrot(45) square(40,center=true); +linear_extrude(height=30) left(30) zrot(45) square(40,center=true); ``` In a similar manner, the BOSL2 `cylindrical_extrude()` module can take a 2d shape and extrude it out radially from the center of a cylinder: ```openscad - cylindrical_extrude(or=40, ir=35) - text(text="Hello World!", size=10, halign="center", valign="center"); +cylindrical_extrude(or=40, ir=35) + text(text="Hello World!", size=10, halign="center", valign="center"); ``` @@ -121,61 +121,61 @@ out radially from the center of a cylinder: Openscad provides the `minkowski()` module to trace a shape over the entire surface of another shape: ```openscad - minkowski() { - union() { - cube([100,33,33], center=true); - cube([33,100,33], center=true); - cube([33,33,100], center=true); - } - sphere(r=8); +minkowski() { + union() { + cube([100,33,33], center=true); + cube([33,100,33], center=true); + cube([33,33,100], center=true); } + sphere(r=8); +} ``` However, it doesn't provide the inverse of this operation; to remove a shape from the entire surface of another object. For this, the BOSL2 library provides the `minkowski_difference()` module: ```openscad - minkowski_difference() { - union() { - cube([100,33,33], center=true); - cube([33,100,33], center=true); - cube([33,33,100], center=true); - } - sphere(r=8); +minkowski_difference() { + union() { + cube([100,33,33], center=true); + cube([33,100,33], center=true); + cube([33,33,100], center=true); } + sphere(r=8); +} ``` To perform a `minkowski_difference()` on 2D shapes, you need to supply the `planar=true` argument: ```openscad-2D - minkowski_difference(planar=true) { - union() { - square([100,33], center=true); - square([33,100], center=true); - } - circle(r=8); +minkowski_difference(planar=true) { + union() { + square([100,33], center=true); + square([33,100], center=true); } + circle(r=8); +} ``` ### Round2d The `round2d()` module lets you take a 2D shape and round inside and outside corners. The inner concave corners are rounded to the radius `ir=`, while the outer convex corners are rounded to the radius `or=`: ```openscad-2D - round2d(or=8) star(6, step=2, d=100); +round2d(or=8) star(6, step=2, d=100); ``` ```openscad-2D - round2d(ir=12) star(6, step=2, d=100); +round2d(ir=12) star(6, step=2, d=100); ``` ```openscad-2D - round2d(or=8,ir=12) star(6, step=2, d=100); +round2d(or=8,ir=12) star(6, step=2, d=100); ``` You can use `r=` to effectively set both `ir=` and `or=` to the same value: ```openscad-2D - round2d(r=8) star(6, step=2, d=100); +round2d(r=8) star(6, step=2, d=100); ``` ### Shell2d @@ -183,62 +183,62 @@ With the `shell2d()` module, you can take an arbitrary shape, and get the shell With a positive thickness, the shell is offset outwards from the original shape: ```openscad-2D - shell2d(thickness=5) star(5,step=2,d=100); - color("blue") stroke(star(5,step=2,d=100),closed=true); +shell2d(thickness=5) star(5,step=2,d=100); +color("blue") stroke(star(5,step=2,d=100),closed=true); ``` With a negative thickness, the shell if inset from the original shape: ```openscad-2D - shell2d(thickness=-5) star(5,step=2,d=100); - color("blue") stroke(star(5,step=2,d=100),closed=true); +shell2d(thickness=-5) star(5,step=2,d=100); +color("blue") stroke(star(5,step=2,d=100),closed=true); ``` You can give a pair of thickness values if you want it both inset and outset from the original shape: ```openscad-2D - shell2d(thickness=[-5,5]) star(5,step=2,d=100); - color("blue") stroke(star(5,step=2,d=100),closed=true); +shell2d(thickness=[-5,5]) star(5,step=2,d=100); +color("blue") stroke(star(5,step=2,d=100),closed=true); ``` You can add rounding to the outside by passing a radius to the `or=` argument. ```openscad-2D - shell2d(thickness=-5,or=5) star(5,step=2,d=100); +shell2d(thickness=-5,or=5) star(5,step=2,d=100); ``` If you need to pass different radii for the convex and concave corners of the outside, you can pass them as `or=[CONVEX,CONCAVE]`: ```openscad-2D - shell2d(thickness=-5,or=[5,10]) star(5,step=2,d=100); +shell2d(thickness=-5,or=[5,10]) star(5,step=2,d=100); ``` A radius of 0 can be used to specify no rounding: ```openscad-2D - shell2d(thickness=-5,or=[5,0]) star(5,step=2,d=100); +shell2d(thickness=-5,or=[5,0]) star(5,step=2,d=100); ``` You can add rounding to the inside by passing a radius to the `ir=` argument. ```openscad-2D - shell2d(thickness=-5,ir=5) star(5,step=2,d=100); +shell2d(thickness=-5,ir=5) star(5,step=2,d=100); ``` If you need to pass different radii for the convex and concave corners of the inside, you can pass them as `ir=[CONVEX,CONCAVE]`: ```openscad-2D - shell2d(thickness=-5,ir=[8,3]) star(5,step=2,d=100); +shell2d(thickness=-5,ir=[8,3]) star(5,step=2,d=100); ``` You can use `or=` and `ir=` together to get nice combined rounding effects: ```openscad-2D - shell2d(thickness=-5,or=[7,2],ir=[7,2]) star(5,step=2,d=100); +shell2d(thickness=-5,or=[7,2],ir=[7,2]) star(5,step=2,d=100); ``` ```openscad-2D - shell2d(thickness=-5,or=[5,0],ir=[5,0]) star(5,step=2,d=100); +shell2d(thickness=-5,or=[5,0],ir=[5,0]) star(5,step=2,d=100); ``` @@ -253,21 +253,21 @@ easier to select colors using other color schemes. You can use the HSL or Hue-S color scheme with the `HSL()` module: ```openscad - for (h=[0:0.1:1], s=[0:0.1:1], l=[0:0.1:1]) { - translate(100*[h,s,l]) { - HSL(h*360,1-s,l) cube(10,center=true); - } +for (h=[0:0.1:1], s=[0:0.1:1], l=[0:0.1:1]) { + translate(100*[h,s,l]) { + HSL(h*360,1-s,l) cube(10,center=true); } +} ``` You can use the HSV or Hue-Saturation-Value color scheme with the `HSV()` module: ```openscad - for (h=[0:0.1:1], s=[0:0.1:1], v=[0:0.1:1]) { - translate(100*[h,s,v]) { - HSV(h*360,1-s,v) cube(10,center=true); - } +for (h=[0:0.1:1], s=[0:0.1:1], v=[0:0.1:1]) { + translate(100*[h,s,v]) { + HSV(h*360,1-s,v) cube(10,center=true); } +} ``` diff --git a/tutorials/Paths.md b/tutorials/Paths.md index 83aad46..bcba35c 100644 --- a/tutorials/Paths.md +++ b/tutorials/Paths.md @@ -18,64 +18,64 @@ A path can be hard to visualize, since it's just a bunch of numbers in the sourc One way to see the path is to pass it to `polygon()`: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - polygon(path); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +polygon(path); ``` Sometimes, however, it's easier to see just the path itself. For this, you can use the `stroke()` module. At its most basic, `stroke()` just shows the path's line segments: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path); ``` You can vary the width of the drawn path with the `width=` argument: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, width=3); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, width=3); ``` You can vary the line length along the path by giving a list of widths, one per point: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, width=[3,2,1,2,3]); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, width=[3,2,1,2,3]); ``` If a path is meant to represent a closed polygon, you can use `closed=true` to show it that way: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, closed=true); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, closed=true); ``` The ends of the drawn path are normally capped with a "round" endcap, but there are other options: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcaps="round"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcaps="round"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcaps="butt"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcaps="butt"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcaps="line"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcaps="line"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcaps="tail"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcaps="tail"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcaps="arrow2"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcaps="arrow2"); ``` For more standard supported endcap options, see the docs for [`stroke()`](shapes2d.scad#stroke). @@ -83,26 +83,26 @@ For more standard supported endcap options, see the docs for [`stroke()`](shapes The start and ending endcaps can be specified individually or separately, using `endcap1=` and `endcap2=`: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcap2="arrow2"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcap2="arrow2"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcap1="butt", endcap2="arrow2"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcap1="butt", endcap2="arrow2"); ``` ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - stroke(path, endcap1="tail", endcap2="arrow"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +stroke(path, endcap1="tail", endcap2="arrow"); ``` The size of the endcaps will be relative to the width of the line where the endcap is to be placed: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - widths = [1, 1.25, 1.5, 1.75, 2]; - stroke(path, width=widths, endcaps="arrow2"); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +widths = [1, 1.25, 1.5, 1.75, 2]; +stroke(path, width=widths, endcaps="arrow2"); ``` If none of the standard endcaps are useful to you, it is possible to design your own, simply by @@ -114,104 +114,104 @@ line width size. Untrimmed: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - dblarrow = [[0,0], [2,-3], [0.5,-2.3], [2,-4], [0.5,-3.5], [-0.5,-3.5], [-2,-4], [-0.5,-2.3], [-2,-3]]; - stroke(path, endcaps=dblarrow); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +dblarrow = [[0,0], [2,-3], [0.5,-2.3], [2,-4], [0.5,-3.5], [-0.5,-3.5], [-2,-4], [-0.5,-2.3], [-2,-3]]; +stroke(path, endcaps=dblarrow); ``` Trimmed: ```openscad-2D - path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; - dblarrow = [[0,0], [2,-3], [0.5,-2.3], [2,-4], [0.5,-3.5], [-0.5,-3.5], [-2,-4], [-0.5,-2.3], [-2,-3]]; - stroke(path, trim=3.5, endcaps=dblarrow); +path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; +dblarrow = [[0,0], [2,-3], [0.5,-2.3], [2,-4], [0.5,-3.5], [-0.5,-3.5], [-2,-4], [-0.5,-2.3], [-2,-3]]; +stroke(path, trim=3.5, endcaps=dblarrow); ``` ### Standard 2D Shape Polygons BOSL2 will let you get the perimeter polygon for almost all of the standard 2D shapes simply by calling them like a function: ```openscad-2D - path = square(40, center=true); - stroke(path, closed=true, endcap2="arrow2"); +path = square(40, center=true); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = rect([40,30], rounding=5, center=true); - stroke(path, closed=true, endcap2="arrow2"); +path = rect([40,30], rounding=5, center=true); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = trapezoid(w1=40, w2=20, h=30); - stroke(path, closed=true, endcap2="arrow2"); +path = trapezoid(w1=40, w2=20, h=30); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = circle(d=50); - stroke(path, closed=true, endcap2="arrow2"); +path = circle(d=50); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = oval(d=[50,30]); - stroke(path, closed=true, endcap2="arrow2"); +path = oval(d=[50,30]); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = pentagon(d=50); - stroke(path, closed=true, endcap2="arrow2"); +path = pentagon(d=50); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = star(n=5, step=2, d=50); - stroke(path, closed=true, endcap2="arrow2"); +path = star(n=5, step=2, d=50); +stroke(path, closed=true, endcap2="arrow2"); ``` ### Arcs Often, when you are constructing a path, you will want to add an arc. The `arc()` command lets you do that: ```openscad-2D - path = arc(r=30, angle=120); - stroke(path, endcap2="arrow2"); +path = arc(r=30, angle=120); +stroke(path, endcap2="arrow2"); ``` ```openscad-2D - path = arc(d=60, angle=120); - stroke(path, endcap2="arrow2"); +path = arc(d=60, angle=120); +stroke(path, endcap2="arrow2"); ``` If you give the `N=` argument, you can control exactly how many points the arc is divided into: ```openscad-2D - path = arc(N=5, r=30, angle=120); - stroke(path, endcap2="arrow2"); +path = arc(N=5, r=30, angle=120); +stroke(path, endcap2="arrow2"); ``` With the `start=` argument, you can start the arc somewhere other than the X+ axis: ```openscad-2D - path = arc(start=45, r=30, angle=120); - stroke(path, endcap2="arrow2"); +path = arc(start=45, r=30, angle=120); +stroke(path, endcap2="arrow2"); ``` Alternatively, you can give starting and ending angles in a list in the `angle=` argument: ```openscad-2D - path = arc(angle=[120,45], r=30); - stroke(path, endcap2="arrow2"); +path = arc(angle=[120,45], r=30); +stroke(path, endcap2="arrow2"); ``` The `cp=` argument lets you center the arc somewhere other than the origin: ```openscad-2D - path = arc(cp=[10,0], r=30, angle=120); - stroke(path, endcap2="arrow2"); +path = arc(cp=[10,0], r=30, angle=120); +stroke(path, endcap2="arrow2"); ``` The arc can also be given by three points on the arc: ```openscad-2D - pts = [[-15,10],[0,20],[35,-5]]; - path = arc(points=pts); - stroke(path, endcap2="arrow2"); +pts = [[-15,10],[0,20],[35,-5]]; +path = arc(points=pts); +stroke(path, endcap2="arrow2"); ``` @@ -222,75 +222,75 @@ turtle or cursor walking a path. It can "move" forward or backward, or turn "le place: ```openscad-2D - path = turtle([ - "move", 10, - "left", 90, - "move", 20, - "left", 135, - "move", 10*sqrt(2), - "right", 90, - "move", 10*sqrt(2), - "left", 135, - "move", 20 - ]); - stroke(path, endcap2="arrow2"); +path = turtle([ + "move", 10, + "left", 90, + "move", 20, + "left", 135, + "move", 10*sqrt(2), + "right", 90, + "move", 10*sqrt(2), + "left", 135, + "move", 20 +]); +stroke(path, endcap2="arrow2"); ``` The position and the facing of the turtle/cursor updates after each command. The motion and turning commands can also have default distances or angles given: ```openscad-2D - path = turtle([ - "angle",360/6, - "length",10, - "move","turn", - "move","turn", - "move","turn", - "move","turn", - "move" - ]); - stroke(path, endcap2="arrow2"); +path = turtle([ + "angle",360/6, + "length",10, + "move","turn", + "move","turn", + "move","turn", + "move","turn", + "move" +]); +stroke(path, endcap2="arrow2"); ``` You can use "scale" to relatively scale up the default motion length: ```openscad-2D - path = turtle([ - "angle",360/6, - "length",10, - "move","turn", - "move","turn", - "scale",2, - "move","turn", - "move","turn", - "scale",0.5, - "move" - ]); - stroke(path, endcap2="arrow2"); +path = turtle([ + "angle",360/6, + "length",10, + "move","turn", + "move","turn", + "scale",2, + "move","turn", + "move","turn", + "scale",0.5, + "move" +]); +stroke(path, endcap2="arrow2"); ``` Sequences of commands can be repeated using the "repeat" command: ```openscad-2D - path=turtle([ - "angle",360/5, - "length",10, - "repeat",5,["move","turn"] - ]); - stroke(path, endcap2="arrow2"); +path=turtle([ + "angle",360/5, + "length",10, + "repeat",5,["move","turn"] +]); +stroke(path, endcap2="arrow2"); ``` More complicated commands also exist, including those that form arcs: ```openscad-2D - path = turtle([ - "move", 10, - "left", 90, - "move", 20, - "arcleft", 10, 180, - "move", 20 - ]); - stroke(path, endcap2="arrow2"); +path = turtle([ + "move", 10, + "left", 90, + "move", 20, + "arcleft", 10, 180, + "move", 20 +]); +stroke(path, endcap2="arrow2"); ``` A comprehensive list of supported turtle commands can be found in the docs for [`turtle()`](shapes2d.scad#turtle). @@ -299,97 +299,97 @@ A comprehensive list of supported turtle commands can be found in the docs for [ To translate a path, you can just pass it to the `move()` (or up/down/left/right/fwd/back) function in the `p=` argument: ```openscad-2D - path = move([-15,-30], p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = move([-15,-30], p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = fwd(30, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = fwd(30, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = left(30, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = left(30, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` To scale a path, you can just pass it to the `scale()` (or [xyz]scale) function in the `p=` argument: ```openscad-2D - path = scale([1.5,0.75], p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = scale([1.5,0.75], p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = xscale(1.5, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = xscale(1.5, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = yscale(1.5, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = yscale(1.5, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` To rotate a path, just can pass it to the `rot()` (or [xyz]rot) function in the `p=` argument: ```openscad-2D - path = rot(30, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = rot(30, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = zrot(30, p=square(50,center=true)); - stroke(path, closed=true, endcap2="arrow2"); +path = zrot(30, p=square(50,center=true)); +stroke(path, closed=true, endcap2="arrow2"); ``` To mirror a path, just can pass it to the `mirror()` (or [xyz]flip) function in the `p=` argument: ```openscad-2D - path = mirror([1,1], p=trapezoid(w1=40, w2=10, h=25)); - stroke(path, closed=true, endcap2="arrow2"); +path = mirror([1,1], p=trapezoid(w1=40, w2=10, h=25)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = xflip(p=trapezoid(w1=40, w2=10, h=25)); - stroke(path, closed=true, endcap2="arrow2"); +path = xflip(p=trapezoid(w1=40, w2=10, h=25)); +stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D - path = yflip(p=trapezoid(w1=40, w2=10, h=25)); - stroke(path, closed=true, endcap2="arrow2"); +path = yflip(p=trapezoid(w1=40, w2=10, h=25)); +stroke(path, closed=true, endcap2="arrow2"); ``` You can get raw transformation matrices for various transformations by calling them like a function without a `p=` argument: ```openscad-2D - mat = move([5,10,0]); - multmatrix(mat) square(50,center=true); +mat = move([5,10,0]); +multmatrix(mat) square(50,center=true); ``` ```openscad-2D - mat = scale([1.5,0.75,1]); - multmatrix(mat) square(50,center=true); +mat = scale([1.5,0.75,1]); +multmatrix(mat) square(50,center=true); ``` ```openscad-2D - mat = rot(30); - multmatrix(mat) square(50,center=true); +mat = rot(30); +multmatrix(mat) square(50,center=true); ``` Raw transformation matrices can be multiplied together to precalculate a compound transformation. For example, to scale a shape, then rotate it, then translate the result, you can do something like: ```openscad-2D - mat = move([5,10,0]) * rot(30) * scale([1.5,0.75,1]); - multmatrix(mat) square(50,center=true); +mat = move([5,10,0]) * rot(30) * scale([1.5,0.75,1]); +multmatrix(mat) square(50,center=true); ``` To apply a compound transformation matrix to a path, you can use the `apply()` function: ```openscad-2D - mat = move([5,10]) * rot(30, planar=true) * scale([1.5,0.75]); - path = square(50,center=true); - tpath = apply(mat, path); - stroke(tpath, endcap2="arrow2"); +mat = move([5,10]) * rot(30, planar=true) * scale([1.5,0.75]); +path = square(50,center=true); +tpath = apply(mat, path); +stroke(tpath, endcap2="arrow2"); ``` @@ -401,39 +401,39 @@ XORed against all the others. You can display a region using the `region()` mod If you have a region with one polygon fully inside another, it makes a hole: ```openscad-2D - rgn = [square(50,center=true), circle(d=30)]; - region(rgn); +rgn = [square(50,center=true), circle(d=30)]; +region(rgn); ``` If you have a region with multiple polygons that are not contained by any others, they make multiple discontiguous shapes: ```openscad-2D - rgn = [ - move([-30, 20], p=square(20,center=true)), - move([ 0,-20], p=trapezoid(w1=20, w2=10, h=20)), - move([ 30, 20], p=square(20,center=true)), - ]; - region(rgn); +rgn = [ + move([-30, 20], p=square(20,center=true)), + move([ 0,-20], p=trapezoid(w1=20, w2=10, h=20)), + move([ 30, 20], p=square(20,center=true)), +]; +region(rgn); ``` Region polygons can be nested abitrarily deep, in multiple discontiguous shapes: ```openscad-2D - rgn = [ - for (d=[50:-10:10]) left(30, p=circle(d=d)), - for (d=[50:-10:10]) right(30, p=circle(d=d)) - ]; - region(rgn); +rgn = [ + for (d=[50:-10:10]) left(30, p=circle(d=d)), + for (d=[50:-10:10]) right(30, p=circle(d=d)) +]; +region(rgn); ``` A region with crossing polygons is somewhat poorly formed, but the intersection(s) of the polygons become holes: ```openscad-2D - rgn = [ - left(15, p=circle(d=50)), - right(15, p=circle(d=50)) - ]; - region(rgn); +rgn = [ + left(15, p=circle(d=50)), + right(15, p=circle(d=50)) +]; +region(rgn); ``` ### Boolean Region Geometry @@ -441,65 +441,65 @@ Similarly to how OpenSCAD can perform operations like union/difference/intersect the BOSL2 library lets you perform those same operations on regions: ```openscad-2D - rgn1 = [for (d=[40:-10:10]) circle(d=d)]; - rgn2 = [square([60,12], center=true)]; - rgn = union(rgn1, rgn2); - region(rgn); +rgn1 = [for (d=[40:-10:10]) circle(d=d)]; +rgn2 = [square([60,12], center=true)]; +rgn = union(rgn1, rgn2); +region(rgn); ``` ```openscad-2D - rgn1 = [for (d=[40:-10:10]) circle(d=d)]; - rgn2 = [square([60,12], center=true)]; - rgn = difference(rgn1, rgn2); - region(rgn); +rgn1 = [for (d=[40:-10:10]) circle(d=d)]; +rgn2 = [square([60,12], center=true)]; +rgn = difference(rgn1, rgn2); +region(rgn); ``` ```openscad-2D - rgn1 = [for (d=[40:-10:10]) circle(d=d)]; - rgn2 = [square([60,12], center=true)]; - rgn = intersection(rgn1, rgn2); - region(rgn); +rgn1 = [for (d=[40:-10:10]) circle(d=d)]; +rgn2 = [square([60,12], center=true)]; +rgn = intersection(rgn1, rgn2); +region(rgn); ``` ```openscad-2D - rgn1 = [for (d=[40:-10:10]) circle(d=d)]; - rgn2 = [square([60,12], center=true)]; - rgn = exclusive_or(rgn1, rgn2); - region(rgn); +rgn1 = [for (d=[40:-10:10]) circle(d=d)]; +rgn2 = [square([60,12], center=true)]; +rgn = exclusive_or(rgn1, rgn2); +region(rgn); ``` ```openscad-2D - orig_rgn = [star(n=5, step=2, d=50)]; - rgn = offset(orig_rgn, r=-3, closed=true); - color("blue") region(orig_rgn); - region(rgn); +orig_rgn = [star(n=5, step=2, d=50)]; +rgn = offset(orig_rgn, r=-3, closed=true); +color("blue") region(orig_rgn); +region(rgn); ``` You can use regions for several useful things. If you wanted a grid of holes in your object that form the shape given by a region, you can do that with `grid2d()`: ```openscad-3D - rgn = [ - circle(d=100), - star(n=5,step=2,d=100,spin=90) - ]; - difference() { - cyl(h=5, d=120); - grid2d(size=[120,120], spacing=[4,4], inside=rgn) cyl(h=10,d=2); - } +rgn = [ + circle(d=100), + star(n=5,step=2,d=100,spin=90) +]; +difference() { + cyl(h=5, d=120); + grid2d(size=[120,120], spacing=[4,4], inside=rgn) cyl(h=10,d=2); +} ``` You can also sweep a region through 3-space to make a solid: ```openscad-3D - $fa=1; $fs=1; - rgn = [ for (d=[50:-10:10]) circle(d=d) ]; - tforms = [ - for (a=[90:-5:0]) xrot(a, cp=[0,-70]), - for (a=[0:5:90]) xrot(a, cp=[0,70]), - move([0,150,-70]) * xrot(90), - ]; - sweep(rgn, tforms, closed=false, caps=true); +$fa=1; $fs=1; +rgn = [ for (d=[50:-10:10]) circle(d=d) ]; +tforms = [ + for (a=[90:-5:0]) xrot(a, cp=[0,-70]), + for (a=[0:5:90]) xrot(a, cp=[0,70]), + move([0,150,-70]) * xrot(90), +]; +sweep(rgn, tforms, closed=false, caps=true); ``` diff --git a/tutorials/Shapes2d.md b/tutorials/Shapes2d.md index 17e4c0f..122f103 100644 --- a/tutorials/Shapes2d.md +++ b/tutorials/Shapes2d.md @@ -12,15 +12,15 @@ and more ways to simply reorient them. You can still use the built-in `square()` in the familiar ways that OpenSCAD provides: ```openscad-2D - square(100, center=false); +square(100, center=false); ``` ```openscad-2D - square(100, center=true); +square(100, center=true); ``` ```openscad-2D - square([60,40], center=true); +square([60,40], center=true); ``` The BOSL2 library provides an enhanced equivalent to `square()` called `rect()`. @@ -28,13 +28,13 @@ You can use it in the same way you use `square()`, but it also provides extended functionality. For example, it allows you to round the corners: ```openscad-2D - rect([60,40], center=true, rounding=10); +rect([60,40], center=true, rounding=10); ``` Or chamfer them: ```openscad-2D - rect([60,40], center=true, chamfer=10); +rect([60,40], center=true, chamfer=10); ``` You can even specify *which* corners get rounded or chamfered. If you pass a @@ -44,26 +44,26 @@ corner, counter-clockwise around to the back-left (quadrant II) corner, to the forward-left (quadrant III) corner, to the forward-right (quadrant IV) corner: ```openscad-2DImgOnly - module text3d(text) color("black") text( - text=text, font="Times", size=10, - halign="center", valign="center" - ); - translate([ 50, 50]) text3d("I"); - translate([-50, 50]) text3d("II"); - translate([-50,-50]) text3d("III"); - translate([ 50,-50]) text3d("IV"); - rect([90,80], center=true); +module text3d(text) color("black") text( + text=text, font="Times", size=10, + halign="center", valign="center" +); +translate([ 50, 50]) text3d("I"); +translate([-50, 50]) text3d("II"); +translate([-50,-50]) text3d("III"); +translate([ 50,-50]) text3d("IV"); +rect([90,80], center=true); ``` If a size is given as `0`, then there is no rounding and/or chamfering for that quadrant's corner: ```openscad-2D - rect([60,40], center=true, rounding=[0,5,10,15]); +rect([60,40], center=true, rounding=[0,5,10,15]); ``` ```openscad-2D - rect([60,40], center=true, chamfer=[0,5,10,15]); +rect([60,40], center=true, chamfer=[0,5,10,15]); ``` You can give both `rounding=` and `chamfer=` arguments to mix rounding and @@ -71,7 +71,7 @@ chamfering, but only if you specify per corner. If you want a rounding in a corner, specify a 0 chamfer for that corner, and vice versa: ```openscad-2D - rect([60,40], center=true, rounding=[5,0,10,0], chamfer=[0,5,0,15]); +rect([60,40], center=true, rounding=[5,0,10,0], chamfer=[0,5,0,15]); ``` #### Anchors and Spin @@ -84,19 +84,19 @@ the side or corner you want to align to the origin. For example, to align the center of the back edge to the origin, set the anchor to `[0,1]`: ```openscad-2D - rect([60,40], anchor=[0,1]); +rect([60,40], anchor=[0,1]); ``` To align the front right corner to the origin: ```openscad-2D - rect([60,40], anchor=[1,-1]); +rect([60,40], anchor=[1,-1]); ``` To center: ```openscad-2D - rect([60,40], anchor=[0,0]); +rect([60,40], anchor=[0,0]); ``` To make it clearer when giving vectors, there are several standard vector @@ -116,52 +116,52 @@ Note that even though these are 3D vectors, you can use most of them, (except `UP`/`DOWN`, of course) for anchors in 2D shapes: ```openscad-2D - rect([60,40], anchor=BACK); +rect([60,40], anchor=BACK); ``` ```openscad-2D - rect([60,40], anchor=CENTER); +rect([60,40], anchor=CENTER); ``` You can add vectors together to point to corners: ```openscad-2D - rect([60,40], anchor=FRONT+RIGHT); +rect([60,40], anchor=FRONT+RIGHT); ``` Finally, the `spin` argument can rotate the shape by a given number of degrees clockwise: ```openscad-2D - rect([60,40], anchor=CENTER, spin=30); +rect([60,40], anchor=CENTER, spin=30); ``` Anchoring or centering is performed before the spin: ```openscad-2D - rect([60,40], anchor=BACK, spin=30); +rect([60,40], anchor=BACK, spin=30); ``` Anchor points double as attachment points, so that you can attach other shapes: ```openscad-2D - rect([60,40],center=true) - show_anchors(); +rect([60,40],center=true) + show_anchors(); ``` ### 2D Circles and Ovals The built-in `circle()` primitive can be used as expected: ```openscad-2D - circle(r=50); +circle(r=50); ``` ```openscad-2D - circle(d=100); +circle(d=100); ``` ```openscad-2D - circle(d=100, $fn=8); +circle(d=100, $fn=8); ``` The BOSL2 library also provides an enhanced equivalent of `circle()` called `oval()`. @@ -176,7 +176,7 @@ The `realign=` argument, if set `true`, rotates the `oval()` by half the angle between the sides: ```openscad-2D - oval(d=100, $fn=8, realign=true); +oval(d=100, $fn=8, realign=true); ``` The `circum=` argument, if true, makes it so that the polygon forming the @@ -185,19 +185,19 @@ The `circum=` argument, if true, makes it so that the polygon forming the Inscribing the ideal circle: ```openscad-2D - difference() { - circle(d=100, $fn=360); - oval(d=100, $fn=8); - } +difference() { + circle(d=100, $fn=360); + oval(d=100, $fn=8); +} ``` Circumscribing the ideal circle: ```openscad-2D - difference() { - oval(d=100, $fn=8, circum=true); - circle(d=100, $fn=360); - } +difference() { + oval(d=100, $fn=8, circum=true); + circle(d=100, $fn=360); +} ``` The `oval()` module, as its name suggests, can be given separate X and Y radii @@ -205,29 +205,29 @@ or diameters. To do this, just give `r=` or `d=` with a list of two radii or diameters: ```openscad-2D - oval(r=[30,20]); +oval(r=[30,20]); ``` ```openscad-2D - oval(d=[60,40]); +oval(d=[60,40]); ``` Another way that `oval()` is enhanced over `circle()`, is that you can anchor, spin and attach it. ```openscad-2D - oval(r=50, anchor=BACK); +oval(r=50, anchor=BACK); ``` ```openscad-2D - oval(r=50, anchor=FRONT+RIGHT); +oval(r=50, anchor=FRONT+RIGHT); ``` Using spin on a circle may not make initial sense, until you remember that anchoring is performed before spin: ```openscad-2D - oval(r=50, anchor=FRONT, spin=-30); +oval(r=50, anchor=FRONT, spin=-30); ``` @@ -239,51 +239,51 @@ The BOSL2 library can provide all of these shapes with the `trapezoid()` module. To make a simple triangle, just make one of the widths zero: ```openscad-2D - trapezoid(w1=50, w2=0, h=50); +trapezoid(w1=50, w2=0, h=50); ``` To make a right triangle, you need to use the `shift=` argument, to shift the back of the trapezoid along the X axis: ```openscad-2D - trapezoid(w1=50, w2=0, h=50, shift=-25); +trapezoid(w1=50, w2=0, h=50, shift=-25); ``` ```openscad-2D - trapezoid(w1=50, w2=0, h=50, shift=25); +trapezoid(w1=50, w2=0, h=50, shift=25); ``` ```openscad-2D - trapezoid(w1=0, w2=50, h=50, shift=-25); +trapezoid(w1=0, w2=50, h=50, shift=-25); ``` ```openscad-2D - trapezoid(w1=0, w2=50, h=50, shift=25); +trapezoid(w1=0, w2=50, h=50, shift=25); ``` You can make a trapezoid by specifying non-zero widths for both the front (`w1=`) and back (`w2=`): ```openscad-2D - trapezoid(w1=30, w2=50, h=50); +trapezoid(w1=30, w2=50, h=50); ``` A parallelogram is just a matter of using the same width for front and back, with a shift along the X axis: ```openscad-2D - trapezoid(w1=50, w2=50, shift=20, h=50); +trapezoid(w1=50, w2=50, shift=20, h=50); ``` A quadrilateral can be made by having unequal, non-zero front (`w1=`) and back (`w2=`) widths, with the back shifted along the X axis: ```openscad-2D - trapezoid(w1=50, w2=30, shift=20, h=50); +trapezoid(w1=50, w2=30, shift=20, h=50); ``` You can use `anchor=` and `spin=`, just like with other attachable shapes. However, the anchor points are based on the side angles of the faces, and may not be where you expect them: ```openscad-2D - trapezoid(w1=30, w2=50, h=50) - show_anchors(); +trapezoid(w1=30, w2=50, h=50) + show_anchors(); ``` ### Regular N-Gons @@ -292,25 +292,25 @@ OpenSCAD lets you make regular N-gons (pentagon, hexagon, etc) by using `circle( While this is concise, it may be less than obvious at first glance: ```openscad-2D - circle(d=50, $fn=5); +circle(d=50, $fn=5); ``` The BOSL2 library has modules that are named more clearly: ```openscad-2D - pentagon(d=50); +pentagon(d=50); ``` ```openscad-2D - hexagon(d=50); +hexagon(d=50); ``` ```openscad-2D - octagon(d=50); +octagon(d=50); ``` ```openscad-2D - regular_ngon(n=7, d=50); +regular_ngon(n=7, d=50); ``` These modules also provide you with extra functionality. @@ -318,44 +318,44 @@ These modules also provide you with extra functionality. They can be sized by side length: ```openscad-2D - pentagon(side=20); +pentagon(side=20); ``` They can be sized by circumscribed circle radius/diameter: ```openscad-2D - pentagon(ir=25); - pentagon(id=50); +pentagon(ir=25); +pentagon(id=50); ``` They can be realigned by half a side's angle: ```openscad-2D - left(30) pentagon(d=50, realign=true); - right(30) pentagon(d=50, realign=false); +left(30) pentagon(d=50, realign=true); +right(30) pentagon(d=50, realign=false); ``` They can be rounded: ```openscad-2D - pentagon(d=50, rounding=10); +pentagon(d=50, rounding=10); ``` ```openscad-2D - hexagon(d=50, rounding=10); +hexagon(d=50, rounding=10); ``` They also have somewhat different attachment behavior: ```openscad-2D - color("green") stroke(circle(d=50), closed=true); - oval(d=50,$fn=5) - attach(LEFT) color("blue") anchor_arrow2d(); +color("green") stroke(circle(d=50), closed=true); +oval(d=50,$fn=5) + attach(LEFT) color("blue") anchor_arrow2d(); ``` ```openscad-2D - pentagon(d=50) - attach(LEFT) color("blue") anchor_arrow2d(); +pentagon(d=50) + attach(LEFT) color("blue") anchor_arrow2d(); ``` You can use `anchor=` and `spin=`, just like with other attachable shapes. However, the anchor @@ -363,15 +363,15 @@ points are based on where the anchor vector would intersect the side of the N-go be where you expect them: ```openscad-2D - pentagon(d=50) - show_anchors(custom=false); +pentagon(d=50) + show_anchors(custom=false); ``` N-gons also have named anchor points for their sides and tips: ```openscad-2D - pentagon(d=30) - show_anchors(std=false); +pentagon(d=30) + show_anchors(std=false); ``` @@ -381,72 +381,72 @@ The BOSL2 library has stars as a basic supported shape. They can have any numbe You can specify a star's shape by point count, inner and outer vertex radius/diameters: ```openscad-2D - star(n=3, id=10, d=50); +star(n=3, id=10, d=50); ``` ```openscad-2D - star(n=5, id=15, r=25); +star(n=5, id=15, r=25); ``` ```openscad-2D - star(n=10, id=30, d=50); +star(n=10, id=30, d=50); ``` Or you can specify the star shape by point count and number of points to step: ```openscad-2D - star(n=7, step=2, d=50); +star(n=7, step=2, d=50); ``` ```openscad-2D - star(n=7, step=3, d=50); +star(n=7, step=3, d=50); ``` If the `realign=` argument is given a true value, then the star will be rotated by half a point angle: ```openscad-2D - left(30) star(n=5, step=2, d=50); - right(30) star(n=5, step=2, d=50, realign=true); +left(30) star(n=5, step=2, d=50); +right(30) star(n=5, step=2, d=50, realign=true); ``` The `align_tip=` argument can be given a vector so that you can align the first point in a specific direction: ```openscad-2D - star(n=5, ir=15, or=30, align_tip=BACK+LEFT) - attach("tip0") color("blue") anchor_arrow2d(); +star(n=5, ir=15, or=30, align_tip=BACK+LEFT) + attach("tip0") color("blue") anchor_arrow2d(); ``` ```openscad-2D - star(n=5, ir=15, or=30, align_tip=BACK+RIGHT) - attach("tip0") color("blue") anchor_arrow2d(); +star(n=5, ir=15, or=30, align_tip=BACK+RIGHT) + attach("tip0") color("blue") anchor_arrow2d(); ``` Similarly, the first indentation or pit can be oriented towards a specific vector with `align_pit=`: ```openscad-2D - star(n=5, ir=15, or=30, align_pit=BACK+LEFT) - attach("pit0") color("blue") anchor_arrow2d(); +star(n=5, ir=15, or=30, align_pit=BACK+LEFT) + attach("pit0") color("blue") anchor_arrow2d(); ``` ```openscad-2D - star(n=5, ir=15, or=30, align_pit=BACK+RIGHT) - attach("pit0") color("blue") anchor_arrow2d(); +star(n=5, ir=15, or=30, align_pit=BACK+RIGHT) + attach("pit0") color("blue") anchor_arrow2d(); ``` You can use `anchor=` and `spin=`, just like with other attachable shapes. However, the anchor points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D - star(n=5, step=2, d=50) - show_anchors(custom=false); +star(n=5, step=2, d=50) + show_anchors(custom=false); ``` Stars also have named anchor points for their pits, tips, and midpoints between tips: ```openscad-2D - star(n=5, step=2, d=40) - show_anchors(std=false); +star(n=5, step=2, d=40) + show_anchors(std=false); ``` @@ -460,36 +460,36 @@ The `teardrop2d()` module will let you make a 2D version of the teardrop shape, extrude it later: ```openscad-2D - teardrop2d(r=20); +teardrop2d(r=20); ``` ```openscad-2D - teardrop2d(d=50); +teardrop2d(d=50); ``` The default overhang angle is 45 degrees, but you can adjust that with the `ang=` argument: ```openscad-2D - teardrop2d(d=50, ang=30); +teardrop2d(d=50, ang=30); ``` If you prefer to flatten the top of the teardrop, to encourage bridging, you can use the `cap_h=` argument: ```openscad-2D - teardrop2d(d=50, cap_h=25); +teardrop2d(d=50, cap_h=25); ``` ```openscad-2D - teardrop2d(d=50, ang=30, cap_h=30); +teardrop2d(d=50, ang=30, cap_h=30); ``` You can use `anchor=` and `spin=`, just like with other attachable shapes. However, the anchor points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D - teardrop2d(d=50, ang=30, cap_h=30) - show_anchors(); +teardrop2d(d=50, ang=30, cap_h=30) + show_anchors(); ``` @@ -499,57 +499,57 @@ A more unusal shape that BOSL2 provides is Glued Circles. It's basically a pair connected by what looks like a gloopy glued miniscus: ```openscad-2D - glued_circles(d=30, spread=40); +glued_circles(d=30, spread=40); ``` The `r=`/`d=` arguments can specify the radius or diameter of the two circles: ```openscad-2D - glued_circles(r=20, spread=45); +glued_circles(r=20, spread=45); ``` ```openscad-2D - glued_circles(d=40, spread=45); +glued_circles(d=40, spread=45); ``` The `spread=` argument specifies the distance between the centers of the two circles: ```openscad-2D - glued_circles(d=30, spread=30); +glued_circles(d=30, spread=30); ``` ```openscad-2D - glued_circles(d=30, spread=40); +glued_circles(d=30, spread=40); ``` The `tangent=` argument gives the angle of the tangent of the meniscus on the two circles: ```openscad-2D - glued_circles(d=30, spread=30, tangent=45); +glued_circles(d=30, spread=30, tangent=45); ``` ```openscad-2D - glued_circles(d=30, spread=30, tangent=20); +glued_circles(d=30, spread=30, tangent=20); ``` ```openscad-2D - glued_circles(d=30, spread=30, tangent=-20); +glued_circles(d=30, spread=30, tangent=-20); ``` One useful thing you can do is to string a few `glued_circle()`s in a line then extrude them to make a ribbed wall: ```openscad-3D - $fn=36; s=10; - linear_extrude(height=50,convexity=16,center=true) - xcopies(s*sqrt(2),n=3) - glued_circles(d=s, spread=s*sqrt(2), tangent=45); +$fn=36; s=10; +linear_extrude(height=50,convexity=16,center=true) + xcopies(s*sqrt(2),n=3) + glued_circles(d=s, spread=s*sqrt(2), tangent=45); ``` You can use `anchor=` and `spin=`, just like with other attachable shapes. However, the anchor points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D - glued_circles(d=40, spread=40, tangent=45) - show_anchors(); +glued_circles(d=40, spread=40, tangent=45) + show_anchors(); ``` diff --git a/tutorials/Shapes3d.md b/tutorials/Shapes3d.md index 4df0ff3..e0389c8 100644 --- a/tutorials/Shapes3d.md +++ b/tutorials/Shapes3d.md @@ -12,15 +12,15 @@ that they support more features, and more ways to simply reorient them. BOSL2 overrides the built-in `cube()` module. It still can be used as you expect from the built-in: ```openscad-3D - cube(100); +cube(100); ``` ```openscad-3D - cube(100, center=true); +cube(100, center=true); ``` ```openscad-3D - cube([50,40,20], center=true); +cube([50,40,20], center=true); ``` It is also enhanced to allow you to anchor, spin, orient, and attach it. @@ -30,21 +30,21 @@ except you can also anchor vertically in 3D, allowing anchoring to faces, edges, and corners: ```openscad-3D - cube([50,40,20], anchor=BOTTOM); +cube([50,40,20], anchor=BOTTOM); ``` ```openscad-3D - cube([50,40,20], anchor=TOP+BACK); +cube([50,40,20], anchor=TOP+BACK); ``` ```openscad-3D - cube([50,40,20], anchor=TOP+FRONT+LEFT); +cube([50,40,20], anchor=TOP+FRONT+LEFT); ``` You can use `spin=` to rotate around the Z axis: ```openscad-3D - cube([50,40,20], anchor=FRONT, spin=30); +cube([50,40,20], anchor=FRONT, spin=30); ``` 3D objects also gain the ability to use an extra trick with `spin=`; @@ -52,29 +52,29 @@ if you pass a list of `[X,Y,Z]` rotation angles to `spin=`, it will rotate by the three given axis angles, similar to using `rotate()`: ```openscad-3D - cube([50,40,20], anchor=FRONT, spin=[15,0,30]); +cube([50,40,20], anchor=FRONT, spin=[15,0,30]); ``` 3D objects also can be given an `orient=` argument as a vector, pointing to where the top of the shape should be rotated towards. ```openscad-3D - cube([50,40,20], orient=UP+BACK+RIGHT); +cube([50,40,20], orient=UP+BACK+RIGHT); ``` If you use `anchor=`, `spin=`, and `orient=` together, the anchor is performed first, then the spin, then the orient: ```openscad-3D - cube([50,40,20], anchor=FRONT); +cube([50,40,20], anchor=FRONT); ``` ```openscad-3D - cube([50,40,20], anchor=FRONT, spin=45); +cube([50,40,20], anchor=FRONT, spin=45); ``` ```openscad-3D - cube([50,40,20], anchor=FRONT, spin=45, orient=UP+FWD+RIGHT); +cube([50,40,20], anchor=FRONT, spin=45, orient=UP+FWD+RIGHT); ``` BOSL2 provides a `cuboid()` module that expands on `cube()`, by providing @@ -84,13 +84,13 @@ except that `cuboid()` centers by default. You can round the edges with the `rounding=` argument: ```openscad-3D - cuboid([100,80,60], rounding=20); +cuboid([100,80,60], rounding=20); ``` Similarly, you can chamfer the edges with the `chamfer=` argument: ```openscad-3D - cuboid([100,80,60], chamfer=10); +cuboid([100,80,60], chamfer=10); ``` You can round only some edges, by using the `edges=` arguments. It can be @@ -98,80 +98,80 @@ given a few types of arguments. If you gave it a vector pointed at a face, it will only round the edges surrounding that face: ```openscad-3D - cuboid([100,80,60], rounding=20, edges=TOP); +cuboid([100,80,60], rounding=20, edges=TOP); ``` ```openscad-3D - cuboid([100,80,60], rounding=20, edges=RIGHT); +cuboid([100,80,60], rounding=20, edges=RIGHT); ``` If you give `edges=` a vector pointing at a corner, it will round all edges that meet at that corner: ```openscad-3D - cuboid([100,80,60], rounding=20, edges=RIGHT+FRONT+TOP); +cuboid([100,80,60], rounding=20, edges=RIGHT+FRONT+TOP); ``` ```openscad-3D - cuboid([100,80,60], rounding=20, edges=LEFT+FRONT+TOP); +cuboid([100,80,60], rounding=20, edges=LEFT+FRONT+TOP); ``` If you give `edges=` a vector pointing at an edge, it will round only that edge: ```openscad-3D - cuboid([100,80,60], rounding=10, edges=FRONT+TOP); +cuboid([100,80,60], rounding=10, edges=FRONT+TOP); ``` ```openscad-3D - cuboid([100,80,60], rounding=10, edges=RIGHT+FRONT); +cuboid([100,80,60], rounding=10, edges=RIGHT+FRONT); ``` If you give the string "X", "Y", or "Z", then all edges aligned with the specified axis will be rounded: ```openscad-3D - cuboid([100,80,60], rounding=10, edges="X"); +cuboid([100,80,60], rounding=10, edges="X"); ``` ```openscad-3D - cuboid([100,80,60], rounding=10, edges="Y"); +cuboid([100,80,60], rounding=10, edges="Y"); ``` ```openscad-3D - cuboid([100,80,60], rounding=10, edges="Z"); +cuboid([100,80,60], rounding=10, edges="Z"); ``` If you give a list of edge specs, then all edges referenced in the list will be rounded: ```openscad-3D - cuboid([100,80,60], rounding=10, edges=[TOP,"Z",BOTTOM+RIGHT]); +cuboid([100,80,60], rounding=10, edges=[TOP,"Z",BOTTOM+RIGHT]); ``` The default value for `edges=` is `EDGES_ALL`, which is all edges. You can also give an `except_edges=` argument that specifies edges to NOT round: ```openscad-3D - cuboid([100,80,60], rounding=10, except_edges=BOTTOM+RIGHT); +cuboid([100,80,60], rounding=10, except_edges=BOTTOM+RIGHT); ``` You can give the `except_edges=` argument any type of argument that you can give to `edges=`: ```openscad-3D - cuboid([100,80,60], rounding=10, except_edges=[BOTTOM,"Z",TOP+RIGHT]); +cuboid([100,80,60], rounding=10, except_edges=[BOTTOM,"Z",TOP+RIGHT]); ``` You can give both `edges=` and `except_edges=`, to simplify edge specs: ```openscad-3D - cuboid([100,80,60], rounding=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); +cuboid([100,80,60], rounding=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); ``` You can specify what edges to chamfer similarly: ```openscad-3D - cuboid([100,80,60], chamfer=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); +cuboid([100,80,60], chamfer=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); ``` @@ -180,37 +180,37 @@ BOSL2 overrides the built-in `cylinder()` module. It still can be used as you expect from the built-in: ```openscad-3D - cylinder(r=50,h=50); +cylinder(r=50,h=50); ``` ```openscad-3D - cylinder(r=50,h=50,center=true); +cylinder(r=50,h=50,center=true); ``` ```openscad-3D - cylinder(d=100,h=50,center=true); +cylinder(d=100,h=50,center=true); ``` ```openscad-3D - cylinder(d1=100,d2=80,h=50,center=true); +cylinder(d1=100,d2=80,h=50,center=true); ``` You can also anchor, spin, orient, and attach like the `cuboid()` module: ```openscad-3D - cylinder(r=50, h=50, anchor=TOP+FRONT); +cylinder(r=50, h=50, anchor=TOP+FRONT); ``` ```openscad-3D - cylinder(r=50, h=50, anchor=BOTTOM+LEFT); +cylinder(r=50, h=50, anchor=BOTTOM+LEFT); ``` ```openscad-3D - cylinder(r=50, h=50, anchor=BOTTOM+LEFT, spin=30); +cylinder(r=50, h=50, anchor=BOTTOM+LEFT, spin=30); ``` ```openscad-3D - cylinder(r=50, h=50, anchor=BOTTOM, orient=UP+BACK+RIGHT); +cylinder(r=50, h=50, anchor=BOTTOM, orient=UP+BACK+RIGHT); ``` @@ -219,55 +219,55 @@ rounding and chamfering of edges. You can use it similarly to `cylinder()`, except that `cyl()` centers the cylinder by default. ```openscad-3D - cyl(r=60, l=100); +cyl(r=60, l=100); ``` ```openscad-3D - cyl(d=100, l=100); +cyl(d=100, l=100); ``` ```openscad-3D - cyl(d=100, l=100, anchor=TOP); +cyl(d=100, l=100, anchor=TOP); ``` You can round the edges with the `rounding=` argument: ```openscad-3D - cyl(d=100, l=100, rounding=20); +cyl(d=100, l=100, rounding=20); ``` Similarly, you can chamfer the edges with the `chamfer=` argument: ```openscad-3D - cyl(d=100, l=100, chamfer=10); +cyl(d=100, l=100, chamfer=10); ``` You can specify rounding and chamfering for each end individually: ```openscad-3D - cyl(d=100, l=100, rounding1=20); +cyl(d=100, l=100, rounding1=20); ``` ```openscad-3D - cyl(d=100, l=100, rounding2=20); +cyl(d=100, l=100, rounding2=20); ``` ```openscad-3D - cyl(d=100, l=100, chamfer1=10); +cyl(d=100, l=100, chamfer1=10); ``` ```openscad-3D - cyl(d=100, l=100, chamfer2=10); +cyl(d=100, l=100, chamfer2=10); ``` You can even mix and match rounding and chamfering: ```openscad-3D - cyl(d=100, l=100, rounding1=20, chamfer2=10); +cyl(d=100, l=100, rounding1=20, chamfer2=10); ``` ```openscad-3D - cyl(d=100, l=100, rounding2=20, chamfer1=10); +cyl(d=100, l=100, rounding2=20, chamfer1=10); ``` @@ -276,26 +276,26 @@ BOSL2 overrides the built-in `sphere()` module. It still can be used as you expect from the built-in: ```openscad-3D - sphere(r=50); +sphere(r=50); ``` ```openscad-3D - sphere(d=100); +sphere(d=100); ``` You can anchor, spin, and orient `sphere()`s, much like you can with `cylinder()` and `cube()`: ```openscad-3D - sphere(d=100, anchor=FRONT); +sphere(d=100, anchor=FRONT); ``` ```openscad-3D - sphere(d=100, anchor=FRONT, spin=30); +sphere(d=100, anchor=FRONT, spin=30); ``` ```openscad-3D - sphere(d=100, anchor=BOTTOM, orient=RIGHT+TOP); +sphere(d=100, anchor=BOTTOM, orient=RIGHT+TOP); ``` BOSL2 also provides `spheroid()`, which enhances `sphere()` with a few features @@ -305,27 +305,27 @@ You can use the `circum=true` argument to force the sphere to circumscribe the ideal sphere, as opposed to the default inscribing: ```openscad-3D - spheroid(d=100, circum=true); +spheroid(d=100, circum=true); ``` The `style=` argument can choose the way that the sphere will be constructed: The "orig" style matches the `sphere()` built-in's construction. ```openscad-3D - spheroid(d=100, style="orig", $fn=20); +spheroid(d=100, style="orig", $fn=20); ``` The "aligned" style will ensure that there is a vertex at each axis extrema, so long as `$fn` is a multiple of 4. ```openscad-3D - spheroid(d=100, style="aligned", $fn=20); +spheroid(d=100, style="aligned", $fn=20); ``` The "stagger" style will stagger the triangulation of the vertical rows: ```openscad-3D - spheroid(d=100, style="stagger", $fn=20); +spheroid(d=100, style="stagger", $fn=20); ``` The "icosa" style will make for roughly equal-sized triangles for the entire @@ -333,7 +333,7 @@ sphere surface, based on subdividing an icosahedron. This style will round the effective `$fn` to a multiple of 5 when constructing the spheroid: ```openscad-3D - spheroid(d=100, style="icosa", $fn=20); +spheroid(d=100, style="icosa", $fn=20); ``` The "octa" style will also make for roughly equal-sized triangles for the entire @@ -342,6 +342,6 @@ guarantees vertices at the axis extrema. This style will round the effective `$ to a multiple of 4 when constructing the spheroid: ```openscad-3D - spheroid(d=100, style="octa", $fn=20); +spheroid(d=100, style="octa", $fn=20); ``` diff --git a/tutorials/Transforms.md b/tutorials/Transforms.md index 137b3e4..8738546 100644 --- a/tutorials/Transforms.md +++ b/tutorials/Transforms.md @@ -14,124 +14,124 @@ just what axis is being moved along, and in which direction. It's also a bit ve frequently used command. For these reasons, BOSL2 provides you with shortcuts for each direction. These shortcuts are `up()`, `down()`, `fwd()`, `back()`, `left()`, and `right()`: ```openscad - #sphere(d=20); - up(30) sphere(d=20); +#sphere(d=20); +up(30) sphere(d=20); ``` ```openscad - #sphere(d=20); - down(30) sphere(d=20); +#sphere(d=20); +down(30) sphere(d=20); ``` ```openscad - #sphere(d=20); - fwd(30) sphere(d=20); +#sphere(d=20); +fwd(30) sphere(d=20); ``` ```openscad - #sphere(d=20); - back(30) sphere(d=20); +#sphere(d=20); +back(30) sphere(d=20); ``` ```openscad - #sphere(d=20); - left(30) sphere(d=20); +#sphere(d=20); +left(30) sphere(d=20); ``` ```openscad - #sphere(d=20); - right(30) sphere(d=20); +#sphere(d=20); +right(30) sphere(d=20); ``` There is also a more generic `move()` command that can work just like `translate()`, or you can specify the motion on each axis more clearly: ```openscad - #sphere(d=20); - move([30,-10]) sphere(d=20); +#sphere(d=20); +move([30,-10]) sphere(d=20); ``` ```openscad - #sphere(d=20); - move(x=30,y=10) sphere(d=20); +#sphere(d=20); +move(x=30,y=10) sphere(d=20); ``` ## Scaling The `scale()` command is also fairly simple: ```openscad - scale(2) cube(10, center=true); +scale(2) cube(10, center=true); ``` ```openscad - scale([1,2,3]) cube(10, center=true); +scale([1,2,3]) cube(10, center=true); ``` If you want to only change the scaling on one axis, though, BOSL2 provides clearer commands to do just that; `xscale()`, `yscale()`, and `zscale()`: ```openscad - xscale(2) cube(10, center=true); +xscale(2) cube(10, center=true); ``` ```openscad - yscale(2) cube(10, center=true); +yscale(2) cube(10, center=true); ``` ```openscad - zscale(2) cube(10, center=true); +zscale(2) cube(10, center=true); ``` ## Rotation The `rotate()` command is fairly straightforward: ```openscad - rotate([0,30,0]) cube(20, center=true); +rotate([0,30,0]) cube(20, center=true); ``` It is also a bit verbose, and can, at a glance, be difficult to tell just how it is rotating. BOSL2 provides shortcuts for rotating around each axis, for clarity; `xrot()`, `yrot()`, and `zrot()`: ```openscad - xrot(30) cube(20, center=true); +xrot(30) cube(20, center=true); ``` ```openscad - yrot(30) cube(20, center=true); +yrot(30) cube(20, center=true); ``` ```openscad - zrot(30) cube(20, center=true); +zrot(30) cube(20, center=true); ``` The `rot()` command is a more generic rotation command, and shorter to type than `rotate()`: ```openscad - rot([0,30,15]) cube(20, center=true); +rot([0,30,15]) cube(20, center=true); ``` All of the rotation shortcuts can take a `cp=` argument, that lets you specify a centerpoint to rotate around: ```openscad - cp = [0,0,40]; - color("blue") move(cp) sphere(d=3); - #cube(20, center=true); - xrot(45, cp=cp) cube(20, center=true); +cp = [0,0,40]; +color("blue") move(cp) sphere(d=3); +#cube(20, center=true); +xrot(45, cp=cp) cube(20, center=true); ``` ```openscad - cp = [0,0,40]; - color("blue") move(cp) sphere(d=3); - #cube(20, center=true); - yrot(45, cp=cp) cube(20, center=true); +cp = [0,0,40]; +color("blue") move(cp) sphere(d=3); +#cube(20, center=true); +yrot(45, cp=cp) cube(20, center=true); ``` ```openscad - cp = [0,40,0]; - color("blue") move(cp) sphere(d=3); - #cube(20, center=true); - zrot(45, cp=cp) cube(20, center=true); +cp = [0,40,0]; +color("blue") move(cp) sphere(d=3); +#cube(20, center=true); +zrot(45, cp=cp) cube(20, center=true); ``` You can also do a new trick with it. You can rotate from pointing in one direction, towards another. You give these directions using vectors: ```openscad - #cylinder(d=10, h=50); - rot(from=[0,0,1], to=[1,0,1]) cylinder(d=10, h=50); +#cylinder(d=10, h=50); +rot(from=[0,0,1], to=[1,0,1]) cylinder(d=10, h=50); ``` There are several direction vectors constants and aliases you can use for clarity: @@ -150,51 +150,51 @@ Constant | Value | Direction This lets you rewrite the above vector rotation more clearly as: ```openscad - #cylinder(d=10, h=50); - rot(from=UP, to=UP+RIGHT) cylinder(d=10, h=50); +#cylinder(d=10, h=50); +rot(from=UP, to=UP+RIGHT) cylinder(d=10, h=50); ``` ## Mirroring The standard `mirror()` command works like this: ```openscad - #yrot(60) cylinder(h=50, d1=20, d2=10); - mirror([1,0,0]) yrot(60) cylinder(h=50, d1=20, d2=10); +#yrot(60) cylinder(h=50, d1=20, d2=10); +mirror([1,0,0]) yrot(60) cylinder(h=50, d1=20, d2=10); ``` BOSL2 provides shortcuts for mirroring across the standard axes; `xflip()`, `yflip()`, and `zflip()`: ```openscad - #yrot(60) cylinder(h=50, d1=20, d2=10); - xflip() yrot(60) cylinder(h=50, d1=20, d2=10); +#yrot(60) cylinder(h=50, d1=20, d2=10); +xflip() yrot(60) cylinder(h=50, d1=20, d2=10); ``` ```openscad - #xrot(60) cylinder(h=50, d1=20, d2=10); - yflip() xrot(60) cylinder(h=50, d1=20, d2=10); +#xrot(60) cylinder(h=50, d1=20, d2=10); +yflip() xrot(60) cylinder(h=50, d1=20, d2=10); ``` ```openscad - #cylinder(h=50, d1=20, d2=10); - zflip() cylinder(h=50, d1=20, d2=10); +#cylinder(h=50, d1=20, d2=10); +zflip() cylinder(h=50, d1=20, d2=10); ``` All of the flip commands can offset where the mirroring is performed: ```openscad - #zrot(30) cube(20, center=true); - xflip(x=-20) zrot(30) cube(20, center=true); - color("blue",0.25) left(20) cube([0.1,50,50], center=true); +#zrot(30) cube(20, center=true); +xflip(x=-20) zrot(30) cube(20, center=true); +color("blue",0.25) left(20) cube([0.1,50,50], center=true); ``` ```openscad - #zrot(30) cube(20, center=true); - yflip(y=20) zrot(30) cube(20, center=true); - color("blue",0.25) back(20) cube([40,0.1,40], center=true); +#zrot(30) cube(20, center=true); +yflip(y=20) zrot(30) cube(20, center=true); +color("blue",0.25) back(20) cube([40,0.1,40], center=true); ``` ```openscad - #xrot(30) cube(20, center=true); - zflip(z=-20) xrot(30) cube(20, center=true); - color("blue",0.25) down(20) cube([40,40,0.1], center=true); +#xrot(30) cube(20, center=true); +zflip(z=-20) xrot(30) cube(20, center=true); +color("blue",0.25) down(20) cube([40,40,0.1], center=true); ```