从 CSV 文件构建 PGF/TikZ 矩阵

从 CSV 文件构建 PGF/TikZ 矩阵

我想根据使用 读取的一些外部数据自动构建基于 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}

在此处输入图片描述

相关内容