`graph` 命令不接受以 `-` 命名的节点

`graph` 命令不接受以 `-` 命名的节点

似乎\graph命令不接受名称包含 的节点-

编译

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{graphs}

\begin{document}
\begin{tikzpicture}
    \node[draw] (A-1) {A};  
    \node[draw] (B-1) at (1,0) {B};
    \graph [use existing nodes] { A-1 -> B-1;};
\end{tikzpicture}
\end{document}

结束并显示错误消息:

! Package tikz Error: One of the arrow types <-, --, ->, -!- or <-> expected.

因此看起来-(抱歉我不记得英文名字了)被视为箭头而不是节点名称的一部分。

这不是什么大问题,因为我们可以使用没有 的名称-。但是当节点用 声明时matrix of nodes,它们包含两个-。这意味着 的主要优点之一是 ,matrix of nodes它自动不能使用名称和选项|(...)|,或者|[name=...]|必须在每个带有节点的单元中使用 。

命令是否可以\graph接受-节点名称?

答案1

除了可以修改与矩阵或图形相关的代码外,这里还有另一种选择。

我们通常的想法是保护通过添加额外的括号来区分敏感字符,例如(\x,sin(\x))不起作用,但(\x,{sin(\x)})起作用。

对于图形来说,括号有另一种含义,我们应该保护用引号括住节点名称。理想的代码应该是这样的

\begin{tikzpicture}
    \node[draw] (A-1) {A};
    \node[draw] (B-1) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B-1";};
\end{tikzpicture}

但是,出于安全原因,引号内的任何内容都会被处理:特殊字符将被其他内容替换,例如-变为@HYPHEN MINUS@>变为@GREATER THAN SIGN@。因此,以下代码实际上是有效的。

\begin{tikzpicture}
    \node[draw] (A@HYPHEN MINUS@1) {A};
    \node[draw] (B@GREATER THAN SIGN@2) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B>2";};
\end{tikzpicture}

下一步是,每当我们(或 TiZ) 创建并命名一个节点,我们想用-上面的相同字符串替换名称。因此我们破解了这个name=方案

\makeatletter
\tikzset{
    name/.code={
        {
            \catcode`\-=13\relax
            \scantokens{
                \def-{@HYPHEN MINUS@}
                \xdef\hypenminusname{#1}
            }
        }
        \edef\tikz@fig@name{\tikz@pp@name{\hypenminusname}}
    }
}
\makeatother

如果涉及其他特殊字符,您可以自行扩展列表。

现在开头的代码可以正常工作了。以下代码也可以正常工作

\tikz{
    \matrix(magic)[matrix of nodes]{
        8 & 1 & 6 \\
        3 & 5 & 7 \\
        4 & 9 & 2 \\
    };
    \graph[use existing nodes]{
        "magic-2-1"->{"magic-1-3","magic-2-3","magic-3-3"};
    };
}


完整代码

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{graphs,matrix}
\begin{document}

\begin{tikzpicture}
    \node[draw] (A@HYPHEN MINUS@1) {A};
    \node[draw] (B@GREATER THAN SIGN@2) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B>2";};
\end{tikzpicture}

\makeatletter
\tikzset{
    name/.code={
        {
            \catcode`\-=13\relax
            \scantokens{
                \def-{@HYPHEN MINUS@}
                \xdef\hypenminusname{#1}
            }
        }
        \edef\tikz@fig@name{\tikz@pp@name{\hypenminusname}}
    }
}
\makeatother

\begin{tikzpicture}
    \node[draw] (A-1) {A};
    \node[draw] (B-1) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B-1";};
\end{tikzpicture}

\tikz{
    \matrix(magic)[matrix of nodes]{
        8 & 1 & 6 \\
        3 & 5 & 7 \\
        4 & 9 & 2 \\
    };
    \graph[use existing nodes]{
        "magic-2-1"->{"magic-1-3","magic-2-3","magic-3-3"};
    };
}

\end{document}

答案2

graph您可以更改代码的相关部分,而不是破解库或解析matrix of nodes。您还可以将其设为本地行为等。

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,matrix}
\makeatletter
\def\tikz@lib@matrix@empty@cell{\iftikz@lib@matrix@empty\node[name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]{};\fi}
\def\tikz@lib@matrix@with@options|#1|{\tikz@lib@matrix@plainfalse\node%
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]#1\bgroup\tikz@lib@matrix@startup}
\def\tikz@lib@matrix@normal@start@cell{\pgfutil@ifnextchar\let{\tikz@lib@matrix@check}{\tikz@lib@matrix@plainfalse\node
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]\bgroup\tikz@lib@matrix@startup}}%
\def\tikz@lib@matrix@check#1{% evil hackery to find out about start of path
  \pgfutil@ifnextchar\tikz@signal@path{\tikz@lib@matrix@plaintrue\let}{\tikz@lib@matrix@plainfalse\node
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]\bgroup\tikz@lib@matrix@startup\let}%
}
\makeatother

\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes] (a) {
A\\[4mm]
B\\
};
    \graph [use existing nodes] {a!1!1 -> a!2!1;};
\end{tikzpicture}
\end{document}

相关内容