1 Tutorial Shapes2d
Revar Desmera edited this page 2024-12-14 02:23:46 -08:00

2D Shapes Tutorial

Primitives

There are two built-in 2D primitive shapes that OpenSCAD provides: square(), and circle(). You can still use them in the familiar ways that OpenSCAD provides:

include <BOSL2/std.scad>
square([60,40], center=true);

Figure 1

include <BOSL2/std.scad>
circle(r=50);

Figure 2

include <BOSL2/std.scad>
circle(d=100, $fn=8);

Figure 3

These modules have also been enhanced in the BOSL2 library in three ways: Anchoring, spin, and attachability.

Anchoring:

When you create a square(), you can specify what corner or side will be anchored at the origin. This is used in place of the center= argument, and is more flexible. The anchor= argument takes a vector as a value, pointing roughly towards 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]:

include <BOSL2/std.scad>
square([60,40], anchor=[0,1]);

Figure 4

To align the front right corner to the origin:

include <BOSL2/std.scad>
square([60,40], anchor=[1,-1]);

Figure 5

To center:

include <BOSL2/std.scad>
square([60,40], anchor=[0,0]);

Figure 6

To make it clearer when giving vectors, there are several standard vector constants defined:

Constant Direction Value
LEFT X- [-1, 0, 0]
RIGHT X+ [ 1, 0, 0]
FRONT/FORWARD/FWD Y- [ 0,-1, 0]
BACK Y+ [ 0, 1, 0]
BOTTOM/BOT/BTM/DOWN Z- [ 0, 0,-1] (3D only.)
TOP/UP Z+ [ 0, 0, 1] (3D only.)
CENTER/CTR Centered [ 0, 0, 0]

Note that even though these are 3D vectors, you can use most of them, (except UP/DOWN, of course) for anchors in 2D shapes:

include <BOSL2/std.scad>
square([60,40], anchor=BACK);

Figure 7

include <BOSL2/std.scad>
square([60,40], anchor=CENTER);

Figure 8

You can add vectors together to point to corners:

include <BOSL2/std.scad>
square([60,40], anchor=FRONT+RIGHT);

Figure 9

For circle(), the anchor vector can point at any part of the circle perimeter:

include <BOSL2/std.scad>
circle(d=50, anchor=polar_to_xy(1,150));

Figure 10

Note that the radius does not matter for the anchor because only the anchor's direction affects the result. You can see the typical anchor points by giving show_anchors() as a child of the shape:

include <BOSL2/std.scad>
square([60,40], center=true)
    show_anchors();

Figure 11

include <BOSL2/std.scad>
circle(d=50)
    show_anchors();

Figure 12

Spin:

The second way that square() and circle() have been enhanced is with spin. When you create the shape, you can spin it in place with the spin= argument. You just pass it a number of degrees to rotate clockwise:

include <BOSL2/std.scad>
square([60,40], anchor=CENTER, spin=30);

Figure 13

Anchoring or centering is performed before the spin:

include <BOSL2/std.scad>
square([60,40], anchor=BACK, spin=30);

Figure 14

For circles, spin can be useful when $fn= is also given:

include <BOSL2/std.scad>
circle(d=50, $fn=6, spin=15);

Figure 15

Since anchoring is performed before spin, you can use them together to spin around the anchor:

include <BOSL2/std.scad>
circle(d=50, $fn=6, anchor=LEFT, spin=15);

Figure 16

Attachability:

The third way square() and circle() have been enhanced is that you can attach them together at anchoring points in various ways. This is done by making one shape a child of the shape you want to attach to. By default, just making one shape a child of the other will position the child shape at the center of the parent shape.

include <BOSL2/std.scad>
square(50, center=true)
    #square(50, spin=45, center=true);

Figure 17

include <BOSL2/std.scad>
square(50, center=true)
    #square([20,40], anchor=FWD);

Figure 18

By adding the position() module, you can position the child at any anchorpoint on the parent:

include <BOSL2/std.scad>
square(50, center=true)
    position(BACK)
        #square(25, spin=45, center=true);

Figure 19

include <BOSL2/std.scad>
square(50, center=true)
    position(FWD+RIGHT)
        #square(25, spin=45, center=true);

Figure 20

include <BOSL2/std.scad>
circle(d=50)
    position(polar_to_xy(1,60))
        #circle(d=10);

Figure 21

Anchorpoints aren't just positions on the parent, though. They also have an orientation. In most cases, the orientation of an anchorpoint is outward away from the face of the wall, generally away from the center of the shape. You can see this with the show_anchors() module:

include <BOSL2/std.scad>
square(50, center=true)
    show_anchors();

Figure 22

include <BOSL2/std.scad>
circle(d=50)
    show_anchors();

Figure 23

If you want to orient the child to match the orientation of an anchorpoint, you can use the orient() module. It does not position the child. It only rotates it:

include <BOSL2/std.scad>
square(50, center=true)
    orient(anchor=LEFT)
        #square([10,40], anchor=FWD);

Figure 24

include <BOSL2/std.scad>
square(50, center=true)
    orient(anchor=FWD)
        #square([10,40], anchor=FWD);

Figure 25

include <BOSL2/std.scad>
square(50, center=true)
    orient(anchor=RIGHT)
        #square([10,40], anchor=FWD);

Figure 26

include <BOSL2/std.scad>
circle(d=50)
    orient(polar_to_xy(1,30))
        #square([10,40], anchor=FWD);

Figure 27

You can use position() and orient() together to both position and orient to an anchorpoint:

include <BOSL2/std.scad>
square(50, center=true)
    position(RIGHT+BACK)
        orient(anchor=RIGHT+BACK)
            #square([10,40], anchor=FWD);

Figure 28

include <BOSL2/std.scad>
circle(d=50)
    position(polar_to_xy(1,30))
        orient(polar_to_xy(1,30))
            #square([10,40], anchor=FWD);

Figure 29

But it's simpler to just use the attach() module to do both at once:

include <BOSL2/std.scad>
square(50, center=true)
    attach(LEFT+BACK)
        #square([10,40], anchor=FWD);

Figure 30

include <BOSL2/std.scad>
circle(d=50)
    attach(polar_to_xy(1,30))
        #square([10,40], center=true);

Figure 31

Instead of specifying the anchor= in the child, you can pass a second argument to attach() that tells it which side of the child to attach to the parent:

include <BOSL2/std.scad>
square([10,50], center=true)
    attach(BACK, LEFT)
        #square([10,40], center=true);

Figure 32

include <BOSL2/std.scad>
circle(d=50)
    attach(polar_to_xy(1,30), LEFT)
        #square([10,40], center=true);

Figure 33

Rectangles

The BOSL2 library provides an alternative to square(), that support more features. It is called rect(). 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:

include <BOSL2/std.scad>
rect([60,40], rounding=10);

Figure 34

Or chamfer them:

include <BOSL2/std.scad>
rect([60,40], chamfer=10);

Figure 35

You can even specify which corners get rounded or chamfered. If you pass a list of four size numbers to the rounding= or chamfer= arguments, it will give each corner its own size. In order, it goes from the back-right (quadrant I) 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:

Figure 36

If a size is given as 0, then there is no rounding and/or chamfering for that quadrant's corner:

include <BOSL2/std.scad>
rect([60,40], rounding=[0,5,10,15]);

Figure 37

include <BOSL2/std.scad>
rect([60,40], chamfer=[0,5,10,15]);

Figure 38

You can give both rounding= and chamfer= arguments to mix rounding and 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:

include <BOSL2/std.scad>
rect([60,40], rounding=[5,0,10,0], chamfer=[0,5,0,15]);

Figure 39

Ellipses

The BOSL2 library also provides an enhanced equivalent of circle() called ellipse(). You can use it in the same way you use circle(), but it also provides extended functionality. For example, it allows more control over its size.

Since a circle in OpenSCAD can only be approximated by a regular polygon with a number of straight sides, this can lead to size and shape inaccuracies. To counter this, the realign= and circum= arguments are also provided.

The realign= argument, if set true, rotates the ellipse() by half the angle between the polygon sides:

include <BOSL2/std.scad>
ellipse(d=100, $fn=8);
#ellipse(d=100, $fn=8, realign=true);

Figure 40

The circum= argument, if true, makes it so that the polygon forming the ellipse() circumscribes the ideal circle instead of inscribing it.

Inscribing the ideal circle:

include <BOSL2/std.scad>
color("green") ellipse(d=100, $fn=360);
ellipse(d=100, $fn=6);

Figure 41

Circumscribing the ideal circle:

include <BOSL2/std.scad>
ellipse(d=100, $fn=6, circum=true);
color("green") ellipse(d=100, $fn=360);

Figure 42

The ellipse() module, as its name suggests, can be given separate X and Y radii or diameters. To do this, just give r= or d= with a list of two radii or diameters:

include <BOSL2/std.scad>
ellipse(r=[30,20]);

Figure 43

include <BOSL2/std.scad>
ellipse(d=[60,40]);

Figure 44

Like circle(), you can anchor, spin and attach ellipse() shapes:

include <BOSL2/std.scad>
ellipse(d=50, anchor=BACK);

Figure 45

include <BOSL2/std.scad>
ellipse(d=50, anchor=FRONT+RIGHT);

Figure 46

include <BOSL2/std.scad>
ellipse(d=50)
    attach(BACK+RIGHT, FRONT+LEFT)
        ellipse(d=30);

Figure 47

Right Triangles

The BOSL2 library provides a simple way to make a 2D right triangle by using the right_triangle() module:

include <BOSL2/std.scad>
right_triangle([40,30]);

Figure 48

You can use xflip() and yflip() to change which quadrant the triangle is formed in:

include <BOSL2/std.scad>
xflip() right_triangle([40,30]);

Figure 49

include <BOSL2/std.scad>
yflip() right_triangle([40,30]);

Figure 50

include <BOSL2/std.scad>
xflip() yflip() right_triangle([40,30]);

Figure 51

Or, alternatively, just rotate it into the correct quadrant with spin=:

include <BOSL2/std.scad>
right_triangle([40,30], spin=90);

Figure 52

include <BOSL2/std.scad>
right_triangle([40,30], spin=-90);

Figure 53

You can also use anchoring with right triangles:

include <BOSL2/std.scad>
right_triangle([40,30], anchor=FWD+RIGHT);

Figure 54

Trapezoids

OpenSCAD doesn't provide a simple way to make general 2D triangles, trapezoids, or parallelograms. 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:

include <BOSL2/std.scad>
trapezoid(w1=50, w2=0, h=40);

Figure 55

To make a right triangle, you need to use the shift= argument, to shift the back of the trapezoid along the X axis:

include <BOSL2/std.scad>
trapezoid(w1=50, w2=0, h=50, shift=-25);

Figure 56

include <BOSL2/std.scad>
trapezoid(w1=50, w2=0, h=50, shift=25);

Figure 57

include <BOSL2/std.scad>
trapezoid(w1=0, w2=50, h=50, shift=-25);

Figure 58

include <BOSL2/std.scad>
trapezoid(w1=0, w2=50, h=50, shift=25);

Figure 59

You can make a trapezoid by specifying non-zero widths for both the front (w1=) and back (w2=):

include <BOSL2/std.scad>
trapezoid(w1=30, w2=50, h=50);

Figure 60

A parallelogram is just a matter of using the same width for front and back, with a shift along the X axis:

include <BOSL2/std.scad>
trapezoid(w1=50, w2=50, shift=20, h=50);

Figure 61

A quadrilateral can be made by having unequal, non-zero front (w1=) and back (w2=) widths, with the back shifted along the X axis:

include <BOSL2/std.scad>
trapezoid(w1=50, w2=30, shift=20, h=50);

Figure 62

You can use anchor= and spin=, just like with other attachable shapes. However, the anchor point orientations are based on the side angles of the faces, and may not be what you expect:

include <BOSL2/std.scad>
trapezoid(w1=30, w2=50, h=50)
    show_anchors();

Figure 63

Regular N-Gons

OpenSCAD lets you make regular N-gons (pentagon, hexagon, etc) by using circle() with $fn. While this is concise, it may be less than obvious at first glance:

include <BOSL2/std.scad>
circle(d=50, $fn=5);

Figure 64

The BOSL2 library has modules that are named more clearly, for common N-gons:

include <BOSL2/std.scad>
pentagon(d=50);

Figure 65

include <BOSL2/std.scad>
hexagon(d=50);

Figure 66

include <BOSL2/std.scad>
octagon(d=50);

Figure 67

include <BOSL2/std.scad>
regular_ngon(n=7, d=50);

Figure 68

These modules also provide you with extra functionality. They can be sized by side length:

include <BOSL2/std.scad>
pentagon(side=20);

Figure 69

They can be sized by circumscribed circle radius/diameter:

include <BOSL2/std.scad>
pentagon(ir=25);
pentagon(id=50);

Figure 70

They can be rotated by half a side:

include <BOSL2/std.scad>
left(30)  pentagon(d=50, realign=true);
right(30) pentagon(d=50, realign=false);

Figure 71

They can be rounded:

include <BOSL2/std.scad>
pentagon(d=50, rounding=10);

Figure 72

include <BOSL2/std.scad>
hexagon(d=50, rounding=10);

Figure 73

They also have somewhat different attachment behavior. A circle with a small $fn= will attach things at the ideal circle, not along the created polygon:

include <BOSL2/std.scad>
color("green") stroke(circle(d=50), closed=true);
circle(d=50,$fn=6)
    show_anchors();

Figure 74

While an N-gon will attach along the polygon itself:

include <BOSL2/std.scad>
hexagon(d=50)
    show_anchors(custom=false);

Figure 75

You can use anchor= and spin=, just like with other attachable shapes. However, the anchor points are based on where the anchor vector would intersect the side of the N-gon, and may not be where you expect them:

include <BOSL2/std.scad>
pentagon(d=50)
    show_anchors(custom=false);

Figure 76

N-gons also have named anchor points for their sides and tips:

include <BOSL2/std.scad>
pentagon(d=30)
    show_anchors(std=false);

Figure 77

Stars

The BOSL2 library has stars as a basic supported shape. They can have any number of points. You can specify a star's shape by point count, inner and outer vertex radius/diameters:

include <BOSL2/std.scad>
star(n=3, id=10, d=50);

Figure 78

include <BOSL2/std.scad>
star(n=5, id=15, r=25);

Figure 79

include <BOSL2/std.scad>
star(n=10, id=30, d=50);

Figure 80

Or you can specify the star shape by point count and number of points to step:

include <BOSL2/std.scad>
star(n=7, step=2, d=50);

Figure 81

include <BOSL2/std.scad>
star(n=7, step=3, d=50);

Figure 82

If the realign= argument is given a true value, then the star will be rotated by half a point angle:

include <BOSL2/std.scad>
left(30) star(n=5, step=2, d=50);
right(30) star(n=5, step=2, d=50, realign=true);

Figure 83

The align_tip= argument can be given a vector so that you can align the first point in a specific direction:

include <BOSL2/std.scad>
star(n=5, ir=15, or=30, align_tip=BACK)
    attach("tip0") color("blue") anchor_arrow2d();

Figure 84

include <BOSL2/std.scad>
star(n=5, ir=15, or=30, align_tip=BACK+RIGHT)
    attach("tip0") color("blue") anchor_arrow2d();

Figure 85

Similarly, the first indentation or pit can be oriented towards a specific vector with align_pit=:

include <BOSL2/std.scad>
star(n=5, ir=15, or=30, align_pit=BACK)
    attach("pit0") color("blue") anchor_arrow2d();

Figure 86

include <BOSL2/std.scad>
star(n=5, ir=15, or=30, align_pit=BACK+RIGHT)
    attach("pit0") color("blue") anchor_arrow2d();

Figure 87

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:

include <BOSL2/std.scad>
star(n=5, step=2, d=50)
    show_anchors(custom=false);

Figure 88

Stars also have named anchor points for their pits, tips, and midpoints between tips:

include <BOSL2/std.scad>
star(n=5, step=2, d=40)
    show_anchors(std=false);

Figure 89

Teardrop2D

Often when 3D printing, you may want to make a circular hole in a vertical wall. If the hole is too big, however, the overhang at the top of the hole can cause problems with printing on an FDM/FFF printer. If you don't want to use support material, you can just use the teardrop shape. The teardrop2d() module will let you make a 2D version of the teardrop shape, so that you can extrude it later:

include <BOSL2/std.scad>
teardrop2d(r=20);

Figure 90

include <BOSL2/std.scad>
teardrop2d(d=50);

Figure 91

The default overhang angle is 45 degrees, but you can adjust that with the ang= argument:

include <BOSL2/std.scad>
teardrop2d(d=50, ang=30);

Figure 92

If you prefer to flatten the top of the teardrop, to encourage bridging, you can use the cap_h= argument:

include <BOSL2/std.scad>
teardrop2d(d=50, cap_h=25);

Figure 93

include <BOSL2/std.scad>
teardrop2d(d=50, ang=30, cap_h=30);

Figure 94

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:

include <BOSL2/std.scad>
teardrop2d(d=50, ang=30, cap_h=30)
    show_anchors();

Figure 95

Glued Circles

A more unusal shape that BOSL2 provides is Glued Circles. It's basically a pair of circles, connected by what looks like a gloopy glued miniscus:

include <BOSL2/std.scad>
glued_circles(d=30, spread=40);

Figure 96

The r=/d= arguments can specify the radius or diameter of the two circles:

include <BOSL2/std.scad>
glued_circles(r=20, spread=45);

Figure 97

include <BOSL2/std.scad>
glued_circles(d=40, spread=45);

Figure 98

The spread= argument specifies the distance between the centers of the two circles:

include <BOSL2/std.scad>
glued_circles(d=30, spread=30);

Figure 99

include <BOSL2/std.scad>
glued_circles(d=30, spread=40);

Figure 100

The tangent= argument gives the angle of the tangent of the meniscus on the two circles:

include <BOSL2/std.scad>
glued_circles(d=30, spread=30, tangent=45);

Figure 101

include <BOSL2/std.scad>
glued_circles(d=30, spread=30, tangent=20);

Figure 102

include <BOSL2/std.scad>
glued_circles(d=30, spread=30, tangent=-20);

Figure 103

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:

include <BOSL2/std.scad>
$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);

Figure 104

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:

include <BOSL2/std.scad>
glued_circles(d=40, spread=40, tangent=45)
    show_anchors();

Figure 105