免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

半箭头向量

默认向量箭头 $\overrightarrow{AB}$,$\overleftarrow{AB}$,这里我们想让箭头变成“半箭头”。

其实半箭头原先就有,命令是 \leftharpoonup 和 \rightharpoonup ,只是没有做到上面去。
代码 \$a\leftharpoonup b\rightharpoonup c\$ 效果 $a\leftharpoonup b\rightharpoonup c$,类似于 \leftarrow 和 \rightarrow 。

而看 amsmath 宏包后发现 \overrightarrow 命令其实是由 \rightarrow 做上去的,于是我们可以仿照它的定义来把半箭头做上去。

amsmath 宏包中这方面相关定义有一堆,经观察可知关键是这几句
  1. \def\leftarrowfill@{\arrowfill@\leftarrow\relbar\relbar}
  2. \def\rightarrowfill@{\arrowfill@\relbar\relbar\rightarrow}
  3. \ams@renewcommand{\overrightarrow}{%
  4.   \mathpalette{\overarrow@\rightarrowfill@}}
  5. \ams@renewcommand{\overleftarrow}{%
  6.   \mathpalette{\overarrow@\leftarrowfill@}}
复制代码
于是仿照可写出
  1. \makeatletter
  2. \def\leftharpoonfill@{\arrowfill@\leftharpoonup\relbar\relbar}
  3. \def\rightharpoonfill@{\arrowfill@\relbar\relbar\rightharpoonup}
  4. \newcommand\rbjt{\mathpalette{\overarrow@\rightharpoonfill@}}
  5. \newcommand\lbjt{\mathpalette{\overarrow@\leftharpoonfill@}}
  6. \makeatother
复制代码
测试文档: bjt.tex (435 Bytes)

QQ截图20141216154726.gif
2014-12-16 15:47


这样一来,各种箭头应该也可以类似造出来,时间关系有空再试……
分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
$\href{https://kuingggg.github.io/}{\text{About Me}}$

试。
  1. \def\twoheadleftarrowfill@{\arrowfill@\twoheadleftarrow\relbar\relbar}
  2. \def\twoheadrightarrowfill@{\arrowfill@\relbar\relbar\twoheadrightarrow}
  3. \newcommand\ltwojt{\mathpalette{\overarrow@\twoheadleftarrowfill@}}
  4. \newcommand\rtwojt{\mathpalette{\overarrow@\twoheadrightarrowfill@}}
复制代码
要加 amssymb 宏包。

效果
QQ截图20141216171816.gif
2014-12-16 17:18


当然了,这纯粹是玩玩,没什么用
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

  1. \def\nleftarrowfill@{\arrowfill@\nleftarrow\relbar\relbar}
  2. \def\nrightarrowfill@{\arrowfill@\relbar\relbar\nrightarrow}
  3. \newcommand\nljt{\mathpalette{\overarrow@\nleftarrowfill@}}
  4. \newcommand\nrjt{\mathpalette{\overarrow@\nrightarrowfill@}}
复制代码
这个就更无聊了

QQ截图20141216174604.gif
2014-12-16 17:45
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

  1. \def\multimapfill@{\arrowfill@\relbar\relbar\multimap}
  2. \newcommand\multimapjt{\mathpalette{\overarrow@\multimapfill@}}
复制代码
QQ截图20141216175145.gif
2014-12-16 17:51
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

能做双头的么?

TOP

回复 5# 小芳

你说的“双头”是指 <-> 这种?

TOP

双向箭头也类似,amsmath 里关于双向的向量箭头定义如下
  1. \def\leftrightarrowfill@{\arrowfill@\leftarrow\relbar\rightarrow}
  2. \ams@newcommand{\overleftrightarrow}{%
  3.   \mathpalette{\overarrow@\leftrightarrowfill@}}  
复制代码
于是类似地做出
  1. \def\leftrightharpoonfill@{\arrowfill@\leftharpoonup\relbar\rightharpoonup}
  2. \newcommand\lrbjt{\mathpalette{\overarrow@\leftrightharpoonfill@}}
  3. \def\twoheadleftrightarrowfill@{\arrowfill@\twoheadleftarrow\relbar\twoheadrightarrow}
  4. \newcommand\lrtwojt{\mathpalette{\overarrow@\twoheadleftrightarrowfill@}}
复制代码
等,效果
QQ截图20141218182844.gif
2014-12-18 18:28
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

再无聊一个
  1. \def\triangleleftfill@{\arrowfill@{\triangleleft\mkern4mu}\relbar\relbar}
  2. \newcommand\lsjxjt{\mathpalette{\overarrow@\triangleleftfill@}}
  3. \def\trianglerightfill@{\arrowfill@\relbar\relbar{\mkern4mu\triangleright}}
  4. \newcommand\rsjxjt{\mathpalette{\overarrow@\trianglerightfill@}}
  5. \def\triangleleftrightfill@{\arrowfill@{\triangleleft\mkern4mu}\relbar{\mkern4mu\triangleright}}
  6. \newcommand\lrsjxjt{\mathpalette{\overarrow@\triangleleftrightfill@}}
复制代码
效果
QQ截图20141218184607.gif
2014-12-18 18:46

擦,双向单字母的居然变成这样……
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

时隔三年大半,我才发现,上面那些代码中的 \relbar 是一条小横线(实际上就是减号),而其实还有双横线 \Relbar(实际上就是等号),那照上述方法,将其与 `\Rightarrow` 组合,双线的箭头向量应该一样可以做出来,一试果然!
  1. \makeatletter
  2. \def\Leftarrowfill@{\arrowfill@\Leftarrow\Relbar\Relbar}
  3. \def\Rightarrowfill@{\arrowfill@\Relbar\Relbar\Rightarrow}
  4. \def\Leftrightarrowfill@{\arrowfill@\Leftarrow\Relbar\Rightarrow}
  5. \newcommand\liffjt{\mathpalette{\overarrow@\Leftarrowfill@}}
  6. \newcommand\riffjt{\mathpalette{\overarrow@\Rightarrowfill@}}
  7. \newcommand\iffjt{\mathpalette{\overarrow@\Leftrightarrowfill@}}
  8. \makeatother
复制代码
效果:
QQ截图20180812180525.png
2018-8-12 18:05


这样一来,我又可以造出一堆无聊的双线箭头向量了……比如:
  1. \def\Triangleleftfill@{\arrowfill@{\triangleleft\mkern5mu}\Relbar\Relbar}
  2. \newcommand\Lsjxjt{\mathpalette{\overarrow@\Triangleleftfill@}}
  3. \def\Trianglerightfill@{\arrowfill@\Relbar\Relbar{\mkern5mu\triangleright}}
  4. \newcommand\Rsjxjt{\mathpalette{\overarrow@\Trianglerightfill@}}
  5. \def\Triangleleftrightfill@{\arrowfill@{\triangleleft\mkern5mu}\Relbar{\mkern5mu\triangleright}}
  6. \newcommand\LRsjxjt{\mathpalette{\overarrow@\Triangleleftrightfill@}}
复制代码
QQ截图20180812225955.png
2018-8-12 23:00
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

回复 9# kuing

哦,原来
\def\Leftarrowfill@{\arrowfill@\Leftarrow\Relbar\Relbar}
\def\Rightarrowfill@{\arrowfill@\Relbar\Relbar\Rightarrow}
\def\Leftrightarrowfill@{\arrowfill@\Leftarrow\Relbar\Rightarrow}
这三句在 amsmath 中已经有了,楼上那三行多余。
奇怪的是,amsmath 定义了这三句之后,在后续并没有使用到,所以实际中也没见过它的应用,以致于我以为还没被定义。

TOP

闲来无事,细读了一下 amsmath.sty 中关于这类自适应长度的箭头(即 $\vv{XXX}$、$A\xrightarrow[XX]{XXX}B$ 这类)的代码,可知它们都是基于一条命令:\arrowfill@ ,其定义如下:
\def\arrowfill@#1#2#3#4{%
  $\m@th\thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
   \relax#4#1\mkern-7mu%
   \cleaders\hbox{$#4\mkern-2mu#2\mkern-2mu$}\hfill
   \mkern-7mu#3$%
}

关键之处是 \cleaders\hbox{...}\hfill 这行,它将重复 \hbox{...} 来填充给定的空间,这句的前后还各有一个东西,所有东西之间都有负距离,具体来说,\arrowfill@{左}{中}{右}#4(这个#4将会放入style,这里不用管它)得到的是:

左 -9mu 中 -4mu 中 -4mu 中 ... 中 -9mu 右

为什么两边的负距离更大?是因为总长由实际内容而定,需填充的长度一般不为 \hbox{...} 的整数倍,所以两边会余留一点小空白(长度不确定但有上界),因此需要更大的负距离才能确保线不断开。

之后定义向右的可伸长箭头时是这样的:
\def\rightarrowfill@{\arrowfill@\relbar\relbar\rightarrow}
其中 \relbar 是一条短线,因此,可伸长箭头实际上是由短箭头与若干条短线连接起来的,并且连接处是略有重叠的,这就解释了为什么有时看PDF上的长箭头会觉得线的粗浅不均(从楼上上的图也能看出来),当然这跟阅读器有关,打印出来应该不会有这问题。

明白了原理之后,就知道上面用 $\triangleright$ 来做的箭头是有问题的,上面那些测试之所以看起来没问题,完全是运气好,一旦做更细致的测试就会发现不妥:
TIM截图20180814184428.png
2018-8-16 14:16


接下来看看向量箭头和 $A\xrightarrow[XX]{XXX}B$(\xrightarrow)这种箭头的定义。

前者是用一个叫 \overarrow@ 的命令把箭头做上去的,不复杂,暂时懒得讲了,扯扯后者,它里头有一个命令叫 \ext@arrow ,其定义如下:
\def\ext@arrow#1#2#3#4#5#6#7{%
  \mathrel{\mathop{%
    \setbox\z@\hbox{#5\displaystyle}%
    \setbox\tw@\vbox{\m@th
      \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
      \hbox{$\scriptstyle\mkern#3mu{#7}\mkern#4mu$}%
      \copy\z@
    }%
    \hbox to\wd\tw@{\unhbox\z@}}%
  \limits
    \@ifnotempty{#7}{^{\if0#1\else\mkern#1mu\fi
                       #7\if0#2\else\mkern#2mu\fi}}%
    \@ifnotempty{#6}{_{\if0#1\else\mkern#1mu\fi
                       #6\if0#2\else\mkern#2mu\fi}}}%
}

随后定义箭头为:
\newcommand{\xrightarrow}[2][]{\ext@arrow 0359\rightarrowfill@{#1}{#2}}
\newcommand{\xleftarrow}[2][]{\ext@arrow 3095\leftarrowfill@{#1}{#2}}

参数真多,#5 是相应的箭头,#6、#7 是箭头下上方的文字,至于前四个数字,不难看出,#1、#2 是控制上下方文字的左右偏移的,设计者大概觉得,对于右箭头,文字稍微向左偏会好看些,所以先 0 后 3,左箭头则反过来先 3 后 0。

而令我不解的是 #3、#4,对于 \setbox\tw@ 那部分,如果我没理解错,是要获取箭头应有的长度,它将比上下方文字的最大宽度大 (#3+#4)mu(\scriptstyle下),那么 0359 和 030{14} 甚至 03{-100}{114} 应该都是同样的效果,实测发现的确如此,既然只与和有关,何必要两个参数?

明白了原理之后,也可以自己构造这类箭头了,比如说,现在有向左和向右,却没有双向,于是我们可以补充一个:

\newcommand{\xleftrightarrow}[2][]{\ext@arrow 000{17}\leftrightarrowfill@{#1}{#2}}

(为什么我会设成 000{17} ?)

再比如,现在有单线,却没有双线,注意楼上所讲的,\Leftarrowfill@ 等已有定义,只是没被用过,现在正好可以用上(amsmath故意的?):

\newcommand{\xRightarrow}[2][]{\ext@arrow 0359\Rightarrowfill@{#1}{#2}}
\newcommand{\xLeftarrow}[2][]{\ext@arrow 3095\Leftarrowfill@{#1}{#2}}
\newcommand{\xLeftrightarrow}[2][]{\ext@arrow 000{17}\Leftrightarrowfill@{#1}{#2}}

这样,左右双向单线双线共六个箭头,效果如下:
QQ截图20180816150116.png
2018-8-16 15:03


其实,这类箭头已经有宏包统一做过了,它名叫 extarrows ,打开看里面的代码,和上面的差不多,只是都没偏移,全是 0099。
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

A\xrightarrow[a]BC
还能这样的,,,,,,

TOP

搜索相关资料时无意中看到这样一帖:http://bbs.ctex.org/forum.php?mod=viewthread&tid=64298
哪位达人能帮忙定义一个可以带上下文字的\dashrightarrow,万分感谢!
就是像\xrightarrow那样的箭头,上下可以附加文字,只不过把箭头本身改成虚线。

(\dashrightarrow 就是 `\dashrightarrow`)
帖中的楼主在7#想仿照上面那样的做法来定义,发现不行,原因就是他还没弄懂原理。

关键还是那些箭头基于的 \arrowfill@ 命令,上面已经说过,它是将线和箭头略有重叠地连起来,所以用它怎么可能做出虚线呢?

因此我们需要创建一个新的箭头连接命令,不要重叠的,另外,还需要找一个更短的线来用作填充。

更短线的其实已经在 \dashrightarrow 里了,在 amsfonts.sty 中可以找到 \dashrightarrow 的定义是:
\xdef\dashrightarrow{\mathrel{\dabar@\dabar@
                              \mathchar"0\hexnumber@\symAMSa 4B}}
即 \dashrightarrow 是由两个小短线 \dabar@ 和一个小箭头 \mathchar"0\hexnumber@\symAMSa 4B 组成的,故此虚线的填充自然应该用 \dabar@ 。

然后仿照 \arrowfill@ 创建新的命令:
\def\BCDarrowfill@#1#2#3#4{%
  $\m@th\thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
   \relax#4#1%
   \xleaders\hbox{$#4#2$}\hfill
   #3$%
}

其实就是把 \arrowfill@ 的负距离全删掉(BCD 就是不重叠的意思),注意 \dabar@ 本身在线两边就带一点小距离,所以直接将它们放一起即可。
另外我还将 \cleaders 改为 \xleaders ,它们的区别在于填充时的余留空白,前者的空白只在两边,后者的空白将平均地加在各填充物之间(包括两边)。

为了虚线效果更好,我把 \dashrightarrow 中的小箭头提取出来,仿照其定义,定义:

\xdef\justrightarrow{\mathrel{\mathchar"0\hexnumber@\symAMSa 4B}}

(想想如果不提取它,直接用 \dashrightarrow 作为右边会有何问题?)

然后:

\def\rightdasharrowfill@{\BCDarrowfill@{}\dabar@\justrightarrow}
\newcommand{\xrightdasharrow}[2][]{\ext@arrow 030{33}\rightdasharrowfill@{#1}{#2}}

这样,一个向右的可伸长虚线箭头就出来了,效果:

QQ截图20180816170107.png
2018-8-16 17:01


有个明显的缺陷,就是虚线间隙不是恒定的,与上下方文字长度有关,越短越明显,故此我在最后定义时设了 030{33} 把总长搞大。

不过实际中通常上下方文字不会太短,所以问题不大,问题也算是解决了,可惜那边论坛的设置是:50 天以前的主题自动关闭,不再接受新回复……
$\href{https://kuingggg.github.io/}{\text{About Me}}$

TOP

返回列表 回复 发帖