latex 命令的参数数量不确定

latex 命令的参数数量不确定

我正在尝试使用一种智能的方式将一些图表排版为这些单链图。

单链图

但我想再做两件事,一是允许它们中的 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.701

编辑

这是一个“更高级”的宏,它接受逗号分隔的逗号分隔的/对\PlanarDiagram列表,以生成相应图表的产品。例如,代码xy

\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}

相关内容