local IMG_SZ, DEPTH = 512, 3
local fh = assert(io.open("Hilbert_curve.svg", "wb"))
fh:write('<?xml version="1.0" encoding="UTF-8"?>\n',
'<svg version="1.0" width="', IMG_SZ, '" height="', IMG_SZ,
'" xmlns="http://www.w3.org/2000/svg">\n')
local L_SYSTEM_RULES = { -- these are from the Wikipedia article
L = "+RF-LFL-FR+",
R = "-LF+RFR+FL-",
}
local ANGLE_COMMANDS = { -- angle expressed in units of 90 degrees
[0] = "h",
[1] = "v",
[2] = "h-",
[3] = "v-",
}
local STROKE_STYLE = { -- each order drawn with different stroke style
[1] = "stroke:#f00;stroke-width:6;fill:none",
[2] = "stroke:#00f;stroke-width:4;fill:none",
[3] = "stroke:#000;stroke-width:2;fill:none",
[4] = "stroke:#000;stroke-width:1;fill:none",
[5] = "stroke:#000;stroke-width:0.5;fill:none",
}
function turtle_graphics (input, startpos, line_len)
local output = "M" .. startpos .. "," .. startpos
local angle = 0
for i = 1, input:len() do
local cmd = input:sub(i, i)
if cmd == "F" then
output = output .. ANGLE_COMMANDS[angle] .. line_len
elseif cmd == "+" then
angle = (angle + 1) % 4
elseif cmd == "-" then
angle = (angle - 1) % 4
end
end
return output
end
local line_len = IMG_SZ / 2
for d = 1, DEPTH do
local lsys = "L"
for _ = 1, d do
-- Apply the production rules. Note that both 'L' and 'R' rules are
-- applied simultaneously.
lsys = lsys:gsub("([LR])", function (orig)
return L_SYSTEM_RULES[orig]
end)
end
fh:write(' <path style="', STROKE_STYLE[d], '" d="',
turtle_graphics(lsys, line_len / 2, line_len), '"/>\n')
line_len = line_len / 2
end
fh:write('</svg>\n')