以一种好的方式绘制许多弯曲路径 [(n*(n+1))/2] (tikz)

以一种好的方式绘制许多弯曲路径 [(n*(n+1))/2] (tikz)

我必须绘制一个图形,其中许多节点(n=13)都通过路径相互连接(k=78,k=[n*[n+1]]/2)。路径应该是弯曲的(APA 风格要求在 CFA 可视化中表示相关性的路径必须弯曲)。

目前我手工完成了所有工作并得到以下结果:

在此处输入图片描述

这是使用以下(相当冗长的)代码实现的:

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usepackage{calc}
\usetikzlibrary{arrows,positioning,shapes}
\newcommand{\at}{\makeatletter @\makeatother}
\begin{document}
\begin{tikzpicture}[auto, node distance=.2cm,
    latent/.style={circle, draw , very thick, inner sep=0pt, minimum size=22mm, align=center},
    twopaths/.style={<->, thick, >=stealth'}
]

\node [latent] (AFACET) at (0,0) {A};
\node [latent] (BFACET) [below left=0cm and 3cm of AFACET] {B};
\node [latent] (CFACET) [below right=1cm and 3cm of AFACET] {C};
\node [latent] (DFACET) [below=3cm of BFACET] {D};
\node [latent] (EFACET) [below=2cm of DFACET] {E};
\node [latent] (FFACET) [below=2cm of EFACET] {F};
\node [latent] (GFACET) [below=2cm of FFACET] {G};
\node [latent] (HFACET) [below=2cm of GFACET] {H};
\node [latent] (IFACET) [below=2cm of CFACET] {I};
\node [latent] (JFACET) [below=2cm of IFACET] {J};
\node [latent] (KFACET) [below=4cm of JFACET] {K};
\node [latent] (LFACET) [below=3cm of KFACET] {L};
\node [latent] (MFACET) [below=23cm of AFACET] {M};

\draw [twopaths] (BFACET) to [bend left=10] node {} (AFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (CFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (DFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (IFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (JFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (KFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (LFACET);
\draw [twopaths] (BFACET) to [bend left=22] node {} (MFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (EFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (FFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (HFACET);

\draw [twopaths] (AFACET) to [bend left=10] node {} (CFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (DFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (IFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (JFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (KFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (LFACET);
\draw [twopaths] (AFACET) to [bend right=2] node {} (MFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (EFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (FFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (GFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (HFACET);

\draw [twopaths] (CFACET) to [bend right=10] node {} (DFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (IFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (JFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (KFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (CFACET) to [bend right=18] node {} (MFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (CFACET) to [bend right=5] node {} (HFACET);

\draw [twopaths] (DFACET) to [bend left=10] node {} (IFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (JFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (KFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (LFACET);
\draw [twopaths] (DFACET) to [bend left=18] node {} (MFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (EFACET);
\draw [twopaths] (DFACET) to [bend left=30] node {} (FFACET);
\draw [twopaths] (DFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (DFACET) to [bend left=30] node {} (HFACET);

\draw [twopaths] (IFACET) to [bend right=10] node {} (JFACET);
\draw [twopaths] (IFACET) to [bend right=22] node {} (KFACET);
\draw [twopaths] (IFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (IFACET) to [bend right=18] node {} (MFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (IFACET) to [bend right=5] node {} (HFACET);

\draw [twopaths] (JFACET) to [bend right=10] node {} (KFACET);
\draw [twopaths] (JFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (JFACET) to [bend right=18] node {} (MFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (JFACET) to [bend right=5] node {} (HFACET);

\draw [twopaths] (KFACET) to [bend right=10] node {} (LFACET);
\draw [twopaths] (KFACET) to [bend right=18] node {} (MFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (KFACET) to [bend right=5] node {} (HFACET);

\draw [twopaths] (LFACET) to [bend left=10] node {} (MFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (LFACET) to [bend right=5] node {} (HFACET);

\draw [twopaths] (MFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (MFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (MFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (MFACET) to [bend left=10] node {} (HFACET);

\draw [twopaths] (EFACET) to [bend left=10] node {} (FFACET);
\draw [twopaths] (EFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (EFACET) to [bend left=30] node {} (HFACET);

\draw [twopaths] (FFACET) to [bend left=10] node {} (GFACET);
\draw [twopaths] (FFACET) to [bend left=30] node {} (HFACET);

\draw [twopaths] (GFACET) to [bend left=10] node {} (HFACET);

\end{tikzpicture}
\end{document}

原则上,一切都按预期工作。但是,我不喜欢路径没有对齐和有序弯曲。它看起来不太好看。

有没有办法以某种方式管理路径的对齐和弯曲,以使它们看起来更加对称?

附言:此处的标签 A ... M 是通用标签。在“真实”图中,它们被替换为不同的术语(概念)。

答案1

嗯,你说得对,定位节点以始终保持相同的弯曲量是件很棘手的事。这是我的解决方案:

\documentclass[tikz, border=5pt]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[
    latent/.style={circle, draw , very thick, inner sep=0pt, minimum size=22mm, align=center},
    twopaths/.style={<->, >=latex, thick, bend right=20}
]

\draw (0,0) node[latent] (n0) {$A$} node[latent, draw=none] (n13) {};
\foreach \name [count=\i,
                evaluate=\i as \ii using int(\i+13),
                evaluate=\i as \p using \i/7] in {C,I,J,K,L,M}{
  \path (1,0) .. controls (6,-3) and (6,-18) .. (0,-21) node[latent, pos=\p] (n\i) {$\name$} node[latent, draw=none, pos=\p] (n\ii) {};
}
\foreach \name [count=\i from 7,
                evaluate=\i as \ii using int(\i+13),
                evaluate=\i as \p using 1-(\i-6)/7] in {H,G,F,E,D,B}{
  \path (-1,0) .. controls (-6,-3) and (-6,-18) .. (0,-21) node[latent, pos=\p] (n\i) {$\name$} node[latent, draw=none, pos=\p] (n\ii) {};
}
\foreach \x in {1,...,13}{
  \foreach \d [evaluate=\d as \y using int(\x+\d)] in {1,...,6}{
    \draw[twopaths] (n\x) to (n\y);
  }
}
\end{tikzpicture}
\end{document}

完全图

答案2

即使如评论中讨论的那样没有空间进行 n 边形布局,我认为使用对称布局可以更清楚地呈现混乱的外观,因此我将底部节点向右移动并均衡间距。

可以使用一些 foreach 循环来减少一些编码,但是由于在每种情况下弯曲的量都是通过眼睛选择的,因此保持原样可能更简单。对称节点布局后,我确保弧是对称的,并使用匹配的曲率来表示每一对相对的节点。

在此处输入图片描述

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usepackage{calc}
\usetikzlibrary{arrows,positioning,shapes}
\newcommand{\at}{\makeatletter @\makeatother}
\begin{document}
\begin{tikzpicture}[auto, node distance=.2cm,
    latent/.style={circle, draw , very thick, inner sep=0pt, minimum size=22mm, align=center},
    twopaths/.style={<->, thick, >=stealth'}
]

\node [latent] (AFACET) at (0,0) {A};
\node [latent] (BFACET) [below left=0cm and 3cm of AFACET] {B};
\node [latent] (CFACET) [below right=0cm and 3cm of AFACET] {C};
\node [latent] (DFACET) [below=2cm of BFACET] {D};
\node [latent] (EFACET) [below=2cm of DFACET] {E};
\node [latent] (FFACET) [below=2cm of EFACET] {F};
\node [latent] (GFACET) [below=2cm of FFACET] {G};
\node [latent] (HFACET) [below=2cm of GFACET] {H};
\node [latent] (IFACET) [below=2cm of CFACET] {I};
\node [latent] (JFACET) [below=2cm of IFACET] {J};
\node [latent] (KFACET) [below=2cm of JFACET] {K};
\node [latent] (LFACET) [below=2cm of KFACET] {L};
\node [latent] (MFACET) [below=2cm of LFACET] {M};


\draw [twopaths] (AFACET) to [bend right=10] node {} (BFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (DFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (EFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (FFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (GFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (HFACET);
\draw [twopaths] (AFACET) to [bend left=10] node {} (CFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (IFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (JFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (KFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (LFACET);
\draw [twopaths] (AFACET) to [bend right=10] node {} (MFACET);


\draw [twopaths] (BFACET) to [bend left=-10] node {} (DFACET);
\draw [twopaths] (BFACET) to [bend left=25] node {} (EFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (FFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (BFACET) to [bend left=30] node {} (HFACET);
\draw [twopaths] (BFACET) to [bend left=-5] node {} (CFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (IFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (JFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (KFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (LFACET);
\draw [twopaths] (BFACET) to [bend left=10] node {} (MFACET);


\draw [twopaths] (CFACET) to [bend right=10] node {} (DFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (CFACET) to [bend right=10] node {} (HFACET);
\draw [twopaths] (CFACET) to [bend right=-10] node {} (IFACET);
\draw [twopaths] (CFACET) to [bend right=25] node {} (JFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (KFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (CFACET) to [bend right=30] node {} (MFACET);


\draw [twopaths] (DFACET) to [bend left=-10] node {} (EFACET);
\draw [twopaths] (DFACET) to [bend left=20] node {} (FFACET);
\draw [twopaths] (DFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (DFACET) to [bend left=50] node {} (HFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (IFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (JFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (KFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (LFACET);
\draw [twopaths] (DFACET) to [bend left=10] node {} (MFACET);


\draw [twopaths] (IFACET) to [bend right=-10] node {} (JFACET);
\draw [twopaths] (IFACET) to [bend right=20] node {} (KFACET);
\draw [twopaths] (IFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (IFACET) to [bend right=50] node {} (MFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (IFACET) to [bend right=10] node {} (HFACET);

\draw [twopaths] (JFACET) to [bend right=-10] node {} (KFACET);
\draw [twopaths] (JFACET) to [bend right=30] node {} (LFACET);
\draw [twopaths] (JFACET) to [bend right=50] node {} (MFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (JFACET) to [bend right=10] node {} (HFACET);

\draw [twopaths] (KFACET) to [bend right=-10] node {} (LFACET);
\draw [twopaths] (KFACET) to [bend right=40] node {} (MFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (KFACET) to [bend right=10] node {} (HFACET);

\draw [twopaths] (LFACET) to [bend right=-10] node {} (MFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (LFACET) to [bend right=10] node {} (HFACET);

\draw [twopaths] (MFACET) to [bend right=10] node {} (EFACET);
\draw [twopaths] (MFACET) to [bend right=10] node {} (FFACET);
\draw [twopaths] (MFACET) to [bend right=10] node {} (GFACET);
\draw [twopaths] (MFACET) to [bend left=10] node {} (HFACET);

\draw [twopaths] (EFACET) to [bend left=-10] node {} (FFACET);
\draw [twopaths] (EFACET) to [bend left=30] node {} (GFACET);
\draw [twopaths] (EFACET) to [bend left=50] node {} (HFACET);

\draw [twopaths] (FFACET) to [bend left=-10] node {} (GFACET);
\draw [twopaths] (FFACET) to [bend left=40] node {} (HFACET);

\draw [twopaths] (GFACET) to [bend left=-10] node {} (HFACET);

\end{tikzpicture}
\end{document}

答案3

APA 样式接受电路板吗?

\documentclass[border=9,tikz]{standalone}
\usepackage{}
\usetikzlibrary{}
\begin{document}

\tikzset{
    label/.style={
        line width=1,draw,minimum size=4cm
    },
    <-->/.style={
        line width=1,<->,shorten <=1,shorten >=1
    }
}

\tikz{
    \foreach\A[count=\i]in{A,B,C,D,E,F,G}{
        \draw(0,\i*5-5)node[label]{\A};
    }
    \foreach\A[count=\i]in{H,I,J,K,L,M}{
        \draw(19,\i*6-6)node[label]{\A};
    }
    \foreach\i in{1}{
        \draw[<-->](2,30-1/4)--+(10/4,0)|-(2,1/4);
    }
    \foreach\i in{1,...,5}{
        \draw[<-->](2,30-\i/4-1/4)--+(10/4-\i/4,0)|-(2,\i*5+\i/4+1/4);
        \draw[<-->](2,\i*5+\i/4-7/4)--+(10/4-\i/4,0)|-(2,\i/4+1/4);
    }
    \foreach\i in{1,...,3}{
        \draw[<-->](2,25-\i/4-3/4)--+(5/4-\i/4,0)|-(2,\i*5+5+\i/4+3/4);
        \draw[<-->](2,\i*5+5+\i/4-7/4)--+(5/4-\i/4,0)|-(2,5+\i/4+3/4);
    }
    \foreach\i in{1,...,1}{
        \draw[<-->](2,20-6/4)--+(1/4,0)|-(2,\i*5+10+\i/4+5/4);
        \draw[<-->](2,\i*5+10+\i/4-7/4)--+(1/4,0)|-(2,10+6/4);
    }
    \foreach\i in{1}{
        \draw[<-->](17,30-2/4)--+(-8/4,0)|-(17,2/4);
    }
    \foreach\i in{1,...,4}{
        \draw[<-->](17,30-\i/4-2/4)--+(-8/4+\i/4,0)|-(17,\i*6+\i/4+2/4);
        \draw[<-->](17,\i*6+\i/4-7/4)--+(-8/4+\i/4,0)|-(17,\i/4+2/4);
    }
    \foreach\i in{1,...,2}{
        \draw[<-->](17,24-\i/4-4/4)--+(-4/4+\i/4,0)|-(17,\i*6+6+\i/4+4/4);
        \draw[<-->](17,\i*6+6+\i/4-7/4)--+(-4/4+\i/4,0)|-(17,6+\i/4+4/4);
    }
    \foreach\i in{1}{
        \draw[<-->](17,18-6/4)--+(-1/4,0)|-(17,12+6/4);
    }
    \foreach\i in{1,...,7}{
        \foreach\j in{1,...,6}{
            \draw[<-->](2,\i*5-5+\i/4+\j/4-15/8)-|
            ({(6*(\i+\j)+max(7-\i-\j,0)-max(\i+\j-8,0)+\j-18.5)/8+4.2},{(6*(\i+\j)+max(7-\i-\j,0)-max(\i+\j-8,0)+\j-18.5)/2+.25})--+(3.75,0)|-(17,\j*6-6+\j/4+\i/4-15/8);
        }
    }
}

\end{document}

答案4

我不知道这看起来是否更好,但它演示了如何使用图形语法使原始代码不那么冗长。也许你也应该考虑使用图形绘制布局算法。然而,这需要 LuaTeX,而只需使用如下所示的语法就可以在任何引擎上使用。

\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{graphs,positioning}
\begin{document}
\begin{tikzpicture}[every node/.style={circle, draw, minimum size=20pt}]
  \node (A) {A};
  \foreach \i/\k [remember=\i as \j (initially A)] in {B/C,D/I,E/J,F/K,G/L,H/M}
  {
    \node (\i) [below left=of A |- \j] {\i};
    \node (\k) [below right=of A |- \j] {\k};
  }
  \graph [use existing nodes, edges={bend left, <->}] {
    A --[complete bipartite]
    {
      B,D,E,F,G,H
    };
    {
      C,I,J,K,L,M
    }
    --[complete bipartite]
    A;
    {
      B,D,E
    }--[complete bipartite]
    {
      C,I,J
    };
    {
      K,L,M
    }--[complete bipartite]
    {
      F,G,H
    };
    {
      E
    }--
    {
      K,L
    };
    {
      J
    }--
    {
      F,G
    };
    {
      F
    }--
    {
      I,J
    };
    {
      K
    }--
    {
      D,E
    };
    {
      [edges={bend right=15, <->}]
      B -- K;
      C -- F;
      D -- L;
      I -- G;
      E -- M;
      J -- H;
    };
    {
      [edges={bend left=10, <->}]
      B -- L;
      C -- G;
      D -- M;
      I -- H;
    };
    {
      [edges={bend right=5, <->}]
      B -- M;
      C -- H;
    };
    C -- I -- J -- K -- L -- M;
    H -- G -- F -- E -- D -- B;
    B -- {E,F,G,H};
    E -- {G,H};
    F -- H;
    M -- {K,J,I,C};
    L -- {J,I,C};
    K -- {I,C};
    J -- C;
  };
\end{tikzpicture}
\end{document}

与图形语法连接

如果进一步细分情况,您可以调整弯曲程度以获得更好的结果。我只区分了不这样做实际上导致连接跨节点的情况。

相关内容