在 tikzcd 单元格内运行的宏,但稍后(部分)执行

在 tikzcd 单元格内运行的宏,但稍后(部分)执行

\arrow中的功能被tikz-cd放置在给定的单元格中,并使用该单元格的位置,尽管代码本身的执行(如果我理解正确的话)被推迟到矩阵组件完成绘图之后。

我有几个函数想要实现相同的功能。目前,它们是我在 tikzcd 的“在图片末尾执行”键中调用的宏,我将相关的单元格参数作为参数传递。例如,\slice{col}{title}在列之间放置一条虚线col,并col+1在虚线上方放置标题。我希望能够将“slice”命令放在矩阵的单元格中而不是键中,并且能够使用它所在单元格的列来确定第一个参数(减少参数数量,对可用性有很大影响)。我对如何在正确的时间评估事物感到非常困惑,并希望得到一些帮助

我一直在尝试研究 tikz-cd 包的一些代码,但我很快就迷失在所有的符号@s\expandafter\noexpands 中,尽管我明白我可能想将我的命令附加到\tikzcd@savedpaths,并且发现这个答案颇具启发性。

作为部分步骤,为了解决这个问题,我决定尝试使用现有\arrow命令编写一个新宏,该命令使用数字步骤而不是d指示向下步骤的语法,并希望计算目标单元格的名称。如果我仅使用目标单元格的名称作为节点文本,它会正确显示,但是如果我将其用作的参数,它\arrow(大概)会在绘制矩阵后进行评估,因此当前行和列将评估为最后一行和列,并且所有放置都是相对于此完成的。需要明确的是,我不想要一个只查看参数中的数字并调用的解决方案\arrow,并在参数中重复d该次数。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{cd,fit,calc}

\newcommand{\slice}[2]{
    \xdef\Loop{}
    \foreach \n in  {1,...,\the\pgfmatrixcurrentrow} {\xdef\Loop{\Loop(m-\n-#1)} }
    \node (slice-#1) [fit=\Loop, inner sep=0pt] {}; %a node that contains column #1
    \xdef\Loop{}
    \foreach \n in  {1,...,\the\pgfmatrixcurrentrow} {\xdef\Loop{\Loop(m-\n-\the\numexpr#1+1\relax)} }
    \node (slice2-#1) [fit=\Loop, inner sep=0pt] {}; %a node that contains column #1+1
%now draw a line between the two nodes
    \draw[slice] ($1/2*(slice-#1.north east |- m.north)+1/2*(slice2-#1.north west |- m.north)$) to node[pos=0,inner sep=4pt,anchor=south,color=black] {#2} ($1/2*(slice-#1.south east |- m.south)+1/2*(slice2-#1.south west |- m.south)+(0,-3pt)$);
}

\newcommand{\ctrl}[1]{
    %implement essentially an arrow command but take a numerical parameter for the number of rows below (positive) or above (negative)
    %many ways I could do this, but using \pgfmatrixcurrentrow illustrates one of the issues in wider implementation
    \arrow[dash,thick]{\the\numexpr#1+\pgfmatrixcurrentrow\relax-\the\pgfmatrixcurrentcolumn}
    %actually calculates target relative to bottom right of matrix (i.e. \pgfmatrixcurrentrow not evaluated at right time).
}
\newcommand{\slicer}[1]{
%somehow have to make this command execute after matrix. Either through key `execute at end picture' or by adding to macro \tikzcd@savedpaths?
%need this \pgfmatrixcurrentcolumn to evaluate immediately, but values inside the slice macro must be evaluated when run (to give total number of rows/cols)

    %\slice{\the\pgfmatrixcurrentcolumn}{#1}
    %currently gives Undefined control sequence error
}

\tikzcdset{nodes in empty cells,every matrix/.append style={name=m}} %fix name of matrix as m
\tikzset{
    every node/.style={
        anchor=center,minimum size=0pt,inner sep=0pt,outer sep=0pt,thick
    },
    slice/.style={thick,red,dash pattern=on 5pt off 3pt},
    operator/.style={draw,fill=white,minimum size=1.5em}
}

\begin{document}
\begin{center}
\begin{tikzcd}[execute at end picture={\slice{1}{title}}]
|[operator]| A & |[operator]| B \\
|[operator]| C \arrow[u,dash,thick] & |[operator]| D
\end{tikzcd}
\end{center}
The syntax that I'd like to use to achieve this:
\begin{center}
\begin{tikzcd}
|[operator]| A \slicer{title} & |[operator]| B \\
|[operator]| C \ctrl{-1} & |[operator]| D
\end{tikzcd}
\end{center}
\end{document} 

输出为: 在此处输入图片描述

答案1

正如@marmot 所建议的,使该功能正常工作的方法slicer是将命令添加到\tikzcd@savedpaths宏中。然后,只需获取一堆\expandafter命令以确保在将当前列添加到宏之前已对其进行了评估。

\makeatletter
\newcommand{\slicer}[1]{
%somehow have to make this command execute after matrix. Either through key `execute at end picture' or by adding to macro \tikzcd@savedpaths?
%need this \pgfmatrixcurrentcolumn to evaluate immediately, but values inside the slice macro must be evaluated when run (to give total number of rows/cols)
\edef\col{\the\pgfmatrixcurrentcolumn}
\expandafter\pgfutil@g@addto@macro\expandafter\tikzcd@savedpaths\expandafter{%
    \expandafter\slice\expandafter{\col}{#1}
}
}
\makeatother

顺便说一句,这种方式为您提供了许多可能性来实现诸如 tikz 矩阵中的多行和/或多列等想法。

相关内容