15

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}

enter image description here

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}

enter image description here

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}

enter image description here

2
  • Pour moi, c'est un bug
    – rpapa
    Commented Aug 27, 2012 at 19:16
  • The translation for the above comment is "For me, this is a bug". Commented Sep 7, 2012 at 9:08

2 Answers 2

9
+100

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}

enter image description here

5
  • 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. Commented Aug 27, 2012 at 0:09
  • I edited my question to clarify my request. Commented Aug 27, 2012 at 0:26
  • I think I missed it again. you want the blue rectangle rotated too right?
    – percusse
    Commented Aug 27, 2012 at 21:19
  • Yes: the two blue rectangles should be parallel and the second one should fit the red path. Commented Aug 27, 2012 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
    Commented Aug 27, 2012 at 22:37
5

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

Then an example followed by its code:

enter image description here

\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}
2
  • 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
    Commented Sep 2, 2012 at 15:07
  • @percusse Don't delete your answer: it provides a half of the answer! The bounty is not a problem. ;-) Commented Sep 2, 2012 at 15:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .