![从 CSV 文件构建 PGF/TikZ 矩阵](https://linux22.com/image/304217/%E4%BB%8E%20CSV%20%E6%96%87%E4%BB%B6%E6%9E%84%E5%BB%BA%20PGF%2FTikZ%20%E7%9F%A9%E9%98%B5.png)
我想根据使用 读取的一些外部数据自动构建基于 PGF/TikZ 的绘图csvsimple
。我目前的主要问题是大多数节点都是矩阵的一部分,主要是为了设置一致的间距。组装 的内容\matrix{csv-stuff-goes-here}
并没有让我走得太远,所以我尝试使用 来\NewEnviron
定义自定义矩阵环境。第一个例子看起来很有希望:
\documentclass{article}
\usepackage{environ}
\usepackage{tikz}
\begin{document}
% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
\end{document}
现在我想介绍一下这个csvsimple
包——但失败了。MNWE:
\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{tikz}
\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}
\begin{document}
% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\csvreader[separator = semicolon, head to column names]{mystuff.csv}{}{
\draw (0,0) circle (4mm); \& \node (\mynode) {\mytext}; \\
}
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
\end{document}
报告的错误是
pdflatex.exe> ! Missing } inserted.
pdflatex.exe> <inserted text>
pdflatex.exe> }
pdflatex.exe> l.40 \end{TheMatrix}
我不知道为什么系统会认为缺少括号,以及如何找出到底出了什么问题。我尝试使用
\tracinggroups=1
\tracingnesting=2
但我不知道如何从输出中得到任何意义。这里发生了什么,我该如何调试这样的事情?
答案1
这是一个带有一些技巧的 CSV 方法。读取 CSV 文件并将其内容放入宏中\BODY
。\BODY
稍后将在矩阵中使用。
如果 CSV 内容包含宏或变音符号,则这可能不起作用,因为所有内容在添加到之前都会被扩展\BODY
。
\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple,etoolbox}
\usepackage{tikz}
\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}
\begin{document}
% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
\def\BODY{}
% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\csvreader[separator = semicolon, head to column names]{mystuff.csv}{}{
\eappto\BODY{\noexpand\draw (0,0) circle (4mm); \noexpand\& \noexpand\node (\mynode) {\mytext}; \noexpand\\}
}
\matrix[ampersand replacement=\&]{\BODY};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
\end{document}
答案2
这不是一个答案,但我不知道如何\\
在评论中包含它。我在上一个示例中插入过\\
,\end{TheMatrix}
并且成功了。为什么?我不知道,只是运气好而已。
\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{tikz}
\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}
\begin{document}
% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\csvreader[separator = semicolon, head to column names]{mystuff.csv}{}{
\draw (0,0) circle (4mm); \& \node (\mynode) {\mytext}; \\
}\\ %<------------------- This is what I added
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}
\end{document}