具有调整边界框的 Tikz 图形没有正确的间距

具有调整边界框的 Tikz 图形没有正确的间距

\DrawBoundingBox宏在具有 1pt 边框的图形周围绘制边界框。

在使用 生成的第一个图中\MyNode\MyNode,没有对 的边界框进行任何调整tikz。由于循环的控制点,这会导致左侧和右侧的边界框略宽,顶部的边界框大得多。底部的间距似乎是正确的。在这种情况下,使用默认边界框,两个图形按需要彼此相邻放置。

在第二幅图中,我使用\MyNode*中断循环的边界框并手动调整高度以获得正确的边界框。此图显示边界框调整是正确的,因为它具有所需的1pt间距全部四边。

但是,当我将两个带有边界框调整的图形放在一起时,\MyNode*\MyNode*它们似乎重叠了(第三个图形)。似乎宏use as bounding box中的第二个实例\DrawBoundingBox已被忽略。

在此处输入图片描述

我希望分两步完成此操作,因为这样每个图形都可以在调用之前调整自己的边界框,\DrawBoundingBox并根据需要添加额外的调整。

我需要做哪些更改,以便调整边界框后的图形可以彼此相邻放置,而不会与边界框重叠。

代码:

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}

\newcommand*{\DrawBoundingBox}[1][]{%
    \draw [
        use as bounding box,% <-- this seems to have no effect
        draw=gray,
    ]
    ([shift={(-1pt,-1pt)}]current bounding box.south west)
    rectangle
    ([shift={(1pt,1pt)}]current bounding box.north east);
}

\tikzset{Loop Style/.style={loop above, ultra thick, red, distance=1.0cm, ->}}
\newcommand*{\BBoxTweakForLoopDistance}{0.75cm}%

\NewDocumentCommand{\MyNode}{s}{%
    \begin{tikzpicture}[baseline]
        \node [draw=black, circle] (A) at (0,0) {a};
        
        \IfBooleanTF{#1}{% Interrupt bounding box for * variant
            \begin{pgfinterruptboundingbox}
                \path (A) edge[Loop Style] (A);
            \end{pgfinterruptboundingbox}
            
            \path [use as bounding box]%% Expand bounding box to include the loop path
                (current bounding box.south west) 
                rectangle 
                ([shift={(0pt,\BBoxTweakForLoopDistance)}]current bounding box.north east);
        }{%
                \path (A) edge[Loop Style] (A);
        }%
        
        \DrawBoundingBox
    \end{tikzpicture}%
}


\begin{document}
    \MyNode\MyNode
    \quad
    \MyNode*
    \quad
    \MyNode*\MyNode*
\end{document}

答案1

这不是问题的答案,我还没有完全理解重置边界框的工作原理。然而,在我看来,你想在贝塞尔曲线周围画一个紧密的边界框,不幸的是 TiZ 考虑了控制点,因此会放大边界框。这已经讨论过了这里在本例中,可以用一个简单的技巧来建立紧密的边界框:

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}

\newcommand*{\DrawBoundingBox}[1][]{%
    \draw [
        draw=gray,
    ]
    ([shift={(-1pt,-1pt)}]current bounding box.south west)
    rectangle ([shift={(1pt,1pt)}]current bounding box.north east);
}

\tikzset{Loop Style/.style={loop above, ultra thick, red, distance=1.0cm, ->}}
\newcommand*{\BBoxTweakForLoopDistance}{0.75cm}%

\NewDocumentCommand{\MyNode}{s}{%
    \begin{tikzpicture}[baseline]
        \node [draw=black, circle] (A) at (0,0) {a};

        \IfBooleanTF{#1}{% Interrupt bounding box for * variant
            \path[overlay] (A) edge[Loop Style] coordinate[midway](X) (A) ;
            \path (X);
        }{%
                \path (A) edge[Loop Style] (A);
        }%

        \DrawBoundingBox
    \end{tikzpicture}%
}


\begin{document}
    \MyNode\MyNode
    \quad
    \MyNode*
    \quad
    \MyNode*\MyNode*
\end{document}

在此处输入图片描述

我知道这并不能真正回答您的问题,但可能会让您更简单地实现我认为的目标。

答案2

正如 marmot 指出的那样,第 15.8 节:建立边界框(第 175 页)指出use as bounding box

...当前路径的边界框用于确定图片的大小,所有后续路径的大小将被忽略。但是,如果先前的路径操作已经建立了更大的边界框,则此操作不会使其变小(考虑\pgfresetboundingbox重置先前边界框的命令)。从某种意义上说,用作边界框与根据当前路径剪切所有后续绘图具有相同的效果 - 无需实际进行剪切,仅使 pgf 将所有内容视为已剪切。

这与我的想法相反,我的想法是,这将设置当前边界框,而未来的路径将改变边界框,就像没有一样use as bounding box

然而,文档中进一步指出

注意:如果在 TEX 组 ( ) 内的路径上使用此选项scope,则效果仅“持续”到 结束scope。同样,此行为与剪辑相同。考虑\useasboundingbox与 一起使用\pgfresetboundingbox,以便用新边界框替换边界框。

因此,如果我总是use as bounding boxscope

\begin{scope}
    \path [use as bounding box]%% Expand bounding box to include the loop path
            (current bounding box.south west) 
            rectangle 
            ([shift={(0pt,\BBoxTweakForLoopDistance)}]current bounding box.north east);
\end{scope}

我得到的行为与我认为use as bounding box应该做的行为一致:

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}

\newcommand*{\DrawBoundingBox}[1][]{%
    \draw [
        use as bounding box,% <-- this seems to have no effect
        draw=gray,
    ]
    ([shift={(-1pt,-1pt)}]current bounding box.south west)
    rectangle
    ([shift={(1pt,1pt)}]current bounding box.north east);
}

\tikzset{Loop Style/.style={loop above, ultra thick, red, distance=1.0cm, ->}}
\newcommand*{\BBoxTweakForLoopDistance}{0.75cm}%

\NewDocumentCommand{\MyNode}{s}{%
    \begin{tikzpicture}[baseline]
        \node [draw=black, circle] (A) at (0,0) {a};

        \IfBooleanTF{#1}{% Interrupt bounding box for * variant
            \begin{pgfinterruptboundingbox}
                \path (A) edge[Loop Style] (A);
            \end{pgfinterruptboundingbox}

            \begin{scope}
            \path [use as bounding box]%% Expand bounding box to include the loop path
                (current bounding box.south west) 
                rectangle 
                ([shift={(0pt,\BBoxTweakForLoopDistance)}]current bounding box.north east);
            \end{scope}
        }{%
                \path (A) edge[Loop Style] (A);
        }%

        \DrawBoundingBox
    \end{tikzpicture}%
}


\begin{document}
    \MyNode\MyNode
    \quad
    \MyNode*
    \quad
    \MyNode*\MyNode*
\end{document}

相关内容