TikZ 链调整箭头节点的位置

TikZ 链调整箭头节点的位置
\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{chains}
\begin{document}
\begin{tikzpicture}[start chain=circle placed {at=(\tikzchaincount*30:1.5)},regular/.style={draw,circle,inner sep=0,minimum size=4mm}]
\foreach \i in {0,...,11}
  \node [on chain, regular] (\i) {\i};
\foreach \i [evaluate=\i as \ni using {int(mod(\i+1,12))}] \i in {0,3,6,9}
  {\draw [->] (\i) to [bend right] node[auto] {$p_b$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(Mod(\i-1,12))}] \i in {0,3,6,9}
  {\draw [->] (\i) to [bend right] node[auto] {$q_b$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(mod(\i+1,12))}] \i in {1,2,4,5,7,8,10,11}
  {\draw [->] (\i) to [bend right] node[auto] {$p_g$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(Mod(\i-1,12))}] \i in {1,2,4,5,7,8,10,11}
  {\draw [->] (\i) to [bend right] node[auto] {$q_g$} (\ni); }
\end{tikzpicture}
\end{document}

给我

在此处输入图片描述

虽然我已经使用了node[auto],并且肯定有足够的空间来布局所有箭头上的节点标签,但它们仍然很乱。我知道我可以选择使用node[auto,above]node[auto,below]微调位置,但这会使代码变得冗长。有没有一种简单的方法可以漂亮地布置这些标签?

答案1

与其他答案非常相似,但按键次数少一到两次。

\documentclass[border=0.125cm]{standalone}

\usepackage{tikz}
\usetikzlibrary{topaths}

\begin{document}

\begin{tikzpicture}

\foreach \n in {0,...,11}
    \node [draw, circle] at (\n*30+30:2.5) (n-\n) {\n};

\foreach \n [evaluate={\m=int(mod(11+\n, 12)); \p=int(mod(\n+1,3)); \q=int(mod(\n,3)); }] in {0,...,11}{
    \draw [->] (n-\m) to [bend right] node [anchor=\n*30+210] {$P_\ifodd\p b\else g\fi$} (n-\n);
    \draw [<-] (n-\m) to [bend left]  node [anchor=\n*30+30]  {$P_\ifodd\q b\else g\fi$} (n-\n);
}

\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

两个问题:

  1. auto选项默认将节点放置到left,您需要使用auto=right(或swap交换默认侧的选项)。
  2. auto选项会捕捉到主罗盘锚点eastnorth eastnorth、……southsouth east

您想使用circle节点,以便锚点围绕节点呈圆圈放置。
您想使用text depth=+0pt或类似的解决方案来隐藏下标的不同深度。
并且您想使用另一个auto锚点/角度计算器。这就是这个答案所提供的。

顺便说一句,你可能对nodes around center链中节点放置的关键。也可以通过样式添加边缘节点join,但那是另一个问题。

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{chains}
\pgfmathparse{atan2(0,1)}% the CVS version swaps the arguments so I define new atan
                         % functions that have the order of arguments in their name
\ifdim\pgfmathresult pt=0pt % atan2(y, x)
  \tikzset{declare function={atanXY(\x,\y)=atan2(\y,\x);atanYX(\y,\x)=atan2(\y,\x);}}
\else                       % atan2(x, y)
  \tikzset{declare function={atanXY(\x,\y)=atan2(\x,\y);atanYX(\y,\x)=atan2(\x,\y);}}
\fi
\makeatletter
\let\tikz@auto@anchor@orig      \tikz@auto@anchor
\let\tikz@auto@anchor@prime@orig\tikz@auto@anchor@prime
\tikzset{
  Auto/.code=\pgfkeysalso{/tikz/auto=#1}%
    \let\tikz@auto@anchor      \tikz@Auto@anchor
    \let\tikz@auto@anchor@prime\tikz@Auto@anchor@prime,
  auto/.prefix code=\let\tikz@auto@anchor      \tikz@Auto@anchor@orig
                    \let\tikz@auto@anchor@prime\tikz@Auto@anchor@prime@orig}
\def\tikz@Auto@anchor{%
  \pgfmathatanXY@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
  \pgfutil@tempdima=\pgfmathresult pt\relax
  \advance\pgfutil@tempdima-90pt\relax
  \edef\tikz@anchor{\pgf@sys@tonumber\pgfutil@tempdima}}
\def\tikz@Auto@anchor@prime{%
  \pgfmathatanXY@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
  \pgfutil@tempdima=\pgfmathresult pt\relax
  \advance\pgfutil@tempdima90pt\relax
  \edef\tikz@anchor{\pgf@sys@tonumber\pgfutil@tempdima}}
\begin{document}
\begin{tikzpicture}[Auto=right,
  start chain=circle placed {at=(\tikzchaincount*30:1.5)},
  regular/.style={draw,circle,inner sep=+0pt,minimum size=+4mm}]
\foreach \i in {0,...,11} \node [on chain, regular] (\i) {\i};
\tikzset{text depth=+0pt, shape=circle, inner sep=+2pt}
\foreach \i [evaluate=\i as \ni using {int(mod(\i+1,12))}] \i in {0,3,6,9}
  {\draw [->] (\i) to [bend right] node {$p_b$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(Mod(\i-1,12))}] \i in {0,3,6,9}
  {\draw [->] (\i) to [bend right] node {$q_b$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(mod(\i+1,12))}] \i in {1,2,4,5,7,8,10,11}
  {\draw [->] (\i) to [bend right] node {$p_g$} (\ni); }
\foreach \i [evaluate=\i as \ni using {int(Mod(\i-1,12))}] \i in {1,2,4,5,7,8,10,11}
  {\draw [->] (\i) to [bend right] node {$q_g$} (\ni); }
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案3

像往常一样使用 PSTricks 只是为了好玩!

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{pst-node,pst-plot}

\makeatletter
% Get Label
\def\GL#1#2{\pst@mod{#2}{3}\rem\ifcase\rem $#1_b$ \or $#1_g$ \or $#1_g$\fi}
\makeatother

\begin{document}
\begin{pspicture}[radius=12pt,arcangle=30,arrows=<-](-3,-3)(3,3)
    \curvepnodes[plotpoints=13]{0}{360}{2.5 t 30 add PtoC}{P}
    \multido{\i=0+1}{\Pnodecount}{\Cnodeput(P\i){A\i}{\i}}
    \Cnodeput(P\Pnodecount){A\Pnodecount}{}
    \multido{\ix=0+1,\iy=1+1}{\Pnodecount}
    {
        \ncarc{A\iy}{A\ix}\naput{\GL{p}{\ix}}
        \ncarc{A\ix}{A\iy}\naput{\GL{q}{\iy}}
    }
\end{pspicture}
\end{document}

在此处输入图片描述

只是另一种选择

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{pst-node,pst-plot}

\makeatletter
% Get Label
\def\GL#1#2{\pst@mod{#2}{3}\rem\ifcase\rem $#1_b$ \or $#1_g$ \or $#1_g$\fi}
% Angle unit operator
\def\angleunit#1{\degrees[#1]\pstVerb{/angleunit {\pst@angleunit} bind def}}
\makeatother

\begin{document}
\begin{pspicture}[radius=12pt,arcangle=30,arrows=<-](-3,-3)(3,3)
    \angleunit{12}
    \curvepnodes[plotpoints=13]{0}{12}{2.5 t 1 add angleunit PtoC}{P}
    \multido{\i=0+1}{\Pnodecount}{\Cnodeput(P\i){A\i}{\i}}
    \Cnodeput(P\Pnodecount){A\Pnodecount}{}
    \multido{\ix=0+1,\iy=1+1}{\Pnodecount}
    {
        \ncarc{A\iy}{A\ix}\naput{\GL{p}{\ix}}
        \ncarc{A\ix}{A\iy}\naput{\GL{q}{\iy}}
    }
\end{pspicture}
\end{document}

区别在于

\angleunit{12}
\curvepnodes[plotpoints=13]{0}{12}{2.5 t 1 add angleunit PtoC}{P}

在哪里

\makeatletter
\def\angleunit#1{\degrees[#1]\pstVerb{/angleunit {\pst@angleunit} bind def}}
\makeatother

在序言中进行了定义。

最简单的一个

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{pst-node,pst-plot}

\makeatletter
% Get Label
\def\GL#1#2{\pst@mod{#2}{3}\rem\ifodd\rem $#1_b$ \else $#1_g$ \fi}
\makeatother

\begin{document}
\begin{pspicture}[radius=12pt,arcangle=30,arrows=<-](-3,-3)(3,3)
    \multido{\i=0+1}{12}{\Cnodeput(!2.5 \i\space 1 add 30 mul PtoC){A\i}{\i}}
    \Cnodeput(A0){A12}{}% auxiliary node
    \multido{\ix=0+1,\iy=1+1}{12}
    {
        \ncarc{A\iy}{A\ix}\naput{\GL{p}{\iy}}
        \ncarc{A\ix}{A\iy}\naput{\GL{q}{\numexpr\ix+2}}
    }
\end{pspicture}
\end{document}

将来不会再有重大编辑!

答案4

一些坐标计算也很有用。

\documentclass[tikz]{standalone}
\usetikzlibrary{chains,calc}
\begin{document}
\begin{tikzpicture}[start chain=circle placed {at=(\tikzchaincount*30:1.5)},
                    regular/.style={draw,circle,inner sep=0,minimum size=4mm}]
\foreach \i in {0,...,11}
\node [on chain, regular] (\i) {\i};
\foreach \i [evaluate=\i as \ni using {int(mod(\i+1,12))},
           evaluate=\i as \pi using {int(Mod(\i-1,12))}] \i in {0,...,11}
{
\draw [->] (\i) to [bend right] (\ni);
\draw [->] (\i) to [bend right] (\pi); 
\node[] at ($($(\i)!0.5!(\pi)$)!1!90:(\pi)$) {\pgfmathparse{Mod(\i,3)==0?"$q_b$":"$p_g$"}\pgfmathresult};
\node[] at ($($(\i)!0.5!(\ni)$)!1!90:(\ni)$) {\pgfmathparse{Mod(\i,3)==0?"$p_b$":"$q_g$"}\pgfmathresult};
}

\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容