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.

Friends, consider the following code:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on} (q1)
           (q1) edge [bend left] node {off} (q0)
;
\end{tikzpicture}

\end{document}

This code produces the following output:

Automaton

Pretty straightforward, I guess. :) I was wondering if it would be possible to add a second label to each one of those paths in a way I don't need to calculate their coordinates and hardcode them into the picture. My idea for a second label would is to put the text in the opposite direction of the primary label. :)

As a bonus, I was wondering how challenging would be to make the second label a little different than the first one, say, like this gimp'ed image:

Second image

Any hints on how to achieve this? :) I am already happy if a second label is possible, even without these bells and whistles.

share|improve this question
2  
I'm not sure if this suffices your demands, but you could just specify a second node with [above] or below the path. This wouldn't be totally automatic but far away from hardcoded. Yor path would look like this: \path[->] (q0) edge [bend left] node[above] {on} node[below] {a} (q1) (q1) edge [bend left] node[below] {off} node[above] {a} (q0); This produces the two a nodes on the inner sides of the edges. –  Dave Jun 12 at 22:24
    
@Dave: silly me, I had no idea of using a node (living and learning)! Perhaps you could convert your comment to an answer? I think it's a valid approach towards solving my question (of course, it's up to you). Thank you! Edit: actually, one the answers use this very approach, oopsie. But I really appreciate your comment! :) –  Paulo Cereda Jun 13 at 9:34
    
I simply forgot to check this here since I had to do some work yesterday. I'm glad you got your answer anyway :) –  Dave Jun 14 at 12:17
1  
@Dave: thank you for the initial insight! :) –  Paulo Cereda Jun 14 at 13:20

5 Answers 5

up vote 2 down vote accepted

Here is another idea, using pic (requires PGF 3.0.0)

The code which draws the "status" (on/off), and the additional char (a), and the little arrow, is all encapsulated in a pic style, which gets as two arguments the text to show in the "status" and in the "char". We need in fact two different pics, depending on the relative position of "status" and "char".

Defining pics with two arguments is a little more complex than single-argument pics, because the shortcut foo/.pic allows only for a single argument. So we have to go the "low level" pics/foo/.style, but still it is very straightforward:

\tikzset{
  pics/second label below/.style 2 args = {
   code = {
    \node[above] (-status) {#1};
    \node[below=3mm, inner sep=1pt] (-char) {\small #2};
    \draw[->] (0,0) -- (-char);
    }
  },
  pics/second label above/.style 2 args = {
   code = {
    \node[below] (-status) {#1};
    \node[above=3mm, inner sep=1pt] (-char) {\small #2};
    \draw[->] (0,0) -- (-char);
    }
  }
}

This pic can be used like this:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] pic {second label below={on}{a}} (q1)
           (q1) edge [bend left] pic {second label above={off}{a}} (q0)
;
\end{tikzpicture}

And produces:

Result

As a bonus, it can be used at other positions of the curve, and it works too:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] pic[pos=0.8] {second label below={on}{a}} (q1)
           (q1) edge [bend left] pic[pos=0.8] {second label above={off}{a}} (q0)
;
\end{tikzpicture}

Result 2

share|improve this answer
    
Oh my, this is truly awesome! :) –  Paulo Cereda Jun 13 at 9:40

You can use swap or the shorthand ' to put the second label in the opposite direction of the first one:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on} node [swap] {a} (q1)
          (q1) edge [bend left] node {off} node [swap] {a} (q0)
;
\end{tikzpicture}

\end{document}

enter image description here

Maybe you can enlarge the outer sep to shift the second node:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start},
    secn/.style={swap,outer sep=5pt}
]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on}node[secn]{a} (q1)
          (q1) edge [bend left] node {off}node[secn]{a} (q0)
;
\end{tikzpicture}

enter image description here

share|improve this answer
    
How nice, I had no idea there was a swap option! –  Paulo Cereda Jun 13 at 9:36

Another alternative is use of label distance=xxcm and below/above:text, as displayed below. In the direction from q0 to q1 the label a is allocated below of the path, hence the key below is used, actually, left, right, above right and more can be an option too. Utilizing the same idea, the path from q1 to q0 the label a is above the path, hence the key above is used.

node[label={[label distance=0.5cm] below:a}] 

enter image description here

Code

\documentclass[border=10pt]{standalone}%{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] 
node[label={[label distance=0.5cm] below:a}] {on} (q1)
          (q1) edge [bend left] 
node[label={[label distance=0.5cm] above:a}] {off} (q0)
;
\end{tikzpicture}

\end{document}
share|improve this answer
    
Oh my, it looks very interesting! Thank you! :) –  Paulo Cereda Jun 13 at 9:36
    
You are welcome.:-) –  Jesse Jun 13 at 10:05

As none of the existing answers show how to draw the little arrowed paths tangent to the curved ones, let me stole some code from Jake, namely: How to draw tangent line of an arbitrary point on a path in TikZ.

\documentclass[border=10pt,tikz]{standalone}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{decorations.markings}% we need this library
\usetikzlibrary{positioning}

\tikzset{tangent/.style={
        decoration={
            markings,% switch on markings
            mark=
                at position #1
                with
                {
                    \coordinate (tangent point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt);
                    \coordinate (tangent unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt);
                    \coordinate (tangent orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1);
                }
        },
        postaction=decorate
    },
    use tangent/.style={
        shift=(tangent point-#1),
        x=(tangent unit vector-#1),
        y=(tangent orthogonal unit vector-#1)
    },
    use tangent/.default=1
}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};

\path[->] (q0) edge [bend left,tangent=0.5] node {on} (q1);
\draw[->, thick, use tangent] (0,0) --++ (0,-0.25) node[below]{a};

\path[->] (q1) edge [bend left,tangent=0.5] node {off} (q0);
\draw[->, thick, use tangent] (0,0) --++ (0,-0.25) node[above]{a};

\end{tikzpicture}

\end{document}

The result:

enter image description here

share|improve this answer
    
ooh TikZ magic going on! Grazie, Claudio! :) –  Paulo Cereda Jun 13 at 9:37
    
@PauloCereda: you're always welcome! I've seen Brazil managed to win the first match in World Cup.. though the penalty was too generous ;) –  Claudio Fiandrino Jun 13 at 9:43
    
egreg and I were talking in the chatroom that, given the past penalty shootouts, we were likely to miss that one (Neymar almost missed it). :) It wasn't a penalty at all, thankfully Oscar scored the 3rd goal. :) I am waiting for the big game on Saturday. Avanti, Azzurra! :) –  Paulo Cereda Jun 13 at 9:55

With minimal modification, using the pin option

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start},
pin edge={bend left=0,black, thick},
pin distance=3mm,
every pin/.style={font=\small, inner sep=1pt},
point/.style={inner sep=0, outer sep=0, minimum size=0}
]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node[pos=.3] {on} node[point,pin=below:a,pos=.2] {} (q1)
           (q1) edge [bend left] node {off} node[point,pin=above:b] {} (q0)
;
\end{tikzpicture}

\end{document}

If you vary the value of pos you can shift the pin along the path and the arrow will follow it.

preview

share|improve this answer
    
Does anybody know why using coordinate instead of node[point] results in a double arrow for the pin? –  Bordaigorl Jun 13 at 10:36
    
Oh my, another neat trick! Thank you! :) –  Paulo Cereda Jun 13 at 12:09

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.