沿部分命名路径的箭头

沿部分命名路径的箭头

我正在尝试重现以下图像:

在此处输入图片描述

为此,我创建了 3 个节点、一条支撑路径 ( mycurve) 和 (隐藏) 支撑线 (l1l12),然后将其他节点放置在lxmycurve交叉点上。效果很好。

我正在尝试设置箭头。箭头的支撑线只是 的平移mycurve。我使用平滑图来绘制箭头,但结果并不完美,尤其是对于没有中间绘制点的箭头(例如从 7 到 8)。

有没有办法使用之前绘制的支持曲线而不是使用绘图来绘制箭头?换句话说,我想沿着命名路径绘制一条从5.x到的路径,而不是使用绘图(其他路径也一样)。8.xmycurve3

提前致谢。

这是我的结果:

在此处输入图片描述

我的 MWE 来源如下:

\documentclass[preview]{standalone}
\usepackage{calc}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

\tikzset{
  degree/.style = {
    circle,
    draw,
    fill=white,
  },
  l/.style = {
    -latex,
    line width = #1,
  },
  l1/.style = { l=1pt },
  l2/.style = { l=2pt },
  l3/.style = { l=3pt },
}


\begin{document}
\begin{tikzpicture}[xscale=1,
    yscale=1]

  \pgfdeclarelayer{nodes}
  \pgfdeclarelayer{links}
  \pgfsetlayers{main,links,nodes}


  \begin{pgfonlayer}{main}
    %% Create on each degree to intersect later with mycurve.
    %% Each line is a named path from l1 to l12
    \foreach \i in {1,...,12}{
      \coordinate[] (l1-\i) at (0,\i/1.5);
      \coordinate[] (l2-\i) at (3.5,\i/1.5);
      \path[name path global=l\i] (l1-\i) -- (l2-\i);
    }
  \end{pgfonlayer}


  \begin{pgfonlayer}{nodes}
    \node[degree] (1) at (0,    0/1.5) {1};
    \node[degree] (5) at (2,    7/1.5) {5};
    \node[degree] (8) at (0,   12/1.5) {8};
  \end{pgfonlayer}


  \begin{pgfonlayer}{main}
    \draw [line width=5pt,red!20,name path global=mycurve]
    ($ (8) + (0.0,0) $) to[out=-30,in=90]
    ($ (5) + (0.0,0) $) to[in=57,out=-90]
    ($ (1) + (0.0,0) $);

    %% Create an intersection coordinate for each l1-l12 lines and mycurve
    %% to place each degree. Each intersection point is named i1 to i12.
    \def\mycurveIntersection#1{%
      \path[name intersections={of=l#1 and mycurve}] (intersection-1) coordinate (i#1);
    }
    \foreach \i in {1,...,12}{
      \mycurveIntersection\i
      %%\fill[red] (i\i) circle (2pt);
    }
  \end{pgfonlayer}

  \begin{pgfonlayer}{nodes}
    \node[degree] (2) at (i2) {2};
    \node[degree] (3) at (i4) {3};
    \node[degree] (4) at (i5) {4};
    \node[degree] (6) at (i9) {6};
    \node[degree] (7) at (i11) {11};

    %% Draw to arrows supports lines
    \foreach \i in {1,2,3} {
      \draw [red,name path global=mycurve\i]
      ($ (8) + (4-\i,0) $) to[out=-30,in=90]
      ($ (5) + (4-\i,0) $) to[in=57,out=-90]
      ($ (1) + (4-\i,0) $);
    }

  \end{pgfonlayer}


  %% Draw the links
  %%
  %% TODO: find a better way using previously created mycurves 1-3.
  \begin{pgfonlayer}{links}
    \def\myshift{3}
    \draw[l1,shorten <= 2pt] plot[smooth] coordinates{
      ($ (i7) + (\myshift,0)$)
      ($ (i8) + (\myshift,0) $)
      ($ (i9) + (\myshift,0) $)
      ($ (i10) + (\myshift,0) $)
      ($ (i11) + (\myshift,0) $)
      ($ (i12) + (\myshift,0) $)};
    \draw[l1,shorten <= 2pt] plot[smooth] coordinates{
      ($ (i7) + (\myshift,0)$)
      ($ (i6) + (\myshift,0) $)
      ($ (i5) + (\myshift,0) $)
      ($ (i4) + (\myshift,0) $)
      ($ (i3) + (\myshift,0) $)
      ($ (i2) + (\myshift,0) $)
      ($ (i1) + (\myshift,0) $)
      ($ (1) + (\myshift,0) $)
    };

    \def\myshift{2}
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (6) + (\myshift,0)$)
      ($ (i10) + (\myshift,0) $)
      ($ (i11) + (\myshift,0) $)
      ($ (8) + (\myshift,0) $)};
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (6) + (\myshift,0)$)
      ($ (i8) + (\myshift,0) $)
      ($ (5) + (\myshift,0) $)};
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (3) + (\myshift,0)$)
      ($ (i3) + (\myshift,0) $)
      ($ (2) + (\myshift,0) $)};

    \def\myshift{1}
    \draw[l3] plot[smooth] coordinates{
      ($ (2) + (\myshift,0)$)
      ($ (i1) + (\myshift,0)$)
      ($ (1) + (\myshift,0) $)
    };
    %% These ones are really not on the mycurves
    \draw[l3] ($ (7) + (\myshift,0)$) -- ($ (8) + (\myshift,0)$);
    \draw[l3] ($ (4) + (\myshift,0)$) -- ($ (3) + (\myshift,0)$);

  \end{pgfonlayer}

  %% Add extra line helpers for reading
  \begin{pgfonlayer}{main}
    \draw[dashed] (1) -- (8);
    \draw[dashed] ($ (i7) + (3,0) $) -- ($ (1)!(i7)!(8) $);
    \draw[dashed] ($ (i9) + (2,0) $) -- ($ (1)!(i9)!(8) $);
    \draw[dashed] ($ (i4) + (2,0) $) -- ($ (1)!(i4)!(8) $);
    \draw[dashed] ($ (i5) + (1,0) $) -- ($ (1)!(i5)!(8) $);
    \draw[dashed] ($ (i2) + (1,0) $) -- ($ (1)!(i2)!(8) $);
    \draw[dashed] ($ (i11) + (1,0) $) -- ($ (1)!(i11)!(8) $);
  \end{pgfonlayer}

\end{tikzpicture}
\end{document}

答案1

这不是一个完整的答案,因为它需要一些反馈。主要信息是:

是的,有一种方法可以重新绘制任意路径的交叉段。

fillbetween这可以通过 (!)库来实现pgfplots。应用于您不满意的路径,使用这些路径可获得

在此处输入图片描述

这是代码,它们用以下类型的命令绘制

 \RedrawSegment[l3]{3}{5}{4}

其中可选参数是线条样式,第一个是级别,另外两个是要计算交点的线条。

\documentclass[preview]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc} % ,bending would look better but clashes with the way you
% construct your paths
\usepgfplotslibrary{fillbetween}

\tikzset{
  degree/.style = {
    circle,
    draw,
    fill=white,
  },
  l/.style = {
    -latex,
    line width = #1,
  },
  l1/.style = { l=1pt },
  l2/.style = { l=2pt },
  l3/.style = { l=3pt },
}


\begin{document}
\begin{tikzpicture}[xscale=1,
    yscale=1]

  \pgfdeclarelayer{nodes}
  \pgfdeclarelayer{links}
  \pgfsetlayers{main,links,nodes}


  \begin{pgfonlayer}{main}
    %% Create on each degree to intersect later with mycurve.
    %% Each line is a named path from l1 to l12
    \foreach \i in {1,...,12}{
      \coordinate[] (l1-\i) at (0,\i/1.5);
      \coordinate[overlay] (l2-\i) at (10,\i/1.5);
      \path[overlay,name path global=l\i] (l1-\i) -- (l2-\i);
    }
  \end{pgfonlayer}


  \begin{pgfonlayer}{nodes}
    \node[degree] (1) at (0,    0/1.5) {1};
    \node[degree] (5) at (2,    7/1.5) {5};
    \node[degree] (8) at (0,   12/1.5) {8};
  \end{pgfonlayer}


  \begin{pgfonlayer}{main}
    \draw [line width=5pt,red!20,name path global=mycurve]
    (0,   12/1.5)  to[out=-30,in=90]
    (2,    7/1.5) to[in=57,out=-90]
    (0,    0/1.5);
  \end{pgfonlayer}

  %% Create an intersection coordinate for each l1-l12 lines and mycurve
  %% to place each degree. Each intersection point is named i1 to i12.
  \foreach \i in {1,...,12}{
    \path[name intersections={of={l\i} and mycurve}] (intersection-1) coordinate
    (i\i);
    %%\fill[red] (i\i) circle (2pt);
  }

  \begin{pgfonlayer}{nodes}
    \node[degree] (2) at (i2) {2};
    \node[degree] (3) at (i4) {3};
    \node[degree] (4) at (i5) {4};
    \node[degree] (6) at (i9) {6};
    \node[degree] (7) at (i11) {11};

    %% Draw to arrows supports lines
    \foreach \i in {1,2,3} {
      \draw [red,name path global=mycurve\i]
      ($ (8) + (4-\i,0) $) to[out=-30,in=90]
      ($ (5) + (4-\i,0) $) to[in=57,out=-90]
      ($ (1) + (4-\i,0) $);
    }

  \end{pgfonlayer}

  %% Draw the links
  %%
  %% TODO: find a better way using previously created mycurves 1-3.
  \begin{pgfonlayer}{links}
   \begin{scope}[every path/.append style={shorten <= 2pt}]

    \def\myshift{3}
    \draw[l1,shorten <= 2pt] plot[smooth] coordinates{
      ($ (i7) + (\myshift,0)$)
      ($ (i8) + (\myshift,0) $)
      ($ (i9) + (\myshift,0) $)
      ($ (i10) + (\myshift,0) $)
      ($ (i11) + (\myshift,0) $)
      ($ (i12) + (\myshift,0) $)};
    \draw[l1,shorten <= 2pt] plot[smooth] coordinates{
      ($ (i7) + (\myshift,0)$)
      ($ (i6) + (\myshift,0) $)
      ($ (i5) + (\myshift,0) $)
      ($ (i4) + (\myshift,0) $)
      ($ (i3) + (\myshift,0) $)
      ($ (i2) + (\myshift,0) $)
      ($ (i1) + (\myshift,0) $)
      ($ (1) + (\myshift,0) $)
    };

    \def\myshift{2}
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (6) + (\myshift,0)$)
      ($ (i10) + (\myshift,0) $)
      ($ (i11) + (\myshift,0) $)
      ($ (8) + (\myshift,0) $)};
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (6) + (\myshift,0)$)
      ($ (i8) + (\myshift,0) $)
      ($ (5) + (\myshift,0) $)};
    \draw[l2,shorten <= 2pt] plot[smooth] coordinates{
      ($ (3) + (\myshift,0)$)
      ($ (i3) + (\myshift,0) $)
      ($ (2) + (\myshift,0) $)};

    \def\myshift{1}
    \draw[l3] plot[smooth] coordinates{
      ($ (2) + (\myshift,0)$)
      ($ (i1) + (\myshift,0)$)
      ($ (1) + (\myshift,0) $)
    };
    %% These ones are really not on the mycurves
%     \draw[l3] ($ (7) + (\myshift,0)$) -- ($ (8) + (\myshift,0)$);
%     \draw[l3] ($ (4) + (\myshift,0)$) -- ($ (3) + (\myshift,0)$);
    \draw[l3, intersection segments={of=l2 and mycurve3,sequence=R2}];
    \newcommand{\RedrawSegment}[4][]{
    \ifnum#3>#4
    \path[name path=aux,
     intersection segments={of=l#3 and mycurve#2,sequence=R2}];
     \draw[#1, intersection segments={of=l#4 and aux,sequence=R1}];
    \else
    \path[name path=aux,
     intersection segments={of=l#3 and mycurve#2,sequence=R1}];
     \draw[#1, intersection segments={of=l#4 and aux,sequence={R1}}];
    \fi }
    \RedrawSegment[l3]{3}{5}{4} 
    \RedrawSegment[l3,latex-]{3}{10}{11} 
    %\RedrawSegment[l2]{2}{4}{2} 
    %\RedrawSegment[l2,blue]{2}{9}{7} 
   \end{scope}
  \end{pgfonlayer}

  %% Add extra line helpers for reading
  \begin{pgfonlayer}{main}
    \draw[dashed] (1) -- (8);
    \draw[dashed] ($ (i7) + (3,0) $) -- ($ (1)!(i7)!(8) $);
    \draw[dashed] ($ (i9) + (2,0) $) -- ($ (1)!(i9)!(8) $);
    \draw[dashed] ($ (i4) + (2,0) $) -- ($ (1)!(i4)!(8) $);
    \draw[dashed] ($ (i5) + (1,0) $) -- ($ (1)!(i5)!(8) $);
    \draw[dashed] ($ (i2) + (1,0) $) -- ($ (1)!(i2)!(8) $);
    \draw[dashed] ($ (i11) + (1,0) $) -- ($ (1)!(i11)!(8) $);
  \end{pgfonlayer}
\end{tikzpicture}
\end{document}

如您所见,我没有完全重写代码。这有两个原因。其中一个原因是,按照您当前构建路径的方式,这可能会导致dimension too large错误。(这并非特定于重绘,如果您要在相应区域中装饰路径,它们也会显示出来。)第二个原因是我不理解您的某些构造,例如类型的块($ (i7) + (\myshift,0)$),我相信可以将其做得更短。

答案2

使用@marmot 的答案几乎有效。

我可以轻松地将其用于RedrawSegment所有路径。

以下是代码:

\begin{pgfonlayer}{main}
  %% Create on each degree to intersect later with mycurve.
  %% Each line is a named path from l1 to l12
  \foreach \i in {0,...,12}{
    \coordinate[] (l1-\i) at (0,\i/1.5);
    \coordinate[overlay] (l2-\i) at (10,\i/1.5);
    \path[overlay,name path global=l\i] (l1-\i) -- (l2-\i);
  }
\end{pgfonlayer}

[...]

\begin{pgfonlayer}{links}
   \newcommand{\RedrawSegment}[4][]{%
     \ifnum#3>#4%
     \path[name path=aux,%
       intersection segments={of=l#3 and mycurve#2,sequence=R2}];%
     \draw[#1, intersection segments={of=l#4 and aux,sequence=R1}];%
     \else%
     \path[name path=aux,%
       intersection segments={of=l#3 and mycurve#2,sequence=R1}];%
     \draw[#1, intersection segments={of=l#4 and aux,sequence={R1}}];%
     \fi}%

   %% Shorten on this path does not seem to work correctly.
   \RedrawSegment[l1,latex-,shorten >= 10pt]{1}{12}{7}
   \RedrawSegment[l1,shorten <= 2pt]{1}{7}{0}

   \RedrawSegment[l2,latex-,shorten >= 2pt]{2}{12}{9}
   %% For some reason the arrow on this one is not correctly drawn.  But
   %% if we draw to {6} it works nicely. Maybe because {7} is a junction
   %% point?
   \RedrawSegment[l2,-latex,shorten <= 2pt]{2}{9}{7}
   \RedrawSegment[l2]{2}{4}{2}

   %% No apparent issue on this one
   \RedrawSegment[l3]{3}{5}{4} 
   \RedrawSegment[l3,latex-]{3}{10}{11} 
   \RedrawSegment[l3]{3}{2}{0}
\end{pgfonlayer}

结果比情节版本好得多。然而仍然存在一些问题:

  • 从 6 到 5 的箭头绘制不正确。路径与箭头尖端重叠。
  • 5到8的箭头不能缩短。

在此处输入图片描述 在此处输入图片描述

相关内容