与其他几个问题类似,我正在尝试在 tikz 中绘制超图。我想绘制一个有向超图,看起来像这张图片中的那些这里:
与其他问题相反,我不想在相关边之间画弧。相反,我希望边连接成一个段,然后再次分开。
我不介意指定连接点的位置,但我宁愿不必手动指定传入和传出边缘的角度。我希望线条能够平滑地从连接点分离。
这是我重新创建这个数字的拙劣尝试:
\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{tikz}
\begin{document}
\tikz{
\node [circle,draw] (v1) at (0,0) { $v_1$ };
\node [circle,draw] (v2) at (-1,-3) { $v_2$ };
\node [circle,draw] (v3) at (2,-2) { $v_3$ };
\node [circle,draw] (v4) at (1,-4) { $v_4$ };
\node [circle,draw] (v5) at (3,1) { $v_5$ };
\node [circle,draw] (v6) at (5,-1) { $v_6$ };
\node [circle,draw] (v7) at (4,-5) { $v_7$ };
\node [] (e1) at (1,-2) { $e_1$ };
\node [] (e2) at (2,0) { $e_2$ };
\node [] (e3) at (3,-3) { $e_3$ };
\node [] (e4) at (4,0) { $e_4$ };
%
\path
% edge 1
(v1) [-] edge node { } (e1)
(v2) [-] edge node { } (e1)
(e1) [->] edge node { } (v3)
(e1) [->] edge node { } (v4)
% edge 2
(v1) [-] edge node { } (e2)
(v3) [-] edge node { } (e2)
(e2) [->] edge node { } (v5)
% edge 3
(v7) [-] edge node { } (e3)
(e3) [->] edge node { } (v3)
(e3) [->] edge node { } (v4)
% edge 4
(v5) [-] edge node { } (e4)
(e4) [->] edge node { } (v6)
(e4) [->] edge node { } (v7)
;
}
\end{document}
由此得出该图:
答案1
代码
\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\makeatletter
\tikzset{
@pos/.style={@pos1={#1},@pos2={#1}},
@ratio/.style={@ratio1={#1},@ratio2={#1}},
@delta/.style={@delta1={#1},@delta2={#1}},
@edge/.style={@@edge/.append style={#1}},
@edge 0/.style={@@edge 0/.append style={#1}},
@edge 1/.style={@@edge 1/.append style={#1}},
@edge 2/.style={@@edge 2/.append style={#1}},
@edge 3/.style={@@edge 3/.append style={#1}},
@edge 4/.style={@@edge 4/.append style={#1}},
% and for four:
@pos1/.store in=\qrr@posA,
@pos2/.store in=\qrr@posB,
@ratio1/.store in=\qrr@ratioA,
@ratio2/.store in=\qrr@ratioB,
@delta1/.store in=\qrr@deltaA,
@delta2/.store in=\qrr@deltaB,
@pos=.5,
@ratio=.5,
@delta=.1,
}
\newcommand*{\connectThree}[4][]{
\begingroup
\tikzset{#1}
\coordinate (@aux1) at ($(#2)!\qrr@ratioA!(#3)$);
\coordinate (@aux2) at ($(#4)!\qrr@posA!(@aux1)$);
\path (@aux2) edge[@@edge/.try, @@edge 0/.try, @@edge 3/.try] (#4);
\draw[@@edge/.try, @@edge 1/.try] (@aux2) .. controls ($(#4)!\qrr@posA+\qrr@deltaA!(@aux1)$) .. (#2);
\draw[@@edge/.try, @@edge 2/.try] (@aux2) .. controls ($(#4)!\qrr@posA+\qrr@deltaA!(@aux1)$) .. (#3);
\endgroup
}
% \renewcommand*{\connectThree}[4][]{\connectFour[#1, @@edge 4/.style={draw=none}, @ratio2=0]{#2}{#3}{#4}{0,0}}
\newcommand*{\connectFour}[5][]{
\begingroup
\tikzset{#1}
\coordinate (@aux1a) at ($(#2)!\qrr@ratioA!(#3)$);
\coordinate (@aux1b) at ($(#4)!\qrr@ratioB!(#5)$);
\coordinate (@aux2a) at ($(@aux1b)!\qrr@posA!(@aux1a)$);
\coordinate (@aux2b) at ($(@aux1a)!\qrr@posB!(@aux1b)$);
\path (@aux2a) edge[@@edge/.try,@@edge 0/.try] (@aux2b);
\draw[@@edge/.try,@@edge 1/.try] (@aux2a) .. controls ($(@aux1b)!\qrr@posA+\qrr@deltaA!(@aux1a)$) .. (#2);
\draw[@@edge/.try,@@edge 2/.try] (@aux2a) .. controls ($(@aux1b)!\qrr@posA+\qrr@deltaA!(@aux1a)$) .. (#3);
\draw[@@edge/.try,@@edge 3/.try] (@aux2b) .. controls ($(@aux1a)!\qrr@posB+\qrr@deltaB!(@aux1b)$) .. (#4);
\draw[@@edge/.try,@@edge 4/.try] (@aux2b) .. controls ($(@aux1a)!\qrr@posB+\qrr@deltaB!(@aux1b)$) .. (#5);
\draw[help lines] (@aux1a) -- (@aux1b) node[midway,above,sloped,font=\tiny,shape=rectangle,inner xsep=+0pt,draw=none,align=center,fill=white,fill opacity=.75,outer ysep=\pgflinewidth,text opacity=1] {ratio: \qrr@ratioA/\qrr@ratioB\\pos: \qrr@posA/\qrr@posB\\delta: \qrr@deltaA/\qrr@deltaB};
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node [circle,draw] (v1) at (0,0) { $v_1$ };
\node [circle,draw] (v2) at (-1,-3) { $v_2$ };
\node [circle,draw] (v3) at (2,-2) { $v_3$ };
\node [circle,draw] (v4) at (1,-4) { $v_4$ };
\node [circle,draw] (v5) at (3,1) { $v_5$ };
\node [circle,draw] (v6) at (5,-1) { $v_6$ };
\node [circle,draw] (v7) at (4,-5) { $v_7$ };
\connectThree[
@edge 3=->
]{v1}{v3}{v5}
\connectThree[
@ratio=0,
@edge 1=->,
@edge 2=->
]{v6}{v7}{v5}
\connectThree[
@edge 1=->,
@edge 2=->
]{v3}{v4}{v7}
\connectFour[
@ratio=.4,
@pos1=.7,
@pos2=.5,
@edge 3=->,
@edge 4=->,
@edge=thick
]{v1}{v2}{v3}{v4}
\connectFour[@edge=blue,@edge 3=->, @edge 4={draw}, @ratio2=0]{v3}{v5}{v6}{v7}
\end{tikzpicture}
\end{document}
输出
答案2
具有内联的超图Asymptote
,使用flowchart
模块hypg.tex
:
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{asy}
size(0,200);
import flowchart;
pair[]pv={
(0,0) , // pv[0], not used, included for convenient indexing nodes from pv[1]
(0,0) ,
(-1,-3) ,
(2,-2) ,
(1,-4) ,
(3,1) ,
(5,-1) ,
(4,-5) ,
};
pair[][] pe={ // point coordinates and a relative position of the label (N=North etc)
{(0,0), N} , // ev[0], not used, included for convenient indexing nodes from ev[1]
{(0.2,-2) ,N} ,
{(2,0) ,SE} ,
{0.1pv[3]+0.2pv[6]+0.7pv[7],E},
{(4.5,0.75) ,SW} ,
};
pen nodeFill=yellow+opacity(0.8);
pen nodeLine=darkblue+1.2pt+opacity(0.5);
block[] v=new block[pv.length];
block[] e=new block[pe.length];
for(int i=1;i<pv.length;++i){
v[i]=circle("$v_"+string(i)+"$",pv[i],nodeFill,nodeLine);
draw(v[i]);
}
string s;
for(int i=1;i<pe.length;++i){
s="$e_"+string(i)+"$";
e[i]=circle(s,pe[i][0]);
label(s,pe[i][0],pe[i][1]);
dot(pe[i][0]);
}
add(
new void(picture pic, transform t) {
blockconnector operator --=blockconnector(pic,t);
real tg;
pen linePen=darkblue+0.8pt;
currentpen=linePen;
arrowfactor=4;
draw(pic,v[1].bottomleft(t) .. {dir(-30)}t*e[1].center{dir(-30)} ..v[3].bottomleft(t),Arrow(HookHead));
draw(pic,v[2].top(t){dir(80)} .. {dir(-30)}t*e[1].center{dir(-30)} ..v[4].top(t),Arrow(HookHead));
draw(pic,v[1].right(t) .. t*e[2].center ..v[5].bottom(t),Arrow(HookHead));
draw(pic,v[3].topleft(t){dir(120)} .. {dir(20)}(t*pe[2][0]));
tg=-30;
draw(pic,v[5].right(t) .. {dir(tg)}t*e[4].center{dir(tg)} ..v[6].top(t),Arrow(HookHead));
draw(pic,v[5].right(t) .. {dir(tg)}t*e[4].center{dir(tg)} ..v[7].topright(t),Arrow(HookHead));
tg=90;
draw(pic,v[7].top(t) .. {dir(tg)}t*e[3].center{dir(tg)} ..v[3].right(t),Arrow(HookHead));
draw(pic,v[7].top(t) .. {dir(tg)}t*e[3].center{dir(tg)} ..v[4].topright(t),Arrow(HookHead));
}
);
\end{asy}
\end{document}
为了处理它latexmk
,请创建文件latexmkrc
:
sub asy {return system("asy '$_[0]'");}
add_cus_dep("asy","eps",0,"asy");
add_cus_dep("asy","pdf",0,"asy");
add_cus_dep("asy","tex",0,"asy");
然后运行latexmk -pdf hypg.tex
。