0

Is there a simple way of making nested and boxed sub-diagrams using the tikz-cd package?

For example (from Lawvere and Schanuel, Conceptual Mathematics):

Commutative diagram

I currently use the following environment to create boxed commutative diagrams, which works nicely:

\newenvironment{tikzcdb}
                     {\begin{lrbox}{\tikzcdbox}\begin{tikzcd}}
                     {\end{tikzcd}\end{lrbox}\fbox{\usebox{\tikzcdbox}}}
\newsavebox{\tikzcdbox}

I can't figure out how to do the nesting though, and then do nesting AND boxing.

3
  • Welcome to TeX.SE! What mean "simple" to you? What you try so far? Where you stuck in your effort? You should be aware that this site is not service "we-do-your-task-instead-of you" ...
    – Zarko
    Commented Sep 25, 2023 at 12:57
  • I'd use the key boxed as defined in my answer (we can further fine tune the padding and whatnot so that it is the same as with \fbox. We can also use multiple TikZ-CDiagrams in one TikZ picture. Your picture could also be produced by just one CD where we add those boxes with other TikZ means. Commented Sep 25, 2023 at 13:17
  • Have you thought about how the box should look like if an arrow goes beyond the matrix' borders? Commented Sep 25, 2023 at 13:18

1 Answer 1

1

I hope this is helpful, it will depend on the kind of diagrams you need to do.

  1. We patch the tikzcd environment so that it detects when it is used inside a tikzpicture
  2. and add a few forwarded keys up so that the tikzcd environment acts as much as a normal TikZ \matrix as it can.
  3. The combination of between origins, overlayed TikZ labels and a custom padding for each TikZ-CD matrix make sure the boxes (i.e. the drawn matrices) have the same size. Of course, for this, all dots need to be the same size.
  4. The cd arrow key emulates as easy as possible TikZ-CD's own \ar(row) command.

Code

\documentclass{article}
\usepackage{tikz} \usetikzlibrary{cd, positioning, quotes}
\makeatletter
\tikzcdset{
  /utils/temp/.initial/.expand once=\tikzcd,
  /utils/temp/.prefix=\ifx\path\tikz@command@path\let\tikzpicture\scope\let\endtikzpicture\endscope\fi,
  /utils/temp/.get=\tikzcd,
  enable tikzcd quotes/.code=%
    \pgfkeyssetvalue{/handlers/first char syntax/\expandafter\meaning\string"}{\tikz@quote@parser}%
    \def\tikz@quotes@as##1##2{matrices={label={[direction shorthands,##2]##1}}},
  forwarded keys/.style={% the \pgfkeyslet stuff makes sure the keys work normal in an arrow label
    #1/.style={matrices={/tikz/#1={##1}}},
    every label/.append code=\pgfkeyslet{/tikz/commutative diagrams/#1/.@cmd}\pgfutil@undefined}}
\makeatother
\tikzcdset{
  forwarded keys/.list={below, left, right, above, name, anchor, matrix anchor},
  matrices/.style={every matrix/.append style={#1}},
  padding/.style args={#1:#2}{
    matrices={inner xsep={(#1)*1ex}, inner ysep={(#2)*1ex}}},
  tight/.style={inner sep=+.25ex}}
\tikzset{
  Dot Diagram/.code=%
    \tikzcdset{
      tikzcd to/.tip={Stealth[scale width=.75, inset=+.75pt +.5]}, % arrow tip
      matrices={draw, outer sep=+.5ex},
      diagrams={% between origins + overlay labels + padding makes it
                % easy to create matrices that have same dimensions
        enable tikzcd quotes,
        row sep={3em,between origins}, column sep={5em,between origins},
        /tikz/every label/.style={% the labels on matrices
          path only, math nodes, shape=asymmetrical rectangle,
          inner sep=+0pt, outer sep=+0pt},
        cells={
          /tikz/label distance=+-1ex, % because of outer sep=.5ex
          /tikz/every label/.style={% we need to reset all dot settings
            shape=rectangle, path only, overlay,
            commutative diagrams/every label},
          nodes={% these are our dots
            shape=circle, fill, inner sep=+0pt,
            outer sep=+.5ex, minimum size=+.7ex}}}},
  math nodes/.style={execute at begin node=$, execute at end node=$},
  cd arrow/.style={% a very simple TikZ-CD's \arrow implementation
    every edge/.append style={
      nodes={math nodes, commutative diagrams/every label},
      commutative diagrams/every arrow}}}
\begin{document}
\[
\begin{tikzpicture}[Dot Diagram, node distance=1.5em]
\begin{tikzcd}[name=aa,              "{{}=A^2}" right, padding=3:3.1]
  |["{(s, t)}"]|                                 & |["{(t, t)}"]| \\
  |["{(s, s)}" below]| \ar[ur, "{(a, a)}" tight] & |["{(t, s)}" below]|
\end{tikzcd}

\begin{tikzcd}[name=da, below=of aa, "{{}=A}" right, padding=3:1.7]
  |["s" left]| \ar[r, "a"] & |["t" right]|
\end{tikzcd}

\begin{tikzcd}[name=la, left =of aa, "{A={}}" left,  padding=1.7:3.1]
|["t"]| \\ |["s" below]| \ar[u, "a"]
\end{tikzcd}
% a very simple TikZ-CD's \arrow implementation
\path[cd arrow] (aa) edge["p_1"] (da)
                     edge["p_2"] (la);
\end{tikzpicture}
\]
\end{document}

Output

enter image description here

1
  • Thank you very much for this. I don't actually need the dots in the diagrams, I just want to use standard tikz-cd commutative diagrams with boxes around them and using, e.g. (s,s) for the nodes. I tried to edit your code to remove the dots, but failed.
    – Sharanjit
    Commented Sep 26, 2023 at 4:41

You must log in to answer this question.

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