8.2 2D Shapes and Transforms
SLO 3
Describe, design, implement, and test structured programs using currently accepted methodology.
Learning Objectives
By the end of this section, you will be able to:
- create the main 2D primitives in JSCAD — rectangle, circle, ellipse, rounded rectangle, polygon, and star;
- read each primitive's option table and pick the options you need;
- build a custom polygon from a list of points;
- move, rotate, and resize a shape with the translate, rotate, and scale transforms;
- flip, center, and align a shape with the mirror, center, and align transforms.
All 2D primitives live in JSCAD → primitives. Each returns a geom2 object. Options are always passed as a single object; every option shown below is optional unless noted, with its documented default.
Every primitive takes its settings as a single object, like { size: [10, 20] }. That keeps the call tidy and lets you leave out any option you want to keep at its default.
rectangle(options?) → geom2
Axis-aligned rectangle with four right-angle sides.
| Option | Type | Default | Meaning |
|---|---|---|---|
center |
Array | [0,0] |
rectangle center point |
size |
Array | [2,2] |
[width, length] |
An axis-aligned rectangle's sides run straight along the x and y axes — it never leans. If you want a tilted rectangle, you build it upright and then rotate it with a transform.
Create a rectangle that is 30 wide and 8 long, centered at the origin. Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need a rectangle, so we use rectangle.
Step 2 — set the size. The size option takes [width, length]. We want width 30 and length 8, so size: [30, 8].
Step 3 — leave the center at its default. The default center is [0,0], which is the origin, so we do not need to pass center.
Answer: rectangle({ size: [30, 8] }) — a 30-by-8 rectangle centered at the origin.
circle(options?) → geom2
Every point on the boundary is an equal distance from the center.
| Option | Type | Default | Meaning |
|---|---|---|---|
center |
Array | [0,0] |
circle center |
radius |
Number | 1 |
distance from center |
startAngle |
Number | 0 |
beginning angle, radians |
endAngle |
Number | TAU |
ending angle, radians |
segments |
Number | 32 |
divisions per full rotation |
A computer cannot draw a perfect curve, so a circle is built from straight segments. More segments means a smoother circle but a heavier model — 32 is a good default for most parts.
Create a circle with radius 5 centered at the point (2, 3). Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need a circle, so we use circle.
Step 2 — set the radius. We want radius 5, so radius: 5.
Step 3 — set the center. The center is (2, 3), so center: [2, 3].
Answer: circle({ radius: 5, center: [2, 3] }) — a radius-5 circle centered at (2, 3).
ellipse(options?) → geom2
Axis-aligned ellipse.
| Option | Type | Default | Meaning |
|---|---|---|---|
center |
Array | [0,0] |
ellipse center |
radius |
Array | [1,1] |
[xRadius, yRadius] |
startAngle |
Number | 0 |
beginning angle, radians |
endAngle |
Number | TAU |
ending angle, radians |
segments |
Number | 32 |
divisions per full rotation |
A circle has one radius; an ellipse has two — one along x and one along y. When the two radii are equal, the ellipse is a circle.
Create an ellipse with an x-radius of 4 and a y-radius of 9. Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need an ellipse, so we use ellipse.
Step 2 — set the two radii. The radius option takes [xRadius, yRadius]. We want x-radius 4 and y-radius 9, so radius: [4, 9].
Answer: ellipse({ radius: [4, 9] }) — an ellipse with x-radius 4 and y-radius 9.
roundedRectangle(options?) → geom2
Rectangle with rounded corners — useful whenever sharp corners are undesirable on a real part.
| Option | Type | Default | Meaning |
|---|---|---|---|
center |
Array | [0,0] |
center location |
size |
Array | [2,2] |
[width, length] |
roundRadius |
Number | 0.2 |
corner rounding radius |
segments |
Number | 32 |
segments per full rotation |
Sharp corners on a real part can catch, snag, or stress the material. A rounded corner spreads the load and feels better in the hand — that is why phone cases and tool handles use them.
Create a rounded rectangle that is 40 wide and 20 long, with a corner rounding radius of 5. Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need a rounded rectangle, so we use roundedRectangle.
Step 2 — set the size. The size option takes [width, length]. We want width 40 and length 20, so size: [40, 20].
Step 3 — set the corner radius. We want roundRadius: 5.
Answer: roundedRectangle({ size: [40, 20], roundRadius: 5 }) — a 40-by-20 rounded rectangle with corner radius 5.
polygon(options) → geom2
Builds an arbitrary 2D polygon from a list of points. Points must run counter-clockwise.
| Option | Type | Default | Meaning |
|---|---|---|---|
points |
Array | — (required) | flat or nested array of 2D points |
paths |
Array | optional | point indices defining sub-paths |
orientation |
String | 'counterclockwise' |
winding order |
A polygon's points must run counter-clockwise. Think of it as the direction you walk around the shape — JSCAD needs to know which side is the inside, and the winding order tells it.
A polygon's points must run counter-clockwise, or JSCAD can get confused about which side is the inside. Build a triangle whose points already run that way — each comment below is one line for you to write. Press Run when you are done.
Solution
You should see a triangle with vertices at (0,0), (6,0), and (3,5). Going (0,0) → (6,0) → (3,5) walks counter-clockwise, so the winding is correct. List the same three points in the opposite order and run it again — the triangle flips over, because the inside is now on the other side.
Build a triangle polygon from the points (0, 0), (6, 0), and (3, 5). Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need a polygon, so we use polygon.
Step 2 — list the points. The points option takes an array of 2D points. Our three points are [0, 0], [6, 0], and [3, 5].
Step 3 — check the winding order. Going (0,0) → (6,0) → (3,5) runs counter-clockwise, which is the default orientation.
Answer: polygon({ points: [[0, 0], [6, 0], [3, 5]] }) — a triangle with those three vertices.
star(options?) → geom2
Star polygon with a configurable point count and density.
| Option | Type | Default | Meaning |
|---|---|---|---|
center |
Array | [0,0] |
star center |
vertices |
Number | 5 |
number of outer points |
density |
Number | 2 |
star density factor |
outerRadius |
Number | 1 |
outer vertex distance |
innerRadius |
Number | 0 |
inner vertex distance (auto if 0) |
startAngle |
Number | 0 |
angle of the first vertex, radians |
The density factor controls how the points connect. A low density gives a simple star; a higher density makes the points skip and cross, producing a more complex, spiky shape.
Create a star with 6 outer points and an outer radius of 12. Write the JSCAD call.
Solution
Step 1 — pick the primitive. We need a star, so we use star.
Step 2 — set the point count. We want 6 outer points, so vertices: 6.
Step 3 — set the outer radius. We want outerRadius: 12.
Answer: star({ vertices: 6, outerRadius: 12 }) — a 6-point star with outer radius 12.
translate(offset, ...objects) → geom2
Moves a shape by a given offset without changing its size or orientation.
| Option | Type | Default | Meaning |
|---|---|---|---|
offset |
Array | — (required) | [x, y] distance to move the shape |
objects |
geom2 | — (required) | the shape or shapes to move |
The primitives take one options object, but transforms take their settings as plain positional arguments — translate([5, 0], myshape), not translate({ offset: [5, 0] }, myshape). The offset comes first, then the shape.
Transforms are the way a built shape finds its place on the page. Here a rectangle is built at the origin and then nudged to the right — each comment below is one line for you to write. Press Run when you are done.
Solution
You should see the same 10-by-20 rectangle, but 5 units further right. The offset comes first and the shape second — translate([5, 0], myshape), not the other way round. Change the offset to [0, 5] and run it again to move it up instead.
Move a 10-by-20 rectangle 5 units to the right. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a rectangle, so we use rectangle with size: [10, 20].
Step 2 — pick the transform. We are moving the shape, so we use translate.
Step 3 — pass the offset and the shape. The offset is [5, 0] (5 right, 0 up), and the shape comes second.
Answer: translate([5, 0], rectangle({ size: [10, 20] })) — the rectangle shifted 5 units to the right.
rotate(angles, ...objects) → geom2
Turns a shape around the origin by the given angles.
| Option | Type | Default | Meaning |
|---|---|---|---|
angles |
Array | — (required) | [x, y, z] rotation in radians |
objects |
geom2 | — (required) | the shape or shapes to rotate |
JSCAD measures rotation in radians, not degrees. A full turn is TAU (about 6.28) radians, so a quarter turn is Math.PI / 2. For 2D work you rotate around the z axis, and rotateZ(angle, myshape) is a handy shortcut for rotate([0, 0, angle], myshape).
Rotate a 10-by-20 rectangle by a quarter turn. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a rectangle, so we use rectangle with size: [10, 20].
Step 2 — pick the transform. We are turning the shape, so we use rotate.
Step 3 — pass the angles and the shape. A quarter turn is Math.PI / 2 radians around the z axis, so the angles are [0, 0, Math.PI / 2].
Answer: rotate([0, 0, Math.PI / 2], rectangle({ size: [10, 20] })) — the rectangle turned a quarter turn.
scale(factors, ...objects) → geom2
Stretches or shrinks a shape by the given factors along each axis.
| Option | Type | Default | Meaning |
|---|---|---|---|
factors |
Array | — (required) | [x, y] multiplier along each axis |
objects |
geom2 | — (required) | the shape or shapes to scale |
A factor of 2 doubles the shape along that axis, and a factor of 0.5 halves it. A factor of 1 leaves that axis unchanged. Unequal factors stretch the shape out of proportion.
Double the width of a 10-by-20 rectangle. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a rectangle, so we use rectangle with size: [10, 20].
Step 2 — pick the transform. We are resizing the shape, so we use scale.
Step 3 — pass the factors and the shape. Doubling the width means an x factor of 2; the y factor stays 1.
Answer: scale([2, 1], rectangle({ size: [10, 20] })) — the rectangle now 20 wide and 20 long.
mirror(options, ...objects) → geom2
Flips a shape across a mirror plane.
| Option | Type | Default | Meaning |
|---|---|---|---|
normal |
Array | [0,0,1] |
direction perpendicular to the mirror plane |
origin |
Array | [0,0,0] |
a point the mirror plane passes through |
objects |
geom2 | — (required) | the shape or shapes to mirror |
A mirror plane is the flat surface the shape is flipped across, like a pane of glass. It is defined by a point on it (origin) and a direction pointing straight out of it (normal). A normal of [0, 1, 0] mirrors across the x axis.
Mirroring an already-symmetric shape teaches nothing — it looks the same after the flip. Start from an off-centre triangle so the mirror actually moves it, and pick the right normal — each comment below is one line for you to write. Press Run when you are done.
Solution
You should see a second triangle below the x axis, the mirror image of the first. The normal [0, 1, 0] points along y, so the plane it describes is the x axis. Change the normal to [1, 0, 0] and run it again to flip across the y axis instead.
Flip the triangle with vertices (0, 0), (10, 0), and (5, 8) across the x axis. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a triangle, so we build it with polygon from its three points.
Step 2 — pick the transform. We are flipping the shape, so we use mirror.
Step 3 — set the mirror plane. Flipping across the x axis means the plane's normal points along y, so normal: [0, 1, 0].
Answer: mirror({ normal: [0, 1, 0] }, polygon({ points: [[0, 0], [10, 0], [5, 8]] })) — the triangle flipped across the x axis.
center(options, ...objects) → geom2
Centers a shape on the origin along the chosen axes.
| Option | Type | Default | Meaning |
|---|---|---|---|
axes |
Array | [true,true,true] |
which axes to center on |
relativeTo |
Array | [0,0,0] |
point to center relative to |
objects |
geom2 | — (required) | the shape or shapes to center |
Centering slides a shape so its middle sits on the origin — it does not change the shape's size. The axes array tells JSCAD which directions to center in; a false leaves that axis alone.
Center a 10-by-20 rectangle on the origin. The rectangle's center is [12, 8], so it starts off-centre. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a rectangle, so we use rectangle with size: [10, 20]. We also pass center: [12, 8] so the rectangle starts off-centre and the centering visibly moves it.
Step 2 — pick the transform. We are centering the shape, so we use center.
Step 3 — set the axes. We want to center on both x and y, so axes: [true, true, false].
Answer: center({ axes: [true, true, false] }, rectangle({ size: [10, 20], center: [12, 8] })) — the rectangle slides from [12, 8] to sit centered on the origin.
align(options, ...objects) → geom2
Aligns a shape to a reference point along each axis.
| Option | Type | Default | Meaning |
|---|---|---|---|
modes |
Array | ['center','center','min'] |
how to align on each axis |
relativeTo |
Array | [0,0,0] |
point to align to |
grouped |
Boolean | false |
align shapes as one group |
objects |
geom2 | — (required) | the shape or shapes to align |
Each axis has a mode: min puts the shape's low edge on the reference, max puts the high edge there, and center puts the middle there. The default centers on x and y and sets the low edge on z.
Align a 10-by-20 rectangle so its low edge sits on the x axis. The rectangle's center is [12, 8], so it starts off-centre and aligning visibly moves it. Write the JSCAD call.
Solution
Step 1 — build the shape. We need a rectangle, so we use rectangle with size: [10, 20]. We also pass center: [12, 8] so the rectangle starts off-centre and the aligning visibly moves it.
Step 2 — pick the transform. We are aligning the shape, so we use align.
Step 3 — set the modes. We want the low edge on y, so the y mode is min; the x mode can stay center.
Answer: align({ modes: ['center', 'min', 'min'] }, rectangle({ size: [10, 20], center: [12, 8] })) — the rectangle's low edge slides to the x axis.
Problem Set
Problem 1. Write a JSCAD call that creates a rectangle 50 wide and 25 long.
Problem 2. Write a JSCAD call that creates a circle with radius 7 centered at (1, 1).
Problem 3. Write a JSCAD call that creates an ellipse with x-radius 3 and y-radius 6.
Problem 4. Write a JSCAD call that creates a rounded rectangle 30 by 15 with a corner radius of 3.
Problem 5. Write a JSCAD call that builds a square polygon from the points (0, 0), (4, 0), (4, 4), and (0, 4).
Problem 6. Write a JSCAD call that creates a star with 5 outer points and an outer radius of 8.
Problem 7. Write a JSCAD call that moves a 10-by-20 rectangle 5 units to the right.
Problem 8. Write a JSCAD call that rotates a 10-by-20 rectangle by a quarter turn.
Problem 9. Write a JSCAD call that doubles the width of a 10-by-20 rectangle.
Problem 10. Write a JSCAD call that flips the triangle with vertices (0, 0), (10, 0), and (5, 8) across the x axis.
Problem 11. Write a JSCAD call that centers a 10-by-20 rectangle (whose center is [12, 8]) on the origin.
Problem 12. Write a JSCAD call that aligns a 10-by-20 rectangle (whose center is [12, 8]) so its low edge sits on the x axis.
Key Terms
primitive — a basic built-in shape (rectangle, circle, ellipse, polygon, star) that JSCAD can create.
geom2 — the object type JSCAD uses to represent a 2D geometry.
option — a setting passed to a primitive inside a single object, such as size or radius.
axis-aligned — running straight along the x and y axes, with no tilt.
segments — the straight divisions used to build a curved shape; more segments means a smoother curve.
winding order — the direction (counter-clockwise) in which a polygon's points are listed.
transform — an operation that moves, rotates, resizes, flips, or aligns an existing shape.
radians — the unit JSCAD uses for angles; a full turn is TAU radians.
mirror plane — the flat surface a shape is flipped across when mirrored.