图片内意外的 TikZ 编码变化

图片内意外的 TikZ 编码变化

我想要绘制许多包含子图的 TikZ 图片,例如:

在此处输入图片描述

模数样式如下,我可以使用以下代码来做到这一点:

\begin{tikzpicture}
  \node[vertex](1) at (1,0){};
  \node[vertex](2) at (2,0){};
  \draw(1) to[out=60, in=120]node[colour]{$1$}(2);
\end{tikzpicture}

我需要绘制很多这样的图,所以我决定通过定义一张图片来简化它:

\tikzset{
  pics/cap/.style = {
    code = {
      \foreach \x [count=\c from 0, remember=\x as \y] in {#1} {
         \node[vertex](\x) at (\x,0){};
         \ifnum\c>0
             \draw(\y) to [out=60, in=120] node[colour]{$\c$} (\x);
         \fi
      }
    }
  },
}

这样我就可以将上面的例子写成:

\begin{tikzpicture}
  \pic at (0,0) {cap={1,2}};
\end{tikzpicture}

不幸的是,这不起作用,而是产生:

在此处输入图片描述

有人能向我解释为什么我的pics代码没有给出与“动手”方法相同的输出吗?

完整代码如下:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass{article}

\usepackage{tikz}

\tikzset{
  colour/.style = {
    circle,
    draw,
    fill=white,
    font=\small,
    inner sep=0.2pt,
  },
  pics/cap/.style = {
    code = {
      \foreach \x [count=\c from 0, remember=\x as \y] in {#1} {
         \node[vertex](\x) at (\x,0){};
         \ifnum\c>0
             \draw(\y) to [out=60, in=120] node[colour]{$\c$} (\x);
         \fi
      }
    }
  },
  vertex/.style = {
    circle,
    radius=1mm,
    inner sep=-2.0pt,
    fill=black
  },
}

\begin{document}

    \begin{tikzpicture}
      \node[vertex](1) at (1,0){};
      \node[vertex](2) at (2,0){};
      \draw(1) to[out=60, in=120]node[colour]{$1$}(2);
    \end{tikzpicture}

  \bigskip

  \begin{tikzpicture}
    \pic at (0,0) {cap={1,2}};
  \end{tikzpicture}

\end{document}

答案1

图片是一个节点……当然不是,但 TikZ 使用与解析图片节点规范相同的机制,只需举起一个标志(\iftikz@node@is@pic),事实上,可以将图片放在路径上,比如说

\draw (0,0) -- pic[sloped] {cap = {3, 5}} (1,2);

midway(这里,如果 pic 的放置位置明确,不是按照默认值( ) ,我们就会遇到第一个冲突pos = 0.5。pic 内部的节点是否应该放置在midwaypic 外部范围的默认位置,还是与 pic 本身的放置方式相同?)

node现在, a (以及 a )做的第一件事pic就是检查另一个标志:\iftikz@node@is@a@label。该名称具有误导性,因为它不是关于 TikZ 标签,而是关于是否在路径操作( 、 等)与其目标坐标之间找到了节点(或图片--to[…]

如果不是,则 的值pos将被清空,这表明不应应用计时器。(计时器是沿路径段放置节点的算法。)


所有这些确保pos可以给出默认设置,而无需使用先前设置的计时器,因为位于路径段的目标坐标后面的节点不会使用先前设置的计时器。

我们想区分

\path (c1) -- node {X} (c2);

这会将节点放置在直线上(根据pos当前设置)并且

\path (c1) -- (c2) node {X};

这会将节点放置c2

\path (c1) -- (c2) node[midway] {X}; 

将节点放置在线段上,即使它是在它之后指定的。(在最后一种情况下,TikZ 缺少一个界面来将节点切换为“标签”,而无需给出明确的pos设置。)


对于pic应该适用相同规则的情况,我想,我们希望所有这三种情况都与节点一样工作:

\path (c1) --      pic         {X} (c2);
\path (c1) -- (c2) pic         {X};
\path (c1) -- (c2) pic[midway] {X};

TikZ 没有为pos内置的 ition 设定适当的范围,并且所有节点(和图片)始终被视为不位于路径段上。我认为这种情况发生是一个错误,但并不严重。


在哪里希望节点位于圆弧的中间?那么请midway明确设置为胡安·卡斯塔尼奥已经显示。你想把它们像图片那样摆放吗?就像图片外面的设置一样?

如果您没有在路径上使用图片和/或使用名称 ( pic (picname) {cap = …}),那么它只是一个不需要picfor 的花哨快捷方式。可以采用简单的宏或其他 PGFKeys 方法。

这是一个解决方案。它使用 on path 键make colour chain并使用chains库来放置n给定列表的节点n− 1 个“标签”。

第一个节点放置在路径的当前位置,所有其他节点都放置在坐标坐标系向右移动,与手动操作相同。该join选项用于绘制顶点之间的边,它足够智能,不会尝试将第一个节点与不存在的前任连接起来。

不过,我选择默认colour使用midway。用户可以随时更改colour样式以使用其他pos选项:

\tikzset{colour/.append style={pos=.12345}}

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{chains}
\tikzset{
  colour/.style={% yes, explicitly midway
    circle, draw, fill=white, font=\small, inner sep=.2pt, midway},
  vertex/.style={
    circle, draw, fill, inner sep=2pt},
  colour join/.style={bend left=60, edge node={node[colour]{#1}}},
  make colour chain/.style={
    start chain=colour chain going {at={([shift=(right:1)]\tikzchainprevious.center)}},
    insert path={
      node foreach \x in {,#1} [vertex, on chain=colour chain, join=by {colour join={\x}}] {}
    }
  }
}
\begin{document}
\tikz\draw[make colour chain={1, 5, 43}];
\begin{tikzpicture}
\draw[help lines] (0,0) grid (5,3); \draw[help lines, ->] (0,0) -- (30:.8);
\path[rotate=30, ->, blue] (1,0) [make colour chain={5, 4, 11}];
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

在此处输入图片描述

答案2

我认为你正在寻找这样的东西: 在此处输入图片描述

我修改了你的\pic代码并将选项添加midwaycolour样式中。

\documentclass[tikz,border=1.618]{standalone}

\tikzset{
  colour/.style = {
    circle,
    draw,
    fill=white,
    font=\small,
    inner sep=0.2pt,
    midway% <-- added
  },
  pics/cap/.style = {
    code = {
      \node[vertex](0) at (0,0){};
      \foreach \x in {#1} {
         \pgfmathtruncatemacro\y{\x-1}
         \node[vertex](\x) at (\x,0){};
         \draw(\y) to [out=60, in=120] node[colour]{$\x$} (\x);
      }
    }
  },
  vertex/.style = {
    circle,
    radius=1mm,
    inner sep=-2.0pt,
    fill=black
  },
}

\begin{document}
\begin{tikzpicture}
  \pic at (0, 0) {cap={1,2}};
  \pic at (0,-1) {cap={1,...,5}};
\end{tikzpicture}
\end{document}

相关内容