%% tikz_scd.sty
%% updated 2022/05/04

\usetikzlibrary{calc,shapes.geometric,backgrounds,positioning, arrows.meta,decorations.markings}
\pgfdeclarelayer{foreground}
\pgfsetlayers{main,foreground}

\newcommand{\combinexy}[2]{#1 |- #2} % takes x-coordinate from #1 and y-coordinate from #2
% #1 and #2 should be unparanthesised coordinates / node labels (e.g. \combinexy{0,1}{nodeA})
\newcommand{\sfrac}[2]{\ensuremath{\frac{\text{#1}}{\text{#2}}}}

\usepackage{ amssymb }

\usepackage{pgfkeys}

\usepackage{ adjustbox }

\renewcommand{\rmdefault}{phv}

\newcommand{\thickness}{semithick}
\newcommand{\crossedsize}{\footnotesize}

%% stealth arrows for use in subscripts

\newcommand{\stealthstraightarrow}[1]{% for e.g. set advancing/retiring
    % #1 indicates direction: 1 up, -1 down
\adjustbox{raise={-1pt}, lap={\width}{0.5pt}}{%
\begin{tikzpicture}
    \draw[-{Stealth[width=1.3mm,length=0.8mm]}] (0,0) --++ (0,-0.25*#1);
\end{tikzpicture}
}
}

\newcommand\stealthuparrow{\stealthstraightarrow{1}}
\newcommand\stealthdownarrow{\stealthstraightarrow{-1}}

\newcommand{\stealthhookarrow}[2]{%
    % #1 indicates translational direction: 1 up, -1 down
    % #2 indicates rotational direction: 1 clockwise (RSh back), -1 anticlockwise (LSh back)
\adjustbox{raise={-4pt}, lap={-\width*#2/15}{9pt}}{%
\begin{tikzpicture}
    % \draw[-{Stealth[width=1.3mm,length=0.8mm]}] (0,0) --++ (0,-0.15*#1) to[out=90*#1, in=90*#1, looseness=5] ++(-0.12*#2,0);
    \draw[-{Stealth[width=1.3mm,length=0.8mm]}]%[show curve controls]
    (0,0)
    --++ (0,-0.12*#1)
    .. controls
            ++(-90:0.06*#1)
            and
            ++(180:-0.06*#2) ..
    ++(-0.06*#2,-0.2*#1)
    .. controls
            ++(0:-0.06*#2)
            and
            ++(-90:0.06*#1) ..
    ++(-0.06*#2,0.17*#1);
\end{tikzpicture}
}
}

\newcommand{\stealthuphookleftarrow}{\stealthhookarrow{1}{1}}
\newcommand{\stealthuphookrightarrow}{\stealthhookarrow{1}{-1}}
\newcommand{\stealthdownhookleftarrow}{\adjustbox{lap={\width}{-1.8pt}}{\stealthhookarrow{-1}{1}}}
\newcommand{\stealthdownhookrightarrow}{\stealthhookarrow{-1}{-1}}

\newcommand\stealthrotatingarrow{% curled arrow for e.g. set rotating
\raisebox{-1pt}{%
\begin{tikzpicture}
    \draw[-{Stealth[width=1.3mm,length=0.8mm]}] (-0.04,0) 
    to[out=125, in=180, looseness=1.1] (0,-0.24)
    to[out=0, in=55, looseness=1.1] (0.04,0);
\end{tikzpicture}
}
}


\tikzset{%
every picture/.append style={y={(0,-1cm)}},
    % x-axis is rightwards, y-axis is downwards, with origin in top-left corner
    % for "meta" stuff only: for the actual dance diagrams, the row environment modifies the y-axis to be upwards, with y=0 the centre line
square/.style={regular polygon,regular polygon sides=4},
man/.style={circle, draw, minimum size=11pt, inner sep=0, \thickness},
lady/.style={square, draw, minimum size=14pt, inner sep=0, \thickness},
none/.style={minimum size=14pt, inner sep=0},
manpath/.style={-{Stealth[width=2.3mm,length=1.6mm]}, \thickness},
manpathnoarrow/.style={\thickness},
ladypath/.style={-{Stealth[width=2.3mm,length=1.6mm]}, \thickness, densely dashed},
ladypathnoarrow/.style={\thickness, densely dashed},
hand/.style={very thick},
}


%%% HEADER AND FOOTER
\newcommand\music[1]{\renewcommand\@music{#1}}
\newcommand\@music{?x?? ?}
\newcommand\setshape[1]{\renewcommand\@setshape{#1}}
\newcommand\@setshape{?/? set}

\newcommand{\titleheight}{20pt}
\newcommand{\header}{%
    \makeatletter
    \draw[black] (0,0) -- ++(\rowwidth, 0) -- ++(0, \titleheight) -- ++(-\rowwidth, 0) -- ++(0,-\titleheight);
    \node[anchor=west, align=left, inner sep=5pt] at (0,0.5*\titleheight) {\large\MakeUppercase{\textbf{\@title}}};
    \node[anchor=east, align=left, inner sep=5pt] at (\rowwidth,0.5*\titleheight) {\large\textbf{\@music}};
    \makeatother
}

\newcommand{\footer}{%
    \makeatletter
    \node[anchor=north west, align=left, inner sep=3pt] at (0,\value{rowcount}*\rowheight) {\tiny \@author, \@date};
    \node[anchor=north east, align=left, inner sep=3pt] at (\rowwidth,\value{rowcount}*\rowheight) {\tiny \@setshape.};
    \makeatother
}

%%% ROWS

\newcounter{rowcount}
\NewDocumentEnvironment{row}{}%
{
    \draw[black] (0,\value{rowcount}*\rowheight) -- ++(\rowwidth, 0) -- ++(0, \rowheight) -- ++(-\rowwidth, 0) -- ++(0,-\rowheight);
    \begin{scope}[%
    shift={(0, \value{rowcount}*\rowheight)}, % set row position
    % when drawing:
    shift={(0, 0.5*\rowheight)}, % have the set's centre line as the x-axis 
    style={y={(0,1cm)}} % have y-axis directed upwards (x-axis is directed rightwards)
    % (so positive y-values corresponds to ladies' side, negative y-values to men's side)
    ]

}{
    \end{scope}
    \stepcounter{rowcount}
}

% \newcommand{\drawrow}[1]{%
%     \draw[black] (0,#1*\rowheight) -- ++(\rowwidth, 0) -- ++(0, \rowheight) -- ++(-\rowwidth, 0) -- ++(0,-\rowheight);
% }
% \newcommand{\drawrows}{%
%     \foreach \i in {0,...,\number\numexpr\numberofrows-1}
%     \drawrow{\i};
% }

%%% PHRASES

\pgfkeys{%
    /phrase/start/.store in = \phrasestart,
    /phrase/start/.default = {0},
    /phrase/end/.store in = \phraseend,
    /phrase/end/.default = {0},
    /phrase/xlen/.store in = \phrasexlen,
    /phrase/xlen/.default = {0},
    /phrase/endline/.store in = \phraseendline,
    /phrase/endline/.default = {0},
    /phraseline/pos/.store in = \phraselinepos,
    /phraseline/bars/.store in = \phraselinebars,
    /phraseline/bars/.default = {8},
    /phrase/end, /phrase/start, /phrase/xlen, /phrase/endline, /phraseline/bars
}

\NewDocumentEnvironment{phrase}{m}%
    % start=1.4 (x-position of start of phrase)
    % xlen=2.5 (x-length of phrase)
    % end=3.9 (x-position of end of phrase); if not specified, will be calculated as start+xlen
    %% inputting end directly doesn't work correctly at the moment 2022/04/30 -- fix this!
    % endline=8 (if set to 2, 4 or 8, will draw a 2, 4 or 8 bar divider)
{
\begingroup
\pgfkeys{/phrase/.cd, #1}
\pgfmathsetmacro\phraseend{
    \ifnum0=\phraseend{% if end has not been specified
        \phrasestart+\phrasexlen% evaluate it as start+xlen
    }\fi
}
    \begin{scope}[shift={(\phrasestart,0)}]
}{
    \end{scope}
\ifnum0=\phraseendline{% don't draw end line
}
\else{% do draw end line
    \phraseline{bars=\phraseendline, pos=\phraseend}
}\fi
\endgroup
}

%%% bar dividers

\newcommand{\eightbarline}[1]{%
\draw[black] (#1,-0.5*\rowheight) -- ++(0,\rowheight);
}
\newcommand{\fourbarline}[1]{%
\draw[black, dashed] (#1,-0.5*\rowheight) -- ++(0,\rowheight);
}
\newcommand{\twobarline}[1]{%
\draw[black, dotted] (#1,-0.5*\rowheight) -- ++(0,\rowheight);
}

\newcommand{\phraseline}[1]{%
\begingroup
\pgfkeys{/phraseline/.cd, #1}
    \ifnum8=\phraselinebars {% eight bars
        \eightbarline{\phraselinepos}
    }
    \else {
    \ifnum4=\phraselinebars {% four bars
        \fourbarline{\phraselinepos}
    }
    \else {
    \ifnum2=\phraselinebars {% two bars
        \twobarline{\phraselinepos}
    }
    \else {% draw nothing if number other than 2,4,8 specified
    }\fi
    }\fi
    }\fi
\endgroup
}

%%% BRACES AND BRACKETS

%%% simultaneous movements brace
% \angularbrace{a,b}{x,y} where (a,b) is start point and (x,y) is end point (expect b=y)
\newcommand{\angdis}{0.15}
\newcommand{\angularbrace}[2]{%
\coordinate[at={($(#1)!1/2!(#2)$)}] (midpoint);
\draw[\thickness]
    ([shift={(-\angdis,-\angdis)}]#1)
    -- (#1)
    -- ([shift={(-\angdis,0)}]midpoint)
    -- ([shift={(0,\angdis)}]midpoint)
    -- ([shift={(\angdis,0)}]midpoint)
    -- (#2)
    -- ([shift={(\angdis,-\angdis)}]#2);
}

%%% sequential movements bracket
% \squarebrace{a,b}{x,y} where (a,b) is start point and (x,y) is end point (expect b=y)
\newcommand{\squaredis}{0.1}
\newcommand{\squarebrace}[2]{%
\coordinate[at={($(#1)!1/2!(#2)$)}] (midpoint);
\draw[\thickness]
    ([shift={(0,-\angdis)}]#1)
    -- (#1)
    -- (#2)
    -- ([shift={(0,-\angdis)}]#2);
}

\pgfkeys{%
    /dancer/at/.store in = \dancerat,
    /dancer/name/.store in = \dancername,
    /dancer/role/.store in = \dancerrole,
    /dancer/number/.store in = \dancernum,
    /dancer/number/.default = {},
    /dancer/facing/.store in = \dancerfacing,
    /dancer/facing/.default = 0,
    /dancer/nose/.store in = \dancernose,
    /dancer/nose/.default = false,
    /dancer/name, /dancer/number, /dancer/facing, /dancer/nose,
    /joinhands/handlabel/.store in = \handlabel,
    /joinhands/handlabel/.default = {},
    /joinhands/labeldir/.store in = \handlabeldir,
    /joinhands/labeldir/.default = -90,
    /joinhands/labelpos/.store in = \handlabelpos,
    /joinhands/labelpos/.default = 0,
    /joinhands/handlabel, /joinhands/labeldir, /joinhands/labelpos,
    /twopartpath/role/.store in = \twopartpathrole,
    /twopartpath/name/.store in = \twopartpathname,
    /twopartpath/startangle/.store in = \twopartpathstartangle,
    /twopartpath/firstpartoutangle/.store in = \pathfirstpartoutangle,
    /twopartpath/firstpartinangle/.store in = \pathfirstpartinangle,
    /twopartpath/firstpartlooseness/.store in = \pathfirstpartlooseness,
    /twopartpath/firstpartxshift/.store in = \pathfirstpartxshift,
    /twopartpath/firstpartyshift/.store in = \pathfirstpartyshift,
    /twopartpath/secondpartoutangle/.store in = \pathsecondpartoutangle,
    /twopartpath/secondpartinangle/.store in = \pathsecondpartinangle,
    /twopartpath/secondpartlooseness/.store in = \pathsecondpartlooseness,
    /twopartpath/secondpartxshift/.store in = \pathsecondpartxshift,
    /twopartpath/secondpartyshift/.store in = \pathsecondpartyshift,
    /promhold/facing/.store in = \promfacing,
    /promhold/facing/.default = 0,
    /promhold/at/.store in = \promat,
    /promhold/manno/.store in = \prommanno,
    /promhold/ladyno/.store in = \promladyno,
    /promhold/manno/.default = {},
    /promhold/ladyno/.default = {},
    /promhold/manno, /promhold/ladyno, /promhold/facing,
}

%%%% DANCERS

%% places a square or circle in the specified place, possibly with a number or nose
%% \dancer{at=(x,y), role=lady, name=string, number={}, facing=0, nose=false}
\newcommand*{\dancer}[1]{%
\begingroup
\def\truestring{true}%
\pgfkeys{/dancer/.cd, #1}
\node[at=\dancerat, \dancerrole, shape border rotate=90+\dancerfacing, append after command={%
    \ifx\dancernose\truestring
        \pgfextra{%
            \begin{pgfinterruptpath}
            \begin{pgfonlayer}{foreground}
            \draw[\thickness] (\tikzlastnode.\dancerfacing) -- ++(\dancerfacing:2pt);
            \end{pgfonlayer}
            \end{pgfinterruptpath}
        }
    \fi
}] (\dancername) {\dancernum};
\endgroup
}

%%% HOLDS

%% \promhold{at={(x,y)}, facing=dir, manno=label for man, ladyno=label for lady}
\newcommand{\promhold}[1]{
\begingroup
\pgfkeys{/promhold/.cd, #1}
% \node[at=\promholdat] (temp) {};
\coordinate[at=\promat] (centre);
\dancer{at={($(centre)+(270-\promfacing:0.32)$)}, facing=\promfacing, role=man, nose=true, number=\prommanno, name=man}
\dancer{at={($(centre)+(90-\promfacing:0.32)$)}, facing=\promfacing, role=lady, nose=true, number=\promladyno, name=lady}
\coordinate[at={($(centre)+(\promfacing+24:0.26)$)}] (lhand);
\coordinate[at={($(centre)+(\promfacing-20:0.26)$)}] (rhand);
\draw[hand] (man) -- (lhand) -- (lady);
\draw[hand] (man) -- (rhand) -- (lady);
\endgroup
}

%% JOIN HANDS
%% draws a line from a list of specified dancers to their centre point
%% \joinhands{list of dancers}{handlabel={}, labeldir=-90, labelpos=2}
\newcommand*{\joinhands}[2]{%
\begingroup
\pgfkeys{/joinhands/.cd, #2}
\coordinate (b) at (0,0);
\foreach \d [count = \n] in {#1}{%
    \coordinate (b) at ($(b)!1/\n!(\d)$);%
}
\node[at={([shift={(-\handlabeldir:\handlabelpos)}]b)}] {\tiny \handlabel};
\foreach \d in {#1}{%
    \draw[hand] (\d) -- (b);
}
\endgroup
}

%% TWO PART PATH
\newcommand{\twopartpath}[1]{%
\begingroup
\pgfkeys{/twopartpath/.cd, #1}
\draw[\twopartpathrole path] (\twopartpathname.\twopartpathstartangle)
    to[out=\pathfirstpartoutangle, in=\pathfirstpartinangle, looseness=\pathfirstpartlooseness] ++(\pathfirstpartxshift,-\pathfirstpartyshift)
    to[out=\pathsecondpartoutangle, in=\pathsecondpartinangle, looseness=\pathsecondpartlooseness] ++(\pathsecondpartxshift,-\pathsecondpartyshift);
\endgroup
}


%%%% FIGURES

\pgfkeys{%
    /fig/at/.store in = \figat,
    /fig/name/.store in = \figname,
    /fig/half/.store in = \fighalf,
    /fig/half/.default = false,
    /fig/subscript/.store in = \figsub,
    /fig/subscript/.default = {},
    /fig/corner/.store in = \figcorner,
    /fig/corner/.default = false,
    /fig/subscript, /fig/half, /fig/name, /fig/corner,
    /reelofthree/at/.store in = \reelat,
    /reelofthree/entry/.store in = \reelentry,
    /reelofthree/entry/.default = false,
    /reelofthree/half/.store in = \reelhalf,
    /reelofthree/half/.default = false,
    /reelofthree/entrylobe/.store in = \reelentrylobe,
    /reelofthree/entryangle/.store in = \reelentryangle,
    /reelofthree/shoulder/.store in = \reelshoulder,
    /reelofthree/shoulder/.default = right,
    /reelofthree/entry, reelofthree/half, reelofthree/shoulder,
    /chase/at/.store in = \chaseat,
    /chase/half/.store in = \chasehalf,
    /chase/half/.default = false,
    /chase/anticlockwise/.store in = \chaseanticlockwise,
    /chase/anticlockwise/.default = false,
    /chase/half, /chase/anticlockwise,
    /DFEcrossandcast/name/.store in = \crossandcastname,
    /DFEcrossandcast/role/.store in = \crossandcastrole,
    /DFEcrossandcast/fromside/.store in = \crossandcastfromside,
    /DFEcrossandcast/dir/.store in = \crossandcastdir,
    /DFEcrossandcast/first/.store in = \crossandcastfirst,
}

%%% figures denoted by letters (possibly with a subscript)
%% \fig{TEXT}{at={(x,y)}, name=string, half=false, subscript={}}
\newcommand*{\fig}[2]{%
\begingroup
\def\truestring{true}%
\def\falsestring{false}%
\pgfkeys{/fig/.cd, #2}
\node[at=\figat, inner sep=1pt, append after command={%
\ifx\fighalf\truestring
    \pgfextra{
    \begin{pgfinterruptpath}
    \begin{pgfonlayer}{foreground}
        \draw[\thickness] (\tikzlastnode.east) -- (\tikzlastnode.west);
    \end{pgfonlayer}
    \end{pgfinterruptpath}
    }
\fi
}] (\figname) {\large\textbf{#1}\textsubscript{\rlap{\smash{\figsub}}}};
\ifx\figcorner\falsestring
\else
    \coordinate[at={([shift={(\figcorner:4pt)}]\figname.\figcorner)}] (corner);
    \draw (corner) -- +(\figcorner-135:6pt) -- (corner) -- +(\figcorner+135:6pt);
\fi
\endgroup
}

%%% CASTS
%% \cast{{(x,y)}}{number of places}
\newcommand{\cast}[2]{%
\node[at={#1}] (string) {\textbf{#2}};
\draw[manpath] (string.150) to[out=90,in=95, looseness=1.9] (string.25);
}
%% \castup{{(x,y)}}{number of places}
\newcommand{\castup}[2]{%
\node[at={#1}] (string) {\textbf{#2}};
\draw[manpath] (string.30) to[out=90,in=85, looseness=1.9] (string.155);
}
%% \longcast{{(x,y)}}{number of places}
\newcommand{\longcast}[2]{%
\node[at={#1}] (string) {\textbf{#2}};
\draw[manpath] (string.145) to[out=-90,in=-90, looseness=2.5] ++(-0.2,0) to[out=85, in=100, looseness=1.8] (string.15);
}

%%% REELS
\tikzset{%
reelcircle/.style={circle, draw, minimum size=16pt, inner sep=0, \thickness},
}
%% \reelofthree{at={(x,y)}, entry=false, entryangle=145, entrylobe=left, half=false, reelshoulder=right}
\newcommand{\reelofthree}[1]{%
\begingroup
\def\truestring{true}%
\def\leftstring{left}%
\pgfkeys{/reelofthree/.cd, #1}
\node[at=\reelat, xshift=-8pt, reelcircle] (left) {};
\node[at=\reelat, xshift=8pt, reelcircle] (right) {};
\pgfmathsetmacro{\tangentangle}{-90}
\ifx\reelshoulder\leftstring
    \pgfmathsetmacro{\tangentangle}{90}
\fi
\ifx\reelentry\truestring
    \draw[\thickness] ([shift={(\reelentryangle:-0.3pt)}]\reelentrylobe.\reelentryangle) -- ++(\reelentryangle+\tangentangle:8pt);
\fi
\ifx\reelhalf\truestring
    \draw[\thickness] ([shift={(0:-3pt)}]left.west) -- ([shift={(180:-3pt)}]right.east);
\fi
\endgroup
}

%%% CIRCLES
%% \handsround{{x,y}}{number of "hands" (=number of dancers)}
\newcommand{\handsround}[2]{%
\node[at={#1}, circle, draw, minimum size=26pt, inner sep=0, \thickness] (string) {\textbf{#2}};
}


%%% CHASES
\tikzset{%
chasecircle/.style={circle, minimum size=20pt, inner sep=0},
}
%% 
\newcommand{\chase}[1]{%
\begingroup
\def\truestring{true}%
\pgfkeys{/chase/.cd, #1}
\node[at=\chaseat, chasecircle, append after command={%
  \ifx\chasehalf\truestring
  \pgfextra{
    \begin{pgfinterruptpath}
    \begin{pgfonlayer}{foreground}
    \draw[\thickness] ([shift={(4pt,0)}]\tikzlastnode.east) -- ([shift={(-4pt,0)}]\tikzlastnode.west);
    \end{pgfonlayer}
    \end{pgfinterruptpath}
  }
  \fi
}] (temp) {};
\draw[manpath] (temp.145) arc (145:-45:10pt);
\draw[manpath] (temp.-35) arc (325:135:10pt);
\endgroup
}


%%% CHAINS
\tikzset{%
chainsquare/.style={square, draw, minimum size=19pt, inner sep=0, \thickness},
}
\newcommand{\ladieschain}[1]{%
% \node[chainsquare, at={([shift={()}]#1)}]
\node[chainsquare, shift={(-0.12,-0.12)}, at=#1] () {};
\node[chainsquare, shift={(0.12,0.12)}, at=#1] {};
}

%%% DOUBLE FIGURES OF EIGHT

\newcommand{\xdownfrommstartangle}{30}
\newcommand{\xdownfrommoutangle}{20}
\newcommand{\xdownfromminangle}{-90}
\newcommand{\xdownfrommlooseness}{1.1}
\newcommand{\xdownfrommxshift}{0.9}
\newcommand{\xdownfrommyshift}{-1}
\newcommand{\cupfrommoutangle}{90}
\newcommand{\cupfromminangle}{45}
\newcommand{\cupfrommlooseness}{1.1}
\newcommand{\cupfrommxshift}{-0.9}
\newcommand{\cupfrommyshift}{-0.3}

\newcommand{\cdownfrommstartangle}{-30}
\newcommand{\cdownfrommoutangle}{-40}
\newcommand{\cdownfromminangle}{-90}
\newcommand{\cdownfrommlooseness}{1.1}
\newcommand{\cdownfrommxshift}{0.9}
\newcommand{\cdownfrommyshift}{-0.1}
\newcommand{\xupfrommoutangle}{90}
\newcommand{\xupfromminangle}{-30}
\newcommand{\xupfrommlooseness}{1}
\newcommand{\xupfrommxshift}{-0.7}
\newcommand{\xupfrommyshift}{-0.7}

%% \crossandcast{role=man, fromside=mens, dir=down, name=string}
\newcommand{\crossandcast}[1]{%
\begingroup
\pgfkeys{/DFEcrossandcast/.cd, #1}
\def\crossstr{cross}
\def\caststr{cast}
\ifx\crossandcastfirst\crossstr
    \pgfmathsetmacro{\startangle}{\xdownfrommstartangle}
    \pgfmathsetmacro{\firstout}{\xdownfrommoutangle}
    \pgfmathsetmacro{\firstin}{\xdownfromminangle}
    \pgfmathsetmacro{\firstlooseness}{\xdownfrommlooseness}
    \pgfmathsetmacro{\firstxshift}{\xdownfrommxshift}
    \pgfmathsetmacro{\firstyshift}{\xdownfrommyshift}
    \pgfmathsetmacro{\secondout}{\cupfrommoutangle}
    \pgfmathsetmacro{\secondin}{\cupfromminangle}
    \pgfmathsetmacro{\secondlooseness}{\cupfrommlooseness}
    \pgfmathsetmacro{\secondxshift}{\cupfrommxshift}
    \pgfmathsetmacro{\secondyshift}{\cupfrommyshift}
\fi
\ifx\crossandcastfirst\caststr
    \pgfmathsetmacro{\startangle}{\cdownfrommstartangle}
    \pgfmathsetmacro{\firstout}{\cdownfrommoutangle}
    \pgfmathsetmacro{\firstin}{\cdownfromminangle}
    \pgfmathsetmacro{\firstlooseness}{\cdownfrommlooseness}
    \pgfmathsetmacro{\firstxshift}{\cdownfrommxshift}
    \pgfmathsetmacro{\firstyshift}{\cdownfrommyshift}
    \pgfmathsetmacro{\secondout}{\xupfrommoutangle}
    \pgfmathsetmacro{\secondin}{\xupfromminangle}
    \pgfmathsetmacro{\secondlooseness}{\xupfrommlooseness}
    \pgfmathsetmacro{\secondxshift}{\xupfrommxshift}
    \pgfmathsetmacro{\secondyshift}{\xupfrommyshift}
\fi
\def\ladiesstr{ladies}
\ifx\crossandcastfromside\ladiesstr
    \pgfmathsetmacro{\startangle}{-\startangle}
    \pgfmathsetmacro{\firstout}{-\firstout}
    \pgfmathsetmacro{\firstin}{-\firstin}
    \pgfmathsetmacro{\firstyshift}{-\firstyshift}
    \pgfmathsetmacro{\secondout}{-\secondout}
    \pgfmathsetmacro{\secondin}{-\secondin}
    \pgfmathsetmacro{\secondyshift}{-\secondyshift}
\fi
\def\upstr{up}
\ifx\crossandcastdir\upstr
        \pgfmathsetmacro{\startangle}{180-\startangle}
        \pgfmathsetmacro{\firstout}{180-\firstout}
        \pgfmathsetmacro{\firstin}{180-\firstin}
        \pgfmathsetmacro{\firstxshift}{-\firstxshift}
        \pgfmathsetmacro{\secondout}{180-\secondout}
        \pgfmathsetmacro{\secondin}{180-\secondin}
        \pgfmathsetmacro{\secondxshift}{-\secondxshift}
\fi
\twopartpath{%
    role=\crossandcastrole,
    name=\crossandcastname,
    startangle=\startangle,
    firstpartoutangle=\firstout,
    firstpartinangle=\firstin,
    firstpartlooseness=\firstlooseness,
    firstpartxshift=\firstxshift,
    firstpartyshift=\firstyshift,
    secondpartoutangle=\secondout,
    secondpartinangle=\secondin,
    secondpartlooseness=\secondlooseness,
    secondpartxshift=\secondxshift,
    secondpartyshift=\secondyshift
}
\endgroup
}


%%% FIGURE OF LOVE

\usetikzlibrary{decorations.pathreplacing}

\tikzset{%
  show curve controls/.style={
    postaction={
      decoration={
        show path construction,
        curveto code={
          \draw [blue, opacity=0.5] 
            (\tikzinputsegmentfirst) -- (\tikzinputsegmentsupporta)
            (\tikzinputsegmentlast) -- (\tikzinputsegmentsupportb);
          \fill [red, opacity=0.5] 
            (\tikzinputsegmentsupporta) circle [radius=.25ex]
            (\tikzinputsegmentsupportb) circle [radius=.25ex];
        }
      },
      decorate
}}}

\newcommand{\dancershift}{0, -0.9}
\newcommand{\Routsecshift}{0.65, 0.95}
\newcommand{\Routshift}{0.1, 0.7}
\newcommand{\Loutshift}{-0.1, 0.7}
\newcommand{\Loutsecshift}{-0.65, 0.95}

\newcommand{\figureoflove}[1]{%
\coordinate (centre) at (#1);
\coordinate (man) at ($(centre)+(\dancershift)$);
\coordinate (mRout) at ($(centre)+(\Routshift)$);
\coordinate (mRout2) at ($(centre)+(\Routsecshift)$);
\coordinate (mLout2) at ($(centre)+(\Loutsecshift)$);
\coordinate (mLout) at ($(centre)+(\Loutshift)$);
\coordinate (lady) at ($(centre)-(\dancershift)$);
\coordinate (lRout) at ($(centre)-(\Routshift)$);
\coordinate (lRout2) at ($(centre)-(\Routsecshift)$);
\coordinate (lLout2) at ($(centre)-(\Loutsecshift)$);
\coordinate (lLout) at ($(centre)-(\Loutshift)$);
\draw
% [show curve controls]
[manpath]
(man) .. controls
    ++(40:2)
    and
    ++(0:0.45) ..
(mRout2) .. controls
    ++(0:-0.3)
    and
    ++(-130:-0.1) ..
(mRout) .. controls
    ++(-130:1)
    and
    ++(-50:1) ..
(mLout) .. controls
    ++(-50:-0.1)
    and
    ++(0:0.3) ..
(mLout2) .. controls
    ++(0:-0.45)
    and
    ++(140:2) ..
(man);
\draw
% [show curve controls]
[ladypath]
(lady) .. controls
    ++(-140:2)
    and
    ++(0:-0.45) ..
(lRout2) .. controls
    ++(0:0.3)
    and
    ++(50:-0.1) ..
(lRout) .. controls
    ++(50:1)
    and
    ++(130:1) ..
(lLout) .. controls
    ++(130:-0.1)
    and
    ++(0:-0.3) ..
(lLout2) .. controls
    ++(0:0.45)
    and
    ++(-40:2) ..
(lady);
}