Transformations
Transformations
All paths support transformations. Transformations return a new path, allowing method chaining.
Basic Transformations
scaled(s)
Uniform scaling around the origin.
local big = h.fullcircle():scaled(100)xscaled(s) / yscaled(s)
Non-uniform scaling along x or y axis.
local ellipse = h.fullcircle()
:scaled(50)
:xscaled(2) -- stretch horizontally
:yscaled(0.5) -- compress verticallyshifted(dx, dy)
Translation by (dx, dy).
local moved = h.fullcircle()
:scaled(50)
:shifted(100, 100)rotated(angle)
Rotation around the origin (angle in degrees).
local rotated = h.unitsquare()
:scaled(50)
:rotated(45)slanted(s)
Horizontal shear transformation.
local slanted = h.unitsquare()
:scaled(50)
:slanted(0.5)Advanced Transformations
rotatedaround(point, angle)
Rotation around a specific point.
local center = h.point(50, 50)
local rotated = h.unitsquare()
:scaled(20)
:shifted(40, 40)
:rotatedaround(center, 45)Alternative syntax with coordinates:
:rotatedaround(50, 50, 45)scaledaround(point, s)
Scaling around a specific point.
local center = h.point(50, 50)
local scaled = h.unitsquare()
:scaled(30)
:shifted(35, 35)
:scaledaround(center, 0.5)zscaled(a, b)
Complex multiplication: scales by √(a² + b²) and rotates by atan2(b, a).
-- Rotate 45° and keep size (cos 45°, sin 45°)
local rotated = h.unitsquare()
:scaled(30)
:zscaled(0.707, 0.707)Can also use a point:
:zscaled(h.dir(30)) -- rotate 30 degreesreflectedabout(p1, p2)
Reflection about the line through p1 and p2.
local p1 = h.point(50, 0)
local p2 = h.point(50, 100)
local reflected = h.fullcircle()
:scaled(30)
:shifted(20, 50)
:reflectedabout(p1, p2)Alternative syntax with coordinates:
:reflectedabout(50, 0, 50, 100)Transformation Order
Transformations are applied in the order they are called. The order matters!
-- Rotate then shift: rotates around origin, then moves
local a = h.unitsquare()
:scaled(30)
:rotated(45)
:shifted(100, 100)
-- Shift then rotate: moves to position, then rotates around origin
local b = h.unitsquare()
:scaled(30)
:shifted(100, 100)
:rotated(45)Complete Example
local h = require("hobby")
-- Original
local original = h.fullcircle()
:scaled(20)
:shifted(30, 80)
:stroke("black")
-- Stretched horizontally
local xstretched = h.fullcircle()
:scaled(20)
:xscaled(2)
:shifted(90, 80)
:stroke("blue")
-- Stretched vertically
local ystretched = h.fullcircle()
:scaled(20)
:yscaled(2)
:shifted(150, 80)
:stroke("red")
-- Slanted square
local slanted = h.unitsquare()
:scaled(30)
:slanted(0.5)
:shifted(30, 20)
:stroke("green")
-- Combined transformations
local combo = h.fullcircle()
:scaled(20)
:xscaled(1.5)
:yscaled(0.7)
:slanted(0.3)
:shifted(130, 30)
:stroke("purple")
h.svg()
:padding(10)
:add(original)
:add(xstretched)
:add(ystretched)
:add(slanted)
:add(combo)
:write("transforms.svg")