当一个 tikzpicture 位于另一个 tikzpicture 内部时,出现覆盖问题

当一个 tikzpicture 位于另一个 tikzpicture 内部时,出现覆盖问题

更新我最近发现这个问题Nickolay Kolev \tikz在 tikzpicture 环境中使用。很多用户认为这是错误的做法,我同意这很奇怪,但有时非常有用。我也同意最好避免这种情况。我在 中使用了这种可能性 pgfornament

我不明白为什么如果我反转 tikzpicture(包装器)的两行,我会得到不同的结果。overlay我认为,重置边界框,但为什么在第二个 tikzpicture 中,覆盖层会重新设置一般边界框。当我使用示波器时,问题就消失了?

更新我认为 tikz 的专家认为最好使用范围而且这个问题很愚蠢......

或者在 pgfmanual 中,我读到

所有图形选项对于它们适用的{tikzpicture}来说都是本地的。

红色图片没有边界框。

\documentclass[11pt]{scrartcl}
\usepackage{tikz}    
\begin{document}

baseline\begin{tikzpicture}[baseline=(current bounding box.north west)] 
 \tikz[overlay] \path (0,0) --  (1,1) node  {\color{blue}$\bullet$};
 \draw[help lines,blue!20] (0,0) grid (2,2) ;
\end{tikzpicture}baseline%
% 
\begin{tikzpicture}[baseline=(current bounding box.south west)] 
  \draw[help lines,red!20] (0,0) grid (2,2) ;
  \tikz[overlay] \path (0,0) --  (1,1) node  {\color{red}$\bullet$}; 
\end{tikzpicture}baseline    
\end{document}

使用 pgfinterruptboundingbox

绿色图片。边界框正确。第一个边界框受到保护。

解决方案是将覆盖线放置在 pgfinterruptboundingbox 环境内,以便问题与当前边界框相关联。

baseline\begin{tikzpicture}[baseline=(current bounding box.south west)]     
 \draw[help lines,green!50] (0,0) grid (2,2) ; 
 \begin{pgfinterruptboundingbox}
   \tikz[overlay] \path (0,0) --  (1,1) node  {\color{green}$\bullet$};
   \end{pgfinterruptboundingbox}
\end{tikzpicture}baseline  

在此处输入图片描述

范围没问题

\documentclass[11pt]{scrartcl}
\usepackage{tikz}

\begin{document}
baseline\begin{tikzpicture}[baseline=(current bounding box.north west)] 
 \tikz[overlay] \path (0,0) --  (1,1) node  {\color{blue}$\bullet$};
 \draw[help lines,blue!20] (0,0) grid (2,2) ;
\end{tikzpicture}baseline 
\begin{tikzpicture}[baseline=(current bounding box.south west)] 
  \draw[help lines,red!20] (0,0) grid (2,2) ; 
\begin{scope} [overlay] \path (0,0) --  (1,1) node  {\color{red}$\bullet$};
\end{scope}  
\end{tikzpicture}baseline

\end{document} 

( 范围和 tikzpicture 之间真正的区别是什么?)

更新这个问题可能太笼统了,更好的答案是 tikz 的表现如何overlay

答案1

很多用户认为 [嵌套 TikZ 图片] 是一种错误的做法

那么那就是我了。

这是另一个可能发生意外结果的例子。主要原因很简单:TikZ 不预计其环境是嵌套的,因此在启动和停止时不会检查各种假设。特别是,通过跟踪代码,我们可以看到 TikZ 花费了大量精力来处理 tikzpicture 环境中的范围和分组。由于必须从范围中提取某些信息(例如边界框信息),因此 TikZ 必须“偷运”这些信息,它通过使用全局变量来实现这一点。它以非常巧妙的方式做到这一点,即信息仅传递到 TikZ 希望传递的地方,而不是传递到任何其他分组之外。

但是对于主 tikzpicture 环境本身,它不期望嵌套,因此不使用这些复杂的方法。例如,对于边界框,它知道这\pgf@picmaxx是当前图片边界框的最大 x 值,并且只涉及一张图片,因此它可以将其视为全局变量,因为这使生活变得容易得多:每个分配都可以是\pgf@picmaxx全局的,以避免组和范围的麻烦。为了避免复杂化,我们需要做的就是确保在 tikzpicture 环境开始时将所有这些全局变量都设置为其默认值。

\pgf@picmaxx让我们通过您的代码来追踪分配:

\documentclass[11pt]{scrartcl}
\usepackage{tikz}    
\begin{document}

baseline\begin{tikzpicture}[baseline=(current bounding box.north west)] 

在 tikzpicture 的开始处,它被设置为:-16000.0pt

 \tikz[overlay]

从技术上讲,这里也设置为 -16000.0pt

                \path (0,0) --  (1,1) node  {\color{blue}$\bullet$};

在该命令结束时,它被设置为 0.0pt,这是该 tikzpicture 的最大 x 范围,因为它有键overlay

 \draw[help lines,blue!20] (0,0) grid (2,2) ;

现在,它被设置为 57.00548pt,这是上述命令的范围。

\end{tikzpicture}baseline%

这是仍然这里是 57.00548pt,因为它是全局分配的。

% 
\begin{tikzpicture}[baseline=(current bounding box.south west)] 

现在重置为 -16000.0pt

  \draw[help lines,red!20] (0,0) grid (2,2) ;

这里设置为 57.00548pt

  \tikz[overlay]

此时,由于我们已经开始了一个新的 tikzpicture,因此我们将其重置为 -16000.0pt。

                 \path (0,0) --  (1,1) node  {\color{red}$\bullet$}; 

由于overlay键的作用,我们在这里得到 0.0pt 的分配,该分配直到图片结束都有效。

\end{tikzpicture}baseline    

这里仍然是0.0pt。

\end{document}

它适用于范围的原因在于,由于范围是嵌套的,因此 TikZ/PGF 会竭尽全力确保在设置和拆除范围时边界框等功能正常工作。我认为这是您最基本问题的答案:

范围和 tikzpicture 之间的真正区别是什么?

要正确嵌套 tikzpictures,必须查看范围的代码,并查看它竭尽全力保留的键、长度和宏。然后做同样的事情。我猜,这就是你用 and 实际做的事情。\savecurrentboundingbox\restorecurrentboundingbox认为你答案末尾的问题本身就是一个很好的问题。即使我认为嵌套 TikZ 图片不是一个好主意,但正如你所指出的,不可避免地存在需要这样做的情况。知道如何确保在必须这样做时安全地做到这一点将是无价的信息(并且,我认为,它会表明人们不应该这样做轻轻因此它可以起到威慑作用)。

答案2

tikzpicture一种可能性是,当创建了带有\begin{tikzpicture}或 的环境时,\tikz许多变量和选项都已正确设置。路径现在为空,但为什么是相同的路径?

下一个代码显示,如果没有覆盖,我们可以在页面上放置一些内容,并且边界框是正确的

我避免\begin{pgfinterruptboundingbox}使用两个宏\savecurrentboundingbox\restorecurrentboundingbox

    \documentclass[11pt]{scrartcl}
    \usepackage{tikz,lipsum}
    \newcommand\savecurrentboundingbox{%
    \coordinate (saved cbb ne) at (current bounding box.north east);
    \coordinate (saved cbb sw) at (current bounding box.south west);  }
    \newcommand\restorecurrentboundingbox{%
    \useasboundingbox (saved cbb sw) rectangle (saved cbb ne); }         
    \begin{document}

    \lipsum[1]
    \fbox{%
      \begin{tikzpicture}[baseline=(current bounding box.south west)] 
      \draw[help lines,red!20] (0,0) grid (2,2) ;
      \savecurrentboundingbox
      \tikz {%
      \path[use as bounding box] (0,0) rectangle (0,0); 
      \path (0,0) --  (4,4) node  {\color{red}$\bullet$};}%
     \restorecurrentboundingbox 
    \end{tikzpicture}%
    }baseline

    \end{document} 

在此处输入图片描述

了解 tikzpicture 环境开始时使用的重要变量是什么将会很有趣。

相关内容