0 / 18 done
Chapter 2 of 6

Fancy Shapes

Work with multiple pens, colours, fill, and variables to create diamonds, crosses, snowflakes, and complex polygons — building a deeper understanding of geometry in the process.

Adding Pens

Discover how to use the addShape(pen:) call and what happens when you create multiple independent pens on the same canvas.

Rendering Shapes

Each pen tracks its own path independently. To display a pen's path on the canvas you must call addShape(pen:). You can call it once at the end, or after each pen individually.

Swift
var p1 = Pen()
p1.addLine(distance: 100)
addShape(pen: p1)   // render p1's path

var p2 = Pen()
p2.turn(degrees: 90)
p2.addLine(distance: 100)
addShape(pen: p2)   // render p2's path
Two Lines
IM1 Curriculum Connections
IM1 ConceptConnection
Coordinate geometryEach pen starts at the origin — independent paths share the same coordinate system
Line segmentsEach addLine call produces a directed segment with defined start and end points

Multiple Pens

Draw two separate squares side-by-side using two independent pens — one starting at the origin and the other offset to the right.

Your Task

Create two pens. Draw a 100-unit square with p1 starting at the origin. Then use p2 — start it at (150, 0) using move(distance:) or by setting its position — and draw a second 100-unit square.

Swift
var p1 = Pen()
// Draw first square with p1

var p2 = Pen()
// Position p2 and draw second square

addShape(pen: p1)
addShape(pen: p2)
Two Lines
Swift
var p1 = Pen()
p1.addLine(distance: 100); p1.turn(degrees: 90)
p1.addLine(distance: 100); p1.turn(degrees: 90)
p1.addLine(distance: 100); p1.turn(degrees: 90)
p1.addLine(distance: 100)
addShape(pen: p1)

var p2 = Pen()
p2.move(distance: 150)  // move right without drawing
p2.addLine(distance: 100); p2.turn(degrees: 90)
p2.addLine(distance: 100); p2.turn(degrees: 90)
p2.addLine(distance: 100); p2.turn(degrees: 90)
p2.addLine(distance: 100)
addShape(pen: p2)
IM1 Curriculum Connections
IM1 ConceptConnection
TranslationsOffsetting p2 by 150 units is a translation — a rigid motion that shifts every point the same distance
CongruenceBoth squares are congruent — same shape, same size, different position

Turning Both Ways

Explore negative degree values — turning right (clockwise) instead of left — and understand how this unlocks a wider range of shapes.

Positive vs Negative Turns

A positive turn angle rotates the pen anti-clockwise (left). A negative angle rotates it clockwise (right). This matches standard mathematical convention.

Swift
p.turn(degrees:  90)  // rotate LEFT  90° (anti-clockwise)
p.turn(degrees: -90)  // rotate RIGHT 90° (clockwise)
Two Lines
IM1 Curriculum Connections
IM1 ConceptConnection
Directed anglesPositive = anti-clockwise, negative = clockwise — this is the convention used in trigonometry and coordinate geometry
RotationsTurning the pen is equivalent to a rotation of the direction vector around the pen's current position

Two Squares

Draw a large square (200 units) and a small square (100 units) that shares the same bottom-left corner — creating a nested effect.

Your Task

Use a single pen to draw both squares without lifting it (use move to reposition if needed), or use two separate pens.

Swift
var p = Pen()
// Draw large square (200 units)
// Draw small square (100 units)
addShape(pen: p)
✏️
02-04-two-squares.png Screenshot: large and small square sharing the same bottom-left corner
Swift
var p = Pen()
// Large square: 200 units
p.addLine(distance: 200); p.turn(degrees: 90)
p.addLine(distance: 200); p.turn(degrees: 90)
p.addLine(distance: 200); p.turn(degrees: 90)
p.addLine(distance: 200); p.turn(degrees: 90)
// Small square: 100 units
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
SimilarityThe two squares are similar — same shape but different sizes, with a scale factor of 2:1
PerimeterPerimeter of large square = 4 × 200 = 800; small = 4 × 100 = 400

Thicker Lines

Use the lineWidth property to draw a bold triangle — and explore how stroke width affects a shape's visual weight.

Your Task

Draw an equilateral triangle (3 sides, turning 120° at each corner) with a lineWidth of 6.

Swift
var p = Pen()
p.lineWidth = 6
// Draw equilateral triangle
addShape(pen: p)
✏️
02-05-thicker-lines.png Screenshot: equilateral triangle drawn with a thick stroke
Swift
var p = Pen()
p.lineWidth = 6
p.addLine(distance: 150); p.turn(degrees: 120)
p.addLine(distance: 150); p.turn(degrees: 120)
p.addLine(distance: 150)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
Equilateral triangleAll three sides equal; all interior angles = 60°; exterior turn = 120°
Exterior angle theorem360° ÷ 3 sides = 120° per turn; verifies sum of exterior angles = 360°

Coloured Triangle

Draw a triangle where each side is a different colour — green, red, and blue — by changing penColor between sides.

Your Task

Use three pens (or change the colour on one pen before each side) to produce a triangle with sides in three different colours.

Swift
var p = Pen()
p.penColor = .green
p.addLine(distance: 150)
p.turn(degrees: 120)
// Continue for red and blue sides…
addShape(pen: p)
✏️
02-06-coloured-triangle.png Screenshot: equilateral triangle with green, red, and blue sides
Swift
var p = Pen()
p.penColor = .green
p.addLine(distance: 150); p.turn(degrees: 120)
p.penColor = .red
p.addLine(distance: 150); p.turn(degrees: 120)
p.penColor = .blue
p.addLine(distance: 150)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
Triangle classificationEquilateral — three sides equal, three angles equal (60° each)
Angle sumInterior angles of any triangle sum to 180°

Diamond

Draw a diamond (rhombus) with equal sides but non-right angles — using turn angles less than and greater than 90°.

Your Task

Draw a diamond with side length 150 and interior angles of 60° and 120°. Hint: the exterior turns will be 120° and 60° alternating.

Swift
var p = Pen()
// 4 equal sides, alternating turns
addShape(pen: p)
✏️
02-07-diamond.png Screenshot: diamond shape with 60° and 120° interior angles
Swift
var p = Pen()
p.addLine(distance: 150); p.turn(degrees: 60)
p.addLine(distance: 150); p.turn(degrees: 120)
p.addLine(distance: 150); p.turn(degrees: 60)
p.addLine(distance: 150)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
Rhombus properties4 equal sides; opposite angles equal; diagonals bisect each other at right angles
Supplementary anglesAdjacent interior angles sum to 180°: 60° + 120° = 180°

Fill It In

Learn about the fillColor property to colour the interior of closed shapes.

Adding Fill

Setting fillColor on a pen before drawing will colour the enclosed area of a closed shape. The path must be closed (return to its starting point) for fill to work correctly.

Swift
var p = Pen()
p.fillColor = .yellow
p.penColor = .orange
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100)
addShape(pen: p)
🟨
02-08-fill-it-in.png Screenshot: yellow-filled square with orange border
IM1 Curriculum Connections
IM1 ConceptConnection
Area vs perimeterFill occupies the interior (area); the pen line defines the boundary (perimeter)
Closed figuresA shape must be topologically closed for fill to render — a key property in geometry

Coloured Squares

Draw three filled squares in a row — red, green, and blue — each 80 units wide with a 20-unit gap between them.

Your Task

Use three separate pens positioned at different x-coordinates. Give each pen a different fillColor.

Swift
// Three pens at x = 0, 100, 200
// Each draws an 80×80 filled square
✏️
02-09-coloured-squares.png Screenshot: three filled squares in red, green, and blue side by side
Swift
var p1 = Pen()
p1.fillColor = .red
p1.addLine(distance: 80); p1.turn(degrees: 90)
p1.addLine(distance: 80); p1.turn(degrees: 90)
p1.addLine(distance: 80); p1.turn(degrees: 90)
p1.addLine(distance: 80)
addShape(pen: p1)

var p2 = Pen()
p2.move(distance: 100)
p2.fillColor = .green
p2.addLine(distance: 80); p2.turn(degrees: 90)
p2.addLine(distance: 80); p2.turn(degrees: 90)
p2.addLine(distance: 80); p2.turn(degrees: 90)
p2.addLine(distance: 80)
addShape(pen: p2)

var p3 = Pen()
p3.move(distance: 200)
p3.fillColor = .blue
p3.addLine(distance: 80); p3.turn(degrees: 90)
p3.addLine(distance: 80); p3.turn(degrees: 90)
p3.addLine(distance: 80); p3.turn(degrees: 90)
p3.addLine(distance: 80)
addShape(pen: p3)
IM1 Curriculum Connections
IM1 ConceptConnection
AreaEach square: area = 80² = 6400 square units; total area = 3 × 6400 = 19,200
TranslationsEach square is a translated copy — same shape, size, and orientation at a different position

Variables

Store sizes in variables so you can change your shape's dimensions in one place and have the whole drawing update automatically.

Using Variables for Dimensions

A variable is a named container for a value. By storing a side length in a variable, changing it once updates the entire drawing.

Swift
let side = 120.0   // change this one value to resize everything
var p = Pen()
p.addLine(distance: side); p.turn(degrees: 90)
p.addLine(distance: side); p.turn(degrees: 90)
p.addLine(distance: side); p.turn(degrees: 90)
p.addLine(distance: side)
addShape(pen: p)

Variables vs Constants

You may have noticed two different keywords in Swift: var and let. They both name a value — but behave differently.

KeywordNameCan it change?Use it for…
varVariableYesThings that change over time — like a Pen as it moves and turns
letConstantNoFixed values that should stay the same — like a side length you set once
Swift
let side = 100.0   // constant — the value is fixed
var p = Pen()      // variable — p changes as we call methods on it

Use let when a value should never change after you set it — Swift will warn you if you accidentally try to modify it. Use var when the value needs to change (or when Swift requires it, as with Pen).

✏️
02-10-variables.png Screenshot: square drawn using a variable side length
IM1 Curriculum Connections
IM1 ConceptConnection
Variables & expressionsSide length s is a variable; perimeter = 4s and area = s² are expressions derived from it
GeneralisationWriting a formula in terms of a variable generalises from specific numbers to all cases

House

Combine a square base and a triangular roof to draw a simple house shape using two pens or careful repositioning.

Your Task

Draw a square (100 units) for the walls, then continue from the top-left corner to draw an isosceles triangle roof. The roof peak should be centred above the square.

Swift
var p = Pen()
// Square body + triangular roof
addShape(pen: p)
✏️
02-11-house.png Screenshot: square base with triangular roof forming a house outline
Swift
var p = Pen()
// Square base
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
p.addLine(distance: 100); p.turn(degrees: 90)
// Move to top-left of square
p.turn(degrees: 90)
p.move(distance: 100)
p.turn(degrees: -90)
// Roof: two sides at 30° from horizontal, meeting at apex
p.turn(degrees: 30)
p.addLine(distance: 57.74)
p.turn(degrees: 120)
p.addLine(distance: 57.74)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
Composite figuresTotal area = area of square + area of triangle — composites are decomposed into simpler shapes
Isosceles triangleRoof triangle has two equal sides and two equal base angles

Calculate

Use Swift arithmetic to compute side lengths and angles — let the code do the maths rather than calculating by hand.

Your Task

Draw a regular hexagon. Instead of calculating the turn angle yourself, store the number of sides in a constant and use 360.0 / 6 to let Swift compute it. Then write one addLine and one turn for each of the six sides.

Swift
let sides = 6
let turn = 360.0 / Double(sides)
var p = Pen()
// Draw each of the 6 sides using 'turn'
addShape(pen: p)
✏️
02-12-calculate.png Screenshot: regular hexagon drawn using a calculated turn angle
Swift
let sides = 6
let turn = 360.0 / Double(sides)
var p = Pen()
p.addLine(distance: 100); p.turn(degrees: turn)
p.addLine(distance: 100); p.turn(degrees: turn)
p.addLine(distance: 100); p.turn(degrees: turn)
p.addLine(distance: 100); p.turn(degrees: turn)
p.addLine(distance: 100); p.turn(degrees: turn)
p.addLine(distance: 100); p.turn(degrees: turn)
addShape(pen: p)
IM1 Curriculum Connections
IM1 ConceptConnection
Regular polygonsExterior angle = 360° ÷ n; interior angle = 180° − (360° ÷ n)
Algebraic reasoningExpressing the angle as 360/n generalises the formula for all regular polygons

Variable House

Refactor the House exercise using a variable for the house width, so you can resize the whole building by changing one number.

Your Task

Store the house width in a variable w. The roof height and angles should be derived from w using arithmetic, so the shape scales correctly.

Swift
let w = 120.0   // change this to resize the house
var p = Pen()
// Use w throughout
addShape(pen: p)
✏️
02-13-variable-house.png Screenshot: house shape drawn using a variable width
IM1 Curriculum Connections
IM1 ConceptConnection
Proportional reasoningScaling all dimensions by the same factor produces a similar figure
Variables in geometryWriting perimeter/area formulas in terms of w models geometric relationships algebraically

Red Cross

Draw a filled red cross (plus sign) shape — a composite figure made from rectangles.

Your Task

A cross can be drawn as a 12-sided polygon. Start at the bottom-left of the lower arm and work around the perimeter, alternating between long (100) and short (40) sides.

Swift
var p = Pen()
p.fillColor = .red
p.penColor = .red
// 12 sides, 4 outer corners (90°), 8 inner corners (-90°)
addShape(pen: p)
✏️
02-14-red-cross.png Screenshot: filled red cross (plus sign) shape
IM1 Curriculum Connections
IM1 ConceptConnection
Area of composite figuresCross area = 3 rectangles overlapping; use inclusion-exclusion: 3(100×40) − 2(40×40)
Perimeter of irregular shapesCount each boundary segment: 4 long sides + 8 short sides

Simple Snowflake

Draw 6 arms radiating from the centre — each arm a straight line — to create a basic snowflake with 6-fold symmetry.

Your Task

Draw 6 arms of equal length, each rotated 60° from the last. After each arm, return to the centre.

Swift
var p = Pen()
// Arm 1
p.addLine(distance: 100); p.move(distance: -100); p.turn(degrees: 60)
// Arm 2
p.addLine(distance: 100); p.move(distance: -100); p.turn(degrees: 60)
// Arm 3
p.addLine(distance: 100); p.move(distance: -100); p.turn(degrees: 60)
// Arm 4
p.addLine(distance: 100); p.move(distance: -100); p.turn(degrees: 60)
// Arm 5
p.addLine(distance: 100); p.move(distance: -100); p.turn(degrees: 60)
// Arm 6
p.addLine(distance: 100)
addShape(pen: p)
✏️
02-15-simple-snowflake.png Screenshot: 6-arm snowflake radiating from the centre
IM1 Curriculum Connections
IM1 ConceptConnection
Rotational symmetryA 6-arm snowflake has order-6 rotational symmetry — it maps onto itself after 60° rotations
Angles at a point6 arms × 60° = 360° — the angles around the centre sum to one full rotation

Parallel Lines

Draw four horizontal parallel lines — equally spaced — demonstrating lines that never meet.

Your Task

Draw 4 horizontal lines, each 200 units long, spaced 40 units apart vertically. Use 4 pens — start each one at a different height using turn and move.

Swift
// Line 1 — at y = 0
var p1 = Pen()
p1.addLine(distance: 200)
addShape(pen: p1)

// Line 2 — at y = 40
var p2 = Pen()
// Move p2 up 40 units, then face right again

// Line 3 and 4 — continue the pattern
✏️
02-16-parallel-lines.png Screenshot: four equally-spaced horizontal parallel lines
Swift
// Line 1 — at y = 0
var p1 = Pen()
p1.addLine(distance: 200)
addShape(pen: p1)

// Line 2 — at y = 40
var p2 = Pen()
p2.turn(degrees: 90); p2.move(distance: 40); p2.turn(degrees: -90)
p2.addLine(distance: 200)
addShape(pen: p2)

// Line 3 — at y = 80
var p3 = Pen()
p3.turn(degrees: 90); p3.move(distance: 80); p3.turn(degrees: -90)
p3.addLine(distance: 200)
addShape(pen: p3)

// Line 4 — at y = 120
var p4 = Pen()
p4.turn(degrees: 90); p4.move(distance: 120); p4.turn(degrees: -90)
p4.addLine(distance: 200)
addShape(pen: p4)
IM1 Curriculum Connections
IM1 ConceptConnection
Parallel linesLines in the same direction that never intersect; have equal gradient (slope)
Coordinate geometryOffsetting the y-start corresponds to a vertical translation

Letter Z

Draw the letter Z using three line segments — a top horizontal, a diagonal, and a bottom horizontal — observing how the Z-angles relate to parallel lines.

Your Task

Draw: a horizontal line right 100, then turn down-left to draw the diagonal, then turn to draw the bottom horizontal. The diagonal creates Z-angles (alternate interior angles) with the horizontal lines.

Swift
var p = Pen()
p.addLine(distance: 100)    // top line
p.turn(degrees: -120)
p.addLine(distance: 115.5)  // diagonal
p.turn(degrees: -60)
p.addLine(distance: 100)    // bottom line
addShape(pen: p)
✏️
02-17-letter-z.png Screenshot: letter Z shape showing Z-angles between parallel lines
IM1 Curriculum Connections
IM1 ConceptConnection
Alternate interior anglesThe Z-shape shows alternate angles — equal when lines are parallel — visually embedded in the letter
TransversalThe diagonal is a transversal crossing two parallel (horizontal) lines

Rhombus

Draw a filled rhombus with side length 120 and interior angles of 70° and 110°. Explore how opposite angles in a parallelogram are equal.

Your Task

A rhombus has 4 equal sides. Opposite angles are equal; adjacent angles are supplementary (sum to 180°).

Swift
let interiorAngle = 70.0
let exterior = 180.0 - interiorAngle
var p = Pen()
p.fillColor = .purple
// Use interior/exterior angles to draw rhombus
addShape(pen: p)
✏️
02-18-rhombus.png Screenshot: filled purple rhombus with 70° and 110° interior angles
IM1 Curriculum Connections
IM1 ConceptConnection
Rhombus propertiesAll sides equal; opposite angles equal; diagonals bisect each other at 90°
Co-interior anglesAdjacent interior angles are supplementary — another transversal property applied to parallel sides

Parallelogram

Draw a parallelogram — two pairs of parallel sides — showing how it differs from a rhombus when sides have different lengths.

Your Task

Draw a parallelogram with long sides 160 units, short sides 80 units, and interior angles of 70° and 110°.

Swift
var p = Pen()
p.addLine(distance: 160)
p.turn(degrees: 110)
p.addLine(distance: 80)
p.turn(degrees: 70)
p.addLine(distance: 160)
p.turn(degrees: 110)
p.addLine(distance: 80)
addShape(pen: p)
✏️
02-19-parallelogram.png Screenshot: parallelogram with long sides 160, short sides 80, and 70° angles
IM1 Curriculum Connections
IM1 ConceptConnection
Parallelogram propertiesOpposite sides parallel and equal; opposite angles equal; diagonals bisect each other
Area formulaArea = base × height = 160 × 80 × sin(70°) ≈ 12,030 sq units

Polygon Properties Explorer

Draw a selection of regular polygons — from a triangle to a decagon — and observe how the shape approaches a circle as the number of sides increases.

Your Task

Change sides to explore different regular polygons — try 3, 4, 5, 6, 8. Add or remove addLine/turn pairs so the number of lines matches the number of sides. Notice how the shape changes as sides increase.

Swift
// Change 'sides' and add/remove lines to match
let sides = 6
let turn = 360.0 / Double(sides)
var p = Pen()
p.addLine(distance: 80); p.turn(degrees: turn)
p.addLine(distance: 80); p.turn(degrees: turn)
p.addLine(distance: 80); p.turn(degrees: turn)
p.addLine(distance: 80); p.turn(degrees: turn)
p.addLine(distance: 80); p.turn(degrees: turn)
p.addLine(distance: 80); p.turn(degrees: turn)
addShape(pen: p)
✏️
02-20-polygon-explorer.png Screenshot: regular hexagon drawn with calculated turn angle
IM1 Curriculum Connections
IM1 ConceptConnection
Regular polygon formulasInterior angle = (n − 2) × 180° ÷ n; exterior angle = 360° ÷ n
Limit concept (preview)As n → ∞, the polygon approaches a circle — an intuitive preview of limits

Angle Classification

Draw shapes whose interior angles represent each angle type — acute, right, obtuse, and reflex — then label them with your understanding.

Your Task

Draw at least four shapes: one with a reflex angle, one with all right angles (square), one with acute angles (equilateral triangle), and one with obtuse angles (regular hexagon). Try to draw them adjacent on the canvas.

💡 Think About It

  • What is the interior angle of a regular pentagon? Is it acute, right, or obtuse?
  • Can a triangle have an obtuse angle? Can it have two?
  • What is the minimum number of sides a polygon needs to have a reflex angle?
✏️
02-21-angle-classification.png Screenshot: shapes side by side showing acute, right, obtuse, and reflex angles
IM1 Curriculum Connections
IM1 ConceptConnection
Angle classificationAcute <90°; right = 90°; obtuse 90°–180°; straight = 180°; reflex >180°
Interior angle formula(n − 2) × 180° ÷ n — determines whether a regular polygon has acute or obtuse angles