Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In TikZ, I sometimes want to rotate the text within a node and then position the node relative to another. However, the approach below doesn't work as expected:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [draw, right=of first, opacity=0.5] {2};
  \node [draw, rotate=90, right=of first] {2};
\end{tikzpicture}
\end{document}

enter image description here

To solve this, I wrap the rotating node inside another node which contains its own tikzpicture:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [draw, right=of first, opacity=0.5] {2};
  \node [right=of first] {
    \begin{tikzpicture}
      \node [draw, rotate=90] {2};    
    \end{tikzpicture}
  };
\end{tikzpicture}
\end{document}

enter image description here

This is better, but not exactly as I want it due to the inner sep of the wrapper node. Explicitly setting inner sep=0pt causes the inner node to get the same setting, which is not intended.

I figure there must be some better way of doing this. Any ideas?

Using anchors and rotation

Frédéric gave a nice solution to fix this problem by using anchors. However, I found it a bit hard to understand how it worked. With some experimentations I figured it out, and thought to include it here in case someone else have the same problem.

When using relative positioning (e.g. \node [left= of ...] {};), a point of rotation will implicitly be specified on the node. For instance, if we say left=of ... then the rotation will be around node.east, and with above right=of ... the point of rotation will be around node.south west (see below).

enter image description here

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning, decorations.markings}
\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \foreach \o [count=\oi from 0] in {0.1, 0.15, 0.3, 0.5, 1} {%
    \pgfmathtruncatemacro{\angle}{90 * \oi/4}
    \node [draw, right=of first, opacity=\o, rotate=\angle] (second\oi) {2};
    \coordinate (second_rotated_center) at (second\oi.center);
  }
  \begin{scope}[red, very thin]
    \node at (second0.west) {
      \begin{tikzpicture}[scale=0.02, very thin]
        \draw (-1, -1) -- (1,  1);
        \draw (-1,  1) -- (1, -1);
      \end{tikzpicture}
    };
    \begin{scope}[dash pattern=on 0.1mm off 0.1mm]
      \draw (second0.west) -- (second0.center);
      \draw (second0.west) -- (second_rotated_center);
    \end{scope}
    \draw ([yshift=0.5mm] second0.west)
      -- ([yshift=0.5mm, xshift=0.5mm] second0.west)
      -- ([xshift=0.5mm] second0.west);
    \draw [>=stealth,
           decoration={markings, mark=at position 1 with
             {\arrow[scale=0.5]{>}}}, 
           postaction={decorate}]
      (second0.center) to [bend right=45] (second_rotated_center);
  \end{scope}
\end{tikzpicture}
\end{document}

This is why we don't get the desired result with [rotate=90, right=of first].

By specifying an anchor, we say which point to use on the node when doing the relative positioning. Hence, with \node [right=of first, anchor=north], we say "place the node right of first such that the node's north anchor is at the appropriate distance away from first". Left alone, this will cause the entire node to end up below and slightly to the left of where we want it. However, if we now do rotate=90, it will rotate into the position where we want it since we are rotating around the node's north anchor. Note also that the anchor must be declared after the positioning.

enter image description here

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning, decorations.markings}
\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \foreach \o [count=\oi from 0] in {0.1, 0.15, 0.3, 0.5, 1} {%
    \pgfmathtruncatemacro{\angle}{90 * \oi/4}
    \node [draw, right=of first, opacity=\o, rotate=\angle, anchor=north] (second\oi) {2};
    \coordinate (second_rotated_center) at (second\oi.center);
  }
  \begin{scope}[red, very thin]
    \node at (second0.north) {
      \begin{tikzpicture}[scale=0.02, very thin]
        \draw (-1, -1) -- (1,  1);
        \draw (-1,  1) -- (1, -1);
      \end{tikzpicture}
    };
    \begin{scope}[dash pattern=on 0.1mm off 0.1mm]
      \draw (second0.north) -- (second0.center);
      \draw (second0.north) -- (second_rotated_center);
    \end{scope}
    \draw ([yshift=-0.5mm] second0.north)
      -- ([yshift=-0.5mm, xshift=0.5mm] second0.north)
      -- ([xshift=0.5mm] second0.north);
    \draw [>=stealth,
           decoration={markings, mark=at position 1 with
             {\arrow[scale=0.5]{>}}}, 
           postaction={decorate}]
      (second0.center) to [bend right=45] (second_rotated_center);
  \end{scope}
\end{tikzpicture}
\end{document}
share|improve this question
    
if you add anchor=base to the nodes in your first example, it rotates more or less at the current location. But the unrotated one shifts a little higher. So use it only when you want to rotate it, –  percusse Feb 26 '12 at 15:24
    
That's really good doing the follow-up investigation, but I'd like to quibble with just one bit. The right=of ... doesn't set a "point of rotation". The node is rotated about its centre. But it is then translated so that the specified anchor is at the specified coordinate, giving the impression that it has been rotated about that anchor. What right=of ... does implicitly is to set this anchor and the anchor=... overrides this. You can see this because if you put the anchor=north first then it is ignored. –  Loop Space Feb 27 '12 at 10:50
    
@AndrewStacey: Yeah, I suspected I wouldn't get it 100% correct when I wrote it, but better make a failed attempt than no attempt at all. ^^ Unfortunately, I don't really understand your explanation. More specifically, I don't get how the node being rotated around its center is connected with it being "then translated so that the specified anchor is at the specified coordinate". Could you please explain further? If you find it easier, you may edit my question to illustrate your point. –  gablin Feb 27 '12 at 12:27
2  
Nice follow up. –  Frédéric Feb 27 '12 at 13:36

5 Answers 5

up vote 16 down vote accepted

method 1 You may achieve some of what you want by changing the anchor point of the node. In addition you may also change the outer sep or use xshift, yshiftor shift. Be careful with the shiftcommands: the order in which they appear in the node settings has an effect on the result. For example:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [draw, right=of first, opacity=0.5] {2};
  \node [draw=red, right=of first,rotate=90,anchor=north] {2};    
  \node [draw=blue, right=of first,rotate=90,anchor=north,outer sep=-4pt] {2};
  \node [draw=green, right=of first,xshift=-0.4cm,rotate=90,anchor=north] {2};    
  \node [draw=cyan, right=of first,rotate=90,anchor=north,xshift=-0.4cm] {2};    


\end{tikzpicture}
\end{document}

The result is

enter image description here

method 2 This is a modification of the answer from ignasi: rotate the text within the node and also specifying a minimum size for the node. Specifying a minimum size makes sure the node is square.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[every node/.style={minimum size=1cm}]
  \node [draw] (first) {1};
  \node [draw, right=of first, opacity=0.5] {2};
  \node [draw, right=of first] {\rotatebox{90}{2}};
\end{tikzpicture}

\end{document}

The result is

enter image description here

share|improve this answer
    
I like method one. The point is that right=of first does two things: it computes the coordinate of the new node and sets the anchor of the new node accordingly. The rotation doesn't change this anchor, so effectively rotates about the anchor. Explicitly resetting the anchor afterwards corrects for this. One could imagine a complicated setup which extended the rotate key by making it also rotate the anchor, but in the meantime explicitly saying anchor=north is probably the simplest. –  Loop Space Feb 27 '12 at 10:33

If you want to rotate it exactly around the position where it would have been placed non-rotated you could use this approach:

Place the node unrotated with opacity=0.0 and store the coordinates at tmp Place your rotated node at tmp and rotate it with rotate around.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [right=of first, opacity=0.0] (tmp) {2};
  \node [draw, rotate around={90:(tmp.center)}] at (tmp) {2};
\end{tikzpicture}

\end{document}

As mentioned, the problem ist that the text has to be typed twice. A solution would be to define a macro:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

% Usage: \rotnode[options]{rotation}{text}
\newcommand\rotnode[3][]{%
  \node [#1, opacity=0.0] (tmp) {#3};
  \node [draw, rotate around={#2:(tmp.center)}] at (tmp) {#3};
}

\begin{document}

\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [draw,right=of first, opacity=0.5] (tmp) {2};
  \rotnode[right=of first]{90}{2};
\end{tikzpicture}

\end{document}

example

share|improve this answer
1  
Yes this is a good method. –  Alain Matthes Feb 26 '12 at 22:27
    
Clever, but the problem with this is that you have to repeat the text content twice. So if you want to modify the text, you have to remember to do the change in both nodes. –  gablin Feb 27 '12 at 8:37
    
Yes, that's true. I added a simple macro definition –  ejoerns Feb 27 '12 at 9:02

Another option would be to just rotate the text inside the node.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
  \node [draw] (first) {1};
  \node [draw, right=of first, opacity=0.5] {2};
  \node [draw, right=of first] {\rotatebox{90}{2}};
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer

First remark : The use of positioning is only useful here with the option on grid because after the rotation the distance between the two nodes are different from the initial distance. With on grid the distance is between the centers. In the two methods, the use of coordinate avoids the use opacity=0

Two methods, first one with the old manner right of= first. The code uses only one line \path coordinate [right of =first] (tmp) ...

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}
  \node [draw] (first) {1};  
  \node [draw,right of= first, opacity=0.5]  {2}; 
  \path  coordinate [right of =first] (tmp) node [draw, rotate around={90:(tmp.center)}] at (tmp) {2};
\end{tikzpicture}    

\end{document} 

Second method with positioning and on grid. Here the line begins with : \path coordinate [on grid,right= of first] (tmp) ...

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}
  \node [draw] (first) {1};  
  \node [on grid,draw,right= of first, opacity=0.5]  {2}; 
  \path  coordinate [on grid,right= of first] (tmp) node [draw, rotate around={90:(tmp.center)}] at (tmp) {2};
\end{tikzpicture}     
\end{document} 

In each case the result is the same :

enter image description here

share|improve this answer

A simple(ish) way is to use intermediate coordinate nodes:

\begin{tikzpicture}
% Node 1
  \node [coordinate] (a) {};
  \node [draw] at (a) {1};
% Node 2
  \node [coordinate, right=of a] (a) {};
  \node [draw, opacity=0.5] at (a) {2};
  \node [draw, rotate=90] at (a) {2};
% Node 3
  \node [coordinate, right=of a] (a) {};
  \node [draw, opacity=0.5] at (a) {3};
  \node [draw, rotate=90] at (a) {3};
\end{tikzpicture}

Note that the (a) coordinate name is re-usable, provided you "keep things in order".

I recognise that the internode spacing is different, so you may need to add a global node distance qualifier.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.