我试图用在 TikZ 中绘制的小方块覆盖整张横向 A4 纸,从页面左下角开始以螺旋状向页面中心移动,但我的方法存在缺陷,因为页面最后没有填满。
每个小方块的边长为 1.5 毫米。要让整个页面完全被方块覆盖,还需要满足一些先决条件。
页面的宽度和高度(297 毫米 × 210 毫米)必须能被正方形的边长整除。
210模1.5=0
297 模 1.5 = 0
页面的面积必须能被正方形的面积整除。
297 毫米 × 210 毫米 = 62370 毫米2
1.5 毫米 × 1.5 毫米 = 2.25 毫米2
62370 模 2.25 = 0
而且我必须迭代 62370 / 2.25 = 27720 次才能覆盖整个页面。所有条件都满足,所以我的算法不正确。(请注意,以下代码需要编译两次,lualatex
这在较旧的 i7 CPU 上大约需要 2 分钟。)
\documentclass{article}
\usepackage[nohead,%
nofoot,%
nomarginpar,%
paperwidth=297mm,%
paperheight=210mm,%
tmargin=5mm,%
rmargin=5mm,%
bmargin=5mm,%
lmargin=5mm,%
vscale=1,%
hscale=1]{geometry}
\usepackage{tikz}
\usepackage{luacode}
\pagestyle{empty}
\begin{luacode*}
function square_spiral()
local direction = 0
local x = 0
local y = 0
local shift = 1.5
local x_min = 0
local y_min = shift
local x_max = 297 - 1.5 * shift
local y_max = 210 - 1.5 * shift
local square_count = (297 * 210) / (1.5 * 1.5)
tex.sprint("\\begin{tikzpicture}[remember picture, overlay]")
for i = 1, square_count, 1 do
tex.sprint("\\filldraw[black!" .. (i - 1) / (square_count - 1) * 100 ..
", line width=0pt] (current page.south west) ++(" ..
string.format("%.1f", x) .. "mm, " .. string.format("%.1f", y) ..
"mm) rectangle +(" .. shift .. "mm, " .. shift .. "mm);")
if direction == 0 then -- right
if x < x_max then
x = x + shift
else
direction = 1
x_max = x_max - shift
end
elseif direction == 1 then -- up
if y < y_max then
y = y + shift
else
direction = 2
y_max = y_max - shift
end
elseif direction == 2 then -- left
if x > x_min then
x = x - shift
else
direction = 3
x_min = x_min + shift
end
elseif direction == 3 then -- down
if y > y_min then
y = y - shift
else
direction = 0
y_min = y_min + shift
end
end
--[[
print(string.format("%.1f", x) .. ", " ..
string.format("%.1f", y) .. ", " .. i)
]]
end
tex.sprint("\\end{tikzpicture}")
end
\end{luacode*}
\begin{document}
\luadirect{square_spiral()}
\end{document}
答案1
我认为问题出现的原因在于当螺旋改变方向时,每个角都会绘制两个方块。例如,如果螺旋向右移动,当条件x < x_max
不满足时,方向会改变,但坐标y
不会向上移动,因此下一个方块会绘制在与上一个方块相同的位置。
我已在下面的代码中更正了这个问题(并做了一些其他希望不重要的更改)
\documentclass{article}
\usepackage[nohead,%
nofoot,%
nomarginpar,%
paperwidth=297mm,%
paperheight=210mm,%
tmargin=5mm,%
rmargin=5mm,%
bmargin=5mm,%
lmargin=5mm,%
vscale=1,%
hscale=1]{geometry}
\usepackage{tikz}
\usepackage{luacode}
\pagestyle{empty}
\begin{luacode*}
function square_spiral()
local direction = 0
local x = 0
local y = 0
local shift = 1.5
local x_min = 0
local y_min = shift
local paperwidth = math.floor(tex.dimen["paperwidth"]/65536/2.84526)
local paperheight = math.floor(tex.dimen["paperheight"]/65536/2.84526)
local x_max = paperwidth - 1.5*shift
local y_max = paperheight - 1.5*shift
local square_count = (paperwidth)*(paperheight) / (shift*shift)
tex.sprint("\\begin{tikzpicture}[remember picture, overlay]")
for i = 1, square_count, 1 do
tex.sprint("\\filldraw[black!" .. (i - 1) / (square_count - 1) * 100 ..
", line width=0pt] (current page.south west) ++(" ..
string.format("%.1f", x) .. "mm, " .. string.format("%.1f", y) ..
"mm) rectangle +(" .. shift .. "mm, " .. shift .. "mm);")
if direction == 0 then -- right
if x < x_max then
x = x + shift
else
direction = 1
x_max = x_max - shift
y = y + shift -- MOVE UP
end
elseif direction == 1 then -- up
if y < y_max then
y = y + shift
else
direction = 2
y_max = y_max - shift
x = x - shift -- MOVE LEFT
end
elseif direction == 2 then -- left
if x > x_min then
x = x - shift
else
direction = 3
x_min = x_min + shift
y = y - shift -- MOVE DOWN
end
elseif direction == 3 then -- down
if y > y_min then
y = y - shift
else
direction = 0
y_min = y_min + shift
x = x + shift -- MOVE RIGHT
end
end
--[[
print(string.format("%.1f", x) .. ", " ..
string.format("%.1f", y) .. ", " .. i)
]]
end
tex.sprint("\\end{tikzpicture}")
end
\end{luacode*}
\begin{document}
\luadirect{square_spiral()}
\end{document}