将 TikZ Pics (\pic) 命名为节点

将 TikZ Pics (\pic) 命名为节点

我对 tikz 图片感到困惑。我可以自由地定义它们而不会出现问题,甚至可以在里面添加坐标,这些坐标将通过名称继承获得,例如(-A)在 中\pic (S) at (0,0) {myPic}; \draw (S-A) -- ++(0,0);。这一切都记录在 pgf 手册第 255 页左右。

但是我不明白为什么如果图片内部没有定义坐标就不能给上面这样的图片命名。默认情况下,如果它可以像普通节点一样运行就太好了。

梅威瑟:

\documentclass{minimal}
\usepackage{tikz}

\tikzset{
    myBlock/.pic = {
        \node[draw,minimum width=1cm,minimum height=0.5cm] at (0,0) {};
    },
    myBlockNamed/.pic = {
        \node[draw,minimum height=1cm,minimum width=0.5cm] (-m) at (0,0) {};
    },
}

\begin{document}
\begin{tikzpicture}
    \pic () at (0,0) {myBock}; % can't give it a name
    \pic (S) at (3,0) {myBlockNamed}; % can give it a name
    \draw (S-A) -- ++(2,0);
\end{tikzpicture}
\end{document}

根本问题是我正在开发一个控制块库(这样我们就可以停止下面与@Alenanno 的聊天)。例如,这是数学运算符的定义

\tikzset{
    mySum background/.style = {
        circle, minimum size=1.5em, fill=white,
    },
    mySum edge/.style = {
        draw=black, circle, minimum size=1.5em, line width=.5pt,
    },
    pics/bOp/.style = {
    code = {
      \node [mySum background] {};
      \foreach \t [count=\i] in {#1}{
        \pgfmathsetmacro{\angle}{\i*90}
        \node[anchor=center, font=\tiny] at (\angle:0.45em) {$\t$};
      }
      \node [mySum edge] {};
    },
  },
}

答案1

在某些情况下可以使用一种技巧,利用将 apic放在scope可以用local bounding box键命名的 a 中的事实。请注意,这在树或图中不起作用。

\documentclass[tikz,border=5]{standalone}
\tikzset{pics/.cd,
  pic a/.style={code={
      \node [fill=red!20, shape=circle] {A};
  }}
}

\begin{document}
\begin{tikzpicture}
\pic [local bounding box=A1] at (0,0) {pic a};
\pic [local bounding box=A2] at (3,0) {pic a};
\foreach \i in {0,15,...,345}{
  \draw [red, ->] (\i:1) -- (A1);
  \draw [blue, ->] (3,0)++(\i:1) -- (A2);
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

还可以pic通过定义“包装器”键来使用给定的名称,该键明确向代码添加范围:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fit}%
\makeatletter
\tikzset{pics/named scope code/.style={code={\tikz@fig@mustbenamed%
  \begin{scope}[local bounding box/.expanded=\tikz@fig@name]#1\end{scope}%
}}}
\makeatother

\tikzset{pics/.cd,
  pic a/.style={named scope code={
      \node [fill=red!20, shape=circle] {A};
  }}
}

\begin{document}
\begin{tikzpicture}
\pic (A1) at (0,0) {pic a};
\pic (A2) at (3,0) {pic a};
\foreach \i in {0,15,...,345}{
  \draw [red, ->] (\i:1) -- (A1);
  \draw [blue, ->] (3,0)++(\i:1) -- (A2);
}
\end{tikzpicture}
\end{document}

结果和以前一样。

答案2

来自Pgf 手册(版本 3.0.0),第252页:

  1. 与节点不同,图片不能在以后引用。您可以引用图片内的节点,但不能引用“图片本身”。特别是,您不能像在节点之间画线那样在图片之间画线。一般来说,只要某些绘图可以连接到其他类似节点的东西,那么节点就比图片好。

  2. 如果使用 pics 来模拟节点的全部功能(原则上是可能的),那么与实现相同效果的节点相比,它们的构建速度会更慢,并且占用更多内存。

因此,如果你正在做某件事,一个节点做得很好,并且没有特别的理由使用pic,那么您最好使用节点。在回答问题“如何给 \pic 命名“,但它确实是一种解决方法。

但是,如果您希望能够将节点定位在另一个节点周围,您可以查看我前段时间问过的这个问题(如何在 TiKZ 中将节点定位在另一个节点周围?)或者你将 Tikz foreach 与常规节点结合使用。

更新答案

现在我知道您需要什么了,下面是使用 Tikz 的解决方案。 newcommand \mySumn(您可以重命名它)接受两个参数,例如\mySumn{#1}{#2},其中#1是节点的名称,#2是位置。

我尝试使用添加可选参数above of,但没有成功。但是,您可以使用此代码以不同的方式执行相同操作。请考虑以下内容:

\mySumn{p1}{0,0};
\mySumn{p2}{$(p1.north east)+(1em,1em)$};

它会p1在坐标处放置一个节点,然后在 x 和 y 轴上(右上方对角线)在 p1 的东北 +1em 处(0,0)放置另一个节点。p2

当然,您仍然可以从一个节点到另一个节点画边。

输出

图1

代码

\documentclass[margin=10pt]{standalone}
\usepackage{tikz}
\usepackage{xparse}

\usetikzlibrary{calc,arrows.meta,positioning}

\tikzset{
    mySumbk/.style = {
        draw, circle, minimum size=1.5em, fill=white,
    },
}

\newcommand{\mySumn}[2]{
    \node[mySumbk,fill=white] (#1) at (#2) {};
        \foreach \angle/\maop in {
        90/+,
        180/-
        }{
   \node[anchor=center, font=\tiny] at ($(#1)+(\angle:.45em)$) {$\maop$};
}}

\begin{document}
\begin{tikzpicture}[>=latex]

\mySumn{p1}{0,0};
\mySumn{p2}{$(p1.north east)+(1em,1em)$};

\draw (p1) -- (3,0);
\draw (p1) edge[out=90,in=180] (p2);
\end{tikzpicture}
\end{document}

答案3

老问题,但我对这个解决方案不满意,local bounding box因为我找不到更好地控制它的方法(例如,到内部内容的距离)。

我的解决方案是在 中使用嵌套图片pic,以及remember picture选项。名称以级联方式作为参数传递。这样,您不仅可以将 引用pic为节点(因为它实际上是一个节点),还可以引用其内容。

另一点是,使用此解决方案,a 的内容pic始终是集中的,这也是我在处理此代码时所寻找的。

意识到:

  • 由于,您必须编译该文档两次remember picture
  • 由于继承,嵌套节点可能会很棘手。

在此处输入图片描述

以下是代码:

\documentclass[tikz]{standalone}

\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}[remember picture]
  \tikzset{
    mine/.pic={
      \node[draw](#1){
        \begin{tikzpicture}[remember picture]
          \node[draw](#1-1){#1-1};          
          \node[draw, right=of #1-1](#1-2){#1-2};
        \end{tikzpicture}
      };
    },
  }

  \pic{mine=a};
  \pic[right=of a]{mine=b};

  \draw[thick, blue, <->](a-1)to[out=90, in=90](b-1);
  \draw[thick, blue, <->](a-2)to[out=-90, in=-90](b-2);
  \draw[thick, red](a)to(b);
\end{tikzpicture}
\end{document}

答案4

看来如果我为我的操作员定义一个像这样的命令:

\tikzset{
    mySum background/.style = {
        circle, minimum size=1.5em, fill=white,
    },
    mySum edge/.style = {
        draw=black, circle, minimum size=1.5em, line width=.5pt,
    },
}
\newcommand{\bOp}[1]{
  \tikz[outer sep=0pt]{
    \node [mySum background] {};
    \foreach \t [count=\i] in {#1}{
      \pgfmathsetmacro{\angle}{\i*90}
      \node[anchor=center, font=\tiny] at (\angle:0.45em) {$\t$};
    }
    \node [mySum edge] {};
  }
}

然后就可以创建一个包含假图片的节点,因为上面的内容正是人们用来定义图片的内容。

\node (1) at (0,0) {\bOp{+,-,,}};
\draw (4,0) -- (1);

相关内容