如何在 TikZ 中将节点从(节点 1)均匀分布到(节点 2)?

如何在 TikZ 中将节点从(节点 1)均匀分布到(节点 2)?

我有一个比较长而浅的矩形,我需要在它的底部放置一些节点。我不想手动调整坐标,当然也不想多次复制相同的代码。

到目前为止我已经想出了以下代码:

\documentclass{standalone}
\usepackage{tikz} 
\usetikzlibrary{positioning,fit,petri,arrows,backgrounds}
\begin{document}
 \begin{tikzpicture}[inner sep=0mm,>=stealth',very thick,color=black!50,
    background rectangle/.style={fill=black},show background rectangle,
    font=\sffamily,pics/two dots/.style={code={
     \node [draw,minimum size=5mm,circle,colored tokens={black!50}] 
     (#1-left) {};
    \node [draw,minimum size=5mm,circle,colored tokens={black!50},
    right=0pt of #1-left]
        (#1-right) {};
    \node [rectangle, fit=(#1-left) (#1-right)] (#1){};
    }},
    every pin edge/.style={<-,very thick},
    box/.style={draw,rectangle,inner sep=#1},box/.default=2mm]
  % 
  \node (W1)  {factorial:};
  \node (fake1) [right=190mm of W1] {};

  %
  \node (g env) [box, fit=(W1) (fake1),
  pin={[text width=1cm,pin distance=10mm]left:global env}]
  { };
  %
  \path ([yshift=-20mm]W1.east)pic{two dots=w1fun}
    (w1fun) edge [<-, to path={|- (\tikztotarget)}] (W1.east);
  %
  \node [below=of w1fun-left, align=left] {parameters: n \\ body: \dots}
    edge [<-] (w1fun-left.center); 

  \path (w1fun-right.center) edge[->,to path={-| (\tikztotarget)}] 
    (node cs:name=g env,angle=183);
\foreach \angl/\idx in {185/6, 195/5, 345/4, 355/3, 357/2, 358/1}  
{  
  \draw (node cs:name=g env,angle=\angl) node [rectangle, draw] (fake2-\idx)  {};
  \node (E\idx-env) [below=5mm of fake2-\idx,box,
    pin={[pin distance=5mm]left:E\idx}] {n:\idx}
    edge [->] (fake2-\idx);

  \node (E\idx-code) [below=5mm of E\idx-env, align=center]{
       (* \idx \hskip5pt (factorial \pgfmathparse{int(\idx - 1)}\pgfmathresult))
    };
}; 

\end{tikzpicture}
\end{document}

这不是一个“最小”的例子,但 \foreach 中的代码才是重要的。

这里发生了什么:

  • (g env) 节点就是这个宽浅的矩形。
  • 我正在使用 \angle 和 \idx 变量来 -- 查找“锚点”节点的位移。 -- 更改“附加”节点的名称。 -- 计算示例代码中索引的值

在此处输入图片描述

我不喜欢这里:

  1. \pgfmathparse 。我似乎做错了什么。我尝试使用 ($$) 构造,但失败了。有没有比直接使用 \pgfmathparse 更好的方法来查找索引的值?
  2. 角度。$$sin(x) != x$$,所以我无法为循环设置一个常规范围。有没有办法以惯用的方式等距设置节点?

答案1

等距定位通过语法很容易实现pos。在

foreach \idx  in {1,...,6}  
{  
   node [pos=\idx/7.5-1/7.5,rectangle, draw] (fake2-\idx)  {}
  node (E\idx-env) [below=5mm of fake2-\idx,box,
    pin={[pin distance=5mm]left:E\idx}] {n:\idx}
    edge [->] (fake2-\idx)
  node (E\idx-code) [below=5mm of E\idx-env, align=center]{
       (* \idx \hskip5pt (factorial \the\numexpr\idx-1))
    }
}; 

节点的位置为\idx/7.5-1/7.5,因此等距。对于整数,可以使用\the\numexpr,这样就可以去掉\pgfmathparse

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{positioning,fit,petri,arrows,backgrounds}
\begin{document}
 \begin{tikzpicture}[inner sep=0mm,>=stealth',very thick,color=black!50,
    background rectangle/.style={fill=black},show background rectangle,
    font=\sffamily,pics/two dots/.style={code={
     \node [draw,minimum size=5mm,circle,colored tokens={black!50}] 
     (#1-left) {};
    \node [draw,minimum size=5mm,circle,colored tokens={black!50},
    right=0pt of #1-left]
        (#1-right) {};
    \node [rectangle, fit=(#1-left) (#1-right)] (#1){};
    }},
    every pin edge/.style={<-,very thick},
    box/.style={draw,rectangle,inner sep=#1},box/.default=2mm]
  % 
  \node (W1)  {factorial:};
  \node (fake1) [right=190mm of W1] {};
  %
  \node (g env) [box, fit=(W1) (fake1),
  pin={[text width=1cm,pin distance=10mm]left:global env}]
  { };
  %
  \path ([yshift=-20mm]W1.east)pic{two dots=w1fun}
    (w1fun) edge [<-, to path={|- (\tikztotarget)}] (W1.east);
  %
  \node [below=of w1fun-left, align=left] {parameters: n \\ body: \dots}
    edge [<-] (w1fun-left.center); 

  \path (w1fun-right.center) edge[->,to path={-| (\tikztotarget)}] 
    (node cs:name=g env,angle=183);
\path (g env.south east) -- (g env.south west) 
foreach \idx  in {1,...,6}  
{  
   node [pos=\idx/7.5-1/7.5,rectangle, draw] (fake2-\idx)  {}
  node (E\idx-env) [below=5mm of fake2-\idx,box,
    pin={[pin distance=5mm]left:E\idx}] {n:\idx}
    edge [->] (fake2-\idx)
  node (E\idx-code) [below=5mm of E\idx-env, align=center]{
       (* \idx \hskip5pt (factorial \the\numexpr\idx-1))
    }
}; 

\end{tikzpicture}
\end{document}

在此处输入图片描述

请注意,我必须添加backgrounds库并移动,\node (W1) {factorial:};然后从 fit 中\node (fake1) [right=190mm of W1] {};删除make withdraw,以使代码编译。我还切换到类,standalone因为图片对于常规文章来说有点太宽了。

答案2

编写图像的另一种方法:

  • 首先使用循环在链中绘制“阶乘”节点
  • 比绘制其他节点
\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{arrows.meta,
                backgrounds,
                chains,
                fit,
                petri,
                positioning}

\begin{document}
 \begin{tikzpicture}[
    > = Stealth,
 font = \small\sffamily,
 thick,
 color=gray!50,
 inner sep = 0pt,
 %
background rectangle/.style={fill=black}, show background rectangle,
 %
PN/.style = {place, minimum size=5mm, colored tokens={gray!50}},
pics/two dots/.style = {code={
    \node   [PN]                        (#1-left)   {};
    \node   [PN, right=0pt of #1-left]  (#1-right)  {};
    \node   [fit=(#1-left) (#1-right)]  (#1)        {};
                        }},
 %
every pin/.style={pin edge={<-, thick, gray!50}, align=left},
box/.style = {draw, inner sep=#1},
box/.default = 2mm,
 %
node distance = 4mm and 2mm,
  start chain = going left
                    ]
\foreach \x [count=\xx from 0] in {1,...,6}
{
\node (f\x) [on chain] {(*\,\x\,(factorial \xx))};
\node (n\x) [box,
             pin=left:E\x,
             above=of f\x]  {n\x};
\draw[->]   (n\x.north) -- ++ (0,4mm) coordinate (p\x);
}
%
\pic at ([shift={(-22mm,2mm)}] f6.north west) {two dots=PN}; % PN: petri net
\node (factorial) [above left=of PN.west |- p6] {factorial:};
\node[draw, inner sep=1mm, shift={(-1mm, 1mm)}, 
      pin=left:global\\ env,
      fit=(factorial) (p1)] {};
\draw[->] (factorial) -| (PN);
\draw[->] (PN-right.center) -| ([xshift=3mm] PN.east |- p6);
\draw[->] (PN-left.center) -- ++ (0,-1) 
            node[below, align=left] {parameters: n\\
                                     body: \dots};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

除了上面给出的两个优秀的解决方案之外,还有一个可能有用。

(我只写了负责实际定位的部分。)

\coordinate(g env south west) at (g env.south west);
\coordinate(g env south east) at (g env.south east);
\node (barycentric cs:g env south west=2,g env south east=8) {debug};

可以用 来计算权重的值\mathexpr

相关内容