结果

结果

我有一张 TikZ 绘图(即成对的标尺),我想将其并排复制 12 次。我使用foreach构造来帮助我完成此过程,并为标尺绘制 5 厘米、1 厘米和 1 毫米刻度。但是,当我尝试绘制它们超过第三次时,内存就用完了。

我尝试将进程外部化,但没有成功,而且我不愿意尝试增加主内存。我该如何解决这个问题?

这是MWE:

\documentclass[tikz,convert=false,12pt]{standalone}

\renewcommand*\familydefault{\sfdefault} 
\usepackage[T1]{fontenc}
\usetikzlibrary{external} 
\tikzexternalize

\begin{document}

%%%%  Any unit not specified is multiplied by 1 mm. This allows some fancy scaling. 
\begin{tikzpicture}[x=1mm,line cap=rect]


  %%%% We need 12 rulers, mirrored, for a grand total of 24 rulers. Each pair of
  %%%% rulers will be offset 10 cm from the previous pair. 

  \foreach \i in {0,...,2}{ %%%% Ideally, this would be 11 and not 2. 
    \tikzset{xshift/.expanded=\i*100mm}

    %%%% Draw the red millimeter tick marks.
    \foreach \y in {0.1,0.3,...,69.9}
    \draw [color=red, line width=0.15mm] (10mm,\y) -- (0mm,\y)
    node[color=red] {};   

    %%%% Draw the black millimeter tick marks
    \foreach \y in {0,0.2,...,69.8}
    \draw [color=black, line width=0.15mm] (10mm,\y) -- (0mm,\y)
    node[color=black] {};


    %%%% Draw the red minor(centimeter) tick marks with the red labels. 
    \foreach \y in {1,3,...,69}
    \draw [color=red, line width=1mm] (20mm,\y) -- (0mm,\y)
    node[color=red, anchor=east] {\pgfmathprint{int(\y)}};   

    %%%% Draw the black minor (centimeter) tick marks with the black labels. 
    \foreach \y in {0,2,...,68}
    \draw [color=black, line width=1mm] (20mm,\y) -- (0mm,\y)
    node[color=black, anchor=east] { \pgfmathprint{int(\y)}};



    %%%% Draw the black major (5-cm) tick marks with the black labels. This paints over
    %%%% the minor tick marks in the same place.
    \foreach \y in {0,10,...,70}
    \draw [color=black,line width=2mm] (30mm,\y) -- (0mm,\y)
    node[fill=white,anchor=east] {\Huge \textbf{{\pgfmathprint{int(\y)}}}};

    %%%% Draw the red major (5-cm) tick marks with the red labels. This paints over
    %%%% the minor tick marks in the same place.
    \foreach \y in {5,15,...,65}
    \draw [color=red, line width=2mm] (30mm,\y) -- (0mm,\y)
    node[fill=white,anchor=east] {\Huge \textbf{\pgfmathprint{int(\y)}}};


    %%%% Draw the vertical line that ties it all together.     
    \draw [line width=2mm](0mm, 0mm) -- coordinate (y axis mid) (0mm,700mm);



    %%%% ------------------------------ REVERSED RULERS

    %%%% Draw the red millimeter tick marks. Reversed.
    \foreach \y in {0.1,0.3,...,69.9}
    \draw [color=red, line width=0.15mm] (60mm,\y) -- (70mm,\y)
    node[color=red] {};   

    %%%% Draw the black millimeter tick marks. Reversed
    \foreach \y in {0,0.2,...,69.8}
    \draw [color=black, line width=0.15mm] (60mm,\y) -- (70mm,\y)
    node[color=black] {};

    %%%% Draw the red minor tick marks with the red labels. Reversed
    \foreach \y in {1,3,...,69}
    \draw [color=red, line width=1mm] (50mm,\y) -- (70mm,\y)
    node[color=red, anchor=west] {\pgfmathprint{int(\y)}};   

    %%%% Draw the black minor tick marks with the black labels. Reversed
    \foreach \y in {0,2,...,68}
    \draw [color=black, line width=1mm] (50mm,\y) -- (70mm,\y)
    node[color=black, anchor=west] { \pgfmathprint{int(\y)}};

    %%%% Draw the black major tick marks with the black labels. This paints over
    %%%% the minor tick marks in the same place. Reversed
    \foreach \y in {0,10,...,70}
    \draw [color=black,line width=2mm] (40mm,\y) -- (70mm,\y)
    node[fill=white,anchor=west] {\Huge \textbf{{\pgfmathprint{int(\y)}}}};

    %%%% Draw the red major tick marks with the red labels. This paints over
    %%%% the minor tick marks in the same place. Reversed
    \foreach \y in {5,15,...,65}
    \draw [color=red, line width=2mm] (40mm,\y) -- (70mm,\y)
    node[fill=white,anchor=west] {\Huge \textbf{\pgfmathprint{int(\y)}}};

    %%%% Draw the vertical line that ties it all together, reversed 
    \draw [line width=2mm](70mm, 0cm) -- coordinate (y axis mid) (70mm,700mm);

    % %%%% Draw crop marks.
    % \draw [very thin, color=black, loosely dashed](-1, 0cm) -- coordinate
    % (y axis mid) (-1cm,71cm);

  } 


\end{tikzpicture}

\end{document}

%%% Local Variables: 
%%% mode: latex
%%% LaTeX-command: "latex -shell-escape"
%%% TeX-master: t
%%% End: 

答案1

结果

结果

想法

这个想法是使用 lua 编写所有这些嵌套循环,然后从这些循环生成 tex (tikz) 代码来绘制各个标记。因此,TikZ 最终“看到”的是循环的结果,即一长串简单的线条绘制命令。这样,TeX 内存就不会堵塞。

但是,lua 循环中生成的小标记数量非常多,整个过程需要花费大量时间来编译(在我的机器上,每条标尺需要 12 秒,总共需要 2 分 30 秒)。也许可以优化一下,如果不是将生成的每行都发送给 TeX,而是将它们累积在一个列表中,然后发送整个列表。我必须尝试一下,但我猜真正的瓶颈是 TikZ 解析所有这些行。

代码

它分为两个文件,一个用于 lua 代码,另一个用于使用它的主 TeX 文档。编译:

$ lualatex main.tex

过一会儿,您将获得一个pdf可以打印或包含在其他文档中的文件(通过\includegraphics)。

主文本

乳胶代码现在已很少。

\documentclass[tikz,convert=false,12pt]{standalone}
\renewcommand*\familydefault{\sfdefault} 
\usepackage[T1]{fontenc}
\directlua{dofile("drawrule.lua")}
\def\DrawAllRules{\directlua{DrawAllRules()}}

\begin{document}
%%%%  Any unit not specified is multiplied by 1 mm. This allows some fancy scaling. 
\begin{tikzpicture}[x=1mm,line cap=rect]
  \DrawAllRules
\end{tikzpicture}
\end{document}

绘制规则

我尝试让 lua 代码尽可能接近您的原始 tex 代码。我使用了一些字符串来保存在其他地方重复的 tikz 命令,但使用类似“printf”的占位符进行参数化

function DrawRule()
    t = {}
    mmcmd = "\\draw [color=%s, line width=0.15mm] (10mm,%f) -- (0mm,%f) node[color=%s] {};\n"
    cmcmd = "\\draw [color=%s, line width=1mm] (20mm,%f) -- (0mm,%f) node[color=%s,anchor=east] {%d};\n"
    cm5cmd= "\\draw [color=%s, line width=2mm] (30mm,%f) -- (0mm,%f) node[fill=white, anchor=east] {\\Huge\\textbf{%d}};\n"
    -- Draw the red millimeter tick marks.
    for y = 0.1, 69.9, 0.2 do     -- first, last, step
      tex.print(string.format(mmcmd, "red", y, y, "red"))
    end

    --  Draw the black millimeter tick marks
    for y = 0, 69.8, 0.2 do     -- first, last, step
      tex.print(string.format(mmcmd, "black", y, y, "black"))
    end
    -- Draw the red minor(centimeter) tick marks with the red labels. 
    for y = 1, 69, 2 do     -- first, last, step
      tex.print(string.format(cmcmd, "red", y, y, "red", y))    end

    -- Draw the black minor (centimeter) tick marks with the black labels.     for y = 0, 68, 2 do     -- first, last, step
      tex.print(string.format(cmcmd, "black", y, y, "black", y))
    end
    -- Draw the black major (5-cm) tick marks with the black labels. This paints over
    -- the minor tick marks in the same place.
    for y = 0,70,10 do
      tex.print(string.format(cm5cmd, "black", y, y, y))
    end

    -- Draw the red major (5-cm) tick marks with the red labels. This paints over
    -- the minor tick marks in the same place.
    for y = 5, 65, 10 do
      tex.print(string.format(cm5cmd, "red", y, y, y))
    end

    -- Draw the vertical line that ties it all together.     
    tex.print("\\draw [line width=2mm](0mm, 0mm) -- coordinate (y axis mid) (0mm,700mm);\n")
    ------------------------------ REVERSED RULERS
    mmcmd = "\\draw [color=%s, line width=0.15mm] (60mm,%f) -- (70mm,%f) node[color=%s] {};\n"
    cmcmd = "\\draw [color=%s, line width=1mm] (50mm,%f) -- (70mm,%f) node[color=%s,anchor=west] {%d};\n"
    cm5cmd= "\\draw [color=%s, line width=2mm] (40mm,%f) -- (70mm,%f) node[fill=white, anchor=west] {\\Huge\\textbf{%d}};\n"

    -- Draw the red millimeter tick marks. Reversed.
    for y = 0.1, 69.9, 0.2 do     -- first, last, step
      tex.print(string.format(mmcmd, "red", y, y, "red"))
    end
    --  Draw the black millimeter tick marks. Reversed.
    for y = 0, 69.8, 0.2 do     -- first, last, step
      tex.print(string.format(mmcmd, "black", y, y, "black"))    end

    -- Draw the red minor(centimeter) tick marks with the red labels. Reversed.    for y = 1, 69, 2 do     -- first, last, step
      tex.print(string.format(cmcmd, "red", y, y, "red", y))
    end
    -- Draw the black minor (centimeter) tick marks with the black labels. Reversed.
    for y = 0, 68, 2 do     -- first, last, step
      tex.print(string.format(cmcmd, "black", y, y, "black", y))
    end

    -- Draw the black major (5-cm) tick marks with the black labels. This paints over
    -- the minor tick marks in the same place. Reversed.
    for y = 0,70,10 do
      tex.print(string.format(cm5cmd, "black", y, y, y))
    end

    -- Draw the red major (5-cm) tick marks with the red labels. This paints over
    -- the minor tick marks in the same place. Reversed.
    for y = 5, 65, 10 do
      tex.print(string.format(cm5cmd, "red", y, y, y))
    end

    -- Draw the vertical line that ties it all together, reversed 
    tex.print("\\draw [line width=2mm](70mm, 0cm) -- coordinate (y axis mid) (70mm,700mm);\n")

    -- %%%% Draw crop marks.
    -- \draw [very thin, color=black, loosely dashed](-1, 0cm) -- coordinate
    -- (y axis mid) (-1cm,71cm);
  end


function DrawAllRules()  for i=0,11 do
    tex.print(string.format("\\tikzset{xshift/.expanded=100mm}"))
    DrawRule()  end
end

相关内容