# How to compute rotated bounding boxes?

Edit: As suggested by percusse's answer, I can use transform shape option. My first question is now solved. But although the second bounding box is now locally aligned, it is not correct. In fact, local bounding box always computes a globally aligned bounding box (green points) and fit encloses north, east,south, and west anchors of this bounding box.

My question is now: how to compute a local bounding box locally aligned?

New example (the blue rectangle on the right does not fit the red path):

\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}


Original question:

I want to compute some bounding boxes. Here is my two cases:

1. to fit some nodes (or coordinates), I can use fit library.
2. to fit arbitrary paths, I can use a scope with local bounding box=bb.

The following code shows this two cases:

\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}


Now, I want to make the same things within a rotated picture!

My two questions:

1. In my first case (some nodes), I have to add rotate option to my fitting node (as rotate option does not rotate nodes). How to find automatically the correct value for this option (eg: the angle between current coordinate system and canvas coordinate system)?

2. In my second case (arbitrary paths), I can compute local bounding box but globally aligned. How to compute local bounding box locally aligned of an arbitrary path ?

Here is my attempt:

\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}


-
Pour moi, c'est un bug – rpapa Aug 27 '12 at 19:16
The translation for the above comment is "For me, this is a bug". – kiss my armpit Sep 7 '12 at 9:08

Am I missing the point? transform shape and resetting the rotation seems like a solution.

EDIT: I hope this time I got your point. If not, I would really appreciate explaining in terms of rotated rectangles and shapes, instead of local and global which are relative terminology with respect to the rotated Tikz picture environment.

\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}


-
You give me a solution for my first question. But the second bounding box is always globally aligned. I would like this box is locally aligned. – Paul Gaborit Aug 27 '12 at 0:09
I edited my question to clarify my request. – Paul Gaborit Aug 27 '12 at 0:26
I think I missed it again. you want the blue rectangle rotated too right? – percusse Aug 27 '12 at 21:19
Yes: the two blue rectangles should be parallel and the second one should fit the red path. – Paul Gaborit Aug 27 '12 at 21:27
@PaulGaborit I've read the local bounding box code. It's really difficult to get into it since the node is hardcoded and rotations are a bit tricky. I'll have a more thorough whenever I have the chance and probably patch that macro. It would probably require to draw the path twice. – percusse Aug 27 '12 at 22:37

Note: I finally found a solution myself... but I can not give me my own bounty. ;-)

I define three styles:

1. memoize points names each point of a path (with help of memoizepoints counter) and cumulates these names into a global macro (its argument).

2. cont memoize points is the same as memoize points, but without resetting the global macro (its argument).

3. init memoize points resets the global macro (its argument) and the memoizepoints counter.

Here is the preamble:

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


The memoizepoints counter and the three styles:

\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}{
\coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
\xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
}
},
curveto code={
\foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentsupporta,%
\tikzinputsegmentsupportb,\tikzinputsegmentlast}{
\coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
\xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
}
},
closepath code={
\foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentlast}{
\coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
\xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
}
},
},
},
},
memoize points/.style={init memoize points=#1,cont memoize points=#1},
}


Then an example followed by its code:

\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}

-
I can delete my answer if you like if the bounty is giving problems. I still didn't have the chance to have a look at it. – percusse Sep 2 '12 at 15:07
@percusse Don't delete your answer: it provides a half of the answer! The bounty is not a problem. ;-) – Paul Gaborit Sep 2 '12 at 15:25