已知尺寸后重新定位 Tikz 范围

已知尺寸后重新定位 Tikz 范围

我正在尝试构建一个包含两个范围的 Tikz 图片。第一个范围的大小是已知的,因为它只有一个元素(一张图片)。第二个范围的大小未知,因为它可以包含任意数量的节点。

问题在于我需要能够将两个范围集中放置在彼此的上方,这意味着我要么需要找到一种方法来预先计算第二个范围的大小,要么需要在制作第二个范围之后移动它。

值得注意的是,解决方案还需要在第一个作用域的内容在 的开始部分定义\newenvironment,而第二个作用域的内容在新环境中定义的情况下才能发挥作用。此外,创建作用域的顺序不能改变(如果可以将第一个作用域移动到环境的结束部分,这将是微不足道的,但由于其他限制,这里无法做到这一点)。

大致如下:

\newenvironment{anEnvironment}{
    \begin{tikzpicture}
        \begin{scope}
            %... make some nodes in first scope
        \end{scope}
        \begin{scope}
}{
        \end{scope}
        %... Set centre position of secondscope to match firstscope.
    \end{tikzpicture}
}

\begin{anEnvironment}
        %... make nodes for second environment
\end{anEnvironment}

shift创建范围后可以移动它(应用)吗?

或者,有没有办法创建一个不可见的 tikzpicture,我可以从中获取大小?这样就可以预先计算大小,然后使用正确的位置创建范围。

答案1

基于答案(使用矩阵来集中一个 Tikzpic置于范围内的中心),并且回答(使用NewEnvironsavebox),我已经想出了一个可以满足我需求的解决方案。

本质上,newenvironment我可以使用NewEnviron(不得不在输入参数处理上做出妥协,但我可以接受)来提前知道整个主体。这意味着可以先在 中制作它savebox以允许测量它,然后可以基于这些尺寸制作背景图像节点,随后重新制作以背景图像为中心 的 Tikz 图片。

下面是一个例子(为了清晰起见,我从中去掉了大量其他部分)。

\newif\ifttikzpictureIsDraft

\usepackage{environ}
\environbodyname\ttikzenvironbody
\newsavebox{\ttikzpicturebody}
\newlength{\ttikzpictureheight}
\newlength{\ttikzpicturewidth}

% Include tikzpicture for tfigure
\NewEnviron{ttikzpicture}[2][]{%
% Check if in draft mode, if so, set background box to draft image (yellow box)
\ifttikzpictureIsDraft%
    \def\ttikzbackgroundimage{\templatedir/Classes/EmptyBoxDraft}%
\else%
    \def\ttikzbackgroundimage{#2}%
\fi%
% Save the picture into a tikz pic so we can reuse it later twice
    \tikzset{pics/ttikzpic/.style={code={\ttikzenvironbody}}}
% Create a fake tikzpicture inside a savebox so we can measure its size
    \begin{lrbox}{\ttikzpicturebody}%
        \begin{tikzpicture}[#1]%
            \pic {ttikzpic};%
        \end{tikzpicture}%
    \end{lrbox}%
% Calculate width and height of the tikzpicture
    \settoheight{\ttikzpictureheight}{\usebox{\ttikzpicturebody}}%
    \settowidth{\ttikzpicturewidth}{\usebox{\ttikzpicturebody}}%
% Create the real tikzpicture using same optional input arguments
    \begin{tikzpicture}[#1]%
% Put the background image in a new scope so we can reuse its bounding box for the main image.
        \begin{scope}[local bounding box = backgroundimage]
% Inside add a node using background image scaled to match the tikz picture measured
            \node (bgimage) [inner sep=0mm, anchor=center] (0,0) {\includegraphics[width=\ttikzpicturewidth, height=\ttikzpictureheight]{\ttikzbackgroundimage}};
% Finished with the effective figure
        \end{scope}
% Now we draw the user pic centred on the background image
        \matrix[at={(backgroundimage.center)}] {%
            \pic {ttikzpic};\\%
        };%
% Finish Tikz picture
    \end{tikzpicture}
}

答案2

我最近弄清楚了如何使用tikzmark调整pic(见https://tex.stackexchange.com/a/611460/86这个想法的起源,尽管自那个答案以来语法略有变化)。它的核心功能利用了 apic被 a 包围的事实scope,实际上调整了范围位置。所以它可以在这里使用。它几乎按原样工作,只是因为 apic是路径的一部分,所以我在原始代码中做了一些不适用于范围的假设。幸运的是,这些都是可以修复的,因此使用最新版本的 tikzmark(来自github上面链接的存储库),下面的操作似乎可以满足您的要求。

\documentclass{article}
%\url{https://tex.stackexchange.com/q/567245/86}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\newenvironment{anEnvironment}{
    \begin{tikzpicture}
        \begin{scope}
  \fill (0,0) circle[radius=5pt];
        \end{scope}
        \begin{scope}[
          anchor=center,
          scope anchor location,
          adjust scope position,
        ]
}{
        \end{scope}
    \end{tikzpicture}
}

\begin{document}

\begin{anEnvironment}
\fill[red] (2,0) circle[radius=4pt];
\fill[red] (2,1) circle[radius=4pt];
\fill[red] (3,0) circle[radius=4pt];
\fill[red] (3,1) circle[radius=4pt];
\end{anEnvironment}

\end{document}

与所有 tikzmark 解决方案一样,它需要两次编译才能解决。

调整范围位置

相关内容