![Tikz 外部化 + 宏?或者你会怎么做?](https://linux22.com/image/236068/Tikz%20%E5%A4%96%E9%83%A8%E5%8C%96%20%2B%20%E5%AE%8F%EF%BC%9F%E6%88%96%E8%80%85%E4%BD%A0%E4%BC%9A%E6%80%8E%E4%B9%88%E5%81%9A%EF%BC%9F.png)
我目前正在为我的一些大学老师创建课程。目的是将他们用 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}
(注意:在此代码中,当我取消注释边界框行时,出现了问题。这与获取键的长度和值以正确交互有关。)