14

This code

\documentclass[border=2mm]{standalone}
\usepackage{libertine}
\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \sffamily
        \draw[very thick, label=below:{Darnay}] (0,-1) -- (0,-3);
        \draw[very thick, rotate=120, label=above left:{Lorry}] (0,-1) -- (0,-3);
        \draw[very thick, rotate=240, label=above right:{Stryver}] (0,-1) -- (0,-3);
        \node at (0,0) {Carton};
    \end{tikzpicture}
\end{document}

produces this result:

Carton

What I'm aiming for is for the labels indicated in the code to appear at the end of the respective lines, but that's not happening. Based on this answer I thought I knew what I was doing, but maybe I misread it?

Also, can I associate further labels with the lines (say, halfway along each one), or do I need to create separate nodes and place them individually?

crmdgn
  • 2,628

2 Answers2

16

A path is not a plot and the options which apply to one do not necessarily apply to the other. You need to create nodes or coordinates and/or labels or use edge and labels or.... There are many ways.

However, you can do all this as part of the path specification with \draw. I've also moved very thick to an option for the picture to avoid repeating it.

For example:

\documentclass[border=2mm,tikz]{standalone}
\usepackage{libertine}

\begin{document}
\begin{tikzpicture}[very thick]
  \sffamily

  \draw (0,-1) -- (0,-3) node [label=below:{Darnay}] {};

  \draw[rotate=120] (0,-1) -- (0,-3) node [label=above left:{Lorry}] {};

  \draw[rotate=240] (0,-1) -- (0,-3) node [midway, label=right:Plane] {} node [pos=.75, label=right:Van] {} node [label=above right:{Stryver}] {};

  \node at (0,0) {Carton};
\end{tikzpicture}
\end{document}

By default a node is placed at the last position e.g, where the path just ended. [It is a bit more complex than this, but this is enough for our purposes here.] But you can override this with position specifiers e.g. midway or near end or pos=.04.

labelled carton

EDIT

Here's a more complex method which places both node labels and edge labels using the quotes library to enable the every edge quotes style and the use of "<label>" shorthand.

\documentclass[border=2mm,tikz]{standalone}
\usepackage{libertine}
\usetikzlibrary{quotes}
\begin{document}
\begin{tikzpicture}
  [
    very thick,
    every edge quotes/.append style={auto, text=blue}
  ]
  \sffamily

  \draw (0,0) node {Carton}
  (0,-1) edge ["Here"] node [at end, label=below:{Darnay}] {}  (0,-3)
  edge [rotate=120, "There"'] node [at end, label=above left:{Lorry}] {} (0,-3)
  edge [rotate=240, "Everywhere", "Plane"', "Van"' pos=0.8] node [at end, label=above right:{Stryver}] {} (0,-3)
  ;
\end{tikzpicture}
\end{document}

edgier carton

What does this do?

\usetikzlibrary{quotes}

enables the use of the shorthand and style as explained above.

  [
    very thick,
    every edge quotes/.append style={auto, text=blue}
  ]

sets options for the whole picture: drawn paths should be very thick and all nodes placed as edge labels using the quotes syntax should be auto placed with blue text. Generally, this will place the labels in an acceptable place (above, below, right, left depending on context), but we can reverse this for a particular case using ' after the "<label>" to put it on the opposite side i.e. "<auto-placed label>" "<switched label>"'.

The entire diagram is drawn as a single path using \draw. We start at the origin and immediately create the first node containing the text Carton:

  \draw (0,0) node {Carton}

now we move to (0,-1) but we don't want this move to be drawn, so we just move there:

  (0,-1) 

Everything else radiates from this point in different directions. edge is perfect here because every edge will start from the same position, but can then do its own thing. The first one is going to go to (0,-3). We'll put the node with the label beneathat endand we'll create a labelHere` using the quotes syntax on the way:

  edge ["Here"] node [at end, label=below:{Darnay}] {}  (0,-3)

Since we didn't change anything, Here will be auto placed to the right and will be at the midway point, as that's the default. Now for the second edge, which is rotated:

  edge [rotate=120, "There"'] node [at end, label=above left:{Lorry}] {} (0,-3)

This time, the auto placement would put the label on the left, but we want the label on the right, so we add the ' after "There" to switch the side. The third is the most complex:

  edge [rotate=240, "Everywhere", "Plane"', "Van"' pos=0.8] node [at end, label=above right:{Stryver}] {} (0,-3)

The node at the end is placed as before and the first label, Everywhere is placed in the default position i.e. left in this case, at the halfway point. Plane is halfway, too, but it is on the right, because we've added '. Van is also flipped to the right, but it is further along the edge since pos=0.8, where 0 is the starting point and 1 is where the edge ends.

Finally, we end the \draw operation:

  ;

EDIT EDIT

Zarko is correct in pointing out that it isn't really necessary to use labels for the nodes at the end because the text can go into the node itself. However, some adjustment is needed to simulate the existing spacing because label nodes are placed at a certain distance from the nodes they label, whereas the nodes they label are not.

This uses the positioning library which isn't strictly needed here but seems to give a more visually pleasing result:

\documentclass[border=2mm,tikz]{standalone}
\usepackage{libertine}
\usetikzlibrary{quotes,positioning}
\begin{document}
\begin{tikzpicture}
  [
    very thick,
    every edge quotes/.append style={auto, text=blue}
  ]
  \sffamily

  \draw (0,0) node {Carton}
  (0,-1) edge ["Here"] node [at end, below=10pt] {Darnay}  (0,-3)
  edge [rotate=120, "There"'] node [at end, above left=10pt] {Lorry} (0,-3)
  edge [rotate=240, "Everywhere", "Plane"', "Van"' pos=0.8] node [at end, above right=10pt] {Stryver} (0,-3)
  ;
\end{tikzpicture}
\end{document}

labels in nodes

cfr
  • 198,882
  • good explanation! I only wonder, why to use labels in node and have empty node contents if node text is placed on the same place as it is with labels? By this the code is slightly shorter: ... edge ["Here"] node [at end,below] {Darnay} (0,-3) instead ... edge ["Here"] node [at end, label=below:{Darnay}] {} (0,-3). – Zarko Nov 21 '15 at 01:02
  • @Zarko Just, I think, because I started with the OP's code and then I got very excited by edges and forgot about the nodes. – cfr Nov 21 '15 at 01:18
  • @Zarko I've added another version. Not sure whether it is actually shorter. But it is arguably conceptually simpler, which probably makes it the superior approach here. – cfr Nov 21 '15 at 01:30
  • 2
    if it will be allowed, I will vote for your answer again! – Zarko Nov 21 '15 at 03:00
  • Zarko ;). I don't think it will be allowed, but I believe it is the thought which counts in voting, as in gifts of all kinds! – cfr Nov 21 '15 at 03:14
5

Yes, you can associate further labels with the lines at whatever position you want. This is simply by defining a new macro similar to the one in that answer, with mark=at position #1 customized for your need. So, the new macro here accepts two arguments; one for position and another for content (label/.style args={#1#2}{...}).

\documentclass[border=2mm,tikz]{standalone}
\usetikzlibrary{decorations.markings}
\usepackage{libertine}

\begin{document}
    \begin{tikzpicture}[label/.style args={#1#2}{%
    postaction={ decorate,
    decoration={ markings, mark=at position #1 with \node #2;}}}]
        \sffamily
        \draw[very thick, label={1}{[below]{Darnay}}] (0,-1) -- (0,-3);
        \draw[very thick, label={.5}{{Darnay 2}}] (0,-1) -- (0,-3);
        \draw[very thick, rotate=120, label={1}{[above right]{Lorry}}](0,-1) -- (0,-3);
        \draw[very thick, rotate=240, label={1}{[above left]{Stryver}}](0,-1) -- (0,-3);
        \node at (0,0) {Carton};
    \end{tikzpicture}
\end{document}

enter image description here

AboAmmar
  • 46,352
  • 4
  • 58
  • 127