\arrow
中的功能被tikz-cd
放置在给定的单元格中,并使用该单元格的位置,尽管代码本身的执行(如果我理解正确的话)被推迟到矩阵组件完成绘图之后。
我有几个函数想要实现相同的功能。目前,它们是我在 tikzcd 的“在图片末尾执行”键中调用的宏,我将相关的单元格参数作为参数传递。例如,\slice{col}{title}
在列之间放置一条虚线col
,并col+1
在虚线上方放置标题。我希望能够将“slice”命令放在矩阵的单元格中而不是键中,并且能够使用它所在单元格的列来确定第一个参数(减少参数数量,对可用性有很大影响)。我对如何在正确的时间评估事物感到非常困惑,并希望得到一些帮助
我一直在尝试研究 tikz-cd 包的一些代码,但我很快就迷失在所有的符号@
s\expandafter
和\noexpand
s 中,尽管我明白我可能想将我的命令附加到\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 矩阵中的多行和/或多列等想法。