Hackenbush Diagrams?

I'd like to put diagrams of Hackenbush positions such as the one pictured here in a paper I'm writing. Anyone know how?

EDIT: I would also be happy with simpler orientations, such as where the edges are all vertical.

-
Could you please add a link that shows how these diagrams look like (and what they have to do with fonts). –  Caramdir Feb 9 '11 at 0:05
@Caramdir I think that a font package would work, like Skak for chess positions. –  pgaf Feb 9 '11 at 2:09
related (trackback, actually): holoborodko.com/pavel/2011/02/15/quicklatex-hackenbush-diagram –  Grigory M Dec 20 '11 at 19:44

Easy answer: Don't do it. Use a vector graphics program like Inkscape and export to a format that (pdf)LaTeX knows (e.g. pdf or to TikZ code).

Hard answer: You can use one of the general purpose drawing libraries for TeX. The following is an example with TikZ.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\tikzstyle{hackennode}=[draw,circle,inner sep=0,minimum size=4pt]
\tikzstyle{hackenline}=[line width=3pt]

\begin{tikzpicture}
\node[hackennode] (leftleg-1) at (0,0) {};
\node[hackennode] (leftleg-2) at (1.5,0.75) {};
\node[hackennode] (leftleg-3) at (1.13,3.0) {};
\node[hackennode] (leftleg-4) at (2.65,5.3) {};
\node[hackennode] (rightleg-1) at (3,0) {};
\node[hackennode] (rightleg-2) at (4.15,0.72) {};
\node[hackennode] (rightleg-3) at (3.04,2.65) {};
\node[hackennode] (rightleg-4) at (3.8,4.9) {};

\node[hackennode] (dress-1) at (4.55,8.3) {};
\node[hackennode] (dress-2) at (4.91,4.52) {};
\node[hackennode] (dress-3) at (1.6,5.66) {};

\node[hackennode] (neck) at (5.3,10.6) {};

\node[hackennode] (leftarm-1) at (2.25,9.85) {};
\node[hackennode] (leftarm-2) at (1.53,10.96) {};
\node[hackennode] (rightarm-1) at (7.56,9.07) {};
\node[hackennode] (rightarm-2) at (7.2,7.55) {};

\node[hackennode] (hair-1) at (5.7,12.1) {};
\node[hackennode] (hair-2) at (8.75,9.85) {};

\draw[hackenline,blue]
(leftleg-1) -- (leftleg-2) -- (leftleg-3) -- (leftleg-4) -- (rightleg-4)
(dress-2) -- (dress-1) -- (dress-3)
(neck) -- (leftarm-1) -- (leftarm-2)
(rightarm-1) -- (rightarm-2);
\draw[hackenline,red]
(rightleg-1) -- (rightleg-2) -- (rightleg-3) -- (rightleg-4) -- (dress-2)
(leftleg-4) -- (dress-3)
(dress-1) -- (neck) -- (rightarm-1);

\draw[hackenline,red,looseness=1.6]
(leftarm-2) to[out=45,in=45] ($(leftarm-2)+(-0.76,0.76)$) to[out=225,in=225] (leftarm-2);
\draw[hackenline,red]
(neck) to[out=135,in=170,looseness=1.3] (hair-1)
(hair-1) .. controls (7.9,14.5) and (6.5,8) .. (hair-2);
\draw[hackenline,blue]
(neck) to[out=0,in=-10,looseness=1.3] (hair-1);
\end{tikzpicture}

\end{document}


This might seem like a lot of code, but it isn't so bad. The trickiest thing is to find the right coordinates (which I did by including the original picture and placing a grid on top of it).

Some explanation:

• \tikzstyle defines some styling options we are going to use later on. You only need to include this once in your document.

\tikzstyle{hackennode}=[draw,circle,inner sep=0,minimum size=4pt]


This defines how the vertices (“node” in TikZ-speak) are drawn. Change the minimum size to make them larger or smaller.

\tikzstyle{hackenline}=[line width=3pt]


The same, but for the lines. The line width key changes line thickness.

• \begin{tikzpicture} starts the actual diagram. You can change that to something like \begin{tikzpicture}[scale=0.5] to make the picture smaller/larger. Beware that line thickness and node size are not scaled.

• The syntax to place nodes is

\node (〈nodename〉) at 〈position〉 {〈contents〉};


The 〈nodename〉 is used to refer to that node later on. 〈position〉 may be a pair of coordinates (if no unit is given, the default is cm). Finally, we don't want any text in our nodes, so we leave 〈contents〉 blank (note that the braces have to be there even if we don't want anything in the node). Additionally we pass the hackennode option, which applies the style we defined earlier.

• The syntax to draw straight lines is

\draw 〈postition 1〉 -- 〈position 2〉;


It is possible to chain several lines together. In addition to hackenline, we also pass a color option. Instead we could have defined

\tikzstyle{hackenline}=[line width=3pt]
\tikzstyle{hackenline1}=[hackenline,blue]
\tikzstyle{hackenline2}=[hackenline,red]


and passed the hackenline1 and hackenline2 options (this is probably the better solution as it allows to easily change the color­­­­—but I didn't think of this when I wrote the code and don't want to rewrite it).

• Finally, the hardest part is to get good curved lines. We use a combination of the to[out=〈leaving angle〉,in=〈arriving angle〉] syntax and Bézier curves (see the TikZ manual for explanations).

PS: If anyone has a good idea how to draw that circle in her hand (except fudging the position of a \draw circle and then overpainting with a filled node), please tell me.

-
The following line results in an almost perfect circle (if it weren't for the slight offset at the hackennode): \draw [hackenline, red, out=-45, in=-135, relative, rotate=25] let \n1={0.75} in (leftarm-2) to +(\n1,\n1) to +(-\n1,\n1) to +(-\n1,-\n1) to (leftarm-2); You can control the circle radius by changing the value for \n1, and the rotation of the circle around the origin node by changing the value of rotate. –  Jake Feb 9 '11 at 8:42
Okay, and the proper way to do it is: \draw [hackenline,red] let \n1={0.75cm} in let \n2={35} in (leftarm-2) +(\n2:2pt+.3pt) arc [start angle=(-90+\n2+atan((2pt+.3pt)/\n1)), end angle=(270+\n2-atan((2pt+.3pt)/\n1)),radius=\n1];, where\n1 is the radius of the ball, \n2 is the angle at which the ball is held, 2pt is the radius of the hackennodes (which would ideally also be parametrised) and .3pt is the line width of the hackennodes. –  Jake Feb 9 '11 at 11:55
I think I'd put the nodes in afterwards anyways, but if not here's a circle: \node[draw,circle] (a) {}; \draw (a.north) arc(10:350:1);. Of course, you need to experiment to work out what the right angles are. –  Loop Space Feb 9 '11 at 13:06
@Caramdir Your response was very helpful, and I've gotten it working with Tikz. I'd like to be able to use these in formulas rather than just diagrams--is this possible? For example, I'd like to be able to add 2 blue edges and write Edge+Edge=Stack of edges –  pgaf Feb 14 '11 at 1:43
@pgaf: Yes it is. Just put the {tikzpicture} environment into the formula. The baseline option is useful to get vertical alignment right, and scale is useful to get the size right. But best ask a separate question. –  Caramdir Feb 14 '11 at 4:56

run with xelatex or latex->dvips->ps2pdf

\documentclass{article}
\usepackage{pst-node}
\begin{document}

\begin{pspicture}[dotstyle=o,arrows=o-o,arrowLW=0.2pt,arrowscale=2.5,linewidth=3pt](11,15)
\psset{linecolor=blue}
\psline[showpoints,dotscale=0.75](0,0)(1.5,0.75)(1.13,3.0)(2.65,5.3)(3.8,4.9)
\psline(4.91,4.52)(4.55,8.3)(1.6,5.66)
\psline(5.3,10.6)(2.25,9.85)(1.53,10.96)
\psline(7.56,9.07)(7.2,7.55)
\pccurve[angleB=-10,ncurv=1](5.3,10.6)(5.7,12.1)
\psset{linecolor=red}
\psline[showpoints,dotscale=0.75](3,0)(4.15,0.72)(3.04,2.65)(3.8,4.9)(4.91,4.52)
\psline(4.55,8.3)(5.3,10.6)(7.56,9.07)
\psline(2.65,5.3)(1.6,5.66)
\pnode(1.53,10.96){A}\nccircle{A}{0.5}
\pccurve[angleA=180,angleB=170,ncurv=1](5.3,10.6)(5.7,12.1)
\psbezier(5.7,12.1)(7.9,14.5)(6.5,8)(8.75,9.85)
\end{pspicture}

\end{document}


-

I'd suggest you follow the great answer by Caramdir, although it's a bit complicated.

If not, you could draw the diagram with Inkscape and export it to TikZ with inkscape2tikz.

-