如何计算旋转的边界框?

如何计算旋转的边界框?

编辑:正如 percusse 的回答所建议的,我可以使用transform shape选项。我的第一个问题现在已经解决了。但是,尽管第二个边界框现在是局部对齐的,但它并不正确。事实上,local bounding box总是计算一个全球对齐的边界框(绿点)并fit包围该边界框的north、、和east锚点。southwest

我现在的问题是:如何计算local bounding box 本地对齐?

新示例(右侧的蓝色矩形不适合红色路径):

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
  red pt/.style={pt=red},
  green pt/.style={pt=green},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  \node[green pt] at (bb.north west){};
  \node[green pt] at (bb.north east){};
  \node[green pt] at (bb.south west){};
  \node[green pt] at (bb.south east){};
  % how to find correct bounding box locally aligned ?
  \begin{scope}[transform shape]
    \node[fit=(bb),draw=blue]{};
  \end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

原始问题:

我想计算一些边界框。以下是我的两个案例:

  1. 为了适应一些节点(或坐标),我可以使用fit库。
  2. 为了适应任意路径,我可以使用带有的范围local bounding box=bb

下面的代码展示了这两种情况:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  red pt/.style={circle,minimum size=3pt,fill=red,inner sep=0},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \node[fit=(a)(b)(c)(d),draw=blue]{};

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  \node[fit=(bb),draw=blue]{};
\end{tikzpicture}

在此处输入图片描述

现在,我想做同样的事情在旋转的图片中

我的两个问题:

  1. 在我的第一个案例(某些节点)中,我必须rotate向我的拟合节点添加选项(因为rotate选项不会旋转节点)。如何自动找到此选项的正确值(例如:当前坐标系和画布坐标系之间的角度)?

  2. 在我的第二种情况下(任意路径),我可以计算局部边界框但全局对齐。如何计算任意路径局部对齐的局部边界框?

这是我的尝试:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  red pt/.style={circle,minimum size=3pt,fill=red,inner sep=0},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  % how to find the good value for rotate (here 20)?
  \node[rotate=20,fit=(a)(b)(c)(d),draw=blue]{};

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  % how to find bounding box locally aligned ?
  \node[rotate=20,rotate fit=-20,fit=(bb),draw=blue]{};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案1

我是不是错过了重点?transform shape重置旋转似乎是一个解决方案。


编辑:我希望这次我明白你的意思了。如果没有,我真的很感激你能用旋转的矩形和形状来解释,而不是当地的全球的这是相对于旋转的 Tikz 图片环境的相对术语。

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\tikzset{
  pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
  red pt/.style={pt=red},
  green pt/.style={pt=green},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}
\pgfgettransform{\currtrafo}     %Save the current trafo 

  % second case: fitting arbitrary path
\begin{scope}[local bounding box=bb]
\pgftransformresetnontranslations % Now there is no rotation and it doesn't know 
                                  % things are going to be rotated
\begin{scope}                     % We open a new scope and restore the outer trafo
\pgfsettransform{\currtrafo}      % inside the scope

\draw[red] (4,1) to[bend right] (6,1) -- (5,2);  % Draw anything
\end{scope}                                      % Now the trafo is reset again

\node[fit=(bb),draw=blue]{};     % Externally it doesn't know the content is
                                 % rotated or not

  \end{scope}                    % Back to original trafo.
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

笔记:我终于自己找到了解决方案......但我不能给我自己的赏金。;-)

我定义了三种风格:

  1. memoize points命名路径的每个点(借助memoizepoints计数器)并将这些名称累积到全局宏(其参数)中。

  2. cont memoize points与 相同memoize points,但不重置全局宏(其参数)。

  3. init memoize points重置全局宏(其参数)和memoizepoints计数器。

以下是序言:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit,intersections,decorations.pathreplacing,decorations.markings}

柜台memoizepoints和三种风格:

\newcounter{memoizepoints}
\tikzset{
  init memoize points/.code={\xdef#1{}\setcounter{memoizepoints}{0}},  
  cont memoize points/.style={postaction={
      decorate,decoration={show path construction,
        moveto code={},
        lineto code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
        curveto code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentsupporta,%
            \tikzinputsegmentsupportb,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
        closepath code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
      },
    },
  },
  memoize points/.style={init memoize points=#1,cont memoize points=#1},
}

然后是一个例子,后面是它的代码:

在此处输入图片描述

\begin{document}
\begin{tikzpicture}[rotate=30,inner sep=0pt,line width=1pt]
  \tikzset{
    pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
    red pt/.style={pt=red},
  }
  \draw[gray,line width=.4pt] (0,0) grid (9.5,5.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}

  % second case: fitting arbitrary path
  \draw[red,memoize points=\allpoints] (4,1) to[bend right] (6,1) -- (5,2);
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}

  % another example of fitting arbitrary path
  \draw[red,memoize points=\allpoints] (8,1.2) circle ();
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}

  % another example of fitting arbitrary paths
  \begin{scope}[yshift=2cm]
    \draw[red,memoize points=\allpoints]
    plot[domain=4:8,samples=100] (\x,{2+sin(3 * \x r)});
    \draw[red,cont memoize points=\allpoints]
    plot[domain=4:8,samples=100] (\x,{2.1+cos(3 * \x r)});
  \end{scope}
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}
\end{tikzpicture}

相关内容