我正在尝试使用一种智能的方式将一些图表排版为这些单链图。
但我想再做两件事,一是允许它们中的 n 个堆叠在一起
并能够绘制多链图
现在我已经有了单链图的命令
\newcommand{\Planar}[3]{
\begin{tikzpicture}[->,>=stealth'] % if arrow is ture, add these commands
\draw[color=red] (0,0) rectangle (#1*0.3+0.3,0.7); % draw the outer box according to number of dots
\newcounter{dotnumber}
\foreach \dot in {1,...,#1}{ % draw the dots
\filldraw (0.3*\dot,0) circle [radius=1pt];
\filldraw (0.3*\dot,0.7) circle [radius=1pt];
}
\draw (0.3*#2,0) .. controls +(0,0.2) and +(0,-0.2) .. (0.3*#3,0.7); % draw the line
\end{tikzpicture}
}
但我正在寻找这样的东西
\Planar[number_of_dots][number_of_levels][first_strand_starting][first_strand_ending][...][last_strand_starting][last_strand_ending][secondlevelstrands...]
使用以下命令生成上述图表:
\Planar[3][1][1]...,
\Planar[3][level=2][2][2][2][3]
|this is the number of levels
\Planar[3][1][2][3][1][3][3]
|this is the starting dot of the first line
我知道这可能是一个巨大的宏,而且我定义命令的方式很糟糕,但我至少希望得到一些关于下一步该怎么做的指导。
答案1
这是开始。我不会使用级别,而是定义一个级别pic
(参见第 18.2 节蒂克兹您可以使用以下方法(手动绘制)绘制一个平面图,然后可以将它们堆叠起来。 的第一个参数pic
应给出底线上的点数,第二个参数应为以逗号分隔的字符串x
/y
对列表。 这样,您可以使用:
\begin{tikzpicture}
\draw (0,0) pic{planar=[3]{1/1}};
\draw (3,0) pic{planar=[3]{1/2}};
\draw (6,0) pic{planar=[3]{1/3}};
\end{tikzpicture}
绘制图表
要堆叠图表,你需要将两张图片“叠”在一起,这样
\begin{tikzpicture}
\draw(0,0) pic{planar=[3]{2/2}};
\draw(0,0.7) pic{planar=[3]{2/3}};
\end{tikzpicture}
生成:
最后,这是一个包含多个字符串和四个点的示例:代码
\begin{tikzpicture}
\draw(0,0) pic{planar={4}{1/2, 3/1, 3/3}};
\end{tikzpicture}
产生(非平面图):
我没有添加标签命令,部分原因是我没有立即看到这方面的良好语法,部分原因是当我绘制此类图表时我从不标记字符串:)
完整代码如下:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{pics/planar/.style 2 args = {
code = {
\draw[color=red] (0,0) rectangle (#1*0.3+0.3,0.7);
\foreach \dot in {1,...,#1}{ % draw the dots
\filldraw (0.3*\dot,0) circle [radius=1pt];
\filldraw (0.3*\dot,0.7) circle [radius=1pt];
}
% draw the lines
\foreach \x/\y in {#2}
\draw[->,>=stealth](0.3*\x,0) .. controls +(0,0.2) and +(0,-0.2) .. (0.3*\y,0.7);
}
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) pic{planar={3}{1/1}};
\draw (2,0) pic{planar={3}{1/2}};
\draw (4,0) pic{planar={3}{1/3}};
\end{tikzpicture}
\begin{tikzpicture}
\draw(0,0) pic{planar={3}{2/2}};
\draw(0,0.7) pic{planar={3}{2/3}};
\end{tikzpicture}
\begin{tikzpicture}
\draw(0,0) pic{planar={4}{1/2, 3/1, 3/3}};
\end{tikzpicture}
\end{document}
如您所见,我实际上只是重新打包了 OP 的代码。就我个人而言,我会将上面的0.3
和替换为和,然后重新调整整个环境,因为从长远来看,这可能会让您的生活更轻松一些。0.7
0
1
编辑
这是一个“更高级”的宏,它接受逗号分隔的逗号分隔的/对\PlanarDiagram
列表,以生成相应图表的产品。例如,代码x
y
\PlanarDiagram(5){{1/2}} \quad
\PlanarDiagram{{1/2,2/2}, {2/3,3/1}} \quad
\PlanarDiagram(4){{1/2, 3/1, 3/3}, {1/1, 2/3, 3/3}}
产生输出
请注意,有一个可选参数,它包含在 中(...)
,用于指定点数。这是另一个可选参数,您可以使用它来配置底层tikzpicture1
环境和pic
。例如,
\PlanarDiagram[scale=0.5, draw=blue](4){{1/2, 3/1, 3/3}, {1/1, 2/3, 3/3}}
生成:
以下是更新后的代码:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\tikzset{pics/planar/.style 2 args = {
code = {
\draw[color=red] (0,0) rectangle (#1*0.3+0.3,0.7);
\foreach \dot in {1,...,#1}{ % draw the dots
\filldraw (0.3*\dot,0) circle [radius=1pt];
\filldraw (0.3*\dot,0.7) circle [radius=1pt];
}
% draw the lines
\foreach \x/\y in #2
\draw[->,>=stealth](0.3*\x,0) .. controls +(0,0.2) and +(0,-0.2) .. (0.3*\y,0.7);
}
}
}
\usepackage{xparse}
\NewDocumentCommand\PlanarDiagram{ O{} D(){3} m }{%
\begin{tikzpicture}[#1]
\foreach \diag [count=\c] in {#3} {
\draw(0,\c*0.7) pic[#1]{planar={#2}{\diag}};
}
\end{tikzpicture}%
}
\begin{document}
\PlanarDiagram(5){{1/2}} \quad
\PlanarDiagram{{1/2,2/2}, {2/3,3/1}} \quad
\PlanarDiagram(4){{1/2, 3/1, 3/3}, {1/1, 2/3, 3/3}}
\PlanarDiagram[scale=0.7, draw=blue](4){{1/2, 3/1, 3/3}, {1/1, 2/3, 3/3}}
\end{document}
答案2
作为练习,我尝试了一下metapost
。语法如下:
planar(n,m)("connections")
其中n
是每级点数,m
是级数,connections
是形式为
level 1 arrows | level 2 arrows | level 3 arrows |...
其中,每个级别内的箭头以逗号分隔的有序对列表形式给出。例如
planar(3,1)("(1,1),(2,3),(3,2)");
生产
和
planar(3,2)("(1,1),(2,3),(3,2)|(3,1),(1,3),(2,2)");
生产
代码:
\documentclass{article}
\usepackage{luamplib}
\mplibforcehmode
\begin{document}
\begin{mplibcode}
ux:=1cm; % horizontal scale
uy:=2cm; % vertical scale
ds:=.15*ux; % dot size
def planar(expr pts,levels)(text connections)=
clearxy; save k,l,n;
x=(pts+1)*ux; y=levels*uy; % max x, max y
for i=0 upto levels:
draw (origin--(x,0)) shifted (0,i*uy) withcolor red; % draw horizontal bars
for j=1 upto pts: drawdot (j*ux,i*uy) withpen pencircle scaled ds; endfor; % draw dots
endfor;
draw origin--(0,y) withcolor red; % draw left vertical bar
draw (x,0)--(x,y) withcolor red; % draw right vertical bar
l=length(connections); n=k=0;
for i=0 upto l:
if (substring(i,i+1) of connections="|") or (i=l): % find separators
for p=scantokens(substring(k,i) of connections): % iterate through list up to separator
drawarrow ((xpart p)*ux,n*uy){up}..{up}((ypart p)*ux,(n+1)*uy)
cutafter fullcircle scaled (ds+1) shifted ((ypart p)*ux,(n+1)*uy);
endfor;
k:=i+1; % pickup after separator
n:=n+1; % increase level
fi;
endfor;
enddef;
beginfig(0);
planar(3,2)("(1,1),(2,3),(3,2)|(3,1),(1,3),(2,2)");
endfig;
\end{mplibcode}
\end{document}