The functionality of the top answer can be obtained directly using tikzcd by placing the following command at the end of the diagram:
\arrow[from=2-2, to=4-2, pos=0.75, crossing over, "T f"']
So the complete example would be:
\documentclass{article}
\usepackage{tikz-cd}
\begin{document}
\[
\begin{tikzcd}[ampersand replacement=\&,column sep=small]
GM \arrow[pos=0.75]{rr}{\models_{M}}
\arrow[two heads,swap]{dr}{e_{M}}
\arrow[swap]{dd}{Gf}
\& \&
R^{FM}
\arrow{dd}{R^{Ff}} \\
\& T M
\arrow[tail,swap]{ru}{m_{M}}
\& \\
GN \arrow[pos=0.75,crossing over]{rr}{\models_{N}}
\arrow[two heads,swap]{dr}{e_{N}}
\& \& R^{FN} \\
\& T N
\arrow[tail,swap]{ru}{m_{N}} \&
\arrow[from=2-2, to=4-2, pos=0.75, crossing over, "T f"']
\end{tikzcd}
\]
\end{document}
A solution by defining a command \latearrow
Similar to the solution given by JLDiaz, you can define a command \latearrow
.
My version of \latearrow
is set up so that tikzcd prints first the normal arrows in the order that they appear, then the \latearrow
s in the order they appear. The syntax for \latearrow
is exactly identical to the syntax of \arrow
.
Note that this handles both the new and the old syntax correctly, so you can use the old syntax:
\latearrow[pos=0.75, crossing over,swap]{dd}{T f}
or the new syntax:
\latearrow[dd,pos=0.75, crossing over,"T f"']
and both work (making this work for the old syntax added 8 calls to \patchcmd
and three \let
's).
\documentclass{article}
\usepackage{etoolbox}
\usepackage{tikz-cd}
\makeatletter
\patchcmd\tikzcd@
{\global\let\tikzcd@savedpaths\pgfutil@empty}
{\global\let\tikzcd@savedpaths\pgfutil@empty
\global\let\tikzcd@atendsavedpaths\pgfutil@empty}{}{}
% For some reason this \patchcmd call fails =(
%\patchcmd\endtikzcd{\tikzcd@savedpaths}{\tikzcd@savedpaths\tikzcd@atendsavedpaths}{}{}
% So we have to copy the whole original version of \endtikzcd
\def\endtikzcd{%
\pgfmatrixendrow\egroup%
\pgfextra{\global\let\tikzcdmatrixname\tikzlastnode};%
\tikzcdset{\the\pgfmatrixcurrentrow-row diagram/.try}%
\begingroup%
\pgfkeys{% `quotes' library support
/handlers/first char syntax/the character "/.initial=\tikzcd@forward@quotes,%
/tikz/edge quotes mean={%
edge node={node [execute at begin node=\iftikzcd@mathmode$\fi,%$
execute at end node=\iftikzcd@mathmode$\fi,%$
/tikz/commutative diagrams/.cd,every label,##2]{##1}}}}%
\let\tikzcd@errmessage\errmessage% improve error messages
\def\errmessage##1{\tikzcd@errmessage{##1^^J...^^Jl.\tikzcd@lineno\space%
I think the culprit is a tikzcd arrow in cell
\tikzcd@currentrow-\tikzcd@currentcolumn}}%
\tikzcd@before@paths@hook%
\tikzcd@savedpaths\tikzcd@atendsavedpaths % I just added \tikzcd@atendsavedpaths
\endgroup%
\endtikzpicture%
\ifnum0=`{}\fi}
\let\latearrow\tikzcd@arrow % \patchcmd comes through for us here.
\let\late@@arrow\tikzcd@@arrow
\let\late@ar@new\tikzcd@ar@new
\let\late@ar@old\tikzcd@ar@old
\let\late@ar@getlabel\tikzcd@ar@getlabel
\patchcmd\latearrow{\tikzcd@savedpaths}{\tikzcd@atendsavedpaths}{}{}
\patchcmd\latearrow{\tikzcd@@arrow}{\late@@arrow}{}{}
\patchcmd\latearrow{\tikzcd@ar@old}{\late@ar@old}{}{}
\patchcmd\late@@arrow{\tikzcd@ar@old}{\late@ar@old}{}{}
\patchcmd\late@@arrow{\tikzcd@ar@new}{\late@ar@new}{}{}
\patchcmd\late@ar@old{\tikzcd@ar@getlabel}{\late@ar@getlabel}{}{}
\patchcmd\late@ar@old{\tikzcd@ar@getlabel}{\late@ar@getlabel}{}{}
\patchcmd\late@ar@old{\tikzcd@ar@new}{\late@ar@new}{}{}
\patchcmd\late@ar@getlabel{\tikzcd@ar@getlabel}{\late@ar@getlabel}{}{}
\patchcmd\late@ar@getlabel{\tikzcd@ar@getlabel}{\late@ar@getlabel}{}{}
\patchcmd\late@ar@getlabel{\tikzcd@ar@new}{\late@ar@new}{}{}
\patchcmd\late@ar@new{\tikzcd@savedpaths}{\tikzcd@atendsavedpaths}{}{}
\def\tikzcd@atendsavedpaths{}
\makeatother
\begin{document}
\[
\begin{tikzcd}[ampersand replacement=\&,column sep=small]
GM \arrow[pos=0.75]{rr}{\models_{M}}
\arrow[two heads,swap]{dr}{e_{M}}
\arrow[swap]{dd}{Gf}
\& \&
R^{FM}
\arrow{dd}{R^{Ff}} \\
\& T M\latearrow[pos=0.75, crossing over,swap]{dd}{T f}
% Here's the \latearrow call. This arrow will go on top.
\arrow[tail,swap]{ru}{m_{M}}
\& \\
GN \arrow[pos=0.75,crossing over]{rr}{\models_{N}}
\arrow[two heads,swap]{dr}{e_{N}}
\& \& R^{FN} \\
\& T N
\arrow[tail,swap]{ru}{m_{N}} \&
\end{tikzcd}
\]
\end{document}
The code works by 1) changing \end{tikzcd}
so that it puts both \tikzcd@savedpaths
and \tikzcd@atendsavedpaths
into the diagram and 2) copying the \arrow
code but modifying it to store the paths in \tikzcd@atendsavedpaths
in place of \tikzcd@savedpaths
. Because at the end they are used in the order
\tikzcd@savedpaths\tikzcd@atendsavedpaths
, all paths created using the normal \arrow
command are printed first, and then the paths using \latearrow
, each in the order they appear.
For some reason the \patchcmd
call that should do step 1 fails, so I just copied the entire definition of \endtikzcd
and added the one extra command I needed.
I do step 2 by copying all of the internal commands used in \arrow
and then using a bunch of calls to \patchcmd
to link them to each other, and to replace the savedpaths macro. Because \arrow
has exceptionally complicated syntax, there are four internal commands, each needing up to three substitutions.
Obviously updates to tikzcd may to break this code, but it's very simple so it shouldn't be hard to fix.
Edit: The version I posted yesterday was broken, thanks Aaron Mazel for noticing. I mistakenly thought that the savedpaths was local, and would be emptied automatically when the scope closes at the end of the environment. Instead it's global, and emptied at the beginning of the next tikzcd environment. The fix was to add the line:
\patchcmd\tikzcd@
{\global\let\tikzcd@savedpaths\pgfutil@empty}
{\global\let\tikzcd@savedpaths\pgfutil@empty
\global\let\tikzcd@atendsavedpaths\pgfutil@empty}{}{}