Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

From what I read it seems that align environments are processed twice: the first time for measuring, the second time for actual typesetting. My question is whether one can get access to these measurements?

The goal would be to draw a TikZ overlay graphic whose elements are placed relative the formulas of the align environment.

For the sake of concreteness, suppose I want to draw a dot at the lower right corner of a matrix in an align environment. One might try something like this:

\documentclass{amsart}
\usepackage{tikz}
\newsavebox{\mybox}
\newlength{\myheight}
\newlength{\mywidth}
\begin{document}
\savebox{\mybox}
{
  $\displaystyle
  \left(
  \begin{array}{ccc}
  a_{1,1}&a_{1,2}&a_{1,3}\\
  a_{2,1}&a_{2,2}&a_{2,3}\\
  a_{3,1}&a_{3,2}&a_{3,3}
  \end{array}
  \right)$
}
\settoheight{\myheight}{\usebox{\mybox}}
\settowidth{\mywidth}{\usebox{\mybox}}
\begin{tikzpicture}[overlay,xshift=\mywidth,yshift=-\myheight]
   \filldraw
    (0,0) circle (1.5pt);
\end{tikzpicture}
\begin{align*}
  \left(
  \begin{array}{ccc}
  a_{1,1}&a_{1,2}&a_{1,3}\\
  a_{2,1}&a_{2,2}&a_{2,3}\\
  a_{3,1}&a_{3,2}&a_{3,3}
  \end{array}
  \right)
\end{align*}
\end{document}

Of course this does not work for various reasons, most importantly, because the matrix does not sit in the upper left corner of the align space.

For starters I would also be happy about knowing how to achieve the same for a usual display environment, where it should be easier because the formatting is more predictable.

Edit: egreg's comment below works for me (thanks!).

share|improve this question
2  
Welcome to TeX.SX! Please make your code compilable, starting with \documentclass{...} and ending with \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to help you. Help them help you: remove that one hurdle between you and a solution to your problem. –  Jubobs Nov 5 '13 at 14:43
7  
Look for \tikzmark on the site. –  egreg Nov 5 '13 at 14:47
add comment

1 Answer

up vote 2 down vote accepted

I'm suggesting the tabstackengine package, which is currently available at http://ctan.org/pkg/tabstackengine.

It emulates tabbed, tabular and align type constructions using macros, rather than environments. It completes the task by building stacks for each column, using the stackengine package. These constructions are amenable to being placed in boxes, which many environments are not.

And, as you suggest, it stores details of the complete "array", that can be separately recalled, for use in your tikz overlay. Here's an MWE, and the output explains a bit about what is happening. Comparing the code and output should also help. I am sorry that the documentation is still in the works, which is why the package has not yet been released.

Your question also prompted a few changes to make certain variables global, and thus accessible to follow up coding like tikz. As you will see in my answer, there is one additional piece of info that I don't (yet) store globally (the column widths), but I will work to change that, too.

\documentclass{amsart}
\usepackage{tikz}
\newlength{\myheight}
\newlength{\mywidth}
\newlength{\mydepth}
\newlength{\myhoffset}
\newlength{\myvoffset}
\usepackage{tabstackengine}
\usepackage{scalerel}
\stackMath
\parskip 1em
\begin{document}
First, we start with a stack composed of equally spaced rows (a long
stack), centered on the math axis.  The interbaseline skip is a settable
package parameter, defaulting to \verb|\baselineskip|.

We will add a 2ex horizontal gap between matrix entries.
\def\rowhgap{2ex}%
\setstacktabbedgap{\rowhgap}%
We can then use a (\verb|\mywidth|,\verb|\mydepth|) shift to get the dot
to the lower right corner.

\savestack{\mybox}
{$\parenMatrixstack{
  a_{1,1}&a_{1,2}&a_{1,3}\      a_{2,1}&a_{2,2}&a_{2,3}\      a_{3,1}&a_{3,2}&a_{3,3}
}$}
\settoheight{\myheight}{\mybox}
\settowidth{\mywidth}{\mybox}
\settodepth{\mydepth}{\mybox}
\begin{tikzpicture}[overlay,xshift=\mywidth,yshift=-\mydepth]
   \filldraw
    (0,0) circle (1.5pt);
\end{tikzpicture}%
\mybox

Now, for demonstration, let's say we create something with variable row
height, in which the vertical gap between rows is fixed (default
stacking gap is settable, defaults to 3pt, here I set it to 4pt).
Furthermore, the stack is not centered about the math axis (it's
baseline is at $z=0$).
\def\rowvgap{4pt}
\setstackgap{S}{\rowvgap}

\savestack{\mybox}
{\setstacktabbedgap{2ex}$\scaleleftright[1.7ex]{(}{\tabbedShortstack{
  a_{1,1}&a_{1,2}&a_{1,3}\      a_{2,1}&a_{2,2}&a_{2,3}\      a_{3,1}&a_{3,2}&\dfrac{a_{3,3}}{2}
}}{)}$}
\settoheight{\myheight}{\mybox}
\settowidth{\mywidth}{\mybox}
\settodepth{\mydepth}{\mybox}
\begin{tikzpicture}[overlay,xshift=\mywidth,yshift=-\mydepth]
   \filldraw
    (0,0) circle (1.5pt);
\end{tikzpicture}%
\mybox


\fboxsep=0pt
I have access to the struts for each row\    Row 1: \fbox{$\TABstrut{i}$}
Row 2: \fbox{$\TABstrut{ii}$}
Row 3: \fbox{$\TABstrut{iii}$}

Number of cells in row 1: \TABcells{i}

TAB Cell (iii,3): $\TABcell{iii}{3}$

With that info, I can now (almost) shift things to arbitrary elements.
The one element missing is I don't (yet) store the width of the
individual columns, though in this case, each column element is of equal
width (to its vertical neighbors) so I can get away with it.

To demonstrate, I place the dots at the bottom right of elements (3,3)
and (2,2)

\settoheight{\myheight}{\mybox}
\settowidth{\mywidth}{\mybox}
\settodepth{\mydepth}{\mybox}
\setlength{\myvoffset}{\heightof{$\TABstrut{iii}$}+
                      \depthof{$\TABstrut{iii}$}+\rowvgap}
\setlength{\myhoffset}{1.7ex+% ALLOWED WIDTH OF RIGHT PAREN
                       \widthof{$\TABcell{iii}{3}$}+
                       +\rowhgap}
\begin{tikzpicture}[overlay,xshift=\mywidth,yshift=-\mydepth]
   \filldraw
    (-1.7ex,0) circle (1.5pt);
   \filldraw
    (-\myhoffset,\myvoffset) circle (1.5pt);
\end{tikzpicture}%
\mybox

\end{document}

enter image description here

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.