tikz 中的定位节点和其他一些问题

tikz 中的定位节点和其他一些问题

我在 TikZ 中创建了一个图表。这是我第一次接触 TikZ,虽然我几乎已经完成了,但我还是有一些问题。在提问之前,我会在这里发布我的完整 tex 文件,因为最小版本不足以解释这个问题。

\documentclass{article}
\usepackage{pgfpages}
\pgfpagesuselayout{2 on 1}[a4paper,landscape, border shrink=5mm]

\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{arrows,shapes}
\usepackage[latin1]{inputenc}
\usepackage{verbatim}
\begin{document}
\tikzstyle{pre}=[<-,shorten <=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{post}=[->,shorten >=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{routed}=[to path={-- ++(0,8mm) |- (\tikztotarget)},shorten >=1pt,>=stealth',semithick, draw=blue!75]
\tikzstyle{place}=[circle,thick,draw=blue!75,fill=blue!20,minimum size=6mm]
\tikzstyle{node_box}=[rectangle,thick,draw=blue!75, fill=blue!10,minimum width=25mm, minimum height=5mm]

\begin{tikzpicture}[node distance=3.7cm,>=stealth',bend angle=45,auto]

  \begin{scope}
    \node at (15,0) [node_box] (south_if) {south\_if};
    \node[node_box] (south_r) [above left of=south_if, node distance=80mm] {south\_r}
    edge [pre]  node[sloped,near start] {input} node[sloped,near end,swap] {output} (south_if);

    \node[node_box] (box_a) [above of=south_r] {box\_a}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (south_r);

    \node[node_box] (nout_join) [above of=box_a] {nout\_join}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (box_a);

    \node[node_box] (sout_join) [above right of=south_if, node distance=80mm] {sout\_join}
    edge [post]  node[sloped,near start] {output} node[sloped,below,near end,swap] {input} (south_if);

    \node[node_box] (box_b) [above of=sout_join] {box\_b}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (sout_join);

    \node[node_box] (north_r) [above of=box_b] {north\_r}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (box_b);

    \node[node_box] (north_if) [above left of=north_r, node distance=80mm] {north\_if}
    edge [post]  node[sloped,near start] {output} node[sloped,near end,swap] {input} (north_r)
    edge [pre]  node[sloped,sloped,near start] {input} node[sloped,sloped,near end,swap] {output} (nout_join);

    %% Can this be placed next to box_a automatically with out specifying node distance?                                                                                                                           
    \node[node_box] (box_c) [sloped,above of=south_if, node distance=95mm] {box\_c};
    \node[node_box] (t_rdr) [below of=box_c] {t\_rdr}
    edge [pre]  node[sloped,above,near start] {input} node[sloped,below,near end,swap] {output} (box_c)
    edge [post]  node[sloped,very near start] {output\_n,n\_src} node[sloped,very near end, swap] {output, n\_src} (nout_join)
    edge [post]  node[sloped,very near start] {output\_s,s\_src} node[sloped,very near end, swap] {output, s\_src} (sout_join);

    \node[node_box] (t_output) [above of=box_c] {t\_output}
    edge [post]  node[sloped,above,near start] {output} node[sloped,below,near end,swap] {input} (box_c)
    edge [pre]  node[sloped,at start,anchor= south west] {n\_test\_in, test\_out} node[sloped,near end,swap] {test\_out, n\_test\_in} (north_r)
    edge [pre]  node[sloped,very near start,anchor= south east] {n\_test\_in, test\_out} node[sloped,very near end,anchor= north west] {test\_out, n\_test\_in} (south_r);

    \node[node_box] (south_rp) [below of=t_rdr, node distance=30mm] {south\_rp}
    edge [pre]  node[near start] {input} node[near end,swap] {out} (t_rdr);

    %% Can this node be better placed?                                                                                                                                                                             
    \node[node_box] (test_prov) [above right of=t_rdr, node distance=30mm] {test\_prov}
    edge [pre]  node[sloped,near start] {input} node[sloped,near end,swap] {prov\_out} (t_rdr)
    edge [post]  node[sloped,near start] {output} node[sloped,near end,swap] {test\_prov} (t_output);

    \node[node_box] (sink_prov) [right of=test_prov, node distance=60mm] {sink}
    edge [pre]  node[near start] {fromtest} node[near end,swap] {output1} (test_prov);

    \node[node_box] (sink_test_a) [left of=box_a, node distance=60mm] {sink}
    edge [pre]  node[near start] {test\_a} node[near end,swap] {output4} (box_a);

    \node[node_box] (sink_test_p) [right of=box_b, node distance=60mm] {sink}
    edge [pre]  node[near start] {test\_p} node[near end,swap] {output4} (box_b);
  \end{scope}

\end{tikzpicture}

\end{document}

输出图像为:

在此处输入图片描述

现在回答问题:

  1. box_c通过指定 来放置节点,该节点above of=south_if, node distance=95mm近似于 的水平位置box_a。有没有办法删除node distance并让和自动对齐?box_csouth_ifbox_a

  2. 我可以使用或将south_rt_output和之间的线改为水平和垂直吗?我尝试了一下,如 所示,但没能弄明白。t_rdrnout_join-||-\tikzstyle{routed}

  3. 我对节点的定位不太满意test_prov。这不完全是一个问题,但欢迎提出建议:)

  4. 代码有什么改进吗?这是我的第一个 TikZ 代码,我主要根据手册中的示例完成它。理想情况下,我希望将主图中的硬编码格式和数字删除到顶部的定义中,以便代码更干净且更易于维护。

  5. 我想将其打印在 A4 纸上。还没有弄清楚如何将此图放入 A4 纸中。

感谢您的时间和帮助:)

答案1

  1. 正如 Ignasi 所提到的,你可以使用

    \node (box_c) at (south_if |- box_a)  {box\_c};
    

    放置box_c在 的 x 坐标south_if和 的 y 坐标处box_a

  2. 您可以使用 在两个节点之间绘制水平线和垂直线\draw (a) -| (b);。(另请参阅TikZ:箭头的 |- 符号到底起什么作用?

  3. 没有比下面看到的更好的建议了。

  4. Ignasi 再次提到了几件事:

    在下面的代码中,我实现了这两个。因此,您会发现\tikzset{stylename/.style={<options>}}而不是\tikzstyle{stylename}=[<options>]。我已经从<position> of=<othernode>改为<position>=of <othernode>

    有些节点需要手动调整,但主要是因为第 5 点。

    我还对代码进行了一些重构,先放置所有节点,然后再绘制连接。这样做的最大好处可能是您可以使用环境为所有节点设置相同的样式。这使得代码更短,因此可能更容易跟踪。它还允许人们在循环中收集所有带有/标签的scope线条的绘制。inputoutput\foreach

    不过,您是否认为这种重组有用取决于您自己,如果您希望在edges 后面加上 s \node,那么就这样做吧。

    另外需要指出的是,你倾向于将节点选项拆分成两对括号,例如\node[node_box] (south_r) [above left of=south_if, node distance=80mm] {south\_r}。虽然这显然可行,但我会将所有设置保留在一对括号中,即

    \node[node_box,
         above left of=south_if,
         node distance=80mm]     (south_r) {south\_r}
    

    其他一些事项:该arrows库被视为弃用,以支持新arrows.meta库(尽管它仍可向后兼容)。请参阅第 16.5 节参考:箭头提示手册以获取由 定义的箭头名称列表。此外,当您加载 时,arrows.meta无需明确加载包,因为会加载。pgftikztikzpgf

  5. 图表中有几个地方可以节省水平空间,因此可以使其适合标准边距article。例如,sink节点会增加很多宽度,因此将它们放置在更靠近主体的位置会有所帮助。

    您还可以稍微减少样式minimum widthnode_box,至少对于本示例中的节点文本而言。在下面的代码中,它从 减少25mm20mm

    north_r您可能还注意到,我在和之间的行上的标签中添加了换行符,样式中通过启用了t_output的使用。\\align=centerlabelnode

(下图中的框架是由showframe包生成的,它在文本区域周围绘制一个框架。将其删除以获取真实文档。)

代码输出

\documentclass[a4paper]{article}
\usepackage{showframe}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning}
\usepackage[latin1]{inputenc}
\tikzset{
  line/.style={>=Stealth,semithick, draw=blue!75},
  post/.style={line,->,shorten >=1pt},
  node_box/.style={rectangle,thick,draw=blue!75, fill=blue!10,minimum width=20mm, minimum height=5mm},
  labelnode/.style={auto,sloped,font=\footnotesize,align=center},
}

\begin{document}
\begin{center}
\begin{tikzpicture}[node distance=3cm and 1.7cm]
\begin{scope}[every node/.style={node_box}]
  \node                                       (south_if)    {south\_if};
  \node [above left=of south_if,xshift=5mm]   (south_r)     {south\_r};
  \node [above=of south_r]                    (box_a)       {box\_a};
  \node [above=of box_a]                      (nout_join)   {nout\_join};
  \node [above right=of south_if]             (sout_join)   {sout\_join};
  \node [above=of sout_join]                  (box_b)       {box\_b};
  \node [above=of box_b]                      (north_r)     {north\_r};
  \node [above left=of north_r,yshift=-1.5cm] (north_if)    {north\_if};
%
  \node [at={(south_if |- box_a)}]            (box_c)  {box\_c};
  \node [at={(box_c|-sout_join)}]             (t_rdr)       {t\_rdr};
%
  \node [above=of box_c]                       (t_output)    {t\_output};
  \node [below=2cm of t_rdr]                   (south_rp)    {south\_rp};
  \node [above right=1.5cm and 0mm of t_rdr]   (test_prov)   {test\_prov};
  \node [below right=7mm and 1cm of test_prov] (sink_prov)   {sink};
  \node [above left=1.5cm and -5mm of box_a]   (sink_test_a) {sink};
  \node [above right=1cm and -5mm of box_b]    (sink_test_p) {sink};
\end{scope}

\begin{scope}[every node/.style={labelnode}]

\foreach \i/\j in  {%
    box_b/sout_join,
    box_a/nout_join,
    north_r/box_b,
    box_c/t_rdr,
    t_rdr/south_rp,
    t_output/box_c,
    south_r/box_a}
  \draw [post] (\i) -- (\j)
     node[above,near start] {output}
     node[below,near end,swap] {input};

\foreach \i/\j in{%
    nout_join/north_if,
    sout_join/south_if}
  \draw [post] (\i) |- (\j)
    node[above,near start] {output}
    node[below,near end,swap] {input};

\foreach \i/\j in{%
    north_if/north_r,
    south_if/south_r}
  \draw [post] (\i) -| (\j)
    node[above,near start] {output}
    node[below,near end,swap] {input};

\draw [post] (t_rdr) -- (test_prov)
  node[above,pos=0.4] {prov\_out}
  node[below,pos=0.6] {input};

\draw [post] (test_prov) -- ([xshift=-3mm]t_output.south east)
  node[above,pos=0.7] {test\_prov}
  node[below,pos=0.3] {output};

\draw [post] (t_rdr) -- (sout_join)
  node[above,pos=0.45] {output\_s,src}
  node[below,pos=0.55] {output\_s,src};

\draw [post] (test_prov) -| (sink_prov)
  node[above,pos=0.4] {output1}
  node[left,sloped=false,pos=0.8] {fromtest};

\draw [post] (north_r) -- (t_output)
  node[above,pos=0.65] {n\_test\_in,\\test\_out}
  node[below,pos=0.35] {test\_out,\\n\_test\_in};

\draw [post] (box_a) -| (sink_test_a)
  node[left,sloped=false,pos=0.85] {test\_a}
  node[below,pos=0.49] {output4};

\draw [post] (box_b) -| (sink_test_p)
  node[right,sloped=false,pos=0.85] {test\_p}
  node[below,pos=0.49] {output4};

\draw [post] (t_rdr) -- (nout_join)
  node[below,near start] {output\_n,n\_src}
  node[above,near end] {output\_n,src};

\draw [post] (south_r) -- (t_output)
  node[below,near start] {test\_out,n\_test\_n}
  node[above,near end] {n\_test\_out,test\_out};

\end{scope}

\end{tikzpicture}
\end{center}
\end{document}

相关内容