Paths
Paths are the fundamental building blocks in Hobby. A path is a sequence of points connected by curves or lines.
Creating a Path
Use h.path() to create a new path builder:
local h = require("hobby")
local path = h.path()
:moveto(h.point(0, 0))
:curveto(h.point(50, 30))
:curveto(h.point(100, 0))
:build()Path Commands
moveto(point)
Sets the starting point of the path.
:moveto(h.point(10, 20))curveto(point)
Creates a smooth curve to the given point using the Hobby algorithm.
:curveto(h.point(50, 50))lineto(point)
Creates a straight line to the given point.
:lineto(h.point(100, 0))curvetowithcontrols(point, c1, c2)
Creates a Bézier curve with explicit control points.
:curvetowithcontrols(
h.point(100, 0), -- end point
h.point(30, 50), -- control point 1
h.point(70, 50) -- control point 2
)cycle() / close()
Closes the path by connecting back to the starting point.
:cycle()build()
Solves the path and returns the result. This must be called after defining the path.
local solved_path = path:build()Direction Control
dir(angle)
Sets the outgoing direction at the current point (in degrees).
:moveto(h.point(0, 0))
:dir(45) -- leave at 45 degrees
:curveto(h.point(100, 0))indir(angle)
Sets the incoming direction at the next point.
:curveto(h.point(100, 0))
:indir(0) -- arrive horizontallyTension Control
Tension controls how “tight” the curve is. Higher values produce tighter curves.
tension(t)
Sets tension for both incoming and outgoing directions.
:tension(2) -- tighter curve
:curveto(h.point(50, 50))outtension(t) / intension(t)
Sets tension separately for outgoing and incoming directions.
:outtension(0.75) -- looser departure
:intension(2) -- tighter arrival
:curveto(h.point(50, 50))tensionatleast(t)
Sets a minimum tension value.
:tensionatleast(1.5)
:curveto(h.point(50, 50))tensioninfinity()
Creates a straight segment with smooth connections at endpoints.
:tensioninfinity()
:curveto(h.point(50, 50))Curl Control
Curl controls the curvature at path endpoints.
curl(c)
Sets curl at an endpoint. Default is 1.
:moveto(h.point(0, 0))
:curl(0) -- straight departure
:curveto(h.point(100, 0))outcurl(c) / incurl(c)
Sets curl separately for departure and arrival.
:outcurl(0) -- straight departure
:curveto(h.point(50, 50))
:curveto(h.point(100, 0))
:incurl(2) -- more curved arrivalComplete Example
local h = require("hobby")
-- A path with various controls
local path = h.path()
:moveto(h.point(0, 0))
:dir(90) -- start going up
:tension(1.5)
:curveto(h.point(50, 80))
:curveto(h.point(100, 0))
:indir(-90) -- arrive going down
:stroke("blue")
:strokewidth(2)
:build()
h.svg()
:padding(10)
:add(path)
:write("path_example.svg")