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}

여기에 이미지 설명을 입력하세요

관련 정보