diff --git a/WRITING_DOCS.md b/WRITING_DOCS.md index ce9bf1e..659813c 100644 --- a/WRITING_DOCS.md +++ b/WRITING_DOCS.md @@ -269,7 +269,7 @@ Which outputs Markdown code that renders like: > The golden ration phi. -The `Module` header is used to document a module. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks: +The `Module` header is used to document a module. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. The Usage sub-block body lines are also used when constructing the Cheat Sheet index file: // Module: cross() // Usage: @@ -306,7 +306,7 @@ Which outputs Markdown code that renders like: > GENERATED IMAGE GOES HERE -The `Function` header is used to document a function. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. By default, Examples will not generate images for function blocks: +The `Function` header is used to document a function. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. By default, Examples will not generate images for function blocks. Usage sub-block body lines are also used when constructing the Cheat Sheet index file: // Function: vector_angle() // Usage: @@ -347,8 +347,7 @@ Which outputs Markdown code that renders like: > // Returns: 45 > ``` -The `Function&Module` header is used to document a function which has a related module of the same name. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. You should have Usage blocks for both calling as a function, and calling as a -module: +The `Function&Module` header is used to document a function which has a related module of the same name. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. You should have Usage blocks for both calling as a function, and calling as a module. Usage sub-block body lines are also used in constructing the Cheat Sheet index file: // Function&Module: oval() // Topics: 2D Shapes, Geometry @@ -464,7 +463,7 @@ Which outputs Markdown code that renders like: Usage Block ----------- -The Usage block describes the various ways that the current function or module can be called, with the names of the arguments. By convention, the first few arguments that can be called positionally just have their name shown. The remaining arguments that should be passed by name, will have the name followed by an `=` (equal sign). Arguments that are optional in the given Usage context are shown in `<` and `>` angle brackets: +The Usage block describes the various ways that the current function or module can be called, with the names of the arguments. By convention, the first few arguments that can be called positionally just have their name shown. The remaining arguments that should be passed by name, will have the name followed by an `=` (equal sign). Arguments that are optional in the given Usage context are shown in `[` and `]` angle brackets. Usage sub-block body lines are also used when constructing the Cheat Sheet index file: // Usage: As a Module // oval(rx, ry, ); @@ -608,7 +607,8 @@ metadata directives: - `Big`: Make the image big sized. - `Huge`: Make the image huge sized. - `Size=880x640`: Make the image 880 by 640 pixels in size. -- `Render`: Force full rendering from OpenSCAD, instead of the normal preview. +- `ThrownTogether`: Render in Thrown Together view mode instead of Preview mode. +- `Render`: Force full rendering from OpenSCAD, instead of the normal Preview mode. - `Edges`: Highlight face edges. - `NoAxes`: Hides the axes and scales. - `NoScales`: Hides the scale numbers along the axes. diff --git a/tutorials/Attachments.md b/tutorials/Attachments.md index 38ba93e..c2adceb 100644 --- a/tutorials/Attachments.md +++ b/tutorials/Attachments.md @@ -17,16 +17,19 @@ corner that will be aligned to. For example, a vector of [1,0,-1] refers to the edge of the shape. Each vector component should be -1, 0, or 1: ```openscad-3D +include // Anchor at upper-front-left corner cube([40,30,50], anchor=[-1,-1,1]); ``` ```openscad-3D +include // Anchor at upper-right edge cube([40,30,50], anchor=[1,0,1]); ``` ```openscad-3D +include // Anchor at bottom face cube([40,30,50], anchor=[0,0,-1]); ``` @@ -49,10 +52,12 @@ constants together like `BOTTOM + LEFT`. Ths will result in a vector of `[-1,0, that to the `anchor=` argument for a clearly understandable anchoring: ```openscad-3D +include cube([40,30,50], anchor=BACK+TOP); ``` ```openscad-3D +include cube([40,30,50], anchor=FRONT); ``` @@ -65,14 +70,17 @@ These combined let you point at any place on the bottom or top rims, or at an ar side wall: ```openscad-3D +include cylinder(r1=25, r2=15, h=60, anchor=TOP+LEFT); ``` ```openscad-3D +include cylinder(r1=25, r2=15, h=60, anchor=BOTTOM+FRONT); ``` ```openscad-3D +include cylinder(r1=25, r2=15, h=60, anchor=UP+spherical_to_xyz(1,30,90)); ``` @@ -82,14 +90,17 @@ For Spherical type attachables, you can pass a vector that points at any arbitra the surface of the sphere: ```openscad-3D +include sphere(r=50, anchor=TOP); ``` ```openscad-3D +include sphere(r=50, anchor=TOP+FRONT); ``` ```openscad-3D +include sphere(r=50, anchor=spherical_to_xyz(1,-30,60)); ``` @@ -100,6 +111,7 @@ will be given as strings and will be specific to that type of attachable. For e `teardrop()` attachable has a named anchor called "cap": ```openscad-3D +include teardrop(d=100, l=20, anchor="cap"); ``` @@ -111,10 +123,12 @@ A `center=false` argument can mean `anchor=[-1,-1,-1]` for a cube, or `anchor=BO cylinder, to make them behave just like the builtin versions: ```openscad-3D +include cube([50,40,30],center=true); ``` ```openscad-3D +include cube([50,40,30],center=false); ``` @@ -125,18 +139,22 @@ modules have been overridden to enable attachability and anchoring. The `anchor shapes can accept 3D vectors, but only the X and Y components will be used: ```openscad-2D +include square([40,30], anchor=BACK+LEFT); ``` ```openscad-2D +include circle(d=50, anchor=BACK); ``` ```openscad-2D +include hexagon(d=50, anchor=LEFT); ``` ```openscad-2D +include ellipse(d=[50,30], anchor=FRONT); ``` @@ -148,6 +166,7 @@ clockwise spin around the Z axis (as seen from above), and a negative number wil spin: ```openscad-3D +include cube([20,20,40], center=true, spin=45); ``` @@ -156,16 +175,19 @@ You can even spin around each of the three axes in one pass, by giving 3 angles the order given, X-axis spin, then Y-axis, then Z-axis: ```openscad-3D +include cube([20,20,40], center=true, spin=[10,20,30]); ``` You can also apply spin to 2D shapes from BOSL2, though only by scalar angle: ```openscad-2D +include square([40,30], spin=30); ``` ```openscad-2D +include ellipse(d=[40,30], spin=30); ``` @@ -176,6 +198,7 @@ Another way to specify a rotation for an attachable shape, is to pass a 3D vecto For example, you can make a cone that is tilted up and to the right like this: ```openscad-3D +include cylinder(h=100, r1=50, r2=20, orient=UP+RIGHT); ``` @@ -187,24 +210,28 @@ When giving `anchor=`, `spin=`, and `orient=`, they are applied anchoring first, then orient last. For example, here's a cube: ```openscad-3D +include cube([20,20,50]); ``` You can center it with an `anchor=CENTER` argument: ```openscad-3D +include cube([20,20,50], anchor=CENTER); ``` Add a 45 degree spin: ```openscad-3D +include cube([20,20,50], anchor=CENTER, spin=45); ``` Now tilt the top up and forward: ```openscad-3D +include cube([20,20,50], anchor=CENTER, spin=45, orient=UP+FWD); ``` @@ -212,12 +239,14 @@ Something that may confuse new users is that adding spin to a cylinder may seem However, since spin is applied *after* anchoring, it can actually have a significant effect: ```openscad-3D +include cylinder(d=50, l=40, anchor=FWD, spin=-30); ``` For 2D shapes, you can mix `anchor=` with `spin=`, but not with `orient=`. ```openscad-2D +include square([40,30], anchor=BACK+LEFT, spin=30); ``` @@ -228,6 +257,7 @@ You can do that by making one attachable shape be a child of another attachable By default, the child of an attachable is attached to the center of the parent shape. ```openscad-3D +include cube(50,center=true) cylinder(d1=50,d2=20,l=50); ``` @@ -237,6 +267,7 @@ this will attach the bottom of the child to the given position on the parent. T of the child will be overridden to point outwards from the center of the parent, more or less: ```openscad-3D +include cube(50,center=true) attach(TOP) cylinder(d1=50,d2=20,l=20); ``` @@ -245,6 +276,7 @@ If you give `attach()` a second anchor argument, it attaches that anchor on the first anchor on the parent: ```openscad-3D +include cube(50,center=true) attach(TOP,TOP) cylinder(d1=50,d2=20,l=20); ``` @@ -255,12 +287,14 @@ it's useful to have the child overlap the parent by insetting a bit. You can do a negative value will outset out from the parent: ```openscad-3D +include cube(50,center=true) attach(TOP,overlap=10) cylinder(d=20,l=20); ``` ```openscad-3D +include cube(50,center=true) attach(TOP,overlap=-20) cylinder(d=20,l=20); @@ -270,6 +304,7 @@ If you want to position the child at the parent's anchorpoint, without re-orient use the `position()` module: ```openscad-3D +include cube(50,center=true) position(RIGHT) cylinder(d1=50,d2=20,l=20); ``` @@ -277,6 +312,7 @@ cube(50,center=true) You can attach or position more than one child at a time by enclosing them all in braces: ```openscad-3D +include cube(50, center=true) { attach(TOP) cylinder(d1=50,d2=20,l=20); position(RIGHT) cylinder(d1=50,d2=20,l=20); @@ -287,11 +323,13 @@ If you want to attach the same shape to multiple places on the same parent, you desired anchors as a list to the `attach()` or `position()` modules: ```openscad-3D +include cube(50, center=true) attach([RIGHT,FRONT],TOP) cylinder(d1=50,d2=20,l=20); ``` ```openscad-3D +include cube(50, center=true) position([TOP,RIGHT,FRONT]) cylinder(d1=50,d2=20,l=20); ``` @@ -300,12 +338,14 @@ cube(50, center=true) You can use attachments in 2D as well, but only in the XY plane: ```openscad-2D +include square(50,center=true) attach(RIGHT,FRONT) trapezoid(w1=30,w2=0,h=30); ``` ```openscad-2D +include circle(d=50) attach(BACK,FRONT,overlap=5) trapezoid(w1=30,w2=0,h=30); @@ -316,6 +356,7 @@ One way that is useful to show the position and orientation of an anchorpoint is an anchor arrow to that anchor. ```openscad-3D +include cube(40, center=true) attach(LEFT+TOP) anchor_arrow(); @@ -324,6 +365,7 @@ cube(40, center=true) For large objects, you can change the size of the arrow with the `s=` argument. ```openscad-3D +include sphere(d=100) attach(LEFT+TOP) anchor_arrow(s=30); @@ -332,16 +374,19 @@ sphere(d=100) To show all the standard cardinal anchorpoints, you can use the `show_anchors()` module. ```openscad-3D +include cube(40, center=true) show_anchors(); ``` ```openscad-3D +include cylinder(h=40, d=40, center=true) show_anchors(); ``` ```openscad-3D +include sphere(d=40) show_anchors(); ``` @@ -349,6 +394,7 @@ sphere(d=40) For large objects, you can again change the size of the arrows with the `s=` argument. ```openscad-3D +include cylinder(h=100, d=100, center=true) show_anchors(s=30); ``` @@ -369,6 +415,7 @@ For example, to difference away a child cylinder from the middle of a parent cub do this: ```openscad-3D +include diff("hole") cube(100, center=true) cylinder(h=101, d=50, center=true, $tags="hole"); @@ -379,6 +426,7 @@ given to `neg=` will be differenced away from the shapes marked with tags given Everything else will be unioned to the result. ```openscad-3D +include diff("hole", "post") cube(100, center=true) attach([RIGHT,TOP]) { @@ -390,6 +438,7 @@ cube(100, center=true) The `keep=` argument takes tags for shapes that you want to keep in the output. ```openscad-3D +include diff("dish", keep="antenna") cube(100, center=true) attach([FRONT,TOP], overlap=33) { @@ -401,6 +450,7 @@ cube(100, center=true) If you need to mark multiple children with a tag, you can use the `tags()` module. ```openscad-3D +include diff("hole") cube(100, center=true) attach([FRONT,TOP], overlap=20) @@ -414,6 +464,7 @@ The parent object can be differenced away from other shapes. Tags are inherited though, so you will need to set the tags of the children as well as the parent. ```openscad-3D +include diff("hole") cube([20,11,45], center=true, $tags="hole") cube([40,10,90], center=true, $tags="body"); @@ -429,6 +480,7 @@ To allow you to use tags-based operations with non-attachable shapes, you can wr `tags()` module to specify their tags. For example: ```openscad-3D +include diff("hole") cuboid(50) attach(TOP) @@ -445,6 +497,7 @@ argument to `a=`, the parent and all children *not* tagged with that will be int everything that *is* tagged with it. ```openscad-3D +include intersect("bounds") cube(100, center=true) cylinder(h=100, d1=120, d2=95, center=true, $fn=72, $tags="bounds"); @@ -454,6 +507,7 @@ If given both the `a=` and `b=` arguments, then shapes marked with tags given to intersected with shapes marked with tags given to `b=`, then unioned with all other shapes. ```openscad-3D +include intersect("pole", "cap") cube(100, center=true) attach([TOP,RIGHT]) { @@ -466,6 +520,7 @@ If the `keep=` argument is given, anything marked with tags passed to it will be the result of the union: ```openscad-3D +include intersect("bounds", keep="pole") cube(100, center=true) { cylinder(h=100, d1=120, d2=95, center=true, $fn=72, $tags="bounds"); @@ -478,6 +533,7 @@ You can use the `hulling()` module to hull shapes marked with a given tag togeth unioning the result with every other shape. ```openscad-3D +include hulling("hull") cube(50, center=true, $tags="hull") { cyl(h=100, d=20); @@ -498,6 +554,7 @@ edges. The shape will be tagged as a "mask" so that you can use `diff("mask")`. here's a shape for rounding an edge: ```openscad-3D +include module round_edge(l,r) difference() { translate([-1,-1,-l/2]) cube([r+1,r+1,l]); @@ -510,6 +567,7 @@ round_edge(l=30, r=19); You can use that mask to round various edges of a cube: ```openscad-3D +include module round_edge(l,r) difference() { translate([-1,-1,-l/2]) cube([r+1,r+1,l]); @@ -530,6 +588,7 @@ will be tagged as a "mask" so that you can use `diff("mask")`. For example, her rounding a corner: ```openscad-3D +include module round_corner(r) difference() { translate(-[1,1,1]) cube(r+1); @@ -542,6 +601,7 @@ round_corner(r=10); You can use that mask to round various corners of a cube: ```openscad-3D +include module round_corner(r) difference() { translate(-[1,1,1]) cube(r+1); @@ -558,6 +618,7 @@ cube([50,60,70],center=true) You can use `edge_mask()` and `corner_mask()` together as well: ```openscad-3D +include module round_corner(r) difference() { translate(-[1,1,1]) cube(r+1); @@ -593,12 +654,14 @@ re-oriented towards the edges of the parent shape. A typical mask profile for c edge may look like: ```openscad-2D +include mask2d_roundover(10); ``` Using that mask profile, you can mask the edges of a cube like: ```openscad-3D +include diff("mask") cube([50,60,70],center=true) edge_profile("ALL") @@ -609,6 +672,7 @@ cube([50,60,70],center=true) You can use the same profile to make a rounded corner mask as well: ```openscad-3D +include diff("mask") cube([50,60,70],center=true) corner_profile("ALL", r=10) @@ -620,6 +684,7 @@ As a simple shortcut to apply a profile mask to all edges and corners of a face, `face_profile()` module: ```openscad-3D +include diff("mask") cube([50,60,70],center=true) face_profile(TOP, r=10) @@ -632,6 +697,7 @@ Usually, when coloring a shape with the `color()` module, the parent color overr all children. This is often not what you want: ```openscad-3D +include $fn = 24; color("red") spheroid(d=3) { attach(CENTER,BOT) color("white") cyl(h=10, d=1) { @@ -644,6 +710,7 @@ If you use the `recolor()` module, however, the child's color overrides the colo This is probably easier to understand by example: ```openscad-3D +include $fn = 24; recolor("red") spheroid(d=3) { attach(CENTER,BOT) recolor("white") cyl(h=10, d=1) { @@ -667,6 +734,7 @@ In the most basic form, where the shape is fully cuboid, with top and bottom of and directly over one another, you can just use `size=`. ```openscad-3D +include module cubic_barbell(s=100, anchor=CENTER, spin=0, orient=UP) { attachable(anchor,spin,orient, size=[s*3,s,s]) { union() { @@ -684,6 +752,7 @@ the `size2=` argument as well. While `size=` takes all three axes sizes, the `si only takes the [X,Y] sizes of the top of the shape. ```openscad-3D +include module prismoidal(size=[100,100,100], scale=0.5, anchor=CENTER, spin=0, orient=UP) { attachable(anchor,spin,orient, size=size, size2=[size.x, size.y]*scale) { hull() { @@ -705,6 +774,7 @@ the `shift=` argument. The `shift=` argument takes an [X,Y] vector of the offse of the top from the XY center of the bottom of the shape. ```openscad-3D +include module prismoidal(size=[100,100,100], scale=0.5, shift=[0,0], anchor=CENTER, spin=0, orient=UP) { attachable(anchor,spin,orient, size=size, size2=[size.x, size.y]*scale, shift=shift) { hull() { @@ -726,6 +796,7 @@ arguments should refer to a plane other than XY) you can use the `axis=` argumen you make prismoids naturally oriented forwards/backwards or sideways. ```openscad-3D +include module yprismoidal( size=[100,100,100], scale=0.5, shift=[0,0], anchor=CENTER, spin=0, orient=UP @@ -754,6 +825,7 @@ yprismoidal([100,60,30], scale=1.5, shift=[20,20]) show_anchors(20); To make a cylindrical shape attachable, you use the `l`, and `r`/`d`, args of `attachable()`. ```openscad-3D +include module twistar(l,r,d, anchor=CENTER, spin=0, orient=UP) { r = get_radius(r=r,d=d,dflt=1); attachable(anchor,spin,orient, r=r, l=l) { @@ -769,6 +841,7 @@ If the cylinder is elipsoidal in shape, you can pass the inequal X/Y sizes as a to the `r=` or `d=` argument. ```openscad-3D +include module ovalstar(l,rx,ry, anchor=CENTER, spin=0, orient=UP) { attachable(anchor,spin,orient, r=[rx,ry], l=l) { linear_extrude(height=l, center=true, convexity=4) @@ -783,6 +856,7 @@ ovalstar(l=100, rx=50, ry=30) show_anchors(20); For cylindrical shapes that arent oriented vertically, use the `axis=` argument. ```openscad-3D +include module ytwistar(l,r,d, anchor=CENTER, spin=0, orient=UP) { r = get_radius(r=r,d=d,dflt=1); attachable(anchor,spin,orient, r=r, l=l, axis=BACK) { @@ -800,6 +874,7 @@ To make a conical shape attachable, you use the `l`, `r1`/`d1`, and `r2`/`d2`, a `attachable()`. ```openscad-3D +include module twistar(l, r,r1,r2, d,d1,d2, anchor=CENTER, spin=0, orient=UP) { r1 = get_radius(r1=r1,r=r,d1=d1,d=d,dflt=1); r2 = get_radius(r1=r2,r=r,d1=d2,d=d,dflt=1); @@ -816,6 +891,7 @@ If the cone is ellipsoidal in shape, you can pass the inequal X/Y sizes as a 2-i to the `r1=`/`r2=` or `d1=`/`d2=` arguments. ```openscad-3D +include module ovalish(l,rx1,ry1,rx2,ry2, anchor=CENTER, spin=0, orient=UP) { attachable(anchor,spin,orient, r1=[rx1,ry1], r2=[rx2,ry2], l=l) { hull() { @@ -836,6 +912,7 @@ For conical shapes that are not oriented vertically, use the `axis=` argument to direction of the primary shape axis: ```openscad-3D +include module ytwistar(l, r,r1,r2, d,d1,d2, anchor=CENTER, spin=0, orient=UP) { r1 = get_radius(r1=r1,r=r,d1=d1,d=d,dflt=1); r2 = get_radius(r1=r2,r=r,d1=d2,d=d,dflt=1); @@ -853,6 +930,7 @@ ytwistar(l=100, r1=40, r2=20) show_anchors(20); To make a spherical shape attachable, you use the `r`/`d` args of `attachable()`. ```openscad-3D +include module spikeball(r, d, anchor=CENTER, spin=0, orient=UP) { r = get_radius(r=r,d=d,dflt=1); attachable(anchor,spin,orient, r=r*1.1) { @@ -869,6 +947,7 @@ spikeball(r=50) show_anchors(20); If the shape is more of an ovoid, you can pass a 3-item vector of sizes to `r=` or `d=`. ```openscad-3D +include module spikeball(r, d, scale, anchor=CENTER, spin=0, orient=UP) { r = get_radius(r=r,d=d,dflt=1); attachable(anchor,spin,orient, r=r*1.1*scale) { @@ -892,6 +971,7 @@ to the furthest distance that intersects with the VNF shape. The anchorpoint is center of the points that still intersect that plane. ```openscad-FlatSpin,VPD=500 +include module stellate_cube(s=100, anchor=CENTER, spin=0, orient=UP) { s2 = 3 * s; verts = [ @@ -929,6 +1009,7 @@ face at the intersection. If the intersection is at an edge or corner, then the will bisect the angles between the faces. ```openscad-VPD=1250 +include module stellate_cube(s=100, anchor=CENTER, spin=0, orient=UP) { s2 = 3 * s; verts = [ @@ -956,6 +1037,7 @@ stellate_cube() show_anchors(50); ``` ```openscad-3D +include $fn=32; R = difference(circle(10), right(2, circle(9))); linear_sweep(R,height=10,atype="hull") @@ -980,6 +1062,7 @@ To make a simple attachable shape similar to a `teardrop()` that provides a "cap define it like this: ```openscad-3D +include module raindrop(r, thick, anchor=CENTER, spin=0, orient=UP) { anchors = [ named_anchor("cap", [0,r/sin(45),0], BACK, 0) @@ -998,6 +1081,7 @@ raindrop(r=25, thick=20, anchor="cap"); If you want multiple named anchors, just add them to the list of anchors: ```openscad-FlatSpin,VPD=150 +include module raindrop(r, thick, anchor=CENTER, spin=0, orient=UP) { anchors = [ named_anchor("captop", [0,r/sin(45), thick/2], BACK+UP, 0), diff --git a/tutorials/Distributors.md b/tutorials/Distributors.md index a1a7c2f..2d06b40 100644 --- a/tutorials/Distributors.md +++ b/tutorials/Distributors.md @@ -29,6 +29,7 @@ Using `xcopies()`, you can make a line of evenly spaced copies of a shape centered along the X axis. To make a line of 5 spheres, spaced every 20 units along the X axis, do: ```openscad-2D +include xcopies(20, n=5) sphere(d=10); ``` Note that the first expected argument to `xcopies()` is the spacing argument, @@ -38,26 +39,31 @@ Similarly, `ycopies()` makes a line of evenly spaced copies centered along the Y axis. To make a line of 5 spheres, spaced every 20 units along the Y axis, do: ```openscad-2D +include ycopies(20, n=5) sphere(d=10); ``` And, `zcopies()` makes a line of evenly spaced copies centered along the Z axis. To make a line of 5 spheres, spaced every 20 units along the Z axis, do: -```openscad +```openscad-3D +include zcopies(20, n=5) sphere(d=10); ``` If you don't give the `n=` argument to `xcopies()`, `ycopies()` or `zcopies()`, then it defaults to 2 (two) copies. This actually is the most common usage: ```openscad-2D +include xcopies(20) sphere(d=10); ``` ```openscad-2D +include ycopies(20) sphere(d=10); ``` -```openscad +```openscad-3D +include zcopies(20) sphere(d=10); ``` @@ -65,14 +71,17 @@ If you don't know the spacing you want, but instead know how long a line you want the copies distributed over, you can use the `l=` argument instead of the `spacing=` argument: ```openscad-2D +include xcopies(l=100, n=5) sphere(d=10); ``` ```openscad-2D +include ycopies(l=100, n=5) sphere(d=10); ``` -```openscad +```openscad-3D +include zcopies(l=100, n=5) sphere(d=10); ``` @@ -80,34 +89,40 @@ If you don't want the line of copies centered on the origin, you can give a starting point `sp=`, and the line of copies will start there. For `xcopies()`, the line of copies will extend to the right of the starting point. ```openscad-2D +include xcopies(20, n=5, sp=[0,0,0]) sphere(d=10); ``` For `ycopies()`, the line of copies will extend to the back of the starting point. ```openscad-2D +include ycopies(20, n=5, sp=[0,0,0]) sphere(d=10); ``` For `zcopies()`, the line of copies will extend upwards from the starting point. -```openscad +```openscad-3D +include zcopies(20, n=5, sp=[0,0,0]) sphere(d=10); ``` If you need to distribute copies along an arbitrary line, you can use the `line_of()` command. You can give both the direction vector and the spacing of the line of copies with the `spacing=` argument: -```openscad +```openscad-3D +include line_of(spacing=(BACK+RIGHT)*20, n=5) sphere(d=10); ``` With the `p1=` argument, you can specify the starting point of the line: -```openscad +```openscad-3D +include line_of(spacing=(BACK+RIGHT)*20, n=5, p1=[0,0,0]) sphere(d=10); ``` If you give both `p1=` and `p2=`, you can nail down both the start and endpoints of the line of copies: ```openscad-2D +include line_of(p1=[0,100,0], p2=[100,0,0], n=4) sphere(d=10); ``` @@ -115,22 +130,26 @@ line_of(p1=[0,100,0], p2=[100,0,0], n=4) The `grid2d()` command will let you spread copies across both the X and Y axes at the same time: ```openscad-2D +include grid2d(20, n=6) sphere(d=10); ``` The spacing can be separately specified for both the X and Y axes, as can the count of rows and columns: ```openscad-2D +include grid2d([20,30], n=[6,4]) sphere(d=10); ``` Another neat trick of `grid2d()`, is that you can stagger the output: ```openscad-2D +include grid2d(20, n=[12,6], stagger=true) sphere(d=10); ``` You can get the alternate stagger pattern if you set `stagger="alt"`: ```openscad-2D +include grid2d(20, n=[12,6], stagger="alt") sphere(d=10); ``` @@ -139,32 +158,39 @@ you a hexagonal grid, with the spacing being the distance from an item to all six of the surrounding items. If you give the spacing as a 2-item vector, then that will force the X and Y spacings between columns and rows instead. ```openscad-2D +include grid2d([20,20], n=6, stagger=true) sphere(d=10); ``` You can alternately specify a grid using size and spacing: ```openscad-2D +include grid2d(20, size=100) sphere(d=10); ``` ```openscad-2D +include grid2d(20, size=[100,80]) sphere(d=10); ``` ```openscad-2D +include grid2d(20, size=[100,80], stagger=true) sphere(d=10); ``` You can also make grids by specifying size and column/row count: ```openscad-2D +include grid2d(n=5, size=100) sphere(d=10); ``` ```openscad-2D +include grid2d(n=[4,5], size=100) sphere(d=10); ``` ```openscad-2D +include grid2d(n=[4,5], size=[100,80]) sphere(d=10); ``` @@ -172,7 +198,8 @@ Finally, the `grid2d()` command will let you give a polygon or region shape to fill with items. Only the items in the grid whose center would be inside the polygon or region will be created. To fill a star shape with items, you can do something like: -```openscad +```openscad-3D +include poly = [for (i=[0:11]) polar_to_xy(50*(i%2+1), i*360/12-90)]; grid2d(5, stagger=true, inside=poly) { cylinder(d=4,h=10,spin=90,$fn=6); @@ -182,7 +209,8 @@ grid2d(5, stagger=true, inside=poly) { ### Rotational Distributors You can make six copies of a cone, rotated around a center: -```openscad +```openscad-3D +include zrot_copies(n=6) yrot(90) cylinder(h=50,d1=0,d2=20); ``` diff --git a/tutorials/FractalTree.md b/tutorials/FractalTree.md index 67011ed..f2d5b01 100644 --- a/tutorials/FractalTree.md +++ b/tutorials/FractalTree.md @@ -6,7 +6,7 @@ Firstoff, include the BOSL2 library, then make a starting module that just has a tapered cylinder for the tree trunk. -```openscad +```openscad-3D include module tree(l=1500, sc=0.7) cylinder(l=l, d1=l/5, d2=l/5*sc); @@ -17,7 +17,7 @@ tree(); You can attach a branch to the top of the trunk by using `attach()` as a child of the trunk cylinder. -```openscad +```openscad-3D include module tree(l=1500, sc=0.7) cylinder(l=l, d1=l/5, d2=l/5*sc) @@ -30,7 +30,7 @@ tree(); Instead of attaching each branch individually, you can make multiple copies of one branch, that are rotated relative to each other. -```openscad +```openscad-3D include module tree(l=1500, sc=0.7) cylinder(l=l, d1=l/5, d2=l/5*sc) @@ -118,3 +118,4 @@ module tree(l=1500, sc=0.7, depth=10) tree(); ``` + diff --git a/tutorials/Mutators.md b/tutorials/Mutators.md index 276b62a..a2730be 100644 --- a/tutorials/Mutators.md +++ b/tutorials/Mutators.md @@ -6,51 +6,62 @@ 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 +```openscad-3D +include left_half() sphere(d=100); ``` -```openscad +```openscad-3D +include right_half() sphere(d=100); ``` -```openscad +```openscad-3D +include front_half() sphere(d=100); ``` -```openscad +```openscad-3D +include back_half() sphere(d=100); ``` -```openscad +```openscad-3D +include bottom_half() sphere(d=100); ``` -```openscad +```openscad-3D +include 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 +```openscad-3D +include half_of([-1,0,-1]) sphere(d=100); ``` The plane of dissection can be shifted along the axis of any of these operators: -```openscad +```openscad-3D +include left_half(x=20) sphere(d=100); ``` -```openscad +```openscad-3D +include back_half(y=-20) sphere(d=100); ``` -```openscad +```openscad-3D +include bottom_half(z=20) sphere(d=100); ``` -```openscad +```openscad-3D +include half_of([-1,0,-1], cp=[20,0,20]) sphere(d=100); ``` @@ -58,33 +69,39 @@ By default, these operators can be applied to objects that fit in a cube 1000 on to apply these halving operators to objects larger than this, you can give the size in the `s=` argument: -```openscad +```openscad-3D +include 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 +```openscad-3D +include left_half(planar=true) circle(d=100); ``` -```openscad +```openscad-3D +include right_half(planar=true) circle(d=100); ``` -```openscad +```openscad-3D +include front_half(planar=true) circle(d=100); ``` -```openscad +```openscad-3D +include 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 +```openscad-3D +include chain_hull() { cube(5, center=true); translate([30, 0, 0]) sphere(d=15); @@ -96,20 +113,23 @@ chain_hull() { ## Extrusion Mutators The OpenSCAD `linear_extrude()` module can take a 2D shape and extrude it vertically in a line: -```openscad +```openscad-3D +include 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 +```openscad-3D +include 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 +```openscad-3D +include cylindrical_extrude(or=40, ir=35) text(text="Hello World!", size=10, halign="center", valign="center"); ``` @@ -120,7 +140,8 @@ cylindrical_extrude(or=40, ir=35) ### Minkowski Difference Openscad provides the `minkowski()` module to trace a shape over the entire surface of another shape: -```openscad +```openscad-3D +include minkowski() { union() { cube([100,33,33], center=true); @@ -134,7 +155,8 @@ minkowski() { 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 +```openscad-3D +include minkowski_difference() { union() { cube([100,33,33], center=true); @@ -148,6 +170,7 @@ minkowski_difference() { To perform a `minkowski_difference()` on 2D shapes, you need to supply the `planar=true` argument: ```openscad-2D +include minkowski_difference(planar=true) { union() { square([100,33], center=true); @@ -161,20 +184,24 @@ minkowski_difference(planar=true) { 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 +include round2d(or=8) star(6, step=2, d=100); ``` ```openscad-2D +include round2d(ir=12) star(6, step=2, d=100); ``` ```openscad-2D +include 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 +include round2d(r=8) star(6, step=2, d=100); ``` @@ -183,6 +210,7 @@ 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 +include shell2d(thickness=5) star(5,step=2,d=100); color("blue") stroke(star(5,step=2,d=100),closed=true); ``` @@ -190,6 +218,7 @@ 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 +include shell2d(thickness=-5) star(5,step=2,d=100); color("blue") stroke(star(5,step=2,d=100),closed=true); ``` @@ -197,6 +226,7 @@ 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 +include shell2d(thickness=[-5,5]) star(5,step=2,d=100); color("blue") stroke(star(5,step=2,d=100),closed=true); ``` @@ -204,40 +234,47 @@ 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 +include 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 +include 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 +include 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 +include 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 +include 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 +include shell2d(thickness=-5,or=[7,2],ir=[7,2]) star(5,step=2,d=100); ``` ```openscad-2D +include shell2d(thickness=-5,or=[5,0],ir=[5,0]) star(5,step=2,d=100); ``` @@ -252,7 +289,8 @@ The built-in OpenSCAD `color()` module can let you set the RGB color of an objec easier to select colors using other color schemes. You can use the HSL or Hue-Saturation-Lightness color scheme with the `HSL()` module: -```openscad +```openscad-3D +include n = 10; size = 100/n; for (a=count(n), b=count(n), c=count(n)) { let( h=360*a/n, s=1-b/(n-1), l=c/(n-1)) @@ -264,7 +302,8 @@ for (a=count(n), b=count(n), c=count(n)) { You can use the HSV or Hue-Saturation-Value color scheme with the `HSV()` module: -```openscad +```openscad-3D +include n = 10; size = 100/n; for (a=count(n), b=count(n), c=count(n)) { let( h=360*a/n, s=1-b/(n-1), v=c/(n-1)) diff --git a/tutorials/Paths.md b/tutorials/Paths.md index b31de3e..a147707 100644 --- a/tutorials/Paths.md +++ b/tutorials/Paths.md @@ -6,8 +6,8 @@ A number of advanced features in BOSL2 rely on paths, which are just ordered lists of points. First-off, some terminology: -- A 2D point is a vectors of X and Y axis position values. ie: `[3,4]` or `[7,-3]`. -- A 3D point is a vectors of X, Y and Z axis position values. ie: `[3,4,2]` or `[-7,5,3]`. +- A 2D point is a vector of X and Y axis position values. ie: `[3,4]` or `[7,-3]`. +- A 3D point is a vector of X, Y and Z axis position values. ie: `[3,4,2]` or `[-7,5,3]`. - A 2D path is simply a list of two or more 2D points. ie: `[[5,7], [1,-5], [-5,6]]` - A 3D path is simply a list of two or more 3D points. ie: `[[5,7,-1], [1,-5,3], [-5,6,1]]` - A polygon is a 2D (or planar 3D) path where the last point is assumed to connect to the first point. @@ -18,6 +18,7 @@ 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 +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; polygon(path); ``` @@ -26,6 +27,7 @@ Sometimes, however, it's easier to see just the path itself. For this, you can At its most basic, `stroke()` just shows the path's line segments: ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path); ``` @@ -33,6 +35,7 @@ stroke(path); You can vary the width of the drawn path with the `width=` argument: ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, width=3); ``` @@ -40,6 +43,7 @@ stroke(path, width=3); You can vary the line length along the path by giving a list of widths, one per point: ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, width=[3,2,1,2,3]); ``` @@ -47,6 +51,7 @@ 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 +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, closed=true); ``` @@ -54,26 +59,31 @@ stroke(path, closed=true); The ends of the drawn path are normally capped with a "round" endcap, but there are other options: ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcaps="round"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcaps="butt"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcaps="line"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcaps="tail"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcaps="arrow2"); ``` @@ -83,16 +93,19 @@ 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 +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcap2="arrow2"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcap1="butt", endcap2="arrow2"); ``` ```openscad-2D +include path = [[0,0], [-10,10], [0,20], [10,20], [10,10]]; stroke(path, endcap1="tail", endcap2="arrow"); ``` @@ -100,6 +113,7 @@ 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 +include 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"); @@ -114,6 +128,7 @@ line width size. Untrimmed: ```openscad-2D +include 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); @@ -122,6 +137,7 @@ stroke(path, endcaps=dblarrow); Trimmed: ```openscad-2D +include 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); @@ -131,36 +147,43 @@ stroke(path, trim=3.5, endcaps=dblarrow); 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 +include path = square(40, center=true); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = rect([40,30], rounding=5); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = trapezoid(w1=40, w2=20, h=30); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = circle(d=50); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = ellipse(d=[50,30]); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = pentagon(d=50); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = star(n=5, step=2, d=50); stroke(path, closed=true, endcap2="arrow2"); ``` @@ -169,11 +192,13 @@ stroke(path, closed=true, endcap2="arrow2"); Often, when you are constructing a path, you will want to add an arc. The `arc()` command lets you do that: ```openscad-2D +include path = arc(r=30, angle=120); stroke(path, endcap2="arrow2"); ``` ```openscad-2D +include path = arc(d=60, angle=120); stroke(path, endcap2="arrow2"); ``` @@ -181,6 +206,7 @@ stroke(path, endcap2="arrow2"); If you give the `N=` argument, you can control exactly how many points the arc is divided into: ```openscad-2D +include path = arc(N=5, r=30, angle=120); stroke(path, endcap2="arrow2"); ``` @@ -188,6 +214,7 @@ stroke(path, endcap2="arrow2"); With the `start=` argument, you can start the arc somewhere other than the X+ axis: ```openscad-2D +include path = arc(start=45, r=30, angle=120); stroke(path, endcap2="arrow2"); ``` @@ -195,6 +222,7 @@ stroke(path, endcap2="arrow2"); Alternatively, you can give starting and ending angles in a list in the `angle=` argument: ```openscad-2D +include path = arc(angle=[120,45], r=30); stroke(path, endcap2="arrow2"); ``` @@ -202,6 +230,7 @@ stroke(path, endcap2="arrow2"); The `cp=` argument lets you center the arc somewhere other than the origin: ```openscad-2D +include path = arc(cp=[10,0], r=30, angle=120); stroke(path, endcap2="arrow2"); ``` @@ -209,6 +238,7 @@ stroke(path, endcap2="arrow2"); The arc can also be given by three points on the arc: ```openscad-2D +include pts = [[-15,10],[0,20],[35,-5]]; path = arc(points=pts); stroke(path, endcap2="arrow2"); @@ -222,6 +252,7 @@ turtle or cursor walking a path. It can "move" forward or backward, or turn "le place: ```openscad-2D +include path = turtle([ "move", 10, "left", 90, @@ -240,6 +271,7 @@ The position and the facing of the turtle/cursor updates after each command. Th commands can also have default distances or angles given: ```openscad-2D +include path = turtle([ "angle",360/6, "length",10, @@ -255,6 +287,7 @@ stroke(path, endcap2="arrow2"); You can use "scale" to relatively scale up the default motion length: ```openscad-2D +include path = turtle([ "angle",360/6, "length",10, @@ -272,6 +305,7 @@ stroke(path, endcap2="arrow2"); Sequences of commands can be repeated using the "repeat" command: ```openscad-2D +include path=turtle([ "angle",360/5, "length",10, @@ -283,6 +317,7 @@ stroke(path, endcap2="arrow2"); More complicated commands also exist, including those that form arcs: ```openscad-2D +include path = turtle([ "move", 10, "left", 90, @@ -299,16 +334,19 @@ 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 +include path = move([-15,-30], p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = fwd(30, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = left(30, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` @@ -316,16 +354,19 @@ 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 +include path = scale([1.5,0.75], p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = xscale(1.5, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = yscale(1.5, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` @@ -333,11 +374,13 @@ 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 +include path = rot(30, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = zrot(30, p=square(50,center=true)); stroke(path, closed=true, endcap2="arrow2"); ``` @@ -345,16 +388,19 @@ 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 +include path = mirror([1,1], p=trapezoid(w1=40, w2=10, h=25)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = xflip(p=trapezoid(w1=40, w2=10, h=25)); stroke(path, closed=true, endcap2="arrow2"); ``` ```openscad-2D +include path = yflip(p=trapezoid(w1=40, w2=10, h=25)); stroke(path, closed=true, endcap2="arrow2"); ``` @@ -362,16 +408,19 @@ 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 +include mat = move([5,10,0]); multmatrix(mat) square(50,center=true); ``` ```openscad-2D +include mat = scale([1.5,0.75,1]); multmatrix(mat) square(50,center=true); ``` ```openscad-2D +include mat = rot(30); multmatrix(mat) square(50,center=true); ``` @@ -379,6 +428,7 @@ 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 +include mat = move([5,10,0]) * rot(30) * scale([1.5,0.75,1]); multmatrix(mat) square(50,center=true); ``` @@ -386,6 +436,7 @@ multmatrix(mat) square(50,center=true); To apply a compound transformation matrix to a path, you can use the `apply()` function: ```openscad-2D +include mat = move([5,10]) * rot(30) * scale([1.5,0.75]); path = square(50,center=true); tpath = apply(mat, path); @@ -401,6 +452,7 @@ 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 +include rgn = [square(50,center=true), circle(d=30)]; region(rgn); ``` @@ -408,6 +460,7 @@ region(rgn); If you have a region with multiple polygons that are not contained by any others, they make multiple discontiguous shapes: ```openscad-2D +include rgn = [ move([-30, 20], p=square(20,center=true)), move([ 0,-20], p=trapezoid(w1=20, w2=10, h=20)), @@ -419,6 +472,7 @@ region(rgn); Region polygons can be nested abitrarily deep, in multiple discontiguous shapes: ```openscad-2D +include rgn = [ for (d=[50:-10:10]) left(30, p=circle(d=d)), for (d=[50:-10:10]) right(30, p=circle(d=d)) @@ -429,6 +483,7 @@ region(rgn); A region with crossing polygons is somewhat poorly formed, but the intersection(s) of the polygons become holes: ```openscad-2D +include rgn = [ left(15, p=circle(d=50)), right(15, p=circle(d=50)) @@ -441,6 +496,7 @@ Similarly to how OpenSCAD can perform operations like union/difference/intersect the BOSL2 library lets you perform those same operations on regions: ```openscad-2D +include rgn1 = [for (d=[40:-10:10]) circle(d=d)]; rgn2 = [square([60,12], center=true)]; rgn = union(rgn1, rgn2); @@ -448,6 +504,7 @@ region(rgn); ``` ```openscad-2D +include rgn1 = [for (d=[40:-10:10]) circle(d=d)]; rgn2 = [square([60,12], center=true)]; rgn = difference(rgn1, rgn2); @@ -455,6 +512,7 @@ region(rgn); ``` ```openscad-2D +include rgn1 = [for (d=[40:-10:10]) circle(d=d)]; rgn2 = [square([60,12], center=true)]; rgn = intersection(rgn1, rgn2); @@ -462,6 +520,7 @@ region(rgn); ``` ```openscad-2D +include rgn1 = [for (d=[40:-10:10]) circle(d=d)]; rgn2 = [square([60,12], center=true)]; rgn = exclusive_or(rgn1, rgn2); @@ -469,6 +528,7 @@ region(rgn); ``` ```openscad-2D +include orig_rgn = [star(n=5, step=2, d=50)]; rgn = offset(orig_rgn, r=-3, closed=true); color("blue") region(orig_rgn); @@ -479,6 +539,7 @@ You can use regions for several useful things. If you wanted a grid of holes in form the shape given by a region, you can do that with `grid2d()`: ```openscad-3D +include rgn = [ circle(d=100), star(n=5,step=2,d=100,spin=90) @@ -492,6 +553,7 @@ difference() { You can also sweep a region through 3-space to make a solid: ```openscad-3D +include $fa=1; $fs=1; rgn = [ for (d=[50:-10:10]) circle(d=d) ]; tforms = [ diff --git a/tutorials/Shapes2d.md b/tutorials/Shapes2d.md index b031fd6..e7d3e57 100644 --- a/tutorials/Shapes2d.md +++ b/tutorials/Shapes2d.md @@ -7,14 +7,17 @@ There are two built-in 2D primitive shapes that OpenSCAD provides: `square()`, a You can still use them in the familiar ways that OpenSCAD provides: ```openscad-2D +include square([60,40], center=true); ``` ```openscad-2D +include circle(r=50); ``` ```openscad-2D +include circle(d=100, $fn=8); ``` @@ -29,18 +32,21 @@ want to align to the origin. For example, to align the center of the back edge origin, set the anchor to `[0,1]`: ```openscad-2D +include square([60,40], anchor=[0,1]); ``` To align the front right corner to the origin: ```openscad-2D +include square([60,40], anchor=[1,-1]); ``` To center: ```openscad-2D +include square([60,40], anchor=[0,0]); ``` @@ -60,33 +66,39 @@ 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 +include square([60,40], anchor=BACK); ``` ```openscad-2D +include square([60,40], anchor=CENTER); ``` You can add vectors together to point to corners: ```openscad-2D +include square([60,40], anchor=FRONT+RIGHT); ``` For `circle()`, the anchor vector can point at any part of the circle perimeter: ```openscad-2D +include circle(d=50, anchor=polar_to_xy(1,150)); ``` You can see the typical anchor points by making `show_anchors()` the child of the shape: ```openscad-2D +include square([60,40], center=true) show_anchors(); ``` ```openscad-2D +include circle(d=50) show_anchors(); ``` @@ -97,24 +109,28 @@ the shape, you can spin it in place with the `spin=` argument. You just pass it degrees to rotate clockwise: ```openscad-2D +include square([60,40], anchor=CENTER, spin=30); ``` Anchoring or centering is performed before the spin: ```openscad-2D +include square([60,40], anchor=BACK, spin=30); ``` For circles, spin can be useful when `$fn=` is also given: ```openscad-2D +include circle(d=50, $fn=6, spin=15); ``` Since anchoring is performed before spin, you can use them together to spin around the anchor: ```openscad-2D +include circle(d=50, $fn=6, anchor=LEFT, spin=15); ``` @@ -127,11 +143,13 @@ you want to attach to. By default, just making one shape a child of the other w the child shape at the center of the parent shape. ```openscad-2D +include square(50, center=true) #square(50, spin=45, center=true); ``` ```openscad-2D +include square(50, center=true) #square([20,40], anchor=FWD); ``` @@ -139,18 +157,21 @@ square(50, center=true) By adding the `position()` module, you can position the child at any anchorpoint on the parent: ```openscad-2D +include square(50, center=true) position(BACK) #square(25, spin=45, center=true); ``` ```openscad-2D +include square(50, center=true) position(FWD+RIGHT) #square(25, spin=45, center=true); ``` ```openscad-2D +include circle(d=50) position(polar_to_xy(1,60)) #circle(d=10); @@ -162,11 +183,13 @@ cases, the orientation of an anchorpoint is outward away from the face of the wa from the center of the shape. You can see this with the `show_anchors()` module: ```openscad-2D +include square(50, center=true) show_anchors(); ``` ```openscad-2D +include circle(d=50) show_anchors(); ``` @@ -175,24 +198,28 @@ If you want to orient the child to match the orientation of an anchorpoint, you module. It does not position the child. It only rotates it: ```openscad-2D +include square(50, center=true) orient(anchor=LEFT) #square([10,40], anchor=FWD); ``` ```openscad-2D +include square(50, center=true) orient(anchor=FWD) #square([10,40], anchor=FWD); ``` ```openscad-2D +include square(50, center=true) orient(anchor=RIGHT) #square([10,40], anchor=FWD); ``` ```openscad-2D +include circle(d=50) orient(polar_to_xy(1,30)) #square([10,40], anchor=FWD); @@ -201,6 +228,7 @@ circle(d=50) You can use `position()` and `orient()` together to both position and orient to an anchorpoint: ```openscad-2D +include square(50, center=true) position(RIGHT+BACK) orient(anchor=RIGHT+BACK) @@ -208,6 +236,7 @@ square(50, center=true) ``` ```openscad-2D +include circle(d=50) position(polar_to_xy(1,30)) orient(polar_to_xy(1,30)) @@ -217,12 +246,14 @@ circle(d=50) But it's simpler to just use the `attach()` module to do both at once: ```openscad-2D +include square(50, center=true) attach(LEFT+BACK) #square([10,40], anchor=FWD); ``` ```openscad-2D +include circle(d=50) attach(polar_to_xy(1,30)) #square([10,40], center=true); @@ -232,12 +263,14 @@ Instead of specifying the `anchor=` in the child, you can pass a second argument that tells it which side of the child to attach to the parent: ```openscad-2D +include square([10,50], center=true) attach(BACK, LEFT) #square([10,40], center=true); ``` ```openscad-2D +include circle(d=50) attach(polar_to_xy(1,30), LEFT) #square([10,40], center=true); @@ -252,12 +285,14 @@ called `rect()`. You can use it in the same way you use `square()`, but it also extended functionality. For example, it allows you to round the corners: ```openscad-2D +include rect([60,40], rounding=10); ``` Or chamfer them: ```openscad-2D +include rect([60,40], chamfer=10); ``` @@ -268,6 +303,7 @@ 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 +include module text3d(text) color("black") text( text=text, font="Times", size=10, halign="center", valign="center" @@ -283,10 +319,12 @@ If a size is given as `0`, then there is no rounding and/or chamfering for that quadrant's corner: ```openscad-2D +include rect([60,40], rounding=[0,5,10,15]); ``` ```openscad-2D +include rect([60,40], chamfer=[0,5,10,15]); ``` @@ -295,6 +333,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 +include rect([60,40], rounding=[5,0,10,0], chamfer=[0,5,0,15]); ``` @@ -312,6 +351,7 @@ The `realign=` argument, if set `true`, rotates the `ellipse()` by half the angl between the polygon sides: ```openscad-2D +include ellipse(d=100, $fn=8); #ellipse(d=100, $fn=8, realign=true); ``` @@ -322,6 +362,7 @@ The `circum=` argument, if true, makes it so that the polygon forming the Inscribing the ideal circle: ```openscad-2D +include color("green") ellipse(d=100, $fn=360); ellipse(d=100, $fn=6); ``` @@ -329,6 +370,7 @@ ellipse(d=100, $fn=6); Circumscribing the ideal circle: ```openscad-2D +include ellipse(d=100, $fn=6, circum=true); color("green") ellipse(d=100, $fn=360); ``` @@ -338,24 +380,29 @@ or diameters. To do this, just give `r=` or `d=` with a list of two radii or diameters: ```openscad-2D +include ellipse(r=[30,20]); ``` ```openscad-2D +include ellipse(d=[60,40]); ``` Like `circle()`, you can anchor, spin and attach `ellipse()` shapes: ```openscad-2D +include ellipse(d=50, anchor=BACK); ``` ```openscad-2D +include ellipse(d=50, anchor=FRONT+RIGHT); ``` ```openscad-2D +include ellipse(d=50) attach(BACK+RIGHT, FRONT+LEFT) ellipse(d=30); @@ -366,36 +413,43 @@ ellipse(d=50) The BOSL2 library provides a simple way to make a 2D right triangle by using the `right_triangle()` module: ```openscad-2D +include right_triangle([40,30]); ``` You can use `xflip()` and `yflip()` to change which quadrant the triangle is formed in: ```openscad-2D +include xflip() right_triangle([40,30]); ``` ```openscad-2D +include yflip() right_triangle([40,30]); ``` ```openscad-2D +include xflip() yflip() right_triangle([40,30]); ``` Or, alternatively, just rotate it into the correct quadrant with `spin=`: ```openscad-2D +include right_triangle([40,30], spin=90); ``` ```openscad-2D +include right_triangle([40,30], spin=-90); ``` You can also use anchoring with right triangles: ```openscad-2D +include right_triangle([40,30], anchor=FWD+RIGHT); ``` @@ -408,42 +462,50 @@ 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 +include trapezoid(w1=50, w2=0, h=40); ``` 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 +include trapezoid(w1=50, w2=0, h=50, shift=-25); ``` ```openscad-2D +include trapezoid(w1=50, w2=0, h=50, shift=25); ``` ```openscad-2D +include trapezoid(w1=0, w2=50, h=50, shift=-25); ``` ```openscad-2D +include 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 +include 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 +include 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 +include trapezoid(w1=50, w2=30, shift=20, h=50); ``` @@ -451,6 +513,7 @@ You can use `anchor=` and `spin=`, just like with other attachable shapes. Howe point orientations are based on the side angles of the faces, and may not be what you expect: ```openscad-2D +include trapezoid(w1=30, w2=50, h=50) show_anchors(); ``` @@ -461,36 +524,43 @@ 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 +include circle(d=50, $fn=5); ``` The BOSL2 library has modules that are named more clearly, for common N-gons: ```openscad-2D +include pentagon(d=50); ``` ```openscad-2D +include hexagon(d=50); ``` ```openscad-2D +include octagon(d=50); ``` ```openscad-2D +include regular_ngon(n=7, d=50); ``` These modules also provide you with extra functionality. They can be sized by side length: ```openscad-2D +include pentagon(side=20); ``` They can be sized by circumscribed circle radius/diameter: ```openscad-2D +include pentagon(ir=25); pentagon(id=50); ``` @@ -498,6 +568,7 @@ pentagon(id=50); They can be rotated by half a side: ```openscad-2D +include left(30) pentagon(d=50, realign=true); right(30) pentagon(d=50, realign=false); ``` @@ -505,10 +576,12 @@ right(30) pentagon(d=50, realign=false); They can be rounded: ```openscad-2D +include pentagon(d=50, rounding=10); ``` ```openscad-2D +include hexagon(d=50, rounding=10); ``` @@ -516,6 +589,7 @@ They also have somewhat different attachment behavior. A circle with a small `$ attach things at the ideal circle, not along the created polygon: ```openscad-2D +include color("green") stroke(circle(d=50), closed=true); circle(d=50,$fn=6) show_anchors(); @@ -524,6 +598,7 @@ circle(d=50,$fn=6) While an N-gon will attach along the polygon itself: ```openscad-2D +include hexagon(d=50) show_anchors(custom=false); ``` @@ -533,6 +608,7 @@ points are based on where the anchor vector would intersect the side of the N-go be where you expect them: ```openscad-2D +include pentagon(d=50) show_anchors(custom=false); ``` @@ -540,6 +616,7 @@ pentagon(d=50) N-gons also have named anchor points for their sides and tips: ```openscad-2D,Med +include pentagon(d=30) show_anchors(std=false); ``` @@ -551,30 +628,36 @@ 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 +include star(n=3, id=10, d=50); ``` ```openscad-2D +include star(n=5, id=15, r=25); ``` ```openscad-2D +include 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 +include star(n=7, step=2, d=50); ``` ```openscad-2D +include 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 +include left(30) star(n=5, step=2, d=50); right(30) star(n=5, step=2, d=50, realign=true); ``` @@ -582,11 +665,13 @@ 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 +include star(n=5, ir=15, or=30, align_tip=BACK) attach("tip0") color("blue") anchor_arrow2d(); ``` ```openscad-2D +include star(n=5, ir=15, or=30, align_tip=BACK+RIGHT) attach("tip0") color("blue") anchor_arrow2d(); ``` @@ -595,11 +680,13 @@ Similarly, the first indentation or pit can be oriented towards a specific vecto ```openscad-2D +include star(n=5, ir=15, or=30, align_pit=BACK) attach("pit0") color("blue") anchor_arrow2d(); ``` ```openscad-2D +include star(n=5, ir=15, or=30, align_pit=BACK+RIGHT) attach("pit0") color("blue") anchor_arrow2d(); ``` @@ -608,6 +695,7 @@ You can use `anchor=` and `spin=`, just like with other attachable shapes. Howe points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D +include star(n=5, step=2, d=50) show_anchors(custom=false); ``` @@ -615,6 +703,7 @@ star(n=5, step=2, d=50) Stars also have named anchor points for their pits, tips, and midpoints between tips: ```openscad-2D,Med +include star(n=5, step=2, d=40) show_anchors(std=false); ``` @@ -630,16 +719,19 @@ The `teardrop2d()` module will let you make a 2D version of the teardrop shape, extrude it later: ```openscad-2D +include teardrop2d(r=20); ``` ```openscad-2D +include teardrop2d(d=50); ``` The default overhang angle is 45 degrees, but you can adjust that with the `ang=` argument: ```openscad-2D +include teardrop2d(d=50, ang=30); ``` @@ -647,10 +739,12 @@ If you prefer to flatten the top of the teardrop, to encourage bridging, you can argument: ```openscad-2D +include teardrop2d(d=50, cap_h=25); ``` ```openscad-2D +include teardrop2d(d=50, ang=30, cap_h=30); ``` @@ -658,6 +752,7 @@ You can use `anchor=` and `spin=`, just like with other attachable shapes. Howe points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D +include teardrop2d(d=50, ang=30, cap_h=30) show_anchors(); ``` @@ -669,46 +764,55 @@ 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 +include glued_circles(d=30, spread=40); ``` The `r=`/`d=` arguments can specify the radius or diameter of the two circles: ```openscad-2D +include glued_circles(r=20, spread=45); ``` ```openscad-2D +include glued_circles(d=40, spread=45); ``` The `spread=` argument specifies the distance between the centers of the two circles: ```openscad-2D +include glued_circles(d=30, spread=30); ``` ```openscad-2D +include glued_circles(d=30, spread=40); ``` The `tangent=` argument gives the angle of the tangent of the meniscus on the two circles: ```openscad-2D +include glued_circles(d=30, spread=30, tangent=45); ``` ```openscad-2D +include glued_circles(d=30, spread=30, tangent=20); ``` ```openscad-2D +include 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 +include $fn=36; s=10; linear_extrude(height=50,convexity=16,center=true) xcopies(s*sqrt(2),n=3) @@ -719,6 +823,7 @@ You can use `anchor=` and `spin=`, just like with other attachable shapes. Howe points are based on the furthest extents of the shape, and may not be where you expect them: ```openscad-2D +include glued_circles(d=40, spread=40, tangent=45) show_anchors(); ``` diff --git a/tutorials/Shapes3d.md b/tutorials/Shapes3d.md index e0389c8..4aa924b 100644 --- a/tutorials/Shapes3d.md +++ b/tutorials/Shapes3d.md @@ -12,14 +12,17 @@ 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 +include cube(100); ``` ```openscad-3D +include cube(100, center=true); ``` ```openscad-3D +include cube([50,40,20], center=true); ``` @@ -30,20 +33,24 @@ except you can also anchor vertically in 3D, allowing anchoring to faces, edges, and corners: ```openscad-3D +include cube([50,40,20], anchor=BOTTOM); ``` ```openscad-3D +include cube([50,40,20], anchor=TOP+BACK); ``` ```openscad-3D +include cube([50,40,20], anchor=TOP+FRONT+LEFT); ``` You can use `spin=` to rotate around the Z axis: ```openscad-3D +include cube([50,40,20], anchor=FRONT, spin=30); ``` @@ -52,6 +59,7 @@ 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 +include cube([50,40,20], anchor=FRONT, spin=[15,0,30]); ``` @@ -59,6 +67,7 @@ cube([50,40,20], anchor=FRONT, spin=[15,0,30]); to where the top of the shape should be rotated towards. ```openscad-3D +include cube([50,40,20], orient=UP+BACK+RIGHT); ``` @@ -66,14 +75,17 @@ If you use `anchor=`, `spin=`, and `orient=` together, the anchor is performed first, then the spin, then the orient: ```openscad-3D +include cube([50,40,20], anchor=FRONT); ``` ```openscad-3D +include cube([50,40,20], anchor=FRONT, spin=45); ``` ```openscad-3D +include cube([50,40,20], anchor=FRONT, spin=45, orient=UP+FWD+RIGHT); ``` @@ -84,12 +96,14 @@ except that `cuboid()` centers by default. You can round the edges with the `rounding=` argument: ```openscad-3D +include cuboid([100,80,60], rounding=20); ``` Similarly, you can chamfer the edges with the `chamfer=` argument: ```openscad-3D +include cuboid([100,80,60], chamfer=10); ``` @@ -98,10 +112,12 @@ 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 +include cuboid([100,80,60], rounding=20, edges=TOP); ``` ```openscad-3D +include cuboid([100,80,60], rounding=20, edges=RIGHT); ``` @@ -109,20 +125,24 @@ If you give `edges=` a vector pointing at a corner, it will round all edges that meet at that corner: ```openscad-3D +include cuboid([100,80,60], rounding=20, edges=RIGHT+FRONT+TOP); ``` ```openscad-3D +include 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 +include cuboid([100,80,60], rounding=10, edges=FRONT+TOP); ``` ```openscad-3D +include cuboid([100,80,60], rounding=10, edges=RIGHT+FRONT); ``` @@ -130,14 +150,17 @@ If you give the string "X", "Y", or "Z", then all edges aligned with the specifi axis will be rounded: ```openscad-3D +include cuboid([100,80,60], rounding=10, edges="X"); ``` ```openscad-3D +include cuboid([100,80,60], rounding=10, edges="Y"); ``` ```openscad-3D +include cuboid([100,80,60], rounding=10, edges="Z"); ``` @@ -145,6 +168,7 @@ If you give a list of edge specs, then all edges referenced in the list will be rounded: ```openscad-3D +include cuboid([100,80,60], rounding=10, edges=[TOP,"Z",BOTTOM+RIGHT]); ``` @@ -152,6 +176,7 @@ 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 +include cuboid([100,80,60], rounding=10, except_edges=BOTTOM+RIGHT); ``` @@ -159,18 +184,21 @@ You can give the `except_edges=` argument any type of argument that you can give to `edges=`: ```openscad-3D +include 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 +include cuboid([100,80,60], rounding=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); ``` You can specify what edges to chamfer similarly: ```openscad-3D +include cuboid([100,80,60], chamfer=10, edges=[TOP,FRONT], except_edges=TOP+FRONT); ``` @@ -180,36 +208,44 @@ BOSL2 overrides the built-in `cylinder()` module. It still can be used as you expect from the built-in: ```openscad-3D +include cylinder(r=50,h=50); ``` ```openscad-3D +include cylinder(r=50,h=50,center=true); ``` ```openscad-3D +include cylinder(d=100,h=50,center=true); ``` ```openscad-3D +include cylinder(d1=100,d2=80,h=50,center=true); ``` You can also anchor, spin, orient, and attach like the `cuboid()` module: ```openscad-3D +include cylinder(r=50, h=50, anchor=TOP+FRONT); ``` ```openscad-3D +include cylinder(r=50, h=50, anchor=BOTTOM+LEFT); ``` ```openscad-3D +include cylinder(r=50, h=50, anchor=BOTTOM+LEFT, spin=30); ``` ```openscad-3D +include cylinder(r=50, h=50, anchor=BOTTOM, orient=UP+BACK+RIGHT); ``` @@ -219,54 +255,65 @@ rounding and chamfering of edges. You can use it similarly to `cylinder()`, except that `cyl()` centers the cylinder by default. ```openscad-3D +include cyl(r=60, l=100); ``` ```openscad-3D +include cyl(d=100, l=100); ``` ```openscad-3D +include cyl(d=100, l=100, anchor=TOP); ``` You can round the edges with the `rounding=` argument: ```openscad-3D +include cyl(d=100, l=100, rounding=20); ``` Similarly, you can chamfer the edges with the `chamfer=` argument: ```openscad-3D +include cyl(d=100, l=100, chamfer=10); ``` You can specify rounding and chamfering for each end individually: ```openscad-3D +include cyl(d=100, l=100, rounding1=20); ``` ```openscad-3D +include cyl(d=100, l=100, rounding2=20); ``` ```openscad-3D +include cyl(d=100, l=100, chamfer1=10); ``` ```openscad-3D +include cyl(d=100, l=100, chamfer2=10); ``` You can even mix and match rounding and chamfering: ```openscad-3D +include cyl(d=100, l=100, rounding1=20, chamfer2=10); ``` ```openscad-3D +include cyl(d=100, l=100, rounding2=20, chamfer1=10); ``` @@ -276,10 +323,12 @@ BOSL2 overrides the built-in `sphere()` module. It still can be used as you expect from the built-in: ```openscad-3D +include sphere(r=50); ``` ```openscad-3D +include sphere(d=100); ``` @@ -287,14 +336,17 @@ You can anchor, spin, and orient `sphere()`s, much like you can with `cylinder() and `cube()`: ```openscad-3D +include sphere(d=100, anchor=FRONT); ``` ```openscad-3D +include sphere(d=100, anchor=FRONT, spin=30); ``` ```openscad-3D +include sphere(d=100, anchor=BOTTOM, orient=RIGHT+TOP); ``` @@ -305,6 +357,7 @@ You can use the `circum=true` argument to force the sphere to circumscribe the ideal sphere, as opposed to the default inscribing: ```openscad-3D +include spheroid(d=100, circum=true); ``` @@ -312,6 +365,7 @@ 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 +include spheroid(d=100, style="orig", $fn=20); ``` @@ -319,12 +373,14 @@ 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 +include spheroid(d=100, style="aligned", $fn=20); ``` The "stagger" style will stagger the triangulation of the vertical rows: ```openscad-3D +include spheroid(d=100, style="stagger", $fn=20); ``` @@ -333,6 +389,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 +include spheroid(d=100, style="icosa", $fn=20); ``` @@ -342,6 +399,7 @@ guarantees vertices at the axis extrema. This style will round the effective `$ to a multiple of 4 when constructing the spheroid: ```openscad-3D +include spheroid(d=100, style="octa", $fn=20); ``` diff --git a/tutorials/Transforms.md b/tutorials/Transforms.md index 8738546..c7aa541 100644 --- a/tutorials/Transforms.md +++ b/tutorials/Transforms.md @@ -5,6 +5,7 @@ ## Translation The `translate()` command is very simple: ```openscad +include #sphere(d=20); translate([0,0,30]) sphere(d=20); ``` @@ -14,31 +15,37 @@ 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 +include #sphere(d=20); up(30) sphere(d=20); ``` ```openscad +include #sphere(d=20); down(30) sphere(d=20); ``` ```openscad +include #sphere(d=20); fwd(30) sphere(d=20); ``` ```openscad +include #sphere(d=20); back(30) sphere(d=20); ``` ```openscad +include #sphere(d=20); left(30) sphere(d=20); ``` ```openscad +include #sphere(d=20); right(30) sphere(d=20); ``` @@ -46,11 +53,13 @@ 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 +include #sphere(d=20); move([30,-10]) sphere(d=20); ``` ```openscad +include #sphere(d=20); move(x=30,y=10) sphere(d=20); ``` @@ -59,22 +68,27 @@ move(x=30,y=10) sphere(d=20); ## Scaling The `scale()` command is also fairly simple: ```openscad +include scale(2) cube(10, center=true); ``` ```openscad +include 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 +include xscale(2) cube(10, center=true); ``` ```openscad +include yscale(2) cube(10, center=true); ``` ```openscad +include zscale(2) cube(10, center=true); ``` @@ -82,31 +96,37 @@ zscale(2) cube(10, center=true); ## Rotation The `rotate()` command is fairly straightforward: ```openscad +include 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 +include xrot(30) cube(20, center=true); ``` ```openscad +include yrot(30) cube(20, center=true); ``` ```openscad +include zrot(30) cube(20, center=true); ``` The `rot()` command is a more generic rotation command, and shorter to type than `rotate()`: ```openscad +include 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 +include cp = [0,0,40]; color("blue") move(cp) sphere(d=3); #cube(20, center=true); @@ -114,6 +134,7 @@ xrot(45, cp=cp) cube(20, center=true); ``` ```openscad +include cp = [0,0,40]; color("blue") move(cp) sphere(d=3); #cube(20, center=true); @@ -121,6 +142,7 @@ yrot(45, cp=cp) cube(20, center=true); ``` ```openscad +include cp = [0,40,0]; color("blue") move(cp) sphere(d=3); #cube(20, center=true); @@ -130,6 +152,7 @@ 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 +include #cylinder(d=10, h=50); rot(from=[0,0,1], to=[1,0,1]) cylinder(d=10, h=50); ``` @@ -150,6 +173,7 @@ Constant | Value | Direction This lets you rewrite the above vector rotation more clearly as: ```openscad +include #cylinder(d=10, h=50); rot(from=UP, to=UP+RIGHT) cylinder(d=10, h=50); ``` @@ -158,40 +182,47 @@ rot(from=UP, to=UP+RIGHT) cylinder(d=10, h=50); ## Mirroring The standard `mirror()` command works like this: ```openscad +include #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 +include #yrot(60) cylinder(h=50, d1=20, d2=10); xflip() yrot(60) cylinder(h=50, d1=20, d2=10); ``` ```openscad +include #xrot(60) cylinder(h=50, d1=20, d2=10); yflip() xrot(60) cylinder(h=50, d1=20, d2=10); ``` ```openscad +include #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 +include #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 +include #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 +include #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); @@ -209,26 +240,32 @@ a multiplier of `0.5`, then for each unit further along the Y axis you get, you will add `0.5` units of skew to the X axis. Giving a negative multiplier reverses the direction it skews: ```openscad +include skew(sxy=0.5) cube(10,center=false); ``` ```openscad +include skew(sxz=-0.5) cube(10,center=false); ``` ```openscad +include skew(syx=-0.5) cube(10,center=false); ``` ```openscad +include skew(syz=0.5) cube(10,center=false); ``` ```openscad +include skew(szx=-0.5) cube(10,center=false); ``` ```openscad +include skew(szy=0.5) cube(10,center=false); ``` diff --git a/tutorials/VNF.md b/tutorials/VNF.md index 772fc04..ffc159e 100644 --- a/tutorials/VNF.md +++ b/tutorials/VNF.md @@ -6,6 +6,7 @@ The acronym VNF stands for Vertices 'N' Faces. You have probably already come across the concept of vertices and faces when working with the OpenSCAD built-in module `polyhedron()`. A `polyhedron()` in it's simplest form takes two arguments, the first being a list of vertices, and the second a list of faces, where each face is a lists of indices into the list of vertices. For example, to make a cube, you can do: ```openscad-3D +include verts = [ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], [-1,-1, 1], [1,-1, 1], [1,1, 1], [-1,1, 1] @@ -26,6 +27,7 @@ A VNF structure (usually just called a VNF) is just a two item list where the fi The equivalent to the `polyhedron()` module that takes a VNF instead is `vnf_polyhedron()`. To make the same cube as a VNF, you can do it like: ```openscad-3D +include vnf = [ [ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], @@ -49,6 +51,7 @@ A VNF does not have to contain a complete polyhedron, and the vertices contained As an example, consider a roughly spherical polyhedron with vertices at the top and bottom poles. You can break it down into three major parts: The top cap, the bottom cap, and the side wall. The top and bottom caps both have a ring of vertices linked to the top or bottom vertex in triangles, while the sides are multiple rings of vertices linked in squares. Lets create the top cap first: ```openscad-3D,ThrownTogether +include cap_vnf = [ [[0,0,1], for (a=[0:30:359.9]) spherical_to_xyz(1,a,30)], // Vertices [for (i=[1:12]) [0, i%12+1, i]] // Faces @@ -59,6 +62,7 @@ vnf_polyhedron(cap_vnf); The bottom cap is exactly the same, just mirrored: ```openscad-3D,ThrownTogether +include cap_vnf = [ [[0,0,1], for (a=[0:30:359.9]) spherical_to_xyz(1,a,30)], // Vertices [for (i=[1:12]) [0, i%12+1, i]] // Faces @@ -70,6 +74,7 @@ vnf_polyhedron(cap_vnf2); To create the sides, we can make use of the `vnf_vertex_array()` function to turn a row-column grid of vertices into a VNF. The `col_wrap=true` argument tells it to connect the vertices of the last column to the vertices of the first column. The `caps=false` argument tells it that we don't want it to create caps for the ends of the first and last rows: ```openscad-3D,ThrownTogether +include wall_vnf = vnf_vertex_array( points=[ for (phi = [30:30:179.9]) [ @@ -85,6 +90,7 @@ vnf_polyhedron(wall_vnf); Putting all the parts together with `vnf_join()`, we get: ```openscad-3D,ThrownTogether +include cap_vnf = [ [[0,0,1], for (a=[0:30:359.9]) spherical_to_xyz(1,a,30)], // Vertices [for (i=[1:12]) [0, i%12+1, i]] // Faces @@ -110,6 +116,7 @@ Which is now a complete manifold polyhedron. One of the critical tasks in creating a polyhedron is making sure that all of your faces are facing the correct way. This is also true for VNFs. The best way to find reversed faces is simply to select the View→Thrown Together menu item in OpenSCAD while viewing your polyhedron or VNF. Any purple faces are reversed, and you will need to fix them. For example, one of the two top face triangles on this cube is reversed: ```openscad-3D,ThrownTogether +include vnf = [ [ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], @@ -131,6 +138,7 @@ Another way to find problems with your VNF, is to use the `vnf_validate()` modul ```openscad-3D,ThrownTogether +include vnf = [ [ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], @@ -157,6 +165,7 @@ ECHO: "ERROR REVERSAL (violet): Faces Reverse Across Edge at [[1, 1, 1], [-1, -1 The `vnf_validate()` module will stop after displaying the first found problem type, so once you fix those issues, you will want to run it again to display any other remaining issues. For example, the reversed face in the above example is hiding a non-manifold hole in the front face: ```openscad-3D,ThrownTogether +include vnf = [ [ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1],