diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/braids/braids.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/braids/braids.dtx | 946 |
1 files changed, 946 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/braids/braids.dtx b/Master/texmf-dist/source/latex/braids/braids.dtx new file mode 100644 index 00000000000..463da2c37cc --- /dev/null +++ b/Master/texmf-dist/source/latex/braids/braids.dtx @@ -0,0 +1,946 @@ +% \iffalse meta-comment +%<*internal> +\iffalse +%</internal> +%<*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. +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*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 <stacey@math.ntnu.no> + +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}} +} +%</install> +%<install>\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 +%</internal> +%<*package> +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{braids}[2011/05/07 v1.0 Tikz/PGF commands for drawing braid diagrams] +%</package> +%<*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} +%</driver> +% \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 +%</package> +% \fi +% +% \Finale + +\endinput |