# diagonal text in math mode w/ vertical equality

The goal is a code where one can label elements in math mode in the following way:

without having to manually position each letter of each word as a node in tikz. Preferably, other than the stacks plugin, tikz does not have to be invoked, but no problem if it is in the end.

The two types of diagonals as a macro is the challenging bit. A macro or something is needed to convert a word in

\macro_name{word}


to a diagonal, growing right from the top, or growing left from the bottom, like in the two examples above. Then it can be used, w/ Steven Segletes's tabstackengine package in the MWE below:

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


EDIT: I just noticed that it looks strange if only vertical spacing is controlled. There needs to be a parameter to space the letters horizontally in each diagonal. Is that possible? (When writing by hand, I observe the letters are placed CLOSER together horizontally to make it more readable in addition to the vertical displacement which is already presently controlled in the answer below.)

-
It would be easier to use \rotatebox from the graphics package. You could create a command to place each letter with a linearly increasing or decreasing height using \raisebox. –  John Kormylo May 27 '14 at 3:23
Spacing will probably never look good with variable-width upright characters along a diagonal. This is because your eye expects alignment of the bottom center of each character along the diagonal, and equal spacing along the vertical and variable spacing along the horizontal: clearly, there's a contradiction. Either rotate the characters or use fixed-width font. –  Joce May 27 '14 at 11:57
None of the answers give you satisfaction ? Is there something to achieve ? –  Tarass May 28 '14 at 18:49
I made a bounty to reward the answer. Was traveling so I didn't get to it sooner. I think I can only award the bounty after 23 hours. Great answers! –  Guido Jorg Jun 2 '14 at 1:11

I can't say I'm enamored of the look, but it does the first form you mention. The other can be done if you really want it, still. The key for the diagonal text is a recursive use of \brlap, which is a bottom-right lap, with the vertical offset of each lap scaled back, currently, to 38% of \baselineskip.

EDITED to allow horizontal kerning between letters to be set by \myhkern and vertical offset of successive letters to be set by \myvgap. In addition, \diagunder takes an optional argument (default =) defining the character rotated and placed below the first argument. Set as [] in order to begin the labels at the height where the default = sign would have been.

REEDITED to provide both \diagunder and \diagover, with identical syntax. Note that the diagonal text retains its height, but is perceived to have zero width, so that you will notice that (A,B) line up vertically in both over and under stacks.

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


Adapting to the full MWE of the OP (some changes to my logic had to occur because my MWE above was stacked in text mode, while the OP's full example was stacked in math mode):

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


And if you decided that you wanted to do it in \textstyle rather than \scriptstyle (since a lot of the math spacing, e.g. around = is more natural), then here is your MWE converted for that.

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

-
@GuidoJorg Please see my revision to try to accommodate your wishes. –  Steven B. Segletes May 27 '14 at 10:37
@GuidoJorg Please see my REEDIT, which allows bot \diagover and \diagunder. –  Steven B. Segletes May 27 '14 at 16:07
The over B equal sign seams to be a little left in the last example ;-) All this work diserve a bounty ! –  Tarass May 27 '14 at 19:03
@Tarass Indeed, the equal is shifted only because it was a pure rotation of the original =. There needs to be a shift to compensate, which I leave to the OP... or maybe I'll get to it. –  Steven B. Segletes May 27 '14 at 19:07
@Tarass ...Since \ifx does a comparison without expansion, the test \ifx\relax#1\relax... will only be true if #1 is empty, in which case nothing stray is printed out. But if #1 is anything other than empty or \relax, the test will be false, and the \else clause will be executed. If #1 happens to be \relax, the test is true, but only the third \relax gets executed and does...nothing. Easy, huh? –  Steven B. Segletes May 27 '14 at 19:49

Fun and reccursive :

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

-
This is a nice answer too. Wish I could accept both answers :) –  Guido Jorg Jun 2 '14 at 0:56