% \iffalse meta-comment %<*internal> \iffalse % %<*readme> ---------------------------------------------------------------- braids --- a style file for drawing braid diagrams with TikZ/PGF E-mail: stacey@math.ntnu.no Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- This package defines some commands for drawing braid diagrams with TikZ/PGF. It was designed and tested with PGF2.10. The initial idea of this package came from a question and answer on the site http://tex.stackexchange.com. % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- braids --- a style file for drawing braid diagrams with TikZ/PGF E-mail: stacey@math.ntnu.no Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2011 by Andrew Stacey This work may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Andrew Stacey. This work consists of the files braids.dtx braids_doc.tex and the derived files README.txt, braids.ins, braids.pdf, braids.sty, braids_doc.pdf. \endpostamble \usedir{tex/latex/braids} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } % %\endbatchfile %<*internal> \usedir{source/latex/braids} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \usedir{doc/latex/demopkg} \generate{ \file{README.txt}{\from{\jobname.dtx}{readme}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{braids}[2011/05/07 v1.0 Tikz/PGF commands for drawing braid diagrams] % %<*driver> \documentclass{ltxdoc} \usepackage[T1]{fontenc} \usepackage{lmodern} %\usepackage{morefloats} \usepackage{tikz} \usepackage{\jobname} \usepackage[numbered]{hypdoc} \definecolor{lstbgcolor}{rgb}{0.9,0.9,0.9} \usepackage{listings} \lstloadlanguages{[LaTeX]TeX} \lstset{breakatwhitespace=true,breaklines=true,language=TeX} \usepackage{fancyvrb} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \CheckSum{815} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{1.0}{2011/05/03}{Converted to DTX file} % % \DoNotIndex{\newcommand,\newenvironment} % % \providecommand*{\url}{\texttt} % \GetFileInfo{braids.sty} % \title{The \textsf{braids} package: codebase} % \author{Andrew Stacey \\ \url{stacey@math.ntnu.no}} % \date{\fileversion~from \filedate} % % \maketitle % % \begin{center} % \begin{tikzpicture} % \braid[line width=3pt,line cap=round,style strands={1}{blue},number of strands=7] s_1 s_2 s_5^{-1}; % \end{tikzpicture} % \end{center} % % \section{Introduction} % % This is a package for drawing braid diagrams using PGF/TikZ. % Its inspiration was a question and answer on the website \url{http://tex.stackexchange.com}. % % \StopEventually{} % % \section{Implementation} % % \iffalse %<*package> % \fi % % Test the version of PGF to see if it's what we expect. % If not, issue a warning (but continue anyway; after all, it \emph{might just work}). % \begin{macrocode} \def\braid@pgfversion{2.10}% \ifx\pgfversion\braid@pgfversion \else \PackageWarning{braids}{This package was designed using PGF2.10; you are using \pgfversion.}% \fi % \end{macrocode} % \begin{macro}{\ge@addto@macro} % This is an expanded version of \Verb+\g@addto@macro+. % Namely, it adds the \emph{expansion} of the second argument to the first. % \begin{macrocode} \long\def\ge@addto@macro#1#2{% \begingroup \toks@\expandafter\expandafter\expandafter{\expandafter#1#2}% \xdef#1{\the\toks@}% \endgroup} % \end{macrocode} % \end{macro} % \begin{macro}{\braid} % This is the user command. % We start a group to ensure that all our assignments are local, and then call our initialisation code. % The optional argument is for any keys to be set. % \begin{macrocode} \newcommand{\braid}[1][]{% \begingroup \braid@start{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@process} % This is the token swallower. % This takes the next token on the braid specification and passes it to the handler command (in the macro \Verb+\braid@token+) which decides what to do next. % (Incidentally, the code here is heavily influenced by TikZ. % That's probably not very surprising.) % \begin{macrocode} \def\braid@process{% \afterassignment\braid@handle\let\braid@token=% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@process@start} % This is a variant of \Verb+\braid@process+ which is used at the start where we might have a few extra bits and pieces before the braid itself starts. % Specifically, we test for the \Verb+at+ and \Verb+(name)+ possibilities. % \begin{macrocode} \def\braid@process@start{% \afterassignment\braid@handle@start\let\braid@token=% } % \end{macrocode} % \end{macro} % \begin{macro}{\braid@handle@start} % This is the handler in use at the start. % It looks for the tokens \Verb+a+ or \Verb+(+ which (might) signal the start of an \Verb+at (coordinate)+ or \Verb+(name)+. % If we get anything else (modulo spaces) we decide that we've reached the end of the initialisation stuff and it is time to get started on the braid itself. % \begin{macrocode} \def\braid@handle@start{% \let\braid@next=\braid@handle \ifx\braid@token a % \end{macrocode} % We got an \Verb+a+ so we might have an \Verb+at (coordinate)+ % \begin{macrocode} \let\braid@next=\braid@maybe@locate \else \ifx\braid@token(%) % \end{macrocode} % We got an \Verb+(+ so we have a name % \begin{macrocode} \iffalse)\fi %Indentation hack! \let\braid@next=\braid@assign@name \else \ifx\braid@token\@sptoken % \end{macrocode} % Space; boring, redo from start % \begin{macrocode} \let\braid@next=\braid@process@start \fi \fi \fi \braid@next% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@handle} % This is the main handler for parsing the braid word. % It decides what action to take depending on what the token is. % We have to be a bit careful with catcodes, some packages set % \Verb+;+ and \Verb+|+ to be active. % We should probably also be careful with \Verb+^+ and \Verb+_+. % \begin{macrocode} \let\braid@semicolon=; \let\braid@bar=| \def\braid@handle{% \let\braid@next=\braid@process % \end{macrocode} % Start by checking our catcodes to see what we should check against % \begin{macrocode} \ifnum\the\catcode`\;=\active \expandafter\let\expandafter\braid@semicolon\tikz@activesemicolon \fi \ifnum\the\catcode`\|=\active \expandafter\let\expandafter\braid@bar\tikz@activebar \fi \ifx\braid@token\braid@semicolon % \end{macrocode} % Semicolon, means that we're done reading our braid. % It's time to render it. % \begin{macrocode} \let\braid@next=\braid@render \else \ifx\braid@token^ % \end{macrocode} % Superscript character, the next token tells us whether it's an over-crossing or an under-crossing. % \begin{macrocode} \let\braid@next=\braid@sup \else \ifx\braid@token_ % \end{macrocode} % Subscript character, the next token tells us which strands cross. % \begin{macrocode} \let\braid@next=\braid@sub \else \ifx\braid@token- % \end{macrocode} % Hyphen, this is so that we can have more than one crossing on the same level. % \begin{macrocode} \braid@increase@levelfalse \else \ifx\braid@token[ % \end{macrocode} % Open bracket, this means we have some more options to process. % \begin{macrocode} \let\braid@next=\braid@process@options \else \ifx\braid@token\braid@bar % \end{macrocode} % Bar, this tells us that we want a ``floor'' at this point. % \begin{macrocode} \edef\braid@tmp{,\expandafter\the\value{braid@level}}% \ge@addto@macro\braid@floors\braid@tmp% \else \ifx\braid@token\bgroup % \end{macrocode} % Begin group, which we reinterpret as begining a scope. % \begin{macrocode} \braid@beginscope \else \ifx\braid@token\egroup % \end{macrocode} % End group, which ends the scope % \begin{macrocode} \braid@endscope \else % \end{macrocode} % Otherwise, we add the token to the braid label. % \begin{macrocode} \ge@addto@macro\braid@label{\braid@token}% \fi \fi \fi \fi \fi \fi \fi \fi \braid@next% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@maybe@locate} % If we got an \Verb+a+ token in the \Verb+\braid@handle@start+ then it \emph{might} mean we're looking at \Verb+at (coordinate)+ or it might mean that the user has decided to use \Verb+a+ as the braid parameter. % So we examine the next token for a \Verb+t+. % \begin{macrocode} \def\braid@maybe@locate{% \afterassignment\braid@@maybe@locate\let\braid@token=% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@@maybe@locate} % This is where we test for \Verb+t+ and act appropriately. % \begin{macrocode} \def\braid@@maybe@locate{% \let\braid@next=\braid@handle \ifx\braid@token t \let\braid@next=\braid@find@location \fi \braid@next% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@find@location} % This macro starts us looking for a coordinate. % \begin{macrocode} \def\braid@find@location{% \afterassignment\braid@@find@location\let\braid@token=% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@@find@location} % This is the test for the start of a coordinate. % If we get a \Verb+(+ that means we've reached the coordinate. % A space means ``carry on''. % Anything else is a (non-fatal) error. % \begin{macrocode} \def\braid@@find@location{% \let\braid@next=\braid@location@error \ifx\braid@token(%) \let\braid@next=\braid@locate \else \ifx\braid@token\@sptoken \let\braid@next=\braid@find@location \fi \fi \braid@next% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@location@error} % This is our error message for not getting a location. % \begin{macrocode} \def\braid@location@error{% \PackageWarning{braids}{Could not figure out location for braid}% \braid@process@start% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@locate} % If we reached a \Verb+(+ when looking for a coordinate, everything up to the next \Verb+)+ is that coordinate. % Then we parse the coordinate and call the relocation macro. % \begin{macrocode} \def\braid@locate#1){% \tikz@scan@one@point\braid@relocate(#1)% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@relocate} % This is the macro that actually does the relocation. % \begin{macrocode} \def\braid@relocate#1{% #1\relax \advance\pgf@x by -\braid@width \pgftransformshift{\pgfqpoint{\pgf@x}{\pgf@y}} \braid@process@start% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@assign@name} % This macro saves our name. % \begin{macrocode} \def\braid@assign@name#1){% \def\braid@name{#1}% \braid@process@start% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@process@options} % The intention of this macro is to allow setting of style options mid-braid. % (At present, this wouldn't make a lot of sense.) % \begin{macrocode} \def\braid@process@options#1]{% \tikzset{#1}% \braid@process% } % \end{macrocode} % \end{macro} % % The next macros handle the actual braid elements. % Everything has to have a subscript, but the superscript is optional and can come before or after the subscript. % % \begin{macro}{\braid@sup} % This handles braid elements of the form \Verb+a^{-1}_2+. % \begin{macrocode} \def\braid@sup#1_#2{\g@addto@macro\braid@label{_{#2}^{#1}}\braid@add@crossing{#2}{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@sub} % \begin{macrocode} % This handles braid elements of the form \Verb+a_1+ or \Verb+a_1^{-1}+. \def\braid@sub#1{\@ifnextchar^{\braid@@sub{#1}}{\g@addto@macro\braid@label{_{#1}}\braid@add@crossing{#1}{1}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@@sub} % Helper macro for \Verb+\braid@sub+. % \begin{macrocode} \def\braid@@sub#1^#2{\g@addto@macro\braid@label{_{#1}^{#2}}\braid@add@crossing{#1}{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@ne} % Remember what \Verb+1+ looks like for testing against. % \begin{macrocode} \def\braid@ne{1} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@add@crossing} % This is the macro which adds the crossing to the current list of strands. % The strands are stored as \emph{soft paths} (see the TikZ/PGF documentation). % So this selects the right strands and then extends them according to the crossing type. % \begin{macrocode} \def\braid@add@crossing#1#2{% % \end{macrocode} % Our crossing type, which is \Verb+#2+, is one of \Verb+1+ or \Verb+-1+. % Our strands are \Verb+#1+ and \Verb-#1+1-. % \begin{macrocode} \edef\braid@crossing@type{#2}% \edef\braid@this@strand{#1}% \pgfmathtruncatemacro{\braid@next@strand}{#1+1} % \end{macrocode} % Increment the level counter, if requested. % The controls whether the crossing is on the same level as the previous one or is one level further on. % \begin{macrocode} \ifbraid@increase@level \stepcounter{braid@level} \fi % \end{macrocode} % Default is to request increment so we set it for next time. % \begin{macrocode} \braid@increase@leveltrue % \end{macrocode} % Now we figure out the coordinates of the crossing. % \Verb+(\braid@tx,\braid@ty)+ is the top-left corner (assuming the braid flows down the page). % \Verb+(\braid@nx,\braid@ny)+ is the bottom-right corner (assuming the braid flows down the page). % We start by setting \Verb+(\braid@tx,\braid@ty)+ according to the level and strand number, then shift \Verb+\braid@ty+ by \Verb+\braid@eh+ which is the ``edge height'' (the little extra at the start and end of each strand). % Then from these values, we set \Verb+(\braid@nx,\braid@ny)+ by adding on the appropriate amount. % The heights \Verb+\braid@cy+ and \Verb+\braid@dy+ are for the control points for the strands as they cross. % They're actually the same height, but using two gives us the possibility of changing them independently in a later version of this package. % Lastly, we bring \Verb+\braid@ty+ and \Verb+\braid@ny+ towards each other just a little so that there is ``clear water'' between subsequent crossings (makes it look a bit better if the same strand is used in subsequent crossings). % \begin{macrocode} \braid@tx=\braid@this@strand\braid@width \braid@ty=\value{braid@level}\braid@height \advance\braid@ty by \braid@eh \braid@nx=\braid@tx \braid@ny=\braid@ty \advance\braid@nx by \braid@width \advance\braid@ny by \braid@height \braid@cy=\braid@ty \braid@dy=\braid@ny \advance\braid@cy by .5\braid@height \advance\braid@dy by -.5\braid@height \advance\braid@ty by .05\braid@height \advance\braid@ny by -.05\braid@height % \end{macrocode} % Now we try to find a starting point for the strand ending here. % We might not have used this strand before, so it might not exist. % \begin{macrocode} \expandafter\let\expandafter\braid@this@path@origin\csname braid@strand@\braid@this@strand @origin\endcsname % \end{macrocode} % If we haven't seen this strand before, that one will be \Verb+\relax+. % \begin{macrocode} \ifx\braid@this@path@origin\relax % \end{macrocode} % Haven't seen this strand before, so initialise it. % Record the initial position of the strand. % \begin{macrocode} \let\braid@this@path@origin\braid@this@strand % \end{macrocode} % Start a new soft path. % \begin{macrocode} \pgfsyssoftpath@setcurrentpath{\@empty} \pgfpathmoveto{\pgfpoint{\braid@tx}{0pt}} % \end{macrocode} % Save the path as \Verb+\braid@this@path+. % \begin{macrocode} \pgfsyssoftpath@getcurrentpath{\braid@this@path} \else % \end{macrocode} % We have seen this before, so we simply copy the associated path in to \Verb+\braid@this@path+. % \begin{macrocode} \expandafter\let\expandafter\braid@this@path\csname braid@strand@\braid@this@path@origin\endcsname \fi % \end{macrocode} % Now we do the same again with the other strand in the crossing. % \begin{macrocode} \expandafter\let\expandafter\braid@next@path@origin\csname braid@strand@\braid@next@strand @origin\endcsname \ifx\braid@next@path@origin\relax \let\braid@next@path@origin\braid@next@strand \pgfsyssoftpath@setcurrentpath{\@empty} \pgfpathmoveto{\pgfpoint{\braid@nx}{0pt}} \pgfsyssoftpath@getcurrentpath{\braid@next@path} \else \expandafter\let\expandafter\braid@next@path\csname braid@strand@\braid@next@path@origin\endcsname \fi % \end{macrocode} % Now that we have the paths for our two strands, we extend them to the next level. % We start by selecting the first path. % \begin{macrocode} \pgfsyssoftpath@setcurrentpath{\braid@this@path} % \end{macrocode} % Draw a line down to the current level, note that this line is always non-trivial since we shifted the corners of the crossing in a little. % \begin{macrocode} \pgfpathlineto{\pgfqpoint{\braid@tx}{\braid@ty}} % \end{macrocode} % Curve across to the next position. % Depending on the crossing type, we either have a single curve or we have to break it in two. % \begin{macrocode} \ifx\braid@crossing@type\braid@over@cross % \end{macrocode} % We're on the overpass, so just one curve needed. % \begin{macrocode} \pgfpathcurveto{\pgfqpoint{\braid@tx}{\braid@cy}}{\pgfqpoint{\braid@nx}{\braid@dy}}{\pgfqpoint{\braid@nx}{\braid@ny}} \else % \end{macrocode} % We're on the underpass, so we need to interrupt our path to allow the other curve to go past. % The choice of \Verb+.4+ and \Verb+.6+ should probably be configurable. % \begin{macrocode} \pgfpathcurvebetweentimecontinue{0}{.4}{\pgfqpoint{\braid@tx}{\braid@ty}}{\pgfqpoint{\braid@tx}{\braid@cy}}{\pgfqpoint{\braid@nx}{\braid@dy}}{\pgfqpoint{\braid@nx}{\braid@ny}} \pgfpathcurvebetweentime{.6}{1}{\pgfqpoint{\braid@tx}{\braid@ty}}{\pgfqpoint{\braid@tx}{\braid@cy}}{\pgfqpoint{\braid@nx}{\braid@dy}}{\pgfqpoint{\braid@nx}{\braid@ny}} \fi % \end{macrocode} % We're done with this path, so now we save it. % \begin{macrocode} \pgfsyssoftpath@getcurrentpath{\braid@this@path} % \end{macrocode} % Now do the same with the second path. % \begin{macrocode} \pgfsyssoftpath@setcurrentpath{\braid@next@path} \pgfpathlineto{\pgfqpoint{\braid@nx}{\braid@ty}} \ifx\braid@crossing@type\braid@over@cross \pgfpathcurvebetweentimecontinue{0}{.4}{\pgfqpoint{\braid@nx}{\braid@ty}}{\pgfqpoint{\braid@nx}{\braid@cy}}{\pgfqpoint{\braid@tx}{\braid@dy}}{\pgfqpoint{\braid@tx}{\braid@ny}} \pgfpathcurvebetweentime{.6}{1}{\pgfqpoint{\braid@nx}{\braid@ty}}{\pgfqpoint{\braid@nx}{\braid@cy}}{\pgfqpoint{\braid@tx}{\braid@dy}}{\pgfqpoint{\braid@tx}{\braid@ny}} \else \pgfpathcurveto{\pgfqpoint{\braid@nx}{\braid@cy}}{\pgfqpoint{\braid@tx}{\braid@dy}}{\pgfqpoint{\braid@tx}{\braid@ny}} \fi \pgfsyssoftpath@getcurrentpath{\braid@next@path} % \end{macrocode} % Now save the paths to their proper macros again. % \begin{macrocode} \expandafter\let\csname braid@strand@\braid@this@path@origin \endcsname\braid@this@path \expandafter\let\csname braid@strand@\braid@next@path@origin \endcsname\braid@next@path % \end{macrocode} % Now update the origins % \begin{macrocode} \expandafter\let\csname braid@strand@\braid@this@strand @origin\endcsname\braid@next@path@origin \expandafter\let\csname braid@strand@\braid@next@strand @origin\endcsname\braid@this@path@origin % \end{macrocode} % increment the strand counter, if necessary % \begin{macrocode} \pgfmathparse{\value{braid@strands} < \braid@next@strand ? "\noexpand\setcounter{braid@strands}{\braid@next@strand}" : ""} \pgfmathresult % \end{macrocode} % And merrily go on our way with the next bit of the braid specification. % \begin{macrocode} \braid@process% } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@floors@trim} % The list of floors, if given, will start with a superfluous comma. % This removes it. % \begin{macrocode} \def\braid@floors@trim,{} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@render@floor} % This is the default rendering for floors: it draws a rectangle. % \begin{macrocode} \def\braid@render@floor{% \draw (\floorsx,\floorsy) rectangle (\floorex,\floorey); } % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@render} % This is called at the end of the braid and it renders the braids and floors according to whatever has been built up up to now. % \begin{macrocode} \def\braid@render{ % \end{macrocode} % Check for floors since we do them first. % \begin{macrocode} \ifx\braid@floors\@empty \else % \end{macrocode} % Have some floors, start a scope and prepare to render them. % \begin{macrocode} \pgfsys@beginscope % \end{macrocode} % Clear the path (just to be sure). % \begin{macrocode} \pgfsyssoftpath@setcurrentpath{\empty} % \end{macrocode} % Trim the initial comma off the list of floors. % \begin{macrocode} \edef\braid@floors{\expandafter\braid@floors@trim\braid@floors} % \end{macrocode} % Initialise our horizontal coordinates. % \begin{macrocode} \braid@tx=\braid@width \advance\braid@tx by \braid@eh \braid@nx=\value{braid@strands}\braid@width \advance\braid@nx by -\braid@eh % \end{macrocode} % Loop over the list of floors. % \begin{macrocode} \foreach \braid@f in \braid@floors { \pgfsys@beginscope % \end{macrocode} % Figure out the vertical coordinates for the current floor. % \begin{macrocode} \braid@ty=\braid@f\braid@height \advance\braid@ty by \braid@eh \advance\braid@ty by \braid@height \braid@ny=\braid@ty \advance\braid@ny by \braid@height % \end{macrocode} % Save the coordinates for use in the floor rendering macro. % \begin{macrocode} \edef\floorsx{\the\braid@tx} \edef\floorsy{\the\braid@ty} \edef\floorex{\the\braid@nx} \edef\floorey{\the\braid@ny} \let\tikz@options=\pgfutil@empty % \end{macrocode} % Load general floor style options. % \begin{macrocode} \expandafter\tikzset\expandafter{\braid@floors@style} % \end{macrocode} % Load any style options specific to this floor. % We're actually offset by 2 from what the user thinks the floor level is. % \begin{macrocode} \pgfmathtruncatemacro{\braid@ff}{\braid@f+2} % \end{macrocode} % Load the relevant floor style, if it exists. % \begin{macrocode} \expandafter\let\expandafter\braid@floor@style\csname braid@options@floor@\braid@ff\endcsname \ifx\braid@floor@style\relax \else % \end{macrocode} % There is a floor style for this level, so process it. % \begin{macrocode} \expandafter\tikzset\expandafter{\braid@floor@style}% \fi % \end{macrocode} % The \Verb+\tikzset+ just parses the options, we need to call \Verb+\tikz@options+ to actually set them. % \begin{macrocode} \tikz@options % \end{macrocode} % Now we call the rendering code. % \begin{macrocode} \braid@render@floor % \end{macrocode} % Done! % End the scope for \emph{this} floor and go again. % \begin{macrocode} \pgfsys@endscope } % \end{macrocode} % Done rendering floors, end the scope. % \begin{macrocode} \pgfsys@endscope \fi % \end{macrocode} % Finished with floors (if we had them), now get on with the strands. % \begin{macrocode} \stepcounter{braid@level} \foreach \braid@k in {1,...,\value{braid@strands}} { % \end{macrocode} % Start a local scope to ensure we don't mess with other braids % \begin{macrocode} \pgfsys@beginscope % \end{macrocode} % Default is to draw each braid % \begin{macrocode} \tikz@mode@drawtrue% \let\tikz@mode=\pgfutil@empty \let\tikz@options=\pgfutil@empty % \end{macrocode} % (x,y) coordinates of bottom of strand % \begin{macrocode} \braid@tx=\braid@k\braid@width \braid@ty=\value{braid@level}\braid@height \advance\braid@ty by 2\braid@eh % \end{macrocode} % Try to find the starting point of this strand % \begin{macrocode} \expandafter\let\expandafter\braid@path@origin\csname braid@strand@\braid@k @origin\endcsname \ifx\braid@path@origin\relax % \end{macrocode} % If that doesn't exist, we'll just draw a straight line % so we move to the top of the current position % \begin{macrocode} \pgfsyssoftpath@setcurrentpath{\@empty} \pgfpathmoveto{\pgfqpoint{\braid@tx}{0pt}} \let\braid@path@origin\braid@k \else % \end{macrocode} % If the path does exist, we load it % \begin{macrocode} \expandafter\let\expandafter\braid@path\csname braid@strand@\braid@path@origin\endcsname \pgfsyssoftpath@setcurrentpath{\braid@path} \fi % \end{macrocode} % Extend the path to the bottom % \begin{macrocode} \pgflineto{\pgfqpoint{\braid@tx}{\braid@ty}} % \end{macrocode} % Load common style options % \begin{macrocode} \expandafter\tikzset\expandafter{\braid@style} % \end{macrocode} % Load any style options specific to this strand % \begin{macrocode} \expandafter\let\expandafter\braid@style\csname braid@options@strand@\braid@path@origin\endcsname \ifx\braid@style\relax \else \expandafter\tikzset\expandafter{\braid@style} \fi \braid@options \tikz@mode \tikz@options % \end{macrocode} % This is the command that actually draws the strand. % \begin{macrocode} \edef\tikz@temp{\noexpand\pgfusepath{% \iftikz@mode@draw draw\fi% }}% \tikz@temp % \end{macrocode} % If our braid has a name, we label the ends of the strand. % \begin{macrocode} \ifx\braid@name\pgfutil@empty \else % \end{macrocode} % Label the ends of the strand. % \begin{macrocode} \coordinate (\braid@name-\braid@path@origin-e) at (\braid@tx,\braid@ty); \coordinate (\braid@name-rev-\braid@k-e) at (\braid@tx,\braid@ty); \braid@nx=\braid@path@origin\braid@width \coordinate (\braid@name-\braid@path@origin-s) at (\braid@nx,0pt); \coordinate (\braid@name-rev-\braid@k-s) at (\braid@nx,0pt); \fi % \end{macrocode} % Done with this strand, close the scope and do the next one. % \begin{macrocode} \pgfsys@endscope } % \end{macrocode} % If our braid has a name, we also want to label the centre. % \begin{macrocode} \ifx\braid@name\pgfutil@empty \else \braid@tx=\value{braid@strands}\braid@width \braid@ty=\value{braid@level}\braid@height \advance\braid@ty by 2\braid@eh \advance\braid@tx by \braid@width \braid@tx=.5\braid@tx \braid@ty=.5\braid@ty \coordinate (\braid@name) at (\braid@tx,\braid@ty); \fi % \end{macrocode} % All done now, close the scope and end the group (which was opened right at the start). % \begin{macrocode} \pgfsys@endscope \endgroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\braid@start} % This starts off the braid, initialising a load of stuff. % We start a PGF scope, set the level to \(-1\), the label, floors, and name to empty, process any options we're given, and save certain lengths for later use.. % \begin{macrocode} \def\braid@start#1{% \pgfsys@beginscope \setcounter{braid@level}{-1}% \let\braid@label\@empty \let\braid@floors\@empty \let\braid@name\empty \pgfkeys{/pgf/braid/.cd,#1} \let\braid@options\tikz@options \tikz@transform \setcounter{braid@strands}{\pgfkeysvalueof{/pgf/braid/number of strands}}% \braid@width=\pgfkeysvalueof{/pgf/braid/width} \braid@height=\pgfkeysvalueof{/pgf/braid/height} \braid@eh=\pgfkeysvalueof{/pgf/braid/border height} \braid@height=-\braid@height \braid@eh=-\braid@eh \braid@increase@leveltrue \braid@process@start } % \end{macrocode} % \end{macro} % % These are the lengths we'll use as we construct the braid % \begin{macrocode} \newdimen\braid@width \newdimen\braid@height \newdimen\braid@tx \newdimen\braid@ty \newdimen\braid@nx \newdimen\braid@ny \newdimen\braid@cy \newdimen\braid@dy \newdimen\braid@eh % \end{macrocode} % % An if to decide whether or not to step to the next level or not % \begin{macrocode} \newif\ifbraid@increase@level % \end{macrocode} % % Some initial values % \begin{macrocode} \let\braid@style\pgfutil@empty \let\braid@floors@style\pgfutil@empty \def\braid@over@cross{1} % \end{macrocode} % % Counters to track the strands and the levels. % \begin{macrocode} \newcounter{braid@level} \newcounter{braid@strands} % \end{macrocode} % % All the keys we'll use. % \begin{macrocode} \pgfkeys{ % \end{macrocode} % Handle unknown keys by passing them to \Verb+pgf+ and \Verb+tikz+. % \begin{macrocode} /tikz/braid/.search also={/pgf}, /pgf/braid/.search also={/pgf,/tikz}, % \end{macrocode} % Our ``namespace'' is \Verb+/pgf/braid+. % \begin{macrocode} /pgf/braid/.cd, number of strands/.initial=0, height/.initial=1cm, width/.initial=1cm, border height/.initial=.25cm, name/.code={% \def\braid@name{#1}% }, at/.code={% \braid@relocate{#1}% }, floor command/.code={% \def\braid@render@floor{#1}% }, style strands/.code 2 args={% \def\braid@temp{#2}% \braidset{style each strand/.list={#1}}% }, style each strand/.code={% \expandafter\edef\csname braid@options@strand@#1\endcsname{\braid@temp}% }, style floors/.code 2 args={% \def\braid@temp{#2}% \braidset{style each floor/.list={#1}}% }, style each floor/.code={% \expandafter\edef\csname braid@options@floor@#1\endcsname{\braid@temp}% }, style all floors/.code={% \def\braid@floors@style{#1} } } % \end{macrocode} % \begin{macro}{\braidset} % Shorthand for setting braid-specific keys. % \begin{macrocode} \def\braidset#1{% \pgfkeys{/pgf/braid/.cd,#1}} % \end{macrocode} % \end{macro} % \iffalse % % \fi % % \Finale \endinput