TikZ で曲率が変化する/ランダムなエッジを描く

TikZ で曲率が変化する/ランダムなエッジを描く

ネットワーク プロットを描画したいのですが、多くのエッジが重なっています。重なり合うエッジが見えるように、エッジの曲率を変えたいと思います。

私の最初のアイデアは、曲率を 20 ~ 30 度の間でランダムに均一にすることでした。しかし、それが TikZ で簡単に実装できるかどうかはわかりません。

このソリューションは、曲率を手動で指定しなくても機能するはずなので、より大規模なネットワークにも適用できます。

結果は次のようになります。 複数のエッジを持つネットワーク プロット

MWE コード:

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\node at (0,0) [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3) [circle, fill=blue] (5) {};
\draw (1) to[bend right] (2);
\draw (1) to[bend right] (2);
\draw (1) to[bend right] (2);
\draw (2) to[bend right] (1);
\draw (1) to[bend right] (4);
\draw (2) to[bend right] (3);
\draw (2) to[bend right] (3);
\draw (2) to[bend right] (3);
\draw (2) to[bend right] (5);
\draw (3) to[bend right] (2);
\draw (3) to[bend right] (5);
\draw (3) to[bend right] (5);
\draw (3) to[bend right] (5);
\draw (3) to[bend right] (4);
\draw (4) to[bend right] (1);
\draw (4) to[bend right] (1);
\draw (4) to[bend right] (3);
\draw (4) to[bend right] (3);
\end{tikzpicture}
\end{document}

編集: 背景を説明すると、目標はこれに触発された(ただしこれより小さい)何かを描くことです。

フェイスブックネットワーク (ソース:http://blog.revolutionanalytics.com/2010/12/facebooks-social-network-graph.html

答え1

以下はブルートフォース方式です。

\documentclass{article}
\usepackage{tikz}
\newcommand{\MultiConnect}[5][]{%
\pgfmathsetmacro{\imin}{#2-5*#3}
\pgfmathsetmacro{\imax}{#2+5*#3}
\pgfmathsetmacro{\inext}{#2-5*#3+10}
\foreach \i in {\imin,\inext,...,\imax}
\draw[#1] (#4) to[bend right=\i] (#5);
}
\begin{document}
The command 
\verb|\MultiConnect{offset}{# of connections}{first node}{second node}| 
allows you to draw connections.

\begin{tikzpicture}
\node at (0,0) [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3) [circle, fill=blue] (5) {};
\foreach \j in {1,...,4}{\pgfmathtruncatemacro{\nextj}{\j+1}
\foreach \k in {\nextj,...,5}
{
\MultiConnect{0}{4}{\j}{\k}
}
}
\end{tikzpicture}

\begin{tikzpicture}
\node at (0,0) [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3) [circle, fill=blue] (5) {};
\foreach \j in {1,...,4}{\pgfmathtruncatemacro{\nextj}{\j+1}
\foreach \k in {\nextj,...,5}
{
\pgfmathsetmacro{\Offset}{20+10*rand}
\typeout{\j,\k,\Offset}
\MultiConnect{\Offset}{4}{\j}{\k}
}
}
\end{tikzpicture}

\end{document}

ここに画像の説明を入力してください

本当にランダム性を取り入れたい場合、これは簡単です。

ここに画像の説明を入力してください

答え2

ノード名が常に整数である場合は、エッジの最後のターゲットとソースが現在のものと同じかどうかを確認し、同じ場合は値を増やすという次のアプローチを使用できますbend right

欠点: これは、同じノードからのエッジと同じノードへのエッジが互いに隣接している場合にのみ機能します。つまり、1/2, 3/2, 1/2エッジが重なり合うことになります。

\documentclass[tikz]{standalone}

\newcounter{lastsource}
\newcounter{lasttarget}
\newcounter{samesourcetarget}

\begin{document}
\begin{tikzpicture}
\node at (0,0)  [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3)  [circle, fill=blue] (5) {};

\def\defaultbend{30}
\def\increasebend{5}

\setcounter{samesourcetarget}{\defaultbend}
\foreach \source/\target in {1/2, 1/2, 1/2, 2/1, 1/4, 2/3, 2/3, 2/2, 2/5, 3/2, 3/5, 3/5, 3/5, 3/4, 4/1, 4/1, 4/3, 4/3}{
 \ifnum\value{lastsource}=\source 
  \ifnum\value{lasttarget}=\target
   \addtocounter{samesourcetarget}{\increasebend}
  \else
   \setcounter{samesourcetarget}{\defaultbend}
  \fi
 \else
  \setcounter{samesourcetarget}{\defaultbend}
 \fi
 \draw (\source) to[bend right=\thesamesourcetarget] (\target);
 \setcounter{lastsource}{\source}
 \setcounter{lasttarget}{\target}
}

\end{tikzpicture}
\end{document}

ここに画像の説明を入力してください


編集:ソートメカニズムを追加しましたここ(おそらく、このようなリストを並べ替える方が簡単でしょう):

\documentclass[tikz]{standalone}
\usepackage{expl3,l3sort,xparse}

\ExplSyntaxOn
\prg_new_conditional:Nnn \sort_string_if_before:nn{ p,T,F,TF }{
 \int_compare:nTF {\pdftex_strcmp:D{#1}{#2} < 0}{\prg_return_true:}{\prg_return_false:}
}

\NewDocumentCommand{\sortlist}{smm}{
 \IfBooleanTF{#1}{
  \clist_set:No \l__sort_sortlist_data_clist{#2}
 }{
  \clist_set:Nn \l__sort_sortlist_data_clist{#2}
 }
 \sort_sortlist:N \l__sort_sortlist_data_clist
 \clist_set_eq:NN #3 \l__sort_sortlist_data_clist
}
\clist_new:N \l__sort_sortlist_data_clist

\cs_new_protected:Nn \sort_sortlist:N{
 \clist_sort:Nn #1{
  \sort_string_if_before:nnTF{##1}{##2}{\sort_ordered:}{\sort_reversed:}
  }
}
\ExplSyntaxOff

\newcounter{lastsource}
\newcounter{lasttarget}
\newcounter{samesourcetarget}

\begin{document}

\begin{tikzpicture}
\node at (0,0)  [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3)  [circle, fill=blue] (5) {};

\def\defaultbend{30}
\def\increasebend{5}

\sortlist{2/5, 3/2, 3/5, 1/2, 4/1, 4/3, 1/2, 2/1, 1/4, 2/3, 2/3, 2/2, 3/5, 1/2, 3/5, 3/4, 4/1, 4/3}{\sortedcoords}

\setcounter{samesourcetarget}{\defaultbend}
\foreach \source/\target in \sortedcoords {
 \ifnum\value{lastsource}=\source 
  \ifnum\value{lasttarget}=\target
   \addtocounter{samesourcetarget}{\increasebend}
  \else
   \setcounter{samesourcetarget}{\defaultbend}
  \fi
 \else
  \setcounter{samesourcetarget}{\defaultbend}
 \fi
 \draw (\source) to[bend right=\thesamesourcetarget] (\target);
 \setcounter{lastsource}{\source}
 \setcounter{lasttarget}{\target}
}

\end{tikzpicture}
\end{document}

答え3

これは私自身の解決策です (MWE では少し見苦しいですが、ネットワークが非常に密集すると非常に良くなります)。

\documentclass[tikz]{standalone}
\newcommand{\drawrcurvededge}[2]{
\pgfmathsetmacro{\Offset}{20+10*rand}
\draw (#1) to[bend right=\Offset] (#2);
}
\begin{document}
\begin{tikzpicture}
\node at (0,0) [circle, fill=blue] (1) {};
\node at (0,10) [circle, fill=blue] (2) {};
\node at (7,10) [circle, fill=blue] (3) {};
\node at (10,4) [circle, fill=blue] (4) {};
\node at (4,3) [circle, fill=blue] (5) {};
\drawrcurvededge{1}{2}
\drawrcurvededge{1}{2}
\drawrcurvededge{1}{2}
\drawrcurvededge{2}{1}
\drawrcurvededge{1}{4}
\drawrcurvededge{2}{3}
\drawrcurvededge{2}{3}
\drawrcurvededge{2}{3}
\drawrcurvededge{2}{5}
\drawrcurvededge{3}{2}
\drawrcurvededge{3}{5}
\drawrcurvededge{3}{5}
\drawrcurvededge{3}{5}
\drawrcurvededge{3}{4}
\drawrcurvededge{4}{1}
\drawrcurvededge{4}{1}
\drawrcurvededge{4}{3}
\drawrcurvededge{4}{3}
\end{tikzpicture}
\end{document}

ここに画像の説明を入力してください

関連情報