我该怎么做才能使这段代码编译得更快

我该怎么做才能使这段代码编译得更快

我对 TikZ 还只是个新手。

以下 MWE 看起来相当简单直接,但它的编译速度比我认为的要慢得多。有人能解释一下发生了什么吗?或者可能提出一些建议,这些建议仍然会产生相同的图像,但编译速度更快?

最初,我以为可能是calc库导致速度变慢。MWE 展示了我如何重写以避免使用calc。旧方法只是被注释掉了。

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
%%\usetikzlibrary{calc}
\usetikzlibrary{arrows.meta}

\makeatletter

\def\@aem(#1)#2;{\node[anchor=base] at (#1) {#2}; 
                 \draw (#1/nw) rectangle (#1/se);
                 \path (#1) + (0,6ex) coordinate (#1/t)
                            + (0,2.5ex) coordinate (#1/h);
                 %%\coordinate (#1/t) at ($(#1)+(0,6ex)$); 
                 %%\coordinate (#1/h) at ($(#1)+(0,2ex)$); 
                 \draw[line width=2pt,arrows=-{Stealth[length=2ex,width=1.5ex]}] (#1/t) -- (#1/h); }
\def\@aeo(#1)#2;{\node[inner sep=1ex,anchor=base] at (#1) {#2}; \draw (#1/nw) rectangle (#1/se);}
\def\@aex(#1)#2;{\node[anchor=base] at (#1) {#2};}
\def\@aef(#1)#2;{\node[anchor=base] at (#1) {\textcolor{gray!20}{#2}};}

\def\ae#1#2#3{\csname @ae#1\endcsname(p#3){#2};}

\makeatother

\def\aemarkup#1{%%
  \begin{tikzpicture}
    \foreach \x in {0,1,2,...,14}
      {
        \path (0,0) --  (\x*0.45cm,0) coordinate (p\x)
                     +  (115:3ex)     coordinate (p\x/nw)
                     +  (-20:1.5ex)   coordinate (p\x/se);
        \draw (p\x) ++(0,-0.5ex) -- ++(0,-2ex);
        %%\coordinate (p\x)    at ($(0,0)+\x*(0.45cm,0)$);
        %%\coordinate (p\x/nw) at ($(p\x)+(115:3ex)$);
        %%\coordinate (p\x/se) at ($(p\x)+(-20:1.5ex)$);
        %%\draw (p\x) -- ($(p\x)-(0,2ex)$);
      }
    \foreach \y [count=\yi from 0] in {#1}
      { \expandafter\ae\y\yi}  
  \end{tikzpicture}\par}

\begin{document}

Diagram:

\aemarkup{mx , ox , ox , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}
\aemarkup{fx , ox , mx , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}
\aemarkup{fx , ox , fx , ox , mx , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}
\aemarkup{fx , ox , fx , ox , fx , ox , mx , oM , ox , ox , ox , oa , ox , ob , oc}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , mx , ox , ox , oa , ox , ob , oc}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , mx , oa , ox , ob , oc}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , mx , ob , oc}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , fx , ob , mc}
\aemarkup{mx , ox , ox , oM , ox , oa , ob , xc}
\aemarkup{fx , ox , mx , oM , ox , oa , ob , xc}
\aemarkup{fx , ox , fx , oM , mx , oa , ob , xc}
\aemarkup{fx , ox , fx , oM , fx , oa , mb , xc}
\aemarkup{mx , oM , oa , xb , xc}
\aemarkup{fx , oM , ma , xb , xc}
\aemarkup{mM , xa , xb , xc}

\end{document}

在此处输入图片描述

答案1

我会让代码更简单。

  • 使用chains图书馆。
  • 充分利用节点的功能:
    • text *键,以便所有节点具有相同的大小,
    • append after command有助于将箭头和小线条放置在底部。
  • 使用样式。

我还使用了node contentsCVS 版本中引入的密钥(相对容易实现但非常有用)。请注意,该节点不再有文本组({<text>}缺失)。

需要\aemarkup第三个(第二个强制)参数,表示最大行数/节点数。如果给出的循环元素少于,则使用它来填充行#3。这是您的硬编码14

代码

\documentclass[varwidth]{standalone}
\usepackage{tikz} \usetikzlibrary{chains,arrows.meta}
\tikzset{
  my node/.style 2 args={#1 style/.try, node contents={#2}},
  x style/.style={text width=\widthof{M}, text depth=+0pt, text height=\heightof{M}+2pt,
    align=center, inner xsep=+0.5pt, inner ysep=+1pt,
    append after command={(\tikzlastnode.south) edge ++ (down:+1.5ex)}},
  f style/.style={x style, text=gray},
  o style/.style={x style, draw},
  m style/.style={o style,
    append after command={% the arrow from above
      (\tikzlastnode.north) edge
        [line width=+2pt, arrows={Stealth[length=+2ex,width=+1.5ex]}-] ++ (up:+3.5ex)}}}
\newcommand*\aemarkup[3][]{
\tikzpicture[start chain=going mid right,node distance=+.1em,#1]
  \foreach \aeI[count=\cnt from 2,remember=\cnt] in {#2}% \cnt will be global after this
    \node[on chain,my node/.expand once=\aeI];
  \ifnum\cnt>#3\else
    \foreach \aeI in {\cnt,...,#3}\node[on chain, my node={x}{}];
  \fi
\endtikzpicture\par}
\begin{document}
Diagram:

\aemarkup{mx , ox , ox , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , mx , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , mx , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , mx , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , mx , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , mx , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , mx , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , fx , ob , mc}{15}
\aemarkup{mx , ox , ox , oM , ox , oa , ob , xc}{15}
\aemarkup{fx , ox , mx , oM , ox , oa , ob , xc}{15}
\aemarkup{fx , ox , fx , oM , mx , oa , ob , xc}{15}
\aemarkup{fx , ox , fx , oM , fx , oa , mb , xc}{15}
\aemarkup{mx , oM , oa , xb , xc}{15}
\aemarkup{fx , oM , ma , xb , xc}{15}
\aemarkup{mM , xa , xb , xc}{15}
\end{document}

输出

在此处输入图片描述

代码 (PGF)

为了进行比较,仅使用 PGF(和)进行快速而粗糙的实现pgffor

text width键、text depth和(TikZ 键)的效果text height通过规则(本质上是支柱)和 LaTeX 的 重现\makebox。设置描边和文本颜色的键drawtext是通过设置 TeX 宏的基本键实现的。箭头也是如此。

该库的效果是通过条件和chains硬编码的。\ifnum\cnt\pgftransformshift

TikZ 确实在幕后做了很多事情,不是吗?


\documentclass[varwidth]{standalone}
\usepackage{pgf,pgffor} \usepgflibrary{arrows.meta}
\pgfset{draw path/.code=\def\aeusepath{stroke},
        none path/.code=\def\aeusepath{discard},
        gray text/.code=\def\aenodesetupcol{\color{gray}}}
\let\arrowpath\relax
\let\aenodesetupcol\relax
\def\Arrowpath{%
  \edef\linewidth{\the\pgflinewidth}
  \pgfsetlinewidth{+2pt}
  \pgfsetstrokecolor{black}
  \pgfpathmoveto{\pgfpointanchor{chain-\cnt}{north}}
  \pgfpathlineto{\pgfpointadd{\pgfpointanchor{chain-\cnt}{north}}{\pgfqpoint{0pt}{15pt}}}
  \pgfsetarrowsstart{Stealth[length=+2ex,width=+1.5ex]}
  \pgfusepath{stroke}
  \pgfsetlinewidth{\linewidth}}
\pgfset{
  x style/.style={inner xsep=+0.5pt, inner ysep=+1pt, none path},
  f style/.style={x style, gray text},
  o style/.style={x style, draw path},
  m style/.style={o style, /utils/exec=\let\arrowpath\Arrowpath}}
\newcommand*\aenodesetup[1]{%
  \vrule height1emdepth0ptwidth0pt\relax
  \makebox[1em][c]{\aenodesetupcol#1}}
\newcommand*\aeaux[2]{%
\begingroup
  \pgfset{#1 style}
  \ifnum\cnt=1
    \pgfnode{rectangle}{base}{\aenodesetup{#2}}{chain-\cnt}{\pgfusepath{\aeusepath}}
  \else
    \begingroup
      \pgftransformshift{
        \pgfpointadd{\pgfpointanchor{chain-\the\numexpr\cnt-1\relax}{base east}}
                    {\pgfqpoint{2pt}{0pt}}}
      \pgfnode{rectangle}{base west}{\aenodesetup{#2}}{chain-\cnt}
        {\pgfusepath{\aeusepath}}
    \endgroup
  \fi
  \pgfsetstrokecolor{black}
  \pgfpathmoveto{\pgfpointanchor{chain-\cnt}{south}}
  \pgfpathlineto{\pgfpointadd{\pgfpointanchor{chain-\cnt}{south}}{\pgfqpoint{0pt}{-6pt}}}
  \pgfusepath{stroke}
  \arrowpath
\endgroup}
\newcommand*\aemarkup[3][]{
\pgfpicture[#1]
  \foreach \aeI[count=\cnt,remember=\cnt] in {#2}% \cnt will be global after this
    {\expandafter\aeaux\aeI}
  \ifnum\cnt=#3\else
    \edef\Cnt{\the\numexpr\cnt+1\relax}
    \foreach \cnt in {\Cnt,...,#3}{\aeaux{x}{}}
  \fi
\endpgfpicture\par}
\begin{document}
Diagram:

\aemarkup{mx , ox , ox , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , mx , ox , ox , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , mx , ox , ox , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , mx , oM , ox , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , mx , ox , ox , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , mx , oa , ox , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , mx , ob , oc}{15}
\aemarkup{fx , ox , fx , ox , fx , ox , fx , oM , fx , ox , fx , oa , fx , ob , mc}{15}
\aemarkup{mx , ox , ox , oM , ox , oa , ob , xc}{15}
\aemarkup{fx , ox , mx , oM , ox , oa , ob , xc}{15}
\aemarkup{fx , ox , fx , oM , mx , oa , ob , xc}{15}
\aemarkup{fx , ox , fx , oM , fx , oa , mb , xc}{15}
\aemarkup{mx , oM , oa , xb , xc}{15}
\aemarkup{fx , oM , ma , xb , xc}{15}
\aemarkup{mM, xa, xb, xc}{15}
\end{document}

相关内容