9.2 3D Primitives and Transforms

Aligned outcomes:

SLO 3

Describe, design, implement, and test structured programs using currently accepted methodology.

SLO 4

Explain what an algorithm is and its importance in computer programming.

Learning Objectives

By the end of this section, you will be able to:

In this section, you will learn to:
  • name the main 3D primitives in JSCAD and describe what each one builds;
  • read each primitive's options table and predict the shape it produces;
  • choose the right primitive for a part you want to model;
  • move, rotate, and resize a solid with the translate, rotate, and scale transforms;
  • flip, center, and align a solid with the mirror, center, and align transforms;
  • combine transforms and predict how their order changes the result.

cube

The cube(options?) function returns a geom3 — an axis-aligned solid cube with six equal square faces.

Option Type Default Meaning
center Array [0,0,0] cube center
size Number 2 edge length
A cube is a box with equal sides

A cube is the simplest 3D solid: every edge is the same length. It is a good starting point when you want a plain, blocky part.

Editor
renders in your browser

size is one number

Unlike a box, a cube has only one size value because all three dimensions are equal. If you need different width, depth, and height, you want cuboid instead.

Try It Now 9.2.1

Write a call to cube that creates a cube with edge length 4 centered at the origin.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a cube, so we use cube.

Step 2 — set the size: The edge length is 4, so size: 4.

Step 3 — write the call:

Editor
renders in your browser

Answer: cube({ size: 4 }) creates a cube with edge length 4 centered at [0,0,0].

cuboid

The cuboid(options?) function is like cube, but it lets you set independent width, depth, and height.

Option Type Default Meaning
center Array [0,0,0] cuboid center
size Array [2,2,2] [width, depth, height]
A box for real parts

Most real parts are not perfect cubes. A phone case, a book, or a board is a box with different dimensions, so cuboid is the shape you reach for most often.

Editor
renders in your browser

Order matters

The size array is always [width, depth, height]. Mixing up the order gives you a box with the wrong proportions, so keep the order in mind.

Try It Now 9.2.2

Write a call to cuboid that creates a box 6 wide, 2 deep, and 8 tall.

Editor
renders in your browser

Solution

Step 1 — pick the function: We need different dimensions, so we use cuboid.

Step 2 — set the size array: Width 6, depth 2, height 8 gives size: [6, 2, 8].

Step 3 — write the call:

Editor
renders in your browser

Answer: cuboid({ size: [6, 2, 8] }) creates a box 6 wide, 2 deep, and 8 tall.

sphere

The sphere(options?) function returns a geom3 where every surface point is an equal distance from the center.

Option Type Default Meaning
center Array [0,0,0] sphere center
radius Number 1 distance from center
segments Number 32 divisions per full rotation
axes Array optional three basis vectors for x/y/z
A ball, not a circle

A sphere is the 3D version of a circle. Every point on its surface is the same distance from the center, which is exactly what the radius option sets.

Editor
renders in your browser

segments smooths the ball

Like the rotation in the last section, a sphere is drawn with segments. More segments means a smoother ball; fewer means a faceted, gem-like shape.

Try It Now 9.2.3

Write a call to sphere that creates a sphere with radius 3.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a sphere, so we use sphere.

Step 2 — set the radius: The radius is 3, so radius: 3.

Step 3 — write the call:

Editor
renders in your browser

Answer: sphere({ radius: 3 }) creates a sphere with radius 3 centered at the origin.

cylinder

The cylinder(options?) function returns a geom3 — a Z-axis aligned solid cylinder.

Option Type Default Meaning
center Array [0,0,0] cylinder center
height Number 2 vertical extent
radius Number 1 radius
segments Number 32 divisions per full rotation
A can shape

A cylinder is like a soup can: a circular top and bottom with straight sides. It is the shape you want for a wheel, a pipe, or a peg.

Editor
renders in your browser

Height and radius are separate

The height controls how tall the can is, and the radius controls how wide its circular face is. Change one without the other and you get a taller or wider can.

Try It Now 9.2.4

Write a call to cylinder that creates a cylinder with height 5 and radius 2.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a cylinder, so we use cylinder.

Step 2 — set the options: Height 5 and radius 2 give { height: 5, radius: 2 }.

Step 3 — write the call:

Editor
renders in your browser

Answer: cylinder({ height: 5, radius: 2 }) creates a cylinder 5 tall with radius 2.

torus

The torus(options?) function returns a geom3 — a small circle swept around a larger circular path.

Option Type Default Meaning
innerRadius Number 1 radius of the small (tube) circle
outerRadius Number 4 radius of the large (path) circle
innerSegments Integer 32 divisions of the small circle
outerSegments Integer 32 divisions of the rotation
innerRotation Integer 0 small-circle angle, radians
outerRotation Number TAU rotation of the torus, radians
startAngle Number 0 beginning angle, radians
A donut

A torus is the shape of a donut or a ring. The innerRadius is the thickness of the tube, and the outerRadius is the size of the ring the tube travels around.

Editor
renders in your browser

Two circles, two radii

A torus is really two circles working together. The small circle is the tube's cross-section, and the large circle is the path that tube follows. Each has its own radius.

Try It Now 9.2.5

Write a call to torus that creates a donut with a tube radius of 2 and a ring radius of 10.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a donut, so we use torus.

Step 2 — set the radii: The tube radius is innerRadius: 2, and the ring radius is outerRadius: 10.

Step 3 — write the call:

Editor
renders in your browser

Answer: torus({ innerRadius: 2, outerRadius: 10 }) creates a donut with a tube radius of 2 and a ring radius of 10.

roundedCuboid

The roundedCuboid(options?) function returns a geom3 — a cuboid with rounded edges. It is often preferable for parts that will be handled or 3D-printed.

Option Type Default Meaning
center Array [0,0,0] center location
size Array [2,2,2] [width, depth, height]
roundRadius Number 0.2 radius of the rounded edges
segments Number 32 segments per full rotation
Comfort and print quality

Sharp corners can be uncomfortable to hold and can print poorly. Rounded edges make a part feel nicer in the hand and often print more cleanly, which is why roundedCuboid exists.

Editor
renders in your browser

roundRadius is the corner size

The roundRadius controls how much the sharp corners are rounded off. A small value gives a barely-rounded box; a large value gives a pill-like shape.

Try It Now 9.2.6

Write a call to roundedCuboid that creates a box 8 wide, 4 deep, and 6 tall with rounded edges of radius 1.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a box with rounded edges, so we use roundedCuboid.

Step 2 — set the options: The size array is [8, 4, 6] and the round radius is 1, giving { size: [8, 4, 6], roundRadius: 1 }.

Step 3 — write the call:

Editor
renders in your browser

Answer: roundedCuboid({ size: [8, 4, 6], roundRadius: 1 }) creates a box 8 wide, 4 deep, and 6 tall with rounded edges of radius 1.

roundedCylinder

The roundedCylinder(options?) function returns a geom3 — a cylinder with rounded ends.

Option Type Default Meaning
center Array [0,0,0] center location
height Number 2 cylinder height
radius Number 1 cylinder radius
roundRadius Number 0.2 radius of the rounded edges
segments Number 32 segments per full rotation
A pill shape

A roundedCylinder is like a cylinder whose flat top and bottom have been rounded off, producing a pill or capsule shape. It is useful for parts that will be handled.

Editor
renders in your browser

Same as a cylinder, plus rounding

A roundedCylinder takes all the same options as a cylinder and adds one more: roundRadius, which rounds the ends.

Try It Now 9.2.7

Write a call to roundedCylinder that creates a cylinder with height 6, radius 3, and rounded ends of radius 0.5.

Editor
renders in your browser

Solution

Step 1 — pick the function: We want a cylinder with rounded ends, so we use roundedCylinder.

Step 2 — set the options: Height 6, radius 3, and round radius 0.5 give { height: 6, radius: 3, roundRadius: 0.5 }.

Step 3 — write the call:

Editor
renders in your browser

Answer: roundedCylinder({ height: 6, radius: 3, roundRadius: 0.5 }) creates a cylinder 6 tall with radius 3 and rounded ends.

translate(offset, ...objects) → geom3

Moves a solid by a given offset without changing its size or orientation.

Option Type Default Meaning
offset Array — (required) [x, y, z] distance to move the solid
objects geom3 — (required) the solid or solids to move
Editor
renders in your browser

Positional arguments, not an options object

The primitives take one options object, but transforms take their settings as plain positional arguments — translate([5, 0, 3], myshape), not translate({ offset: [5, 0, 3] }, myshape). The offset comes first, then the solid.

Try It Now 9.2.8

Move a 10-by-20-by-5 box 5 units to the right and 3 units up. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5].

Step 2 — pick the transform. We are moving the solid, so we use translate.

Step 3 — pass the offset and the solid. The offset is [5, 0, 3] (5 right, 0 deep, 3 up), and the solid comes second.

Editor
renders in your browser

Answer: translate([5, 0, 3], cuboid({ size: [10, 20, 5] })) — the box shifted 5 units right and 3 units up.

rotate(angles, ...objects) → geom3

Turns a solid around the origin by the given angles.

Option Type Default Meaning
angles Array — (required) [x, y, z] rotation in radians
objects geom3 — (required) the solid or solids to rotate
Editor
renders in your browser

The third dimension finally tilts

In 2D, rotating around x or y did nothing visible because the shape had no thickness there. A solid has real depth, so rotateX or rotateY now tips the whole part over — a rotation that was a no-op in the last section is a real move here. Angles are still in radians, and rotateX(angle, myshape) is a shortcut for rotate([angle, 0, 0], myshape).

Example 9.2.1: Tipping a box with rotate

A rotation that was a no-op in 2D becomes a real move on a solid, because a box has thickness. Build a box and tip it a quarter turn around the x axis — each comment below is one line for you to write. Press Run when you are done.

Editor
renders in your browser

Solution
Editor
renders in your browser

You should see the box tipped a quarter turn around the x axis, so the axis that used to point up now points sideways. In 2D this rotation did nothing because the shape had no thickness there; the box's depth is what lets it tip over. Change the angle to Math.PI and run again to flip it all the way upside down.

Try It Now 9.2.9

Rotate a 10-by-20-by-5 box a quarter turn around the x axis. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5].

Step 2 — pick the transform. We are turning the solid, so we use rotate.

Step 3 — pass the angles and the solid. A quarter turn is Math.PI / 2 radians around the x axis, so the angles are [Math.PI / 2, 0, 0].

Editor
renders in your browser

Answer: rotate([Math.PI / 2, 0, 0], cuboid({ size: [10, 20, 5] })) — the box tipped a quarter turn around the x axis.

scale(factors, ...objects) → geom3

Stretches or shrinks a solid by the given factors along each axis.

Option Type Default Meaning
factors Array — (required) [x, y, z] multiplier along each axis
objects geom3 — (required) the solid or solids to scale
Editor
renders in your browser

Scaling is a multiplier, not a size

A factor of 2 doubles the solid along that axis, and a factor of 0.5 halves it. A factor of 1 leaves that axis unchanged. In 3D the factors array has three entries, one per axis, and unequal factors stretch the part out of proportion.

Try It Now 9.2.10

Double the width and triple the height of a 10-by-20-by-5 box. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5].

Step 2 — pick the transform. We are resizing the solid, so we use scale.

Step 3 — pass the factors and the solid. Doubling the width means an x factor of 2; tripling the height means a z factor of 3; the depth stays 1.

Editor
renders in your browser

Answer: scale([2, 1, 3], cuboid({ size: [10, 20, 5] })) — the box now 20 wide, 20 deep, and 15 tall.

mirror(options, ...objects) → geom3

Flips a solid 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 geom3 — (required) the solid or solids to mirror
Editor
renders in your browser

The mirror plane

A mirror plane is the flat surface the solid 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 [1, 0, 0] mirrors across the y-z plane. Mirroring a solid that is symmetric about that plane is a no-op, so start from an off-centre part to see the flip.

Try It Now 9.2.11

Flip a 10-by-20-by-5 box (whose center is [5, 0, 0]) across the y-z plane. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5]. We also pass center: [5, 0, 0] so the box starts off-centre and the mirror visibly moves it.

Step 2 — pick the transform. We are flipping the solid, so we use mirror.

Step 3 — set the mirror plane. Flipping across the y-z plane means the plane's normal points along x, so normal: [1, 0, 0].

Editor
renders in your browser

Answer: mirror({ normal: [1, 0, 0] }, cuboid({ size: [10, 20, 5], center: [5, 0, 0] })) — the box flipped from [5, 0, 0] to [-5, 0, 0].

center(options, ...objects) → geom3

Centers a solid 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 geom3 — (required) the solid or solids to center
Editor
renders in your browser

Centering is a move, not a resize

Centering slides a solid so its middle sits on the origin — it does not change the solid's size. The axes array tells JSCAD which directions to center in; a false leaves that axis alone. In 3D there are three axes to choose from, and the default centers on all of them.

Try It Now 9.2.12

Center a 10-by-20-by-5 box on the origin. The box's center is [12, 8, 3], so it starts off-centre. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5]. We also pass center: [12, 8, 3] so the box starts off-centre and the centering visibly moves it.

Step 2 — pick the transform. We are centering the solid, so we use center.

Step 3 — set the axes. We want to center on all three axes, so axes: [true, true, true].

Editor
renders in your browser

Answer: center({ axes: [true, true, true] }, cuboid({ size: [10, 20, 5], center: [12, 8, 3] })) — the box slides from [12, 8, 3] to sit centered on the origin.

align(options, ...objects) → geom3

Aligns a solid 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 solids as one group
objects geom3 — (required) the solid or solids to align
Editor
renders in your browser

Align modes pick the edge

Each axis has a mode: min puts the solid'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 — and in 3D that third mode finally matters, because a solid has a real bottom to sit on.

Try It Now 9.2.13

Align a 10-by-20-by-5 box so its low edge sits on the x-y plane. The box's center is [12, 8, 3], so it starts off-centre and aligning visibly moves it. Write the JSCAD call.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5]. We also pass center: [12, 8, 3] so the box starts off-centre and the aligning visibly moves it.

Step 2 — pick the transform. We are aligning the solid, so we use align.

Step 3 — set the modes. We want the low edge on z, so the z mode is min; the x and y modes can stay center.

Editor
renders in your browser

Answer: align({ modes: ['center', 'center', 'min'] }, cuboid({ size: [10, 20, 5], center: [12, 8, 3] })) — the box's low edge slides down to the x-y plane.

Combining transforms

You can chain transforms on one solid, but the order matters because rotation is about the origin.

Transform Effect
translate then rotate the solid moves first, then the whole moved result spins around the origin
rotate then translate the solid spins in place first, then the tilted result moves
Editor
renders in your browser

Editor
renders in your browser

Order changes the result

translate then rotate moves the box to [5, 0, 0] and then spins that whole moved box around the origin, so it ends up far from where it started. rotate then translate tips the box in place and then slides the tilted box over — a different position. This is the single most common 3D student error, and the fix is to read the call from the inside out: the innermost transform runs first.

Example 9.2.2: Ordering a transform chain

The order you nest transforms changes the final position, because rotation happens about the origin. Build a box, rotate it, then move it — reading the call from the inside out. Each comment below is one line for you to write. Press Run when you are done.

Editor
renders in your browser

Solution
Editor
renders in your browser

You should see the box tipped a quarter turn around x, then slid 5 units to the right. Read it from the inside out: the innermost call (rotate) runs first, then translate wraps the result. Reverse the order — rotate([Math.PI / 2, 0, 0], translate([5, 0, 0], myshape)) — and run again: the box moves first, then the moved box spins around the origin, landing somewhere completely different.

Try It Now 9.2.14

Write the JSCAD call that rotates a 10-by-20-by-5 box a quarter turn around the x axis and then moves it 5 units to the right.

Editor
renders in your browser

Solution

Step 1 — build the shape. We need a box, so we use cuboid with size: [10, 20, 5].

Step 2 — read the order from the inside out. We want to rotate first, then move, so the rotate call is the inner argument and translate wraps it.

Step 3 — write the call. The rotation is Math.PI / 2 around x, and the move is [5, 0, 0].

Editor
renders in your browser

Answer: translate([5, 0, 0], rotate([Math.PI / 2, 0, 0], cuboid({ size: [10, 20, 5] }))) — the box tips a quarter turn around x, then slides 5 units right.

Problem Set

Problem 1. What is the difference between cube and cuboid?

Problem 2. What does the radius option control in sphere?

Problem 3. What does the height option control in cylinder?

Problem 4. In torus, what do innerRadius and outerRadius each control?

Problem 5. What does the roundRadius option do in roundedCuboid and roundedCylinder?

Problem 6. Write a call to cuboid that creates a box 10 wide, 5 deep, and 3 tall.

Problem 7. Write a call to cylinder that creates a cylinder with height 8 and radius 4.

Problem 8. Write a call to torus that creates a donut with a tube radius of 3 and a ring radius of 15.

Problem 9. Write a JSCAD call that moves a 10-by-20-by-5 box 5 units to the right and 3 units up.

Problem 10. Write a JSCAD call that rotates a 10-by-20-by-5 box a quarter turn around the x axis.

Problem 11. Write a JSCAD call that doubles the width and triples the height of a 10-by-20-by-5 box.

Problem 12. Write a JSCAD call that flips a 10-by-20-by-5 box (whose center is [5, 0, 0]) across the y-z plane.

Problem 13. Write a JSCAD call that centers a 10-by-20-by-5 box (whose center is [12, 8, 3]) on the origin.

Problem 14. Write a JSCAD call that aligns a 10-by-20-by-5 box (whose center is [12, 8, 3]) so its low edge sits on the x-y plane.

Problem 15. Write a JSCAD call that rotates a 10-by-20-by-5 box a quarter turn around the x axis and then moves it 5 units to the right.

Key Terms

primitive — a basic, ready-made 3D shape such as a cube, sphere, or cylinder.

axis-aligned — aligned with the x, y, and z axes of the coordinate system.

radius — the distance from the center of a shape to its surface.

geom3 — the object type JSCAD uses to represent a 3D geometry.

transform — an operation that moves, rotates, resizes, flips, or aligns an existing solid.

radians — the unit JSCAD uses for angles; a full turn is TAU radians.

mirror plane — the flat surface a solid is flipped across when mirrored.