12

This question is related to the one here. The question is given in the following text.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{mindmap,arrows}
\usepackage{graphicx}

\tikzset{
  ld/.style={level distance=#1},lw/.style={line width=#1},
  level 1/.style={ld=4.5mm, trunk, lw=1ex ,sibling angle=60},
  level 2/.style={ld=3.5mm, trunk!80!leaf a,lw=.8ex,sibling angle=56},
  level 3/.style={ld=2.75mm,trunk!60!leaf a,lw=.6ex,sibling angle=52},
  level 4/.style={ld=2mm, trunk!40!leaf a,lw=.4ex,sibling angle=48},
  level 5/.style={ld=1mm, trunk!20!leaf a,lw=.3ex,sibling angle=44},
  level 6/.style={ld=1.75mm,leaf a, lw=.2ex,sibling angle=40},
}
\pgfarrowsdeclare{leaf}{leaf}{
  \pgfarrowsleftextend{-2pt} \pgfarrowsrightextend{1pt}
}{
  \pgfpathmoveto{\pgfpoint{-2pt}{0pt}}
  \pgfpatharc{150}{30}{1.8pt}
  \pgfpatharc{-30}{-150}{1.8pt}
  \pgfusepathqfill
}

\makeatletter
\def\agobble#1\nil#2{}
\def\mytextcolor@a#1 #2\nil#3{%
  \mytextcolor@b#1\nil{#3}
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2\nil{#3}%
}
\def\mytextcolor@b#1#2\nil#3{%
  \textcolor{-#3}{\textbf{#1}}\textcolor{#3}{#2}\\
}
\def\mytextcolor#1#2{%
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2 \nil{#1}%
}

\newcommand{\logo}[8]{%
  \colorlet{border}{#1}
  \colorlet{trunk}{#2}
  \colorlet{leaf a}{#3}
  \colorlet{leaf b}{#4}
  % Question:
  % Which tikz feature can I use in place of the following \rotatebox
  % to avoid double rotation in the tikzpicture?
%  \rotatebox{#8}{%
    % One rotation is here:
    \begin{tikzpicture}[rotate=#8,font=\scriptsize\scshape]
      \draw[border,line width=1ex,yshift=.3cm,
        yscale=1.45,xscale=1.05,looseness=1.42]
        (1,0) to [out=90, in=0] (0,1) to [out=180,in=90] (-1,0)
        to [out=-90,in=-180] (0,-1) to [out=0, in=-90] (1,0) -- cycle;
      \coordinate (root) [grow cyclic,rotate=90]
        child {
          child [line cap=round] foreach \a in {0,1} {
            child foreach \b in {0,1} {
              child foreach \c in {0,1} {
                child foreach \d in {0,1} {
                child foreach \leafcolor in {leaf a,leaf b}
                  { edge from parent [color=\leafcolor,-#5] }
                }
              }
            }
          }
          edge from parent [shorten >=-1pt,serif cm-,line cap=butt]
        };
      % Another rotation here:
      \node [rotate=#8,scale=1,align=center,below] at (0pt,-.5ex){%
        \mytextcolor{#6}{#7}\\
      };
    \end{tikzpicture}
%  }
}
\makeatother

\begin{document}
\begin{minipage}[c]{\textwidth}
\centering
\logo{green!80!black}{green!25!black!75}{green}{green!80}{leaf}
  {border}{Theoretical Computer Science}{45}
\logo{purple!80!black}{purple!25!black!75}{purple}{purple!80}{leaf}
  {border}{Theoretical Computer Science}{45}
\end{minipage}
\end{document}

EDIT

The "double rotation" spots are shown above. I want to indicate only one rotation for the entire figure, because my figure contains many other nodes.

enter image description here

EDIT

The environment scope doesn't rotate the entire picture. Andrew Stacey has confirmed in the comments that this is indeed the case.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{mindmap,arrows}
\usepackage{graphicx}

\tikzset{
  ld/.style={level distance=#1},lw/.style={line width=#1},
  level 1/.style={ld=4.5mm, trunk, lw=1ex ,sibling angle=60},
  level 2/.style={ld=3.5mm, trunk!80!leaf a,lw=.8ex,sibling angle=56},
  level 3/.style={ld=2.75mm,trunk!60!leaf a,lw=.6ex,sibling angle=52},
  level 4/.style={ld=2mm, trunk!40!leaf a,lw=.4ex,sibling angle=48},
  level 5/.style={ld=1mm, trunk!20!leaf a,lw=.3ex,sibling angle=44},
  level 6/.style={ld=1.75mm,leaf a, lw=.2ex,sibling angle=40},
}
\pgfarrowsdeclare{leaf}{leaf}{
  \pgfarrowsleftextend{-2pt} \pgfarrowsrightextend{1pt}
}{
  \pgfpathmoveto{\pgfpoint{-2pt}{0pt}}
  \pgfpatharc{150}{30}{1.8pt}
  \pgfpatharc{-30}{-150}{1.8pt}
  \pgfusepathqfill
}

\makeatletter
\def\agobble#1\nil#2{}
\def\mytextcolor@a#1 #2\nil#3{%
  \mytextcolor@b#1\nil{#3}
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2\nil{#3}%
}
\def\mytextcolor@b#1#2\nil#3{%
  \textcolor{-#3}{\textbf{#1}}\textcolor{#3}{#2}\\
}
\def\mytextcolor#1#2{%
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2 \nil{#1}%
}

\newcommand{\logo}[8]{%
  \colorlet{border}{#1}
  \colorlet{trunk}{#2}
  \colorlet{leaf a}{#3}
  \colorlet{leaf b}{#4}
%  \rotatebox{#8}{%
    \begin{tikzpicture}[font=\scriptsize\scshape]
      \begin{scope}[rotate=#8]
      \draw[border,line width=1ex,yshift=.3cm,
        yscale=1.45,xscale=1.05,looseness=1.42]
        (1,0) to [out=90, in=0] (0,1) to [out=180,in=90] (-1,0)
        to [out=-90,in=-180] (0,-1) to [out=0, in=-90] (1,0) -- cycle;
      \coordinate (root) [grow cyclic,rotate=90]
        child {
          child [line cap=round] foreach \a in {0,1} {
            child foreach \b in {0,1} {
              child foreach \c in {0,1} {
                child foreach \d in {0,1} {
                child foreach \leafcolor in {leaf a,leaf b}
                  { edge from parent [color=\leafcolor,-#5] }
                }
              }
            }
          }
          edge from parent [shorten >=-1pt,serif cm-,line cap=butt]
        };
      \node [scale=1,align=center,below] at (0pt,-.5ex){%
        \mytextcolor{#6}{#7}\\
      };
    \end{scope}
    \end{tikzpicture}
%  }
}
\makeatother

\begin{document}
\begin{minipage}[c]{\textwidth}
\centering
\logo{green!80!black}{green!25!black!75}{green}{green!80}{leaf}
  {border}{Theoretical Computer Science}{45}
\logo{purple!80!black}{purple!25!black!75}{purple}{purple!80}{leaf}
  {border}{Theoretical Computer Science}{45}
\logo{purple!80!black}{purple!25!black!75}{purple}{purple!80}{leaf}
  {border}{}{45}
\end{minipage}
\end{document}
7
  • Could you add a picture showing the double rotation that you'd like to avoid? I get what looks like reasonable output with the code you post, but the rotate=#8 key in the node makes me a little hesitant as to whether what I think is reasonable is what I'm meant to be seeing. Aug 15, 2012 at 16:29
  • You can replace rotate=#8 in the node by transform shape but I'm not sure to understand the question. Aug 15, 2012 at 16:34
  • You could put everything into a scope and rotate that.
    – bodo
    Aug 15, 2012 at 16:49
  • 1
    Ah, now I understand. I thought that something was getting rotated twice but you mean that you have to specify the rotation twice. In that case, I would try every node/.append style={transform shape} or every node/.append style={rotate=#8}. Aug 15, 2012 at 16:54
  • 1
    Did you try the transform shape key? The scope wouldn't work: a node is never transformed unless explicitly told to either by putting the transformation in its key list (directly, as your original solution, or indirectly via every node) or by using the magic key transform shape. Aug 15, 2012 at 19:10

2 Answers 2

9

The node shape is almost like a standalone TikZ picture and before starting to draw the node shape, the transformation matrix is reset to identity matrix. Here are a couple of different cases

\begin{tikzpicture}[rotate=45,every node/.style={draw}]
\node (a) {A};
\node (b) at (1,0) {B};                   % Location obeys the transform
\node[transform shape] (c) at (-1,0) {C}; % Transformation is passed to the node too
\pgflowlevel{\pgftransformrotate{-45}}    % Works directly on the canvas,overrides anything, 
                                          % added to the current transformation, and 
                                          % the bounding box is not updated.
\node (d) at (1,0) {D}; 
\end{tikzpicture}

enter image description here

2
  • Thanks. I am new to PGF and hadn't reached \pgflowlevel and \pgftransformrotate.
    – Ahmed Musa
    Aug 16, 2012 at 1:32
  • @AhmedMusa I'm sure it won't take too much time for you to start reading the source code and delve into the relevant keys :) So it's just a little overhead.
    – percusse
    Aug 16, 2012 at 1:34
5

How about this:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{mindmap,arrows}
\usepackage{graphicx}

\tikzset{
  ld/.style={level distance=#1},lw/.style={line width=#1},
  level 1/.style={ld=4.5mm, trunk, lw=1ex ,sibling angle=60},
  level 2/.style={ld=3.5mm, trunk!80!leaf a,lw=.8ex,sibling angle=56},
  level 3/.style={ld=2.75mm,trunk!60!leaf a,lw=.6ex,sibling angle=52},
  level 4/.style={ld=2mm, trunk!40!leaf a,lw=.4ex,sibling angle=48},
  level 5/.style={ld=1mm, trunk!20!leaf a,lw=.3ex,sibling angle=44},
  level 6/.style={ld=1.75mm,leaf a, lw=.2ex,sibling angle=40},
}
\pgfarrowsdeclare{leaf}{leaf}{
  \pgfarrowsleftextend{-2pt} \pgfarrowsrightextend{1pt}
}{
  \pgfpathmoveto{\pgfpoint{-2pt}{0pt}}
  \pgfpatharc{150}{30}{1.8pt}
  \pgfpatharc{-30}{-150}{1.8pt}
  \pgfusepathqfill
}

\makeatletter
\def\agobble#1\nil#2{}
\def\mytextcolor@a#1 #2\nil#3{%
  \mytextcolor@b#1\nil{#3}
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2\nil{#3}%
}
\def\mytextcolor@b#1#2\nil#3{%
  \textcolor{-#3}{\textbf{#1}}\textcolor{#3}{#2}\\
}
\def\mytextcolor#1#2{%
  \if\relax\detokenize{#2}\relax\expandafter\agobble\fi
  \mytextcolor@a#2 \nil{#1}%
}

\newcommand{\logo}[8]{%
  \colorlet{border}{#1}
  \colorlet{trunk}{#2}
  \colorlet{leaf a}{#3}
  \colorlet{leaf b}{#4}
%  \rotatebox{#8}{%
%    \begin{tikzpicture}[font=\scriptsize\scshape]
      \begin{scope}[shift={(#8)}]
      \draw[border,line width=1ex,yshift=.3cm,
        yscale=1.45,xscale=1.05,looseness=1.42]
        (1,0) to [out=90, in=0] (0,1) to [out=180,in=90] (-1,0)
        to [out=-90,in=-180] (0,-1) to [out=0, in=-90] (1,0) -- cycle;
      \coordinate (root) [grow cyclic,rotate=90]
        child {
          child [line cap=round] foreach \a in {0,1} {
            child foreach \b in {0,1} {
              child foreach \c in {0,1} {
                child foreach \d in {0,1} {
                child foreach \leafcolor in {leaf a,leaf b}
                  { edge from parent [color=\leafcolor,-#5] }
                }
              }
            }
          }
          edge from parent [shorten >=-1pt,serif cm-,line cap=butt]
        };
      \node [scale=1,align=center,below,transform shape] at (0pt,-.5ex){%
        \mytextcolor{#6}{#7}\\
      };
    \end{scope}
%    \end{tikzpicture}
%  }
}
\makeatother

\begin{document}
\begin{minipage}[c]{\textwidth}
\centering
\begin{tikzpicture}[font=\scriptsize\scshape,rotate=45]
\logo{green!80!black}{green!25!black!75}{green}{green!80}{leaf}
  {border}{Theoretical Computer Science}{0,0}
\logo{purple!80!black}{purple!25!black!75}{purple}{purple!80}{leaf}
  {border}{Theoretical Computer Science}{3,0}
\logo{purple!80!black}{purple!25!black!75}{purple}{purple!80}{leaf}
  {border}{}{6,0}
\end{tikzpicture}  
\end{minipage}
\end{document}

enter image description here

  • I removed the \begin{tikzpicture} and \end{tikzpicture} from the \logo command, so now you can't use it outside a tikzpicture environment anymore
  • I redefined parameter #8 to be a shift rather than a rotation
  • The rotation is now added to the tikzpicture enclosing all \logo commands
  • the transform shape is neccessary for the node texts to be rotated also
2
  • Great solution. The point was to avoid repeating transform shape and rotate per node.
    – Ahmed Musa
    Aug 16, 2012 at 1:34
  • If you don't want to set transform shape in every node, you could use the every node style via every node/.style={transform shape} Aug 17, 2012 at 15:41

You must log in to answer this question.

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