16

What I want to do: Draw a node decorated with bumps, but with the decoration starting from the right (ie, opposite to the usual) of the node.

Why I want to do it: I will have a node hiding the part of the bumps that connects weirdly, but I want to be able to chose where this connection is made. Luckily, I only need "left of the node" and "right of the node".

What I thought was the solution: I thought I could use shape border rotate, so that only the border would be rotated. Define:

  \newcommand{\drawprost}[2][Prost!]{
    \node [draw,
           decorate,decoration={bumps,mirror},
           #2,
           postaction={decorate,decoration={markings,mark=at position 1 with
                        {\arrow[line width=5pt,blue]{>}}}}]
          {#1};}

Now the following two commands work as expected:

  \drawprost{shape=trapezium,shape border rotate=180}
  \drawprost{shape=trapezium,shape border rotate=0}

with the ugly blue arrow being rotated 180 degrees in the second drawing. But without shape=trapezium or with shape=ellipse, this fails miserably.

An ugly solution: The only solution I came up with is (using ellipse, otherwise I don't even have a solution):

  \drawprost[\phantom{Prost!}]{rotate=180,shape=ellipse,label=center:Prost!}

that is, phantoming the label, and redrawing it.

Question: Is there a better way to do it? Bonus point for a method that would shift the start of the decoration (rotate) at any given point :-)


Full code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations,decorations.pathmorphing,shapes,decorations.markings}

\begin{document}
\begin{tikzpicture}
  \newcommand{\drawprost}[2][Prost!]{
    \node [draw,
           decorate,decoration={bumps,mirror},
           #2,
           postaction={decorate,decoration={markings,mark=at position 1 with
                        {\arrow[line width=5pt,blue]{>}}}}]
          {#1};}

  \newlength\yshift
  % I get the expected result only with trapezium.
  \foreach \shape in {,shape=trapezium,shape=ellipse}
    \foreach \rotate in {0, 180}
    {
      \expandafter\drawprost\expandafter{%
        \shape,yshift=\yshift,shape border rotate=\rotate};
      \global\advance\yshift -2cm
    }

  % What I do want:
  \drawprost[\phantom{Prost!}]{yshift=\yshift,rotate=180,shape=ellipse,label=center:Prost!}
\end{tikzpicture}
\end{document}
7
  • Did you try the options shift only , pre and post stated in the manual for decorations?
    – percusse
    Commented Dec 5, 2011 at 21:43
  • To the extent of my knowledge, I did. Am I missing something?
    – Michaël
    Commented Dec 5, 2011 at 21:54
  • 1
    While code snippets are useful in explanations, it is always best to compose a fully compilable MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. Commented Dec 5, 2011 at 21:58
  • 1
    Sorry for my comment. That did not make too much sense. I was able to compile after some guessing, but I don't understand what I am seeing. What is the blue arrow and what should it look like? And if possible can you put a picture of what you want to achieve. It is kind of difficult to guess now.
    – percusse
    Commented Dec 5, 2011 at 22:13
  • Sorry for my imprecision. I've added the full code. What I want is the last drawing, but without \phantoming. Thanks!
    – Michaël
    Commented Dec 5, 2011 at 22:25

2 Answers 2

9

The source of the difficulty is that ellipses are constructed in a particular way in TikZ. They are paths that start from the x-axis and proceed counter-clockwise around their centre. The vast majority of the time, the exact parametrisation doesn't matter. You appear to have found the one situation where it does!

In the actual question, you only want to be able to mirror the ellipse, and so draw it starting from the negative x-axis (the title of the question suggests a more flexible approach). That's actually not too hard since we can exploit the symmetry of the ellipse. The key is to provide it with a negative x-radius, since then it will start from the negative x-axis (and proceed clockwise, but we could correct for that by negating the y-radius as well). To do this, we interrupt the call from the node shape to the drawing command and flip the sign of the x-radius. The simplest way to do this is to redefine the \pgfpathellipse macro to do the negation and then call the original macro. The following code does this.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations,shapes,decorations.markings}
\makeatletter
\let\origpgfpathellipse=\pgfpathellipse
\def\revpgfpathellipse#1#2#3{%
  #2%
  \pgf@xa=-\pgf@x
  \origpgfpathellipse{#1}{\pgfqpoint{\pgf@xa}{0pt}}{#3}}
\makeatother

\tikzset{
  reversed ellipse/.style={
    ellipse,
    reverse the ellipse%
  },
  reverse the ellipse/.code={
    \let\pgfpathellipse=\revpgfpathellipse
  }
}
\begin{document}
\begin{tikzpicture}
\node[ellipse,
  draw,
  postaction={
    decorate,
    decoration={
      markings,
      mark=at position 1 with {
        \arrow[line width=5pt,blue]{>}
      }
    }
  }
] at (0,0) {hello world};

\node[reversed ellipse,
  draw,
  postaction={
    decorate,
    decoration={
      markings,
      mark=at position 1 with {
        \arrow[line width=5pt,blue]{>}
      }
    }
  }
] at (0,-2) {hello world};
\end{tikzpicture}

\end{document}

Here's the result:

rotated ellipse

(the arrow got clipped, but you can see where it lies)

3

You could move the label to be part of the macro and then specifying the \phantom within the macro allows the width of the node to be computed:

enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations,decorations.pathmorphing,shapes,decorations.markings}

\newcommand{\drawprost}[2][Prost!]{
    \node [draw,
           decorate,decoration={bumps,mirror},
           #2, label=center:#1,
           postaction={decorate,decoration={markings,mark=at position 1 with
                        {\arrow[line width=5pt,blue]{>}}}}]
          {\phantom{#1}};}

\begin{document}
\begin{tikzpicture}
  \drawprost[Prost!]{rotate=180,shape=ellipse}
\end{tikzpicture}
\end{document}
2
  • Sorry, maybe I wasn't clear on my request: I want to avoid using phantom. I have the feeling that there is a TikZ way to do it, rather than this hack: In fact, I don't gather why it works with trapezium and not with ellipse, and think I'm missing something.
    – Michaël
    Commented Dec 6, 2011 at 2:47
  • 1
    @Michaël Well, the manual states "Some shapes (but not all), support a special kind of rotation. This rotation affects only the border of a shape and is independent of the node contents, but in addition to any other transformations." ellipse is problably on of the shapes for which it doesn't work, but I couldn't find a list of shapes for which it does. Commented Dec 6, 2011 at 9:29

You must log in to answer this question.

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