带标签和不带标签的箭头组合

带标签和不带标签的箭头组合

假设一支箭可以

  1. 有一个头(o)、两个头()或“波浪形”(G),
  2. 单线(s)或双线(d),
  3. 和 ()或不带(o)标签(即上方的文字)

其中一些箭头由“标准”包定义,例如\xrightarrow{abc},它对应于开放空间其中一些需要更多“奇特”的包,例如\xLongrightarrow陣水), 被定义为extarrows

有些需要用 Tikz 绘制,例如\xtwoheadrightarrow多伦多),参见 https://tex.stackexchange.com/a/60219/34551

我尝试使用一个宏来一次性定义所有这些组合,并以统一的外观显示它们。我尝试使用xparsel3regex,这似乎是处理这个问题的一个很好的组合(向https://tex.stackexchange.com/a/188593/34551)。

我认为我成功地定义了一个宏来一次性定义它们,但它们看起来很糟糕,也就是说,真的不统一,而我使用的 hack陣水简直糟糕透了。

我是否应该放弃在那儿画一个箭头,在那儿画另一个箭头的想法,而只是在 tiKz 中画它们?在这种情况下,如何确保它们确实像数学运算符一样运行?

以下是我得到的结果:

enter image description here

使用以下代码:

\documentclass{article}
\usepackage{xparse,l3regex}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{extarrows} % For \xLongrightarrow
\usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing,shapes,arrows}

\newcommand\xRightsquigarrow[1]{% https://tex.stackexchange.com/a/83086
  \mathrel{%
    \begin{tikzpicture}[baseline= {( $ (current bounding box.south) + (0,-0.5ex) $ )}]
      \node[inner sep=.5ex] (a) {$\scriptstyle #1$};
      \path[draw,implies-,double distance between line centers=1.5pt,decorate,
      decoration={zigzag,amplitude=0.7pt,segment length=1.2mm,pre=lineto,
    pre   length=4pt}] 
      (a.south east) -- (a.south west);
    \end{tikzpicture}}%
}
\newcommand\Rightsquigarrow{%
  \mathrel{%
    \begin{tikzpicture}[baseline= {( $ (current bounding box.south) + (0,-0.5ex) $ )}]
      \node[inner sep=.5ex] (a) {\hspace*{1em}};
      \path[draw,implies- ,double distance between line centers=1.5pt,decorate,
      decoration={zigzag,amplitude=0.7pt,segment length=1.2mm,pre=lineto,
    pre   length=4pt}] 
      (a.south east) -- (a.south west);
    \end{tikzpicture}}%
}

\makeatletter % https://tex.stackexchange.com/a/114242/34551
\providecommand*{\twoheadrightarrowfill@}{%
  \arrowfill@\relbar\relbar\twoheadrightarrow
}
\providecommand*{\xtwoheadrightarrow}[2][]{%
  \ext@arrow 0579\twoheadrightarrowfill@{#1}{#2}%
}
\makeatother

\ExplSyntaxOn
\NewDocumentCommand{\ar}{ m o }
{
  \IfNoValueTF{#2}
  {% there is no trailing optional argument, set the boolean to false
    \bool_set_false:N \l_label_bool
  }
  {% there is a trailing optional argument, set the boolean to true
    \bool_set_true:N \l_label_bool
    % and store the argument for later usage
    \tl_set:Nn \l_label_tl { #2 }
  }
  \ar_short:n { #1 }
}


% First byte: o, t, g     (one head, two heads, squiggly)
% Second byte: s, d       (single or double)
% Third byte:             (label to write on it)

\bool_new:N \l_label_bool
\tl_new:N \l_label_tl

\cs_new_protected:Npn \ar_short:n #1
{% separate the two characters
  \ar_short_aux:NN #1
}

\cs_new_protected:Npn \ar_short_aux:NN #1 #2{
  \str_case:nn { #1 }
  {
    {o}% One head
    {
      \str_case:nn { #2 }
      {{s}{% Single
      \xtwoheadrightarrow[]{  \bool_if:NT \l_label_bool { \l_label_tl }}
    }{d}{% Double
      \xRightarrow{  \bool_if:NT \l_label_bool { \l_label_tl }}\!\!\!\!\Rightarrow}
      }
    }
    {t}% Two heads
    {\str_case:nn { #2 }
      {{s}{% Single
      \xrightarrow{  \bool_if:NT \l_label_bool { \l_label_tl }}
    }{d}{% Double
      \xLongrightarrow{  \bool_if:NT \l_label_bool { \l_label_tl }}
    }
      }
    }
    {g}% Squiggly
    {\str_case:nn { #2 }
      {{s}{% Single
      \bool_if:NTF \l_label_bool {\overset{\l_label_tl}{\rightsquigarrow}}{\rightsquigarrow}
    }
    {d}{% Double
      \bool_if:NTF \l_label_bool {\xRightsquigarrow{\l_label_tl}}{\Rightsquigarrow}}
      }
    }
  }
}



\ExplSyntaxOff

\begin{document}

  $a \ar{os} b$

  $a \ar{od} b$

  $a \ar{ts} b$

  $a \ar{td} b$

  $a \ar{gs} b$

  $a \ar{gd} b$

  $a \ar{os}[i_2 : \alpha, 34] b$

  $a \ar{od}[i_2 : \alpha, 34] b$

  $a \ar{ts}[i_2 : \alpha, 34] b$

  $a \ar{td}[i_2 : \alpha, 34] b$

  $a \ar{gs}[i_2 : \alpha, 34] b$

  $a \ar{gd}[i_2 : \alpha, 34] b$

\end{document}

它们之间的间距差异,以及其中一个(格斯沃) 不可扩展,这是最让我烦恼的。

答案1

经过大量修改,以弥补之前帖子的缺失。也就是说,支持所有所需的箭头类型(尽管是波浪形,而不是锯齿状的曲线),对于给定的重叠,无论箭头类型如何,都可以实现统一的箭头长度,支持所有数学样式。

为了实现统一大小的构建块和箭头,需要对字体大小进行一些调整(目前为 10pt)(详情见答案底部)。

我没有将它包装在一个总体宏中,但各个箭头类型被称为\zigzagarrow(单波浪线,单箭头)、\ZigZagarrow(双波浪线,单箭头)、\linearrow(单线,单箭头)、\Linearrow(双线,单箭头)、\zzigzagarrow(单波浪线,双箭头)、\ZZigZagarrow(双波浪线,双箭头)、\llinearrow(单线,双箭头)和\LLinearrow(双线,双箭头),

\documentclass[10pt]{article}
\usepackage{stackengine,scalerel,graphicx,trimclip,amsmath,wasysym}
% UNIFORMLY SIZED BUILDING BLOCKS
\savestack\zigzagtextstyle{\vphantom{()}\scalebox{.86666}[1]{\kern-.5pt\AC\kern-.5pt}}
\savestack\onelinetextstyle{\vphantom{()}\scalebox{1}[1]{\kern-1pt{$-$}\kern-1pt}}
\savestack\twolinetextstyle{\vphantom{()}\scalebox{1}[1]{\kern-1pt{$=$}\kern-1pt}}
\savestack\ZigZagtextstyle{% DERIVATIVE OF \zigzagtextstyle
  $\vphantom{()}\smash{\raisebox{-.002em}{$\vcenter{\hbox{%
   \stackengine{-.805em}{\zigzagtextstyle}{\zigzagtextstyle}{O}{c}{F}{F}{S}}}$}}$}
\newlength\repwidth
\repwidth=\wd\zigzagtextstylecontent\relax
% UNIFORMLY SIZED ARROWHEADS
\newcommand\rightarrowhead{\clipbox{4pt -2pt 0pt -2pt}{$\rightarrow$}}
\newcommand\Rightarrowhead{\clipbox{4pt -2pt 0pt -2pt}{$\Rightarrow$}}
\newcommand\rrightarrowhead{\clipbox{5.5pt -2pt 0pt -2pt}{$\rightarrow\kern-8.5pt\rightarrow$}}
\newcommand\RRightarrowhead{\clipbox{5.5pt -2pt 0pt -2pt}{$\Rightarrow\kern-8.5pt\Rightarrow$}}
% HALF-CYCLE BLOCKS PLUS ARROWHEAD
\newcommand\fXarrowtextstyle[2]{$\vphantom{()}\smash{\vcenter{\hbox{\kern-.03\repwidth%
   \clipbox{-.03\repwidth{} 0pt .527\repwidth{} 0pt}{#1}}}}#2$}
%
\savestack\fzigarrowtextstyle{\fXarrowtextstyle{\zigzagtextstyle}{\rightarrowhead}}
\savestack\fZigarrowtextstyle{\fXarrowtextstyle{\ZigZagtextstyle}{\Rightarrowhead}}
\savestack\flinearrowtextstyle{\fXarrowtextstyle{\onelinetextstyle}{\rightarrowhead}}
\savestack\fLinearrowtextstyle{\fXarrowtextstyle{\twolinetextstyle}{\Rightarrowhead}}
\savestack\fzzigarrowtextstyle{\fXarrowtextstyle{\zigzagtextstyle}{\rrightarrowhead}}
\savestack\fZZigarrowtextstyle{\fXarrowtextstyle{\ZigZagtextstyle}{\RRightarrowhead}}
\savestack\fllinearrowtextstyle{\fXarrowtextstyle{\onelinetextstyle}{\rrightarrowhead}}
\savestack\fLLinearrowtextstyle{\fXarrowtextstyle{\twolinetextstyle}{\RRightarrowhead}}
% SUPPORT FOR ALL MATH STYLES
%  - CYCLE BLOCKS
\newcommand\zigzag{\scalerel*{\zigzagtextstyle}{()}}
\newcommand\ZigZag{\scalerel*{\ZigZagtextstyle}{()}}
\newcommand\oneline{\scalerel*{\onelinetextstyle}{()}}
\newcommand\twoline{\scalerel*{\twolinetextstyle}{()}}
%  - ARROW HEADS
\newcommand\fzigarrow{\scalerel*{\fzigarrowtextstyle}{()}}
\newcommand\fZigarrow{\scalerel*{\fZigarrowtextstyle}{()}}
\newcommand\flinearrow{\scalerel*{\flinearrowtextstyle}{()}}
\newcommand\fLinearrow{\scalerel*{\fLinearrowtextstyle}{()}}
\newcommand\fzzigarrow{\scalerel*{\fzzigarrowtextstyle}{()}}
\newcommand\fZZigarrow{\scalerel*{\fZZigarrowtextstyle}{()}}
\newcommand\fllinearrow{\scalerel*{\fllinearrowtextstyle}{()}}
\newcommand\fLLinearrow{\scalerel*{\fLLinearrowtextstyle}{()}}
% ARROW-EXTENDING USER MACROS
\newcommand\zigzagarrow[1][]{\Xarrow{\zigzag}{\fzigarrow}{#1}{-.65}}
\newcommand\ZigZagarrow[1][]{\Xarrow{\ZigZag}{\fZigarrow}{#1}{-.40}}
\newcommand\linearrow[1][]{\Xarrow{\oneline}{\flinearrow}{#1}{-.65}}
\newcommand\Linearrow[1][]{\Xarrow{\twoline}{\fLinearrow}{#1}{-.40}}
\newcommand\zzigzagarrow[1][]{\Xarrow{\zigzag}{\fzzigarrow}{#1}{-.65}}
\newcommand\ZZigZagarrow[1][]{\Xarrow{\ZigZag}{\fZZigarrow}{#1}{-.40}}
\newcommand\llinearrow[1][]{\Xarrow{\oneline}{\fllinearrow}{#1}{-.65}}
\newcommand\LLinearrow[1][]{\Xarrow{\twoline}{\fLLinearrow}{#1}{-.40}}
% \Xarrow EXTENDING-ARROW MACRO
% #1 - arrow building block
% #2 - arrowhead
% #3 - overtext
% #4 - overset distance multiplier wrt top of paren
\newcommand\Xarrow[4]{\ThisStyle{\mathrel{\Xarrowhelp{#1#2}{#3}{#1}{#4}}}}
\newcommand\Xarrowhelp[4]{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \setbox2=\hbox{$\SavedStyle_{\,\,#2\,\,}$}%
  \ifdim\wd0<\wd2\relax\Xarrowhelp{#3#1}{#2}{#3}{#4}%
  \else\stackengine{#4\LMex}{\copy0}{\copy2\,}{O}{c}{F}{T}{S}\fi%
}
\begin{document}
\setstackEOL{\\}
\Longunderstack{
3 cycles:
\\
$\zigzagtextstyle\zigzagtextstyle\zigzagtextstyle$
\setbox0=\hbox{\zigzagtextstyle}\the\wd0
\\
$\ZigZagtextstyle\ZigZagtextstyle\ZigZagtextstyle$
\setbox0=\hbox{\zigzagtextstyle}\the\wd0
\\
$\onelinetextstyle\onelinetextstyle\onelinetextstyle$
\setbox0=\hbox{\onelinetextstyle}\the\wd0
\\
$\twolinetextstyle\twolinetextstyle\twolinetextstyle$
\setbox0=\hbox{\twolinetextstyle}\the\wd0
}
\qquad\Longunderstack{
Arrowheads:
\\
\rightarrowhead\setbox0=\hbox{\rightarrowhead}\the\wd0
\\
\Rightarrowhead\setbox0=\hbox{\Rightarrowhead}\the\wd0
\\
\rrightarrowhead\setbox0=\hbox{\rrightarrowhead}\the\wd0
\\
\RRightarrowhead\setbox0=\hbox{\RRightarrowhead}\the\wd0
}
\qquad\Longunderstack{
Half-cycle + arrowheads
\\
\fzigarrowtextstyle \quad \fzzigarrowtextstyle
\\
\fZigarrowtextstyle \quad \fZZigarrowtextstyle
\\
\flinearrowtextstyle \quad \fllinearrowtextstyle
\\
\fLinearrowtextstyle \quad \fLLinearrowtextstyle
}

Examples:

\Shortunderstack{
$A \zigzagarrow B \zigzagarrow[T=298K] C$
\\
$A \ZigZagarrow B \ZigZagarrow[T=298K] C$
\\
$A \linearrow B \linearrow[T=298K] C$
\\
$A \Linearrow B \Linearrow[T=298K] C$
\\
$A \zzigzagarrow B \zzigzagarrow[T=298K] C$
\\
$A \ZZigZagarrow B \ZZigZagarrow[T=298K] C$
\\
$A \llinearrow B \llinearrow[T=298K] C$
\\
$A \LLinearrow B \LLinearrow[T=298K] C$
}
\quad
\Shortunderstack{
$\scriptstyle A \zigzagarrow B \zigzagarrow[T=298K] C$
\\
$\scriptstyle A \ZigZagarrow B \ZigZagarrow[T=298K] C$
\\
$\scriptstyle A \linearrow B \linearrow[T=298K] C$
\\
$\scriptstyle A \Linearrow B \Linearrow[T=298K] C$
\\
$\scriptstyle A \zzigzagarrow B \zzigzagarrow[T=298K] C$
\\
$\scriptstyle A \ZZigZagarrow B \ZZigZagarrow[T=298K] C$
\\
$\scriptstyle A \llinearrow B \llinearrow[T=298K] C$
\\
$\scriptstyle A \LLinearrow B \LLinearrow[T=298K] C$
}
\quad
\Shortunderstack{
$\scriptscriptstyle A \zigzagarrow B \zigzagarrow[T=298K] C$
\\
$\scriptscriptstyle A \ZigZagarrow B \ZigZagarrow[T=298K] C$
\\
$\scriptscriptstyle A \linearrow B \linearrow[T=298K] C$
\\
$\scriptscriptstyle A \Linearrow B \Linearrow[T=298K] C$
\\
$\scriptscriptstyle A \zzigzagarrow B \zzigzagarrow[T=298K] C$
\\
$\scriptscriptstyle A \ZZigZagarrow B \ZZigZagarrow[T=298K] C$
\\
$\scriptscriptstyle A \llinearrow B \llinearrow[T=298K] C$
\\
$\scriptscriptstyle A \LLinearrow B \LLinearrow[T=298K] C$
}
\end{document}

enter image description here

如前所述,关键是实现统一大小的构建块(分别是循环和箭头)。对于 12pt 字体,需要进行以下调整才能实现此目的:

\savestack\onelinetextstyle{\vphantom{()}\scalebox{.97196}[1]{\kern-1.1pt{$-$}\kern-1.1pt}}
\savestack\twolinetextstyle{\vphantom{()}\scalebox{.97121}[1]{\kern-1pt{$=$}\kern-1pt}}

\newcommand\rrightarrowhead{\clipbox{6.5pt -2pt 0pt -2pt}{$\rightarrow\kern-9.5pt\rightarrow$}}
\newcommand\RRightarrowhead{\clipbox{6.5pt -2pt 0pt -2pt}{$\Rightarrow\kern-9.5pt\Rightarrow$}}

enter image description here

答案2

我用过Steven B. Segletes 的回答多年来我一直很重视它。不幸的是,它的计算量非常大,我花了 26 秒才编译出一些简单的文档。

我重写了自己的解决方案,不带双线(d)变化:这不完全是一个答案对这个问题,但我认为它还是有帮助的。

\documentclass{article}
\usepackage{tikz}
\usepackage{mathtools}
\usetikzlibrary{calc,decorations.pathmorphing,shapes}

\newcounter{sarrow}
\NewDocumentCommand{\xrsquigarrow}{m}{ % Backward arrow
    \stepcounter{sarrow}%
    \mathrel{\begin{tikzpicture}[baseline= {( $(current bounding box.south)$ )}]
            \node[inner sep=.5ex, font=\scriptsize] (\thesarrow) {$#1$};
            \path[draw,->,decorate,
            %decoration={zigzag,amplitude=0.7pt,segment length=1.2mm,pre=lineto,pre length=4pt}
            decoration={snake,
                amplitude=-1pt, segment length =1.5mm, pre=lineto, post length=2pt%, post length=3pt
            }
            ] 
            (\thesarrow.south west) -- (\thesarrow.south east);
    \end{tikzpicture}}%
}

\newcommand{\tootip}{\mathrel{\tikz[anchor=base]{\draw[->](0,0)--(.01,0);}}} % https://tex.stackexchange.com/a/645771/34551

% https://tex.stackexchange.com/a/260581/34551
\newcommand{\rightarrowdbl}{\mathrel{\ooalign{ % https://tex.stackexchange.com/a/22375/34551
            $\rightarrow$\cr %
            \hidewidth\raise.23em\hbox{$\tootip\mkern4mu$}}}
        }

\newcommand{\xrightarrowdbl}[1]{%
    \mathrel{\ooalign{%
            $\xrightarrow{#1}$\cr%
            \hidewidth\raise.23em\hbox{$\tootip\mkern4mu$}}}
}

\ExplSyntaxOn
\RenewDocumentCommand{\r}{m o o} 
% m = direction (b, f, bf)
% o = label
% o = key
% Assumption is that you will never have a key without a label.
{
    \str_case:nnF { #1 }
    {
        {f}{% Forward case
            \IfValueTF{#2} % We test if the label is here.
            {
                \IfValueTF{#3}% We test if the key is here.
                    {\xrightarrow{#2[#3]} } % Forward,  label and key
                    {\xrightarrow{#2}} % Forward, a label but no key
            }
            { \rightarrow } % Forward, no label nor key
        }
        {b}{% backward case
            \IfValueTF{#2} % We test if the label is here.
            {
                \IfValueTF{#3}% We test if the key is here.
                {\xrsquigarrow{#2[#3]}} % Backward,  label and key
                {\xrsquigarrow{#2}} % Backward, a label but no key
            }
            { \xrsquigarrow{\mkern10mu} } % Backward, no label nor key
        }
        {fb}{ % Forward and backward case
        \IfValueTF{#2} % We test if the label is here.
            {
            \IfValueTF{#3}% We test if the key is here.
            { \xrightarrowdbl{#2[#3]}} % Backward, label and key
            { \xrightarrowdbl{#2}} % Backward, a label but no key
        }
        {\rightarrowdbl} % Forward and backward, no label nor key
        }
    }
    { #1 }
}
\ExplSyntaxOff

\begin{document}
\begin{align*}
    \Aboxed{P \r{f} Q} & \Aboxed{P \r{f}[\alpha] Q} & \Aboxed{P \r{f}[\alpha][k] Q}\\
    \Aboxed{P \r{b} Q} & \Aboxed{P \r{b}[\alpha] Q} & \Aboxed{P \r{b}[\alpha][k] Q} \\
    \Aboxed{P \r{fb} Q} & \Aboxed{P \r{fb}[\alpha] Q} & \Aboxed{P \r{fb}[\alpha][k] Q} \\
\end{align*}
\end{document}

给出:

enter image description here

使用这种生成箭头的替代方法,我的文档从 26 秒缩短到了 6 秒……

相关内容