Ollin

Shapes

These examples cover the shape-drawing vocabulary. They show every primitive and the stroke and hollow modes. They also show two ways to compose shapes: boolean set operations on filled outlines, and SDF combinators that merge distance fields.

ExampleWhat it shows
Arrowsa field of drawArrow marks that lean toward the cursor, and a turning ring that sweeps headLength/headWidth. The ring is translucent because each arrow lays one even coat: the shaft stops at the base of the head
Booleansthe four Shape set operations (union/intersection/subtracting/symmetricDifference) applied to the same two moving shapes, a turning star and an orbiting disc. Each filled result is real geometry, so it strokes and exports like anything drawn by hand
Clippingclipping as drawing state: withClip(shape) { } confines fills, strokes, images, and text to the filled region of the shape, and nested clips intersect
CombinatorsSDF combinators: drawSDF and smoothUnion { } compose signed-distance fields, so 2D shapes merge instead of stacking
CombinatorsDetailingthe SDF detailing operations on one pair of crossing bars (drawSDF): columns adds ribs along a seam, pipe adds a bead at a crossing, engrave cuts a v-notch, and groove/tongue cut and raise a channel that mates
CombinatorsGradienta linear or radial Gradient used as fill or stroke paints a whole merged SDF field as one continuous surface, because the gradient is sampled in field space (drawSDF)
CombinatorsJoinerythe SDF joint operations (drawSDF): chamfer and stairs joins, cuts, and intersections, which give machined seams, drawn beside the organic smooth blends
CombinatorsStretchper-axis sizing of a merged SDF field (drawSDF): stretched elongates the field exactly, and scaled(x:y:) gives a non-uniform bound, drawn side by side
ColoringBooka coloring book that colors itself: circles, a wave, and straight strokes drift across the page, every patch their lines wall off comes back as its own Shape (regions(enclosedBy:)) and takes a crayon keyed to its center, and the lines are inked over the fills. The page's edge is one of the outlines, so nothing is left uncolored
CornerCuttingChaikin corner cutting, animated: a spiky burst relaxes into a smooth blob drawn over its raw outline, which stays faint underneath, and an open zigzag smooths while its endpoints never move. The number of passes is a parameter (smoothed(iterations:))
Crossingssix shapes held as values drift about (LineSegment, Circle, Arc, Ellipse, Rectangle), every pair asked each frame where it meets the other (crossings(with:)) with a dot on every answer, and a probe dropped to the nearest place on each (nearestPoint(to:)); the ellipse's exact perimeter is written beside them
HollowShapesa grid of shapes that cycle between solid fills and framed hollow rings (hollow/solid, SDF)
Hullsthree ways to find the shape of a set of points (convexHull/concaveHull/alphaShape). The convex hull is drawn faint with its corner points lit, the concave hull cycles from loose to tight, and the alpha shape finds islands and a hole that neither hull can express
InkRibbona stroke as a shape: a drifting brush line is turned into a real region (stroked), then inset repeatedly (offset) so contour bands nest inside the ribbon
Markersthe five drawPoint markers, one per row, each drawn across a range of sizes (pointMarker, SDF)
MedialAxisletterforms reduced to their skeletons (medialAxis). The skeleton of each glyph is stroked, inscribed circles are drawn from the radii the skeleton carries, and a bead rolls along each branch at the local thickness of the letter
Neighborsa SpatialIndex over four thousand points answers three queries each frame: which point is nearest, which points are within a given distance, and which are inside a sliding box. Every point is also joined to its nearest neighbor
OverUndera tangled loop that finds its own crossings (crossings()) and weaves through them, over and under in turn, by cutting a short gap out of every under pass (piece(from:to:)). A probe reads the nearest place on the loop, with the direction of travel and the side it faces there (nearestPoint(to:), fraction(of:), tangent(at:), normal(at:))
Polygonsregular polygons from 3 to 8 sides drawn with drawNgon. From the pentagon up, each is also drawn and labeled through its named call, which is sugar over drawNgon (drawPentagon/drawHexagon/drawHeptagon/drawOctagon). A five-point drawStar goes from spiky to round as its inner radius grows. Everything turns (SDF)
Primitivesevery draw* primitive, one per cell, turning slowly, as a reference sheet for the whole drawing vocabulary. The shapes that accept cornerRadius: cycle through it
Scatteredfitting: a value known at a few scattered points becomes a value defined everywhere, because each known point contributes a bump (RadialBasis)
Stara concave star with a hole, filled through drawShape and the vector Shape type. This is a triangulated fill, which drawPolygon cannot do
StraightSkeletonthe straight skeleton used as a topographic survey. The ridge network of an island is extracted once (straightSkeleton). Then an animated series of mitered insets (inset(by:)) draws contour lines, which split where the land narrows and ring the lake
StrokeAlignmentthe same shapes stroked inside, centered on, and outside their outline, with the weight pulsing (strokeAlign, SDF)
StrokeJoinsAndCapsa zigzag drawn with each join and a segment ended with each cap, with the weight pulsing (strokeJoin/strokeCap)
Brushworkdrag to paint: a StrokeMark measures how fast and how hard you drew and turns that into width and opacity (StrokeDynamics, drawMark). Three pre-recorded marks show each axis on its own
DashedStrokessix dashed strokes sharing one weight and one clock (strokeDash): marching ants around a rounded rectangle, dots under round caps along a spiral, two rings turning against each other, a four-length pattern on a star, a taper read across the gaps, and a gradient running on through them
HobbySplinethe same drifting points threaded by the default spline and by Hobby's fit (drawCurve(spline: .hobby)), an open run on the left and a filled loop on the right, with tension and curl as parameters
StrokeProfilesone spiral at one weight drawn under each width profile (strokeProfile): taper, lift off, wedge, a turning calligraphy nib, and one defined by hand
Superellipsea wall of superellipse plates, with one exponent moving the whole family from a pinched star through diamond, ellipse, and squircle to an almost-rectangle
Supershapeone closed contour that moves through star, flower, and gear-like forms as slow sines sweep the 2D superformula, drawn over fading copies of its recent shapes
SVGImportSVG import: the bundled rocket badge is drawn as authored (loadSVG/drawSVG), then used as geometry, with its outlines resampled into evenly spaced dots
WavyLetteringlettering that follows a wave: a word's glyph outlines (textToShapes) are bent from their straight baseline along a wave that travels (Shape.warped(from:along:)), and a hand tugs the letters it passes (pulled(toward:amount:radius:)). Hold the mouse to be the hand
TraceToCurvesa scribble becomes a few curves: a dense trace is lightened (simplified), cut at its corners (split(atCornersOver:span:)), and each piece traced with cubic Béziers (fitted(tolerance:)), drawn with their handles (Path.cubics) and the counts of what the fit saved. Draw with the mouse to trace your own
WavingBannera banner waving on its pole: three stripes and a word are drawn flat in a rectangle and bent into a four-sided patch whose top and bottom are waves (CoonsPatch, Shape.warped(from:into:)), each upright strip of cloth lit by the slope of the wave. Hold the mouse to take the far edge in your hand
Trianglesthe two drawTriangle forms side by side: an equilateral triangle that turns on its center, and an isosceles wedge that turns on its apex (SDF)
Watercolorwatercolor pigment made by deforming polygons (Watercolor, drawShape): three pools of interleaved translucent layers that glaze where they overlap, plus a clipped speckle for a granulated texture. Each variation starts a fresh sheet
Brushesmarks made by repeating a shape along a path: strokeBrush replaces the continuous ribbon with a row of stamps, which take their size from strokeWeight and their color from the stroke

Run one with swift run Example-Shapes-<Name>, for example swift run Example-Shapes-Primitives.

↑↓ move ↩ open