tikzcd 智能标签放置

tikzcd 智能标签放置

tikzcd 能不能智能地放置标签?比如,在绘制下图时,

\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}

在此处输入图片描述

标签看起来很丑。我必须手动换边,

\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}

有没有更智能的方法来做到这一点?

答案1

标签的放置方式很巧妙,始终位于箭头的左侧。这是蒂克兹 auto选项安装者TikZ-CD

不过,它只知道leftright,这意味着路径上的节点要么放在路径的左边,要么放在路径的右边。(swap') 钥匙只是检查哪一个是活动的并安装另一个。)

我不喜欢原始代码中的实现方式,但我们以任何方式扩展它也可以接受

  • auto = above
    节点始终位于路径上方(或垂直线的右侧),并且
  • auto = below
    其中节点始终位于路径下方(或垂直线的左侧)。

密钥swap被重写,以便它也能处理这些新添加的内容。


这仍然是某种愚蠢的智能,因为它永远无法检查它是否看起来不错,或者节点是否位于图表的“外部”。

当然,您可以创建一个自动放置功能,当路径为对角线时将节点置于路径上方,当路径为纯水平路径时将节点置于路径下方,但在我看来,图表越复杂,这些功能就越无用。

例如,在第二个图中,我认为它等同于第一个图,所有节点都应该在另一侧,以便它们位于图的“外侧”,但如果没有外界的巨大帮助(即另一个分析该图的工具),TikZ 将无法弄清楚这一点。

这样,节点至少会一致地放置在路径上方或下方,我认为这会很有帮助。在完成这些图之前,您总是会先看一遍这些图。

代码

\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}

输出

在此处输入图片描述

在此处输入图片描述

相关内容