目标是可以按照以下方式在数学模式下标记元素的代码:
而不必手动将每个单词的每个字母定位为 tikz 中的节点。最好除了 stacks 插件之外,不必调用 tikz,但如果在最后调用也没问题。
两种类型的对角线作为宏是具有挑战性的部分。需要一个宏或其他东西来将单词转换为
\macro_name{word}
沿对角线生长,从顶部向右生长,或从底部向左生长,如上两个例子所示。然后它就可以用于Steven Segletes 的 tabstackengine 包在下面的 MWE 中:
\documentclass{minimal}
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{tabstackengine}
\usepackage{mathtools}
\stackMath
\makeatletter
\renewcommand\TAB@delim[1]{\scriptstyle#1}
\def\req{\protect\rotatebox{90}{$\scriptstyle=$}}
\def\rne{\protect\rotatebox{90}{$\scriptstyle\ne$}}
\makeatother
\begin{document}
\[
\setstackgap{L}{.6\baselineskip}\setstacktabulargap{0pt}\TABbinary
\tabularCenterstack{rcl}{
&\mathclap{alpha}& &\mathclap{beta}&\\ &\req& &\req& \\ (&A& , &B&) \hspace{1mm}= \hspace{1mm} F\\
&\rne&\\ &\mathclap{(D , B)}&}
\]
% BTW, for some reason, tex cannot compile if <<\mathclap{(D , B)}>> is replaced with <<\mathclap{\overbrace{(D , B)}}>> or <<\mathclap{\underbrace{(D , B)}}>> but this is a different question, no?
\end{document}
编辑:我刚刚注意到,如果只控制垂直间距,看起来会很奇怪。需要有一个参数来在每个对角线上水平间隔字母。这可能吗?(当用手写时,我观察到除了垂直位移(目前已在下面的答案中控制)之外,字母在水平方向上放置得更近,以使其更易读。)
答案1
我不能说我很喜欢这个外观,但它确实符合你提到的第一种形式。如果你真的想要,另一种形式也可以实现。对角线文本的关键是递归使用\brlap
,即右下角的圈数,每圈的垂直偏移量目前缩减为 的 38% \baselineskip
。
已编辑,允许通过 设置字母之间的水平字距\myhkern
,通过 设置连续字母的垂直偏移\myvgap
。此外,\diagunder
采用可选参数(默认 =)定义旋转并放置在第一个参数下方的字符。设置为,以便从默认符号所在的[]
高度开始标签。=
REEDITED 提供\diagunder
和\diagover
,语法相同。请注意,对角线文本保留其高度,但被视为宽度为零,因此您会注意到(A,B)
在上下堆栈中都垂直排列。
\documentclass{article}
\usepackage{stackengine, graphicx}
\def\myhkern{.8pt}
\def\myvgap{.38\baselineskip}
\def\stacktype{L}
\newcommand\diagunder[3][\raisebox{-5pt}{$=$}]{%
\ifx\relax#1\relax%
\stackunder{$#2$}{\expandafter\angletext#3\relax}%
\else
\stackunder{$#2$}{\stackunder[.7\baselineskip]{\rotatebox{90}{$#1$}}{%
\expandafter\angletext#3\relax}}%
\fi
}
\def\angletext#1#2\relax{\small\setstackgap{L}{\myvgap}%
\kern\myhkern#1\angletextB#2\relax}
\def\angletextB#1#2\relax{%
\brlap{\kern\myhkern#1\ifx\relax#2\relax\else\angletextB#2\relax\fi}%
}
\newcommand\diagover[3][\raisebox{-5pt}{$=$}]{%
\ifx\relax#1\relax%
\stackon{$#2$}{\expandafter\upangletext#3\relax}%
\else
\stackon{$#2$}{\stackon[.9\baselineskip]{\rotatebox{90}{$#1$}}{%
\expandafter\upangletext#3\relax}}%
\fi
}
\def\upangletext#1#2\relax{\small\setstackgap{L}{\myvgap}%
\def\myslant{\kern\myhkern#1}\upangletextB#2\relax}
\makeatletter
\def\upangletextB#1#2\relax{%
\global\protected@edef\myslant{\tllap{\myslant}\kern\myhkern#1}%
\ifx\relax#2\relax\myslant\else\upangletextB#2\relax\fi%
}
\makeatother
\begin{document}
$(\diagunder{A}{alpha},\diagunder{B}{beta})$ versus
$(\diagunder[]{A}{alpha},\diagunder[]{B}{beta})$
$(\diagover{A}{alpha},\diagover{B}{beta})$ versus
$(\diagover[]{A}{alpha},\diagover[]{B}{beta})$
\end{document}
适应 OP 的完整 MWE(我的逻辑必须发生一些变化,因为上面的 MWE 是在文本模式下堆叠的,而 OP 的完整示例是在数学模式下堆叠的):
\documentclass{minimal}
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{tabstackengine}
\usepackage{mathtools}
\stackMath
\makeatletter
\renewcommand\TAB@delim[1]{\scriptstyle#1}
\def\req{\protect\rotatebox{90}{$\scriptstyle=$}}
\def\rne{\protect\rotatebox{90}{$\scriptstyle\ne$}}
\makeatother
\def\myhkern{.3pt}
\def\myvgap{.3\baselineskip}
\def\stacktype{L}
\def\mss#1{\mathrm{\scriptscriptstyle#1}}
\newcommand\diagunder[3][\scriptstyle=]{%
\ifx\relax#1\relax%
\stackunder{\scriptstyle#2}{\expandafter\angletext#3\relax}%
\else
\stackunder{\scriptstyle#2}{\stackunder[.7\baselineskip]{%
\rotatebox{90}{$#1$}}{\expandafter\angletext#3\relax}}%
\fi
}
\def\angletext#1#2\relax{\setstackgap{L}{\myvgap}%
\kern\myhkern\mss{#1}\angletextB#2\relax}
\def\angletextB#1#2\relax{%
\brlap{\kern\myhkern\mss{#1}\ifx\relax#2\relax\else\angletextB#2\relax\fi}%
}
\newcommand\diagover[3][\scriptstyle=]{%
\ifx\relax#1\relax%
\stackon{\scriptstyle#2}{\expandafter\upangletext#3\relax}%
\else
\stackon{\scriptstyle#2}{\stackon[.7\baselineskip]{\rotatebox{90}{$#1$}}{%
\expandafter\upangletext#3\relax}}%
\fi
}
\def\upangletext#1#2\relax{\setstackgap{L}{\myvgap}%
\def\myslant{\kern\myhkern\mss{#1}}\upangletextB#2\relax}
\makeatletter
\def\upangletextB#1#2\relax{%
\global\protected@edef\myslant{\tllap{\myslant}\kern\myhkern\mss{#1}}%
\ifx\relax#2\relax\myslant\else\upangletextB#2\relax\fi%
}
\makeatother
\begin{document}
\[
\setstackgap{L}{.6\baselineskip}\setstacktabulargap{0pt}\TABbinary
\tabularCenterstack{rcl}{
(&\diagover{A}{alpha}& , &\diagover{B}{beta}&) \hspace{1mm}= \hspace{1mm} F\\
&\rne&\\ &\mathclap{(\diagunder[]{D}{delta} , B)}&}
\]
\end{document}
如果你决定要在\textstyle
而不是中进行此操作\scriptstyle
(因为许多数学间距,例如 周围=
更自然),那么这里就是你为此转换的 MWE。
\documentclass{minimal}
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{tabstackengine}
\usepackage{mathtools}
\stackMath
\makeatletter
\def\req{\protect\rotatebox{90}{$=$}}
\def\rne{\protect\rotatebox{90}{$\ne$}}
\makeatother
\def\myhkern{.3pt}
\def\myvgap{.3\baselineskip}
\def\stacktype{L}
\def\mss#1{\mathrm{\scriptscriptstyle#1}}
\newcommand\diagunder[3][=]{%
\ifx\relax#1\relax%
\stackunder[.8\baselineskip]{#2}{\expandafter\angletext#3\relax}%
\else
\stackunder[.8\baselineskip]{#2}{\stackunder[.8\baselineskip]{%
\rotatebox{90}{$#1$}}{\expandafter\angletext#3\relax}}%
\fi
}
\def\angletext#1#2\relax{\setstackgap{L}{\myvgap}%
\kern\myhkern\mss{#1}\angletextB#2\relax}
\def\angletextB#1#2\relax{%
\brlap{\kern\myhkern\mss{#1}\ifx\relax#2\relax\else\angletextB#2\relax\fi}%
}
\newcommand\diagover[3][=]{%
\ifx\relax#1\relax%
\stackon[.8\baselineskip]{#2}{\expandafter\upangletext#3\relax}%
\else
\stackon[.8\baselineskip]{#2}{\stackon[.8\baselineskip]{\rotatebox{90}{$#1$}}{%
\expandafter\upangletext#3\relax}}%
\fi
}
\def\upangletext#1#2\relax{\setstackgap{L}{\myvgap}%
\def\myslant{\kern\myhkern\mss{#1}}\upangletextB#2\relax}
\makeatletter
\def\upangletextB#1#2\relax{%
\global\protected@edef\myslant{\tllap{\myslant}\kern\myhkern\mss{#1}}%
\ifx\relax#2\relax\myslant\else\upangletextB#2\relax\fi%
}
\makeatother
\begin{document}
\[
\setstackgap{L}{.85\baselineskip}\setstacktabulargap{0pt}\TABbinary
\tabularCenterstack{rcl}{
(&\diagover{A}{alpha}& , \diagover{B}{beta}) = F\\
&\rne&\\ &\mathclap{(\diagunder[]{D}{delta} , B)}&}
\]
\end{document}
答案2
有趣且递归:
$(\setstackgap{S}{-1pt}
\DiagUnder<$(\DiagUnder{D}{delta},B)$>{
\setstackgap{S}{3pt}%
\DiagUnder<\NEgal>{\DiagOn<\Egal>{A}{alfpha}}{}
}{},\DiagOn<\NEgal>{B}{beta})=F$
\documentclass{article}
\usepackage{tikz,xstring,ifthen,stackengine,xparse}
\usetikzlibrary{calc}
\def\R{String}
\def\N{0}
\newsavebox{\MyBox}
\makeatletter
\NewDocumentCommand{\DiagUnder}{
d<>
O{(-45:.8em)}
m
m
D<>{l}
}{%
\def\stackalignment{#5}%
\def\useanchorwidth{T}%
\def\@R{#4}%
\def\@N{0}%
\savebox\MyBox{
\begin{tikzpicture}[baseline=(x0),
every node/.style={inner sep=0pt,outer sep=0pt}]
\node (x0) at (0,-.16) {} ;
\whiledo{\NOT\equal{\@R}{}}{%
\StrLeft{\@R}{1}[\@L]
\StrGobbleLeft{\@R}{1}[\@R]
\node at ($(x0) + \@N*#2 $) {\strut\@L} ;
\pgfmathtruncatemacro\@N{\@N+1}
}
\end{tikzpicture}
}
\IfNoValueTF{#1}{% sans
\stackunder{$#3$}{\hspace{-3pt}\usebox{\MyBox}}%
}{% avec
\def\stackalignment{c}%
\stackunder{$#3$}{%
\def\stackalignment{l}%
\setstackgap{S}{1pt}%
\stackunder{%
\makebox[1em]{#1}}{\hspace{-2pt}\usebox{\MyBox}}}%
}%
}%
\NewDocumentCommand{\DiagOn}{
d<>
O{(-45:.8em)}
m
m
D<>{r}
}{%
\def\stackalignment{#5}%
\def\useanchorwidth{T}%
\setstackgap{S}{2pt}
\def\@R{#4}%
\def\@N{0}%
\savebox\MyBox{
\begin{tikzpicture}[baseline=(x0),
every node/.style={inner sep=0pt,outer sep=0pt}]
\node (x0) at (0,.16) {} ;
\whiledo{\NOT\equal{\@R}{}}{%
\StrLeft{\@R}{1}[\@L]
\StrGobbleLeft{\@R}{1}[\@R]
\node at ($(x0) + \@N*#2 $) {\strut\@L} ;
\pgfmathtruncatemacro\@N{\@N+1}
}
\end{tikzpicture}
}
\IfNoValueTF{#1}{% sans
\stackon{$#3$}{\hspace{-2pt}\usebox{\MyBox}}%
}{% avec
\def\stackalignment{c}%
\stackon{$#3$}{%
\def\stackalignment{r}%
\setstackgap{S}{-1pt}%
\stackon{%
\makebox[1em]{#1}}{\usebox{\MyBox}}}%
}%
}%
\makeatother
\newcommand{\Egal}{\,\rotatebox{90}{$=$}}
\newcommand{\NEgal}{\rotatebox{90}{$\neq$}}
\begin{document}
Bob$(\DiagUnder<\Egal>{A}{Diagonale},
\DiagUnder<\NEgal>[(-35:.9em)]{B}{Diagonale},
\DiagUnder[(-.2,.1)]{C}{Diagonale},
\DiagOn<\Egal>{D}{Diagonale},
\DiagOn<\NEgal>[(115:-.9em)]{E}{Diagonale},
\DiagOn[(.2,.1)]{F}{Diagonale}<l>)$
\end{document}