1

In my commutative diagram in my MWE, I want to keep the arrow lengths fixed in such a way that the lengths of elements (math terms or equations) should not affect the individual arrow lengths. Here's my MWE:

\documentclass{report}

\usepackage{amsmath}
\usepackage{tikz-cd}

\begin{document}

$$    
\begin{tikzcd}
        \Psi \arrow[d, "\partial_a"]\arrow[r, "U"] & \Psi' \arrow[d, ]\\
        \partial_a \Psi \arrow[r, "U"] & (\partial_a\Psi)' = U(\partial_a\Psi)
\end{tikzcd}
$$

\end{document}

I am getting the output as follows:

enter image description here

But my desired output is: enter image description here

How can I do it?

3
  • 1
    I suggest using anchor = base east for the left column and anchor = base west for the right column and then using arrows that are strightly going down. See Case 1 in my answer to a similar question. Mar 19 at 10:55
  • 1
    For more on this kind of alignment: tex.stackexchange.com/q/664419 and related. Mar 19 at 13:37
  • 1
    For arrows that should end at the same length you need to make each column's node have the same width as the widest of them, for example /tikz/column 1/.append style={align=center, text width=width("$\partial_a \Psi$")} and width("$(\partial_a\Psi)'$") for the second column while \mathrlaping {} = U(\partial_a\Psi). By the way, the vertical arrows have different lengths, too, it's just not as noticable. Mar 20 at 16:57

4 Answers 4

2

For the particular case,

\documentclass{report}

\usepackage{amsmath,mathtools}
\usepackage{tikz-cd}

\begin{document}

\noindent X\dotfill X

\[
\begin{tikzcd}
  \Psi \arrow[d, "\partial_a"]\arrow[r, "U"] & \Psi' \arrow[d, ]\\
  \partial_a \Psi \arrow[r, "U"] & (\partial_a\Psi)'\mathrlap{{} = U(\partial_a\Psi)}
\end{tikzcd}
\hphantom{{} = U(\partial_a\Psi)}
\]

\end{document}

The excess part is typeset in a zero width box sticking to the right. The same material is added as a phantom to get centering correct.

Please, be aware that $$ is not good in LaTeX and it has been so since the first release, around 1982 (which makes 40 years or so).

enter image description here

4
  • In your code, instead of \mathrlap{{} = U(\partial_a\Psi)}, I can use \makebox[0pt][l]{$= U\Psi$} to generate the same kind of output, right? Which one should be used? And what's the need of using \hphantom{{} = U(\partial_a\Psi)}?
    – raf
    Mar 19 at 16:32
  • 1
    @raf With \mathrlap you don't need to reenter math mode, that's all, but you should use \makebox[0pt][l]{${}=U\Psi$} for the correct spacing. The phantom is to get the correct horizontal centering of the diagram. OK, in my other answer you found I used \makebox: maybe it depends on my mood. ;-)
    – egreg
    Mar 19 at 17:19
  • Thanks you. By the way, I didn't notice earlier that the other answer (tex.stackexchange.com/a/664442/114006) is also yours.
    – raf
    Mar 19 at 19:19
  • I am quite satisfied using your code. For a better understanding of what I desired initially, I updated the photo in my question.
    – raf
    Mar 20 at 10:34
2

Here is a code that uses the macros \mathllap and \mathrlap of the package mathtools. It should be useful in several situations.

\documentclass{report}

\usepackage{mathtools}
\usepackage{tikz-cd}

\begin{document}


\section*{KO}

\[   
\begin{tikzcd}
        \Psi \arrow[d, "\partial_a"]\arrow[r, "U"] & \Psi' \arrow[d, ]\\
        \partial_a \Psi \arrow[r, "U"] & (\partial_a\Psi)' = U(\partial_a\Psi)
\end{tikzcd}
\]

\section*{OK}

\[
\begin{tikzcd}
      \mathllap{\Psi}  
            \arrow[d, "\partial_a", shift right=4pt]
            \arrow[r, "U"]
    & \mathrlap{\Psi'}
            \arrow[d, shift left=4pt]
    \\
      \mathllap{\partial_a \Psi}
            \arrow[r, "U"]
    & \mathrlap{(\partial_a\Psi)' = U(\partial_a\Psi)}
\end{tikzcd}
\]

\section*{Another use}

\[
\begin{tikzcd}
      \mathllap{(\partial_a\Psi)' = U(\partial_a\Psi)}  
            \arrow[d, "\partial_a", shift right=4pt]
            \arrow[r, "U"]
    & \mathrlap{(\partial_a\Psi)' = U(\partial_a\Psi)}
            \arrow[d, "\partial_a", shift left=4pt]
    \\
      \mathllap{\partial_a \Psi}
            \arrow[r, "U"]
    & \mathrlap{(\partial_a\Psi)' = U(\partial_a\Psi)}
\end{tikzcd}
\]

\end{document}

The corresponding output.

enter image description here

2
  • For a better understanding of what I desired, I updated the photo in my question.
    – raf
    Mar 20 at 10:35
  • 1
    It should be ok now. I hope....
    – projetmbc
    Mar 20 at 16:04
2

You habe two things you want to solve here:

  1. The arrows should have the same length. (Only the horizontal ones?)

    The easiest solution to this is to make all the nodes in each column have the same width.

  2. And the right-hand side of one of your cells should not be part of this same width.

    In this simple case, this is easiest achieved with a third column that has no column separation to its predecessor.

For 2. I'm using the key no csep which takes a list of columns that shouldn't have a column separation to their successors. Here, you just want no csep = 2.

For 1. you can use set widest math that is a list of the widest content of each column, here: set widest math={\partial_a \Psi, (\partial_a\Psi)'}.

For other solutions for 2. take a look at another answer of mine where I'll explore some ideas. If handling an extra column is not to your liking that answer's solution 2. and 3. are more appropriate then.

For other solution for 1. you can directly have TikZ measure each node and apply the needed minimum width for it on the next run.

If you don't actually want the column centered, you can actually just use Case 1 of this answer.


In the code below, I've commented an arrow that connects the north anchors of the second row's nodes to show that even the vertical arrows are not the same length.

Code

\documentclass{report}
\usepackage{mathtools, tikz-cd}
\tikzcdset{
  no csep/.style={/utils/temp/.style={/tikz/column ##1/.append style={
    column sep=-2*(\pgfkeysvalueof{/pgf/inner xsep})}},/utils/temp/.list={#1}},
  set widest math/.style={
    /utils/exec=\def\pgfmathcounter{0},
    /utils/temp/.code=\edef\pgfmathcounter{\pgfinteval{\pgfmathcounter+1}}%
      \pgfkeysalso{/tikz/column \pgfmathcounter/.append style={
        align=center, text width={width("$##1$")}}},
    /utils/temp/.list={#1}}}
\usepackage[showframe, pass]{geometry}
\begin{document}
\[
\begin{tikzcd}[set widest math={\partial_a \Psi, (\partial_a\Psi)'}, no csep=2]
  \Psi                   \arrow[d, "\partial_a"] \arrow[r, "U"]
& \Psi'                  \arrow[d] \\
  \partial_a \Psi        \arrow[r, "U"]
& (\partial_a\Psi)'
& {} = U(\partial_a\Psi)
%  \ar[help lines, start anchor=north, end anchor=north, l]
\end{tikzcd}
\]
\end{document}

Output

enter image description here

1

I have used another strategy that is into the code below using \mkern and xshift.

\documentclass[a4paper,12pt]{article}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}[column sep=0pt]
\mkern2mu\Psi \arrow[r, "U",{xshift=4pt}] \arrow[d, "\partial_a"] &    \Psi' \arrow[d] \\
\partial_a \Psi \arrow[r, "U",end anchor={[xshift=6.67em]}]{r}   & \mkern115mu  (\partial_a\Psi)' = U(\partial_a\Psi)
\end{tikzcd}
\end{document}

enter image description here

6
  • The arrow-to-node separation is smaller on the right side than on the left side in the rows. Can you fix it?
    – raf
    Mar 19 at 13:33
  • @raf Hi, can you see the changes of my code? I hope to have understood.
    – Sebastiano
    Mar 20 at 9:05
  • Thank you. Actually, my desired output is the combination of your answer and @egreg's answers so that the element positioning is like his output and the arrow lengths are like yours.
    – raf
    Mar 20 at 9:16
  • 1
    @raf I have seen your drawing and I see that is the same. :-(. I think that the last my code is better than to that of the beginning.
    – Sebastiano
    Mar 20 at 10:17
  • 1
    @raf I have done other changhes. Can you see, please? See if now is better than before.
    – Sebastiano
    Mar 20 at 13:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .