Tikz 外部化 + 宏?或者你会怎么做?

Tikz 外部化 + 宏?或者你会怎么做?

我目前正在为我的一些大学老师创建课程。目的是将他们用 Word/MS paint 生成的学习材料变成高质量的 Latex/Tikz 材料。

我的目标是图形(特别是图表)具有高度的一致性,因此我编写了一堆宏,这些宏可以根据我Matlab使用matlab2tikz.m代码(在我大学编写的!)获得的数据为我生成 tikz 图片。

我所做的就是写一堆““将当前变量设置为某个东西的宏\figxlabel{$x$-axis}(例如,参见下面的代码)将设置另一个宏\thefigxlabel以包含$x$-axis。所有这些信息随后将在下一个中使用\matlabfig{data.tikz},之后将其重置为中性值。由于所有内容都在宏中,因此我不需要记住绘图的特殊设置是什么,甚至更好的是,我可以更改宏\matlabfig以一次更改所有图片!

但是,后来我发现了 Tikzexternalize库,由于我的文档越来越大(我将它们拆分但仍然...),它会非常方便。然而,这个库不支持在 tikzpictures 中使用宏。你会怎么做才能将两个世界的优点结合起来?

我考虑使用宏来设置适用于所有图形的全局 tikz 属性(我不知道是否可以这样做\tikzset{every xlabel={$x$-axis}}),然后在图片之间更改它,这样它只适用于下一个。这样 tikz 环境中就不会有任何宏。我猜我必须使用非宏\begin\end结构。

我编写的所有宏均在下一段代码中给出(这些应该可以工作):

\def\figurewidth{7.5cm}
\def\figureheight{4cm}

\newcommand{\thefigtitle}[0]{\null}%title
\newcommand{\thefigtith}[0]{0cm}
\newcommand{\figtitle}[1]{%
    \renewcommand{\thefigtitle}{#1}%
    \renewcommand{\thefigtith}{0.35cm}%
}

\def\figysep{1}

\newcommand{\thefigxlabel}[0]{\null}%xlabel
\newcommand{\thefigxh}[0]{0}

\newcommand{\figxlabel}[1]{%
    \renewcommand{\thefigxlabel}{#1}%
    \renewcommand{\thefigxh}{-0.35}%
}

\newcommand{\thefigylabel}{}%ylabel
\newcommand{\figylabel}[1]{\renewcommand{\thefigylabel}{#1}}

\newcommand{\thefiglabel}{ }%label
\newcommand{\figlabel}[1]{%
    \renewcommand{\thefiglabel}{\label{#1}}%
}  

\newcommand{\thefigxrange}[0]{ }%x-range
\newcommand{\figxrange}[2]{
    \renewcommand{\thefigxrange}{xmin=#1,xmax=#2,}
}  


\newcommand{\thefigyrange}[0]{ }%y-range
\newcommand{\figyrange}[2]{%
    \renewcommand{\thefigyrange}{ymin=#1,ymax=#2,}
}  

\newcommand{\thefiglegend}{ }%legend
\newcommand{\figlegend}[2]{%
    \renewcommand{\thefiglegend}{legend entries={#1},legend pos={#2}}%
}

\newcommand{\thefigcaption}{\caption{}}%caption
\newcommand{\figcaption}[1]{\renewcommand{\thefigcaption}[0]{\caption{#1}}}

\newcommand{\thefigextra}{ }%extra options
\newcommand{\figextra}[1]{\renewcommand{\thefigextra}[0]{#1}}

\newcommand{\thefigpos}{htp}
\newcommand{\figpos}[1]{\renewcommand{\thefigpos}[0]{#1}}

\newcommand{\matlabfig}[1]{%figuur zelf
    \begin{figure}[\thefigpos]
        \centering
        \begin{tikzpicture}[]
            \draw[use as bounding box,draw=none](0,0+\thefigxh)rectangle(\figurewidth,\figureheight+\thefigtith);           
            \begin{axis}[%
            view={0}{90},
            scale only axis,
            width=\figurewidth,
            height=\figureheight,
            y tick label style={font={\tiny}}, 
            x tick label style={font={\tiny}}, 
            title={\textbf{\textsc{\thefigtitle}}},
            xlabel={\textbf{\thefigxlabel}},
            ylabel={\textbf{\thefigylabel}},
            \thefigxrange
            \thefigyrange
            axis on top,\thefiglegend,
            \thefigextra,
            minor tick num=1
            ]
                \input{#1}
            \end{axis}
        \end{tikzpicture}
    \thefigcaption\thefiglabel
\end{figure}
%alles resetten 
\figreset}


\newcommand{\figreset}[0]{
\renewcommand{\thefigtitle}{ }%
\renewcommand{\thefigxlabel}{ }% 
\renewcommand{\thefigxh}{0}%
\renewcommand{\thefigtith}{0cm}% 
\renewcommand{\thefigylabel}{}% 
\renewcommand{\thefigcaption}{\caption{}}%
\renewcommand{\thefiglabel}{}%
\renewcommand{\thefiglegend}{}%
\renewcommand{\thefigxrange}{}%
\renewcommand{\thefigyrange}{}%
\renewcommand{\thefigextra}{ }%
\renewcommand{\thefigpos}{htp}%
}

编辑:添加了一个有效的最小示例

内容example.tex

\documentclass{article}

\usepackage{tikz}
\usepackage{pgfplots}

\def\figurewidth{7.5cm}
\def\figureheight{4cm}

\newcommand{\thefigtitle}[0]{\null}%title
\newcommand{\thefigtith}[0]{0cm}
\newcommand{\figtitle}[1]{%
    \renewcommand{\thefigtitle}{#1}%
    \renewcommand{\thefigtith}{0.45cm}%
}

\def\figysep{1}

\newcommand{\thefigxlabel}[0]{\null}%xlabel
\newcommand{\thefigxh}[0]{0}

\newcommand{\figxlabel}[1]{%
    \renewcommand{\thefigxlabel}{#1}%
    \renewcommand{\thefigxh}{-0.35}%
}

\newcommand{\thefigylabel}{}%ylabel
\newcommand{\figylabel}[1]{\renewcommand{\thefigylabel}{#1}}

\newcommand{\thefiglabel}{ }%label
\newcommand{\figlabel}[1]{%
    \renewcommand{\thefiglabel}{\label{#1}}%
}  

\newcommand{\thefigxrange}[0]{ }%x-range
\newcommand{\figxrange}[2]{
    \renewcommand{\thefigxrange}{xmin=#1,xmax=#2,}
}  


\newcommand{\thefigyrange}[0]{ }%y-range
\newcommand{\figyrange}[2]{%
    \renewcommand{\thefigyrange}{ymin=#1,ymax=#2,}
}  

\newcommand{\thefiglegend}{ }%legend
\newcommand{\figlegend}[2]{%
    \renewcommand{\thefiglegend}{legend entries={#1},legend pos={#2}}%
}

\newcommand{\thefigcaption}{\caption{}}%caption
\newcommand{\figcaption}[1]{\renewcommand{\thefigcaption}[0]{\caption{#1}}}

\newcommand{\thefigextra}{ }%extra options
\newcommand{\figextra}[1]{\renewcommand{\thefigextra}[0]{#1}}

\newcommand{\thefigpos}{htp}
\newcommand{\figpos}[1]{\renewcommand{\thefigpos}[0]{#1}}

\newcommand{\matlabfig}[1]{%figuur zelf
    \begin{figure}[\thefigpos]
        \centering
        \begin{tikzpicture}[]
            \draw[use as bounding box,draw=none](0,0+\thefigxh)rectangle(\figurewidth,\figureheight+\thefigtith);            
            \begin{axis}[%
            view={0}{90},
            scale only axis,
            width=\figurewidth,
            height=\figureheight,
            y tick label style={font={\tiny}}, 
            x tick label style={font={\tiny}}, 
            title={\textbf{\textsc{\thefigtitle}}},
            xlabel={\textbf{\thefigxlabel}},
            ylabel={\textbf{\thefigylabel}},
            \thefigxrange
            \thefigyrange
            axis on top,\thefiglegend,
            \thefigextra,
            minor tick num=1
            ]
                \input{#1}
            \end{axis}
        \end{tikzpicture}
    \thefigcaption\thefiglabel
\end{figure}
%alles resetten 
\figreset}


\newcommand{\figreset}[0]{
\renewcommand{\thefigtitle}{ }%
\renewcommand{\thefigxlabel}{ }% 
\renewcommand{\thefigxh}{0}%
\renewcommand{\thefigtith}{0cm}% 
\renewcommand{\thefigylabel}{}% 
\renewcommand{\thefigcaption}{\caption{}}%
\renewcommand{\thefiglabel}{}%
\renewcommand{\thefiglegend}{}%
\renewcommand{\thefigxrange}{}%
\renewcommand{\thefigyrange}{}%
\renewcommand{\thefigextra}{ }%
\renewcommand{\thefigpos}{htp}%
}


\pgfplotsset{
    every tick/.style={thin,color=black},
    every axis legend/.append style={nodes={right}},
    every axis legend/.append style={font=\tiny},
    compat=newest
}

\tikzstyle{every node}=[font=\scriptsize]

\begin{document}

 %%
\figcaption{an example fig}
\figlabel{fig:example}
\figtitle{example}
\figxlabel{$x$ axis}
\figylabel{$y$ axis}
\figlegend{data.tikz}{north west}
\figxrange{0}{6}
\figyrange{0}{5}
\figextra{}
\matlabfig{data.tikz}
%%

%another fig, but as you can see all was resetted
\matlabfig{data.tikz} 


\end{document}

内容data.tikz

\addplot [
color=black,
solid
]
coordinates{(0,0) (3,3) (4,5) (5,4)};

如何与环境协调?

newenvironment以下示例包含创建 的最基本内容tikzpicture。我实际上想要的是更多选项,但问题仍然相同。

以下是一小段示例代码:

\documentclass[a4paper]{article}

\usepackage{tikz}
\usetikzlibrary{external}

\newenvironment{mytikz}{%
\begin{figure}[htp]
\centering
\begin{tikzpicture}}
{\end{tikzpicture}
\caption{}
\end{figure}}

\tikzexternalize

\begin{document}

\begin{mytikz}
    \draw(0,0) circle (1cm);
\end{mytikz}

\end{document}

答案1

MWE 使用外部化库工作得很好。将语法转换为使用pgfkeys实际上解决了范围问题,因为键是当前范围的本地键。因此,您可以将键和值作为选项传递给命令matlabfig,并且它们将仅在该命令内部使用。

我只是 of 领域的新手,pgfkeys所以可能有更好的方法来实现这一点,但这是将您的宏转换为pgfkeys语言。我只在输入语法中更改了一件事:范围被指定为x range=0:6而不是x range={0}{6}

当将其放入环境中时,问题在于外部化库会寻找\end{tikzpicture} 没有进行任何扩展。在普通环境中,这不起作用,因为隐藏\end{tikzpicture}在后面\end{myenvironment}。所以我们必须有一个方法来\end{myenvironment}扩展同时。幸运的是\begin{tikzpicture},这种方法是存在的,并且使用环境包。这使得环境的行为有点像命令。

\documentclass{article}
\usepackage{environ}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize
\tikzset{external/force remake=true}
\usepackage{pgfplots}

\def\figurewidth{7.5cm}
\def\figureheight{4cm}

\pgfkeys{/matlab plot/.cd,
  title/.default={\null},
  title height/.default={0cm},
  x label/.default={\null},
  x label height/.default={0},
  x range/.code args={#1:#2}{\pgfkeyssetvalue{/matlab plot/x range}{xmin=#1,xmax=#2}},
  y range/.code args={#1:#2}{\pgfkeyssetvalue{/matlab plot/y range}{ymin=#1,ymax=#2}},
  legend/.code args={#1#2}{\pgfkeyssetvalue{/matlab plot/legend}{legend entries=#1,legend pos=#2}},
  title/.code={%
    \pgfkeyssetvalue{/matlab plot/title}{#1}%
    \pgfkeyssetvalue{/matlab plot/title height}{0.45cm}},
  x label/.code={%
    \pgfkeyssetvalue{/matlab plot/x label}{#1}%
    \pgfkeyssetvalue{/matlab plot/x label height}{-0.35}},
  caption/.code={%
    \pgfkeyssetvalue{/matlab plot/caption}{\caption{#1}}},
  label/.code={\pgfkeyssetvalue{/matlab plot/caption}{\label{#1}}}%
}

% Initialise
\pgfkeyssetvalue{/matlab plot/caption}{}
\pgfkeyssetvalue{/matlab plot/label}{}
\pgfkeyssetvalue{/matlab plot/x label}{}
\pgfkeyssetvalue{/matlab plot/y label}{}
\pgfkeyssetvalue{/matlab plot/extra}{}
\pgfkeyssetvalue{/matlab plot/legend}{}
\pgfkeyssetvalue{/matlab plot/x range}{}
\pgfkeyssetvalue{/matlab plot/x range}{}
\pgfkeyssetvalue{/matlab plot/y range}{}
\pgfkeyssetvalue{/matlab plot/y range}{}
\pgfkeyssetvalue{/matlab plot/pos}{}

\def\figysep{1}

\newcommand{\matlabfig}[2][]{%figuur zelf
  \begingroup
  \pgfkeys{/matlab plot/.cd,#1}
    \begin{figure}[\pgfkeysvalueof{/matlab plot/pos}]
        \centering
        \begin{tikzpicture}[]
%            \draw[use as bounding box,draw=none](0,0+\pgfkeysvalueof{x label height})rectangle(\figurewidth,\figureheight+\pgfkeysvalueof{title height});           
            \begin{axis}[%
            view={0}{90},
            scale only axis,
            width=\figurewidth,
            height=\figureheight,
            y tick label style={font={\tiny}}, 
            x tick label style={font={\tiny}}, 
            title={\textbf{\textsc{\pgfkeysvalueof{/matlab plot/title}}}},
            xlabel={\textbf{\pgfkeysvalueof{/matlab plot/x label}}},
            ylabel={\textbf{\pgfkeysvalueof{/matlab plot/y label}}},
            \pgfkeysvalueof{/matlab plot/x range},
            \pgfkeysvalueof{/matlab plot/y range},
            axis on top,
            \pgfkeysvalueof{/matlab plot/legend},
            \pgfkeysvalueof{/matlab plot/extra}
            minor tick num=1
            ]
                \input{#2}
            \end{axis}
        \end{tikzpicture}
        \pgfkeysvalueof{/matlab plot/caption}
        \pgfkeysvalueof{/matlab plot/label}
\end{figure}
    \endgroup}

\NewEnviron{MatlabFig}[1][]{%
  \begingroup
  \pgfkeys{/matlab plot/.cd,#1}
  \begin{figure}[\pgfkeysvalueof{/matlab plot/pos}]
  \centering
  \begin{tikzpicture}
%            \draw[use as bounding box,draw=none](0,0+\pgfkeysvalueof{x label height})rectangle(\figurewidth,\figureheight+\pgfkeysvalueof{title height});           
            \begin{axis}[%
            view={0}{90},
            scale only axis,
            width=\figurewidth,
            height=\figureheight,
            y tick label style={font={\tiny}}, 
            x tick label style={font={\tiny}}, 
            title={\textbf{\textsc{\pgfkeysvalueof{/matlab plot/title}}}},
            xlabel={\textbf{\pgfkeysvalueof{/matlab plot/x label}}},
            ylabel={\textbf{\pgfkeysvalueof{/matlab plot/y label}}},
            \pgfkeysvalueof{/matlab plot/x range},
            \pgfkeysvalueof{/matlab plot/y range},
            axis on top,
            \pgfkeysvalueof{/matlab plot/legend},
            \pgfkeysvalueof{/matlab plot/extra}
            minor tick num=1
            ]
  \BODY
            \end{axis}
        \end{tikzpicture}
        \pgfkeysvalueof{/matlab plot/caption}
        \pgfkeysvalueof{/matlab plot/label}
\end{figure}
    \endgroup}

\pgfplotsset{
    every tick/.style={thin,color=black},
    every axis legend/.append style={nodes={right}},
    every axis legend/.append style={font=\tiny},
    compat=newest
}

\tikzstyle{every node}=[font=\scriptsize]

\begin{document}

 %%
\matlabfig[
        caption=an example fig,
        label=fig:example,
        title=example,
        x label=$x$ axis,
        y label=$y$ axis,
        legend={data.tikz}{north west},
        x range=0:6,
        y range=0:5,
        ]{tikzextkeys_data.tikz}

%%

%another fig, but as you can see all was resetted
\matlabfig{tikzextkeys_data.tikz} 

\begin{MatlabFig}[
        caption=an example fig,
        label=fig:example,
        title=example,
        x label=$x$ axis,
        y label=$y$ axis,
        legend={data.tikz}{north west},
        x range=0:6,
        y range=0:5,
        ]
\input{tikzextkeys_data.tikz}
\end{MatlabFig}

\end{document}

(注意:在此代码中,当我取消注释边界框行时,出现了问题。这与获取键的长度和值以正确交互有关。)

相关内容