[Tex/LaTex] How to make nice braids diagrams

diagramsxy-pic

This question led to a new package:
braids — Blog: The Braids Package

I search to draw braids diagram, if possible in xy-pic.
I already know how to do that with the knot module and some low-level instructions and I search a nicer way to do that.

The actual code :

\documentclass{minimal}
\usepackage[all,knot]{xy}
\begin{document}
\[\vcenter{\xy 0;/r1pc/:
    @={(0.5,-0.5),(0,0)}, @@{*{\vtwistneg}},(0,-2),\vtwist,
    @i@={(0,-1),(2,0),(2,-2)} @@{="save";"save"-(0,1),**@{-}}\endxy}
    \quad = \quad
    \vcenter{\xy 0;/r1pc/:
    @={(0.5,0),(0,-0.5),(0.5,-1)}, @@{*{\vtwistneg}},
    @i@={(0,0),(2,-1),(0,-2)} @@{="save";"save"-(0,1),**@{-}}\endxy}\]
\end{document}

And the desired result enter image description here

Best Answer

Update (2019-05-09): With the advent of TikZ's pic syntax I figured the braids package was well overdue an overhaul. The syntax below is for the original version of the package which is now depreciated (though still works). See the package documentation for how to use the new syntax.

Update (2011-09-06): The resulting package is now on CTAN as http://www.ctan.org/pkg/braids and you can read about it on our blog at http://tex.blogoverflow.com/2011/09/the-braids-package/.


Taking up Charles' challenge, here's a way of doing this in TikZ/PGF. First, the output:

braid

Next, the user code; namely, if the yucky preamble were in a nice package, this is what you would type:

\begin{document}
\begin{tikzpicture}
\braid[braid colour=red,strands=3,braid start={(0,0)}]
{\sigma_1 \sigma_2 \sigma_1^{-1}}
\node[font=\Huge] at (4.5,-1.5) {\(=\)};
\braid[strands=3,braid start={(5,0)}]
{\sigma_2 \sigma_1 \sigma_2}
\end{tikzpicture}
\end{document}

Lastly, the yucky preamble (actually including the user code so you can just copy this for a MWE):

\documentclass{standalone}
\usepackage{tikz}
\newcounter{braid}
\newcounter{strands}
\pgfkeyssetvalue{/tikz/braid height}{1cm}
\pgfkeyssetvalue{/tikz/braid width}{1cm}
\pgfkeyssetvalue{/tikz/braid start}{(0,0)}
\pgfkeyssetvalue{/tikz/braid colour}{black}
\pgfkeys{/tikz/strands/.code={\setcounter{strands}{#1}}}

\makeatletter
\def\cross{%
  \@ifnextchar^{\message{Got sup}\cross@sup}{\cross@sub}}

\def\cross@sup^#1_#2{\render@cross{#2}{#1}}

\def\cross@sub_#1{\@ifnextchar^{\cross@@sub{#1}}{\render@cross{#1}{1}}}

\def\cross@@sub#1^#2{\render@cross{#1}{#2}}


\def\render@cross#1#2{
  \def\strand{#1}
  \def\crossing{#2}
  \pgfmathsetmacro{\cross@y}{-\value{braid}*\braid@h}
  \pgfmathtruncatemacro{\nextstrand}{#1+1}
  \foreach \thread in {1,...,\value{strands}}
  {
    \pgfmathsetmacro{\strand@x}{\thread * \braid@w}
    \ifnum\thread=\strand
    \pgfmathsetmacro{\over@x}{\strand * \braid@w + .5*(1 - \crossing) * \braid@w}
    \pgfmathsetmacro{\under@x}{\strand * \braid@w + .5*(1 + \crossing) * \braid@w}
    \draw[braid] \pgfkeysvalueof{/tikz/braid start} +(\under@x pt,\cross@y pt) to[out=-90,in=90] +(\over@x pt,\cross@y pt -\braid@h);
    \draw[braid] \pgfkeysvalueof{/tikz/braid start} +(\over@x pt,\cross@y pt) to[out=-90,in=90] +(\under@x pt,\cross@y pt -\braid@h);
    \else
    \ifnum\thread=\nextstrand
    \else
     \draw[braid] \pgfkeysvalueof{/tikz/braid start} ++(\strand@x pt,\cross@y pt) -- ++(0,-\braid@h);
    \fi
   \fi
  }
  \stepcounter{braid}
}

\tikzset{braid/.style={double=\pgfkeysvalueof{/tikz/braid colour},double distance=1pt,line width=2pt,white}}

\newcommand{\braid}[2][]{%
  \begingroup
  \pgfkeys{/tikz/strands=2}
  \tikzset{#1}
  \pgfkeysgetvalue{/tikz/braid width}{\braid@w}
  \pgfkeysgetvalue{/tikz/braid height}{\braid@h}
  \setcounter{braid}{0}
  \let\sigma=\cross
  #2
  \endgroup
}
\makeatother


\begin{document}
\begin{tikzpicture}
\braid[braid colour=red,strands=3,braid start={(0,0)}]%
{\sigma_1 \sigma_2 \sigma_1^{-1}}
\node[font=\Huge] at (4.5,-1.5) {\(=\)};
\braid[strands=3,braid start={(5,0)}]
{\sigma_2 \sigma_1 \sigma_2}
\end{tikzpicture}
\end{document}

Improvements: the actual drawing commands could be optimised a little. The braids don't actually start at the start, but are shifted one over (not hard to correct). It should also be possible to work out the number of strands from the given braid: if we encounter an element using a strand we've yet to see, simply draw it from the top to the current height.

(I did try to do a bit of catcode tomfoolery so that one could use s in place of \sigma, but I couldn't get it to work (and, yes, I did replace the command by an environment in trying to do this).)

Related Question