0

Is it possible for tikzcd to intelligently place labels? For example, when drawing the following diagram,

\begin{tikzcd}[row sep=large]
& C 
\arrow[ld, "f"] 
\arrow[rd, "g"] 
\arrow[d, "!h" , dashed] & \\
A 
& A\times B 
\arrow[r, "\pi_B"] 
\arrow[l, "\pi_A"]          
& B
\end{tikzcd}

enter image description here

the labels look ugly. I have to manually swap sides, with

\begin{tikzcd}[row sep=large]
& C 
\arrow[ld, "f", swap] 
\arrow[rd, "g"] 
\arrow[d, "!h" , dashed] & \\
A 
& A\times B 
\arrow[r, "\pi_B"] 
\arrow[l, "\pi_A", swap]          
& B
\end{tikzcd}

Is there a more intelligent way to do this?

2
  • 2
    Any reason why you don't accept the answers from many of your previous questions? Commented Feb 3, 2021 at 8:19
  • @Dr.ManuelKuehner That's my bad, I often forget. Commented Feb 3, 2021 at 21:52

1 Answer 1

3

The labels are placed intelligently, always to the left of the arrow. That's the default direction of the TikZ auto option that's installed by TikZ-CD.

Though, it only knows left and right, meaning the nodes along a path are placed either to the left or the right of the path. (The swap (') key just checks which one's active and installs the other one.)

I don't like how this is implemented in the original code but we can extend this either way to also accept

  • auto = above
    where the nodes are always placed above the path (or to the right for vertical lines) and
  • auto = below
    where the nodes are always placed below the path (or to the left for vertical lines).

The swap key is rewritten so that it also can deal with these new additions.


This is still some dumb kind of intelligence since it will never be able to check whether it looks good or if the node is on the “outside” of your diagram.

You could of course create an automatic placement that places the nodes above the paths when they're diagonal and below it when it's a purely horizontal path but the more complex your diagrams get the more these will not be helpful, in my opinion.

For example, in the second diagram which I believe to be equivalent to the first all the nodes should be on the other side so that they're on the “outer” side of the diagram but TikZ won't be able to figure that out without tremendous help from the outside (i.e. another tool that analyzes the diagram).

This way, the nodes are at least consistenzly placed above or below a path which I think will help a lot. You will always look at these diagram once before you're going to be finished with them.

Code

\documentclass[tikz,convert]{standalone}
\usetikzlibrary{cd}
\makeatletter
\tikzset{
  swap/.style={swap auto/.expand once=\tikz@auto@anchor@direction},
  swap auto/.is choice,
  /utils/temp/.style args={#1=#2}{
    swap auto/#1/.code=\def\tikz@auto@anchor@direction{#2}},
  /utils/temp/.list={left=right, right=left, above=below, below=above}
}
\def\tikz@install@auto@anchor@above{%
  \let\tikz@do@auto@anchor\tikz@auto@anchor@on
  \def\tikz@auto@anchor@direction{above}}
\def\tikz@auto@anchor@above{%
  \tikz@auto@pre\tikz@auto@anchor@above@\tikz@auto@post}
\def\tikz@install@auto@anchor@below{%
  \let\tikz@do@auto@anchor\tikz@auto@anchor@on
  \def\tikz@auto@anchor@direction{below}}
\def\tikz@auto@anchor@below{%
  \tikz@auto@pre\tikz@auto@anchor@below@\tikz@auto@post}
\def\tikz@auto@anchor@above@{%
  \def\tikz@anchor{south}%
  \ifdim\pgf@x>0.05pt
    \ifdim\pgf@y>0.05pt
      \def\tikz@anchor{south east}%
    \else\ifdim\pgf@y<-0.05pt
      \def\tikz@anchor{south west}%
    \fi\fi
  \else\ifdim\pgf@x<-0.05pt
    \ifdim\pgf@y>0.05pt
      \def\tikz@anchor{south east}%
    \else\ifdim\pgf@y<-0.05pt
      \def\tikz@anchor{south east}%
    \fi\fi
  \else
    \ifdim\pgf@y>0pt
      \def\tikz@anchor{east}%
    \else
      \def\tikz@anchor{west}%
    \fi
  \fi\fi
}
\def\tikz@auto@anchor@below@{%
  \def\tikz@anchor{north}%
  \ifdim\pgf@x>0.05pt
    \ifdim\pgf@y>0.05pt
      \def\tikz@anchor{north west}%
    \else\ifdim\pgf@y<-0.05pt
      \def\tikz@anchor{north east}%
    \fi\fi
  \else\ifdim\pgf@x<-0.05pt
    \ifdim\pgf@y>0.05pt
      \def\tikz@anchor{north east}%
    \else\ifdim\pgf@y<-0.05pt
      \def\tikz@anchor{north west}%
    \fi\fi
  \else
    \ifdim\pgf@y>0pt
      \def\tikz@anchor{west}%
    \else
      \def\tikz@anchor{east}%
    \fi
  \fi\fi}
\makeatother
\begin{document}
\begin{tikzcd}[row sep=large, auto=above]
& C \arrow[ld, "f"] 
    \arrow[rd, "g"] 
    \arrow[d, "!h" , dashed] \\
  A 
& A \times B \arrow[r, "\pi_B"']
             \arrow[l, "\pi_A"']
& B
\end{tikzcd}

\begin{tikzcd}[row sep=large, auto=below]
  A 
& A \times B \arrow[r, "\pi_B"']
             \arrow[l, "\pi_A"']
& B \\
& C \arrow[lu, "f"] 
    \arrow[ru, "g"] 
    \arrow[u, "!h"', dashed]
\end{tikzcd}
\end{document}

Output

enter image description here

enter image description here

You must log in to answer this question.

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