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.

How can I ensure that consecutive diagonal arrows in a tikz-cd commutative diagram spanning many rows and columns lie on a straight line (as is automatically the case for consecutive horizontal arrows)?

I suspect it would be enough to force all the center nodes to lie on a regular grid, but I don't know how to achieve that.

Most minimal example I can think of where this occurs:

\begin{tikzcd}
  A  \arrow{dr}{\alpha} & B \arrow{dr}{\beta} & C & D \\
  A & B \times B \times B \arrow{dr}{\gamma} & C \arrow{dr}{\delta} & D \\
  A & B & C & D
\end{tikzcd}
share|improve this question
1  
Do you have an MWE that you can provide? –  Peter Jansson Jan 3 '13 at 10:57
    
I cannot install tikz-cd to test this, but, perhaps if you add the option [on grid] to your tikzcd environment that would do it? –  JLDiaz Jan 3 '13 at 11:06
    
Sadly [on grid] has no effect. –  Dan Jan 3 '13 at 11:16
add comment

2 Answers

up vote 5 down vote accepted

The option on grid won’t work because internally the diagrams are built with a \matrix.

But the original /tikz/column sep (and /tikz/row sep) styles understand the option between origins.

The problem is that tikz-cd does not provide a (good) hook to add between origins to the already defined separators or to an arbitrary distance (e.g. column sep={between origins}, column sep={normal,between origins}, or column sep={10ex,between origins}).

My solution provides

  • a re-definition of the original \tikzcd@sep#1#2 macro that is used by tikz cd to set the separators and to sort out the likes of column sep=<named distance>;
  • a re-definition of the original /tikz/commutative diagrams/column sep and /tikz/commutative diagrams/row sep keys that accomodate the changes to \tikzcd@sep; and
  • /tikz/commutative diagrams/bo row sep and
  • /tikz/commutative diagrams/bo col sep keys that works (kind of) like the original.

“Kind of” because I opted for a factor of 1.7 to the named distances (tiny, small, scriptsize, normal, large, and huge) because the distances are now smaller due to the fact that the node widths do not affect the separator (just like on grid would).

Code

\documentclass[tikz]{standalone}
\usepackage{tikz-cd}
\makeatletter
\pgfqkeys{/tikz/commutative diagrams}{
  row sep/.code={\tikzcd@sep{row}{#1}{}},
  column sep/.code={\tikzcd@sep{column}{#1}{}},
  bo row sep/.code={\tikzcd@sep{row}{#1}{between origins}},
  bo column sep/.code={\tikzcd@sep{column}{#1}{between origins}},
  bo column sep/.default=normal,
  bo row sep/.default=normal,
}
\def\tikzcd@sep#1#2#3{% re-defintion of original package macro!
  \pgfkeysifdefined{/tikz/commutative diagrams/#1 sep/#2}%
    {\pgfkeysalso{/tikz/#1 sep={\ifx\\#3\\1*\else1.7*\fi\pgfkeysvalueof{/tikz/commutative diagrams/#1 sep/#2},#3}}}%
    {\pgfkeysalso{/tikz/#1 sep={#2,#3}}}}
\makeatother
\begin{document}
\begin{tikzcd}[bo column sep]
  A \arrow{dr}{\alpha} & B \arrow{dr}{\beta}                    & C                    & D \\
  A                    & B \times B \times B \arrow{dr}{\gamma} & C \arrow{dr}{\delta} & D \\
  A                    & B                                      & C                    & D
\end{tikzcd}
\end{document}

Output

enter image description here

A manual way perhaps?

A few other options in this example are

  • left- and right-lapping the biggest node (mathtools required):

    \mathllap{B \times} B \mathrlap{\times B}
    
  • settings a fixed node width that is the maximum of all:

    text width=\widthof{$B \times B \times B$}
    

Code

\documentclass[tikz]{standalone}
\usepackage{tikz-cd} \usepackage{mathtools}
\begin{document}

\begin{tikzcd}
  A  \arrow[shorten >=8pt]{dr} & B \arrow{dr} & C & D \\
  A & \mathllap{B \times} B \mathrlap{\times B} \arrow{dr} & C \arrow{dr} & D \\
  A & B & C & D
\end{tikzcd}

\begin{tikzcd}[column sep=-1ex,cells={nodes={align=center,text width=\widthof{$B \times B \times B$}}}]
  A  \arrow{dr} & B \arrow{dr} & C & D \\
  A & \mathllap{B \times} B \mathrlap{\times B} \arrow{dr} & C \arrow{dr} & D \\
  A & B & C & D
\end{tikzcd}
\end{document}

Output

enter image description here

enter image description here

share|improve this answer
    
What happens if you put every matrix/.append style={...} in the optional argument to the \begin{tikzcd}? Does that provide the right hook? –  Loop Space Jan 3 '13 at 12:00
    
@AndrewStacey No, it does not. The problem, I guess, is that between origins is not even recognized in /tikz/commutative diagrams/column sep={10ex,between origins}. –  Qrrbrbirlbel Jan 3 '13 at 12:07
    
At least you can make it local with \makeatletter \tikzset{enforce orig/.code={\let\pgf@matrix@fixedfalse\pgf@matrix@fixedtrue}} \makeatother and use that option. –  percusse Jan 3 '13 at 13:10
    
This works well with labels on the arrows too. Just out of interest, why does the explicit &[between origins] version require different column/row spacing settings to get the same result as \let\pgf@matrix@fixedfalse\pgf@matrix@fixedtrue? –  Dan Jan 3 '13 at 13:31
    
@Dan I can’t follow. Both solutions had [column sep=10ex]] added to the tikzcd environment? Anyway, I have updated my answer with a hopefully more appropriate way to set between origins. (The manual way &[between origins] still works.) –  Qrrbrbirlbel Jan 3 '13 at 13:40
show 2 more comments

Try specifying the text width, etc., and alignment for the nodes. To stop this affecting labels on the arrows, you should put this inside the specification for the cells. For example, as follows:

enter image description here

\documentclass{article}

\usepackage{tikz,tikz-cd}

\begin{document}

\begin{tikzcd}[/tikz/cells={/tikz/nodes={shape=asymmetrical
  rectangle,text width=1.5cm,text height=2ex,text depth=0.3ex,align=center}}]
  A  \arrow{dr}{t} & B_X \arrow{dr}{p} & C & D \\
  A & B \arrow{dr} \times B \times B & C^Y \arrow{dr} & D \\
  A & B & C & D
\end{tikzcd}

\end{document}
share|improve this answer
    
I guess that to do this automatically one would have to measure all the columns, store that information in the aux file, and read it back in at the start of the table. –  Loop Space Jan 3 '13 at 11:50
    
Thanks! This is a great improvement, but it causes problems when the arrows are labelled, as the position of the label text is affected. (I tried to add an example here but it seems that's not possible in a comment.) –  Dan Jan 3 '13 at 11:55
    
OK I have updated my answer so only the cells get affected. –  Andrew Swann Jan 3 '13 at 12:28
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.