我必须绘制一个图形,其中许多节点(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}
如果进一步细分情况,您可以调整弯曲程度以获得更好的结果。我只区分了不这样做实际上导致连接跨节点的情况。