TikZ:嵌套范围内的“局部边界框”

TikZ:嵌套范围内的“局部边界框”

我正在尝试定义一个新环境,该环境将在其内容周围绘制一个矩形。当这些环境嵌套时,问题就开始了,因为“本地边界框”是一种全局事物。对外部和内部范围使用唯一名称可以解决问题。

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{fit}

\newenvironment{myscope0}[0]{
    \begin{scope}[draw, local bounding box=bounding box 0]
}{
    \end{scope}
    \node [draw, fit=(bounding box 0)] {};
}

\newenvironment{myscope1}[0]{
    \begin{scope}[draw, local bounding box=bounding box 1]
}{
    \end{scope}
    \node [draw, fit=(bounding box 1)] {};
}

\begin{document}
\begin{tikzpicture}
    \begin{myscope0}
        \begin{myscope1}
            \node at (0,0) {test 1};
        \end{myscope1}

        \begin{myscope1}
            \node at (1,1) {test 2};
        \end{myscope1}
    \end{myscope0}
\end{tikzpicture}
\end{document}

预期的

我想要避免为每个可能的嵌套级别定义不同的环境,因为我将使用它来绘制复杂的图表。

我发现了另一个解决非常相似问题的主题:将当前计数器值传递给堆栈数据结构

他们定义了某种堆栈来存储计数器,并使用该计数器来形成名称。问题是它实际上不适用于范围:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{fit}

%Define stack data structure commands (\push, \pop, \splitstack)
\newtoks\mystack
\mystack={\empty}

\def\push#1#2{%
    \def\tmp{{#1}}% 
    \expandafter\expandafter\expandafter%
    #2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
    \ignorespaces
}

\def\pop#1#2{%
    \expandafter\splitstack\the#1\stop{#1}{#2}%
}

\def\splitstack#1#2\stop#3#4{% 
    \def\tmp{#1}
    \ifx\tmp\empty 
    \else
        \def#4{#1}\global#3={#2}%
    \fi
}

%Define bracket pair counting commands (\openbracket, \closebracket)
\newcounter{mycounter}

\newenvironment{myscope}[0]{
    \global\expandafter\edef\csname beginscopenumber\endcsname{\themycounter}%
    \push{\beginscopenumber}{\mystack}%
    \stepcounter{mycounter}%
        
    \begin{scope} [local bounding box=bounding box \beginscopenumber]
}{
    \end{scope}
    \pop{\mystack}{\endscopenumber}%
    \node [draw, fit=(bounding box \endscopenumber)] {};
}

\begin{document}
\begin{tikzpicture}
    \begin{myscope}
        \begin{myscope}
            \node at (0,0) {test 1};
        \end{myscope}

        \begin{myscope}
            \node at (1,1) {test 2};
        \end{myscope}
    \end{myscope}
\end{tikzpicture}
\end{document}

实际的

外部矩形仅包围最后一个嵌套范围。如能得到任何帮助,我将不胜感激。谢谢。

答案1

这是一个带有计数器的简单方法:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{fit}

\newcounter{myscopelevel}
\setcounter{myscopelevel}{0}
\newenvironment{myscope}[0]
{
  \stepcounter{myscopelevel}
  %\typeout{myscopelevel:\themyscopelevel}
  \begin{scope}[local bounding box/.expanded=bounding box \themyscopelevel]
  }{
  \end{scope}
  \node [draw, fit=(bounding box \themyscopelevel)] {};
  \addtocounter{myscopelevel}{-1}
}

\begin{document}
\begin{tikzpicture}
    \begin{myscope}
        \begin{myscope}
            \node at (0,0) {test 1};
        \end{myscope}

        \begin{myscope}
            \node at (1,1) {test 2};
        \end{myscope}
    \end{myscope}
\end{tikzpicture}
\end{document}

下面是一个更简单的版本,使用组内的宏的局部性:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{fit}

\pgfmathsetmacro\myscopelevel{0}
\newenvironment{myscope}[0]
{
  \pgfmathsetmacro\myscopelevel{int(\myscopelevel+1)}
  %\typeout{myscopelevel:\myscopelevel}
  \begin{scope}[local bounding box/.expanded=bounding box \myscopelevel]
  }{
  \end{scope}
  \node [draw, fit=(bounding box \myscopelevel)] {};
}

\begin{document}
\begin{tikzpicture}
    \begin{myscope}
        \begin{myscope}
            \node at (0,0) {test 1};
        \end{myscope}

        \begin{myscope}
            \node at (1,1) {test 2};
        \end{myscope}
    \end{myscope}
\end{tikzpicture}
\end{document}

答案2

TikZ 绘图的主要原则之一是:将nodes 和pics 沿着paths 放置。它们之间存在所谓的平衡:node是具有完整的锚点和名称,形状有限; 是pic具有任何形状,但“黑客”锚点和名称。

您可以通过 like-node 回答您的问题pic具体描述如下这个答案我定义了一个pic有3个参数的:#1是右上方的文本,#2是左下方的文本,#3是稍后可以引用的覆盖节点的名称。

希望这有帮助!PS:local bounding box总是矩形,所以是有限的。

在此处输入图片描述

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}
\tikzset{pics/leonidovic/.style args=
{above right #1 below left #2 nodename #3}{code={%
\path 
(0,0) node[draw,minimum height=15mm,minimum width=20mm] (#3) {}
(#3.north east)+(-.6,-.35) node[draw,minimum height=5mm,minimum width=10mm]{#1}
(#3.south west)+(.6,.35) node[draw,minimum height=5mm,minimum width=10mm]{#2};%
}}} 
        
\path
(0,0) pic{leonidovic=above right test1 below left test2 nodename A}
(5,2) pic{leonidovic=above right test3 below left test4 nodename B}
;
\draw (A)--(B);
\draw[->] (A) -| (B);
\end{tikzpicture}
\end{document}  

相关内容