假设一支箭可以
- 有一个头(o)、两个头(吨)或“波浪形”(G),
- 单线(s)或双线(d),
- 和 (瓦)或不带(o)标签(即上方的文字)
其中一些箭头由“标准”包定义,例如\xrightarrow{abc}
,它对应于开放空间其中一些需要更多“奇特”的包,例如\xLongrightarrow
(陣水), 被定义为extarrows
。
有些需要用 Tikz 绘制,例如\xtwoheadrightarrow
(多伦多),参见 https://tex.stackexchange.com/a/60219/34551
我尝试使用一个宏来一次性定义所有这些组合,并以统一的外观显示它们。我尝试使用xparse
和l3regex
,这似乎是处理这个问题的一个很好的组合(向https://tex.stackexchange.com/a/188593/34551)。
我认为我成功地定义了一个宏来一次性定义它们,但它们看起来很糟糕,也就是说,真的不统一,而我使用的 hack陣水简直糟糕透了。
我是否应该放弃在那儿画一个箭头,在那儿画另一个箭头的想法,而只是在 tiKz 中画它们?在这种情况下,如何确保它们确实像数学运算符一样运行?
以下是我得到的结果:
使用以下代码:
\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}
如前所述,关键是实现统一大小的构建块(分别是循环和箭头)。对于 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$}}
答案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}
给出:
使用这种生成箭头的替代方法,我的文档从 26 秒缩短到了 6 秒……