summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/tilings/tilings_code.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/tilings/tilings_code.dtx')
-rw-r--r--Master/texmf-dist/source/latex/tilings/tilings_code.dtx3780
1 files changed, 3780 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/tilings/tilings_code.dtx b/Master/texmf-dist/source/latex/tilings/tilings_code.dtx
new file mode 100644
index 00000000000..f550e10d4d3
--- /dev/null
+++ b/Master/texmf-dist/source/latex/tilings/tilings_code.dtx
@@ -0,0 +1,3780 @@
+% \iffalse meta-comment
+%<*internal>
+\iffalse
+%</internal>
+%<*readme>
+----------------------------------------------------------------
+penrose --- TikZ library for producing tiling patterns
+E-mail: loopspace@mathforge.org
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+----------------------------------------------------------------
+
+This package is for the creation of Penrose and similar tilings.
+%</readme>
+%<*internal>
+\fi
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+ \expandafter\begingroup
+\fi
+%</internal>
+%<*install>
+\input l3docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+----------------------------------------------------------------
+tilings --- TikZ library for producing tilings
+E-mail: loopspace@mathforge.org
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+----------------------------------------------------------------
+
+\endpreamble
+\postamble
+
+Copyright (C) 2014-2023 by Andrew Stacey <loopspace@mathforge.org>
+
+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 penrose_code.dtx
+ penrose.tex
+and the derived files penrose.ins
+ penrose_code.pdf
+ penrose.pdf
+ tikzlibrarytilings.code.tex
+ tikzlibrarytilings.penrose.code.tex
+ tikzlibrarytilings.polykite.code.tex
+ tikzlibrarypenrose.code.tex
+ README.txt
+
+\endpostamble
+\usedir{tex/latex/penrose}
+\generate{
+ \file{tikzlibrarytilings.code.tex}{\from{\jobname.dtx}{tilings}}
+}
+\generate{
+ \file{tikzlibrarytilings.penrose.code.tex}{\from{\jobname.dtx}{penrose}}
+}
+\generate{
+ \file{tikzlibrarytilings.polykite.code.tex}{\from{\jobname.dtx}{polykite}}
+}
+\generate{
+ \file{tikzlibrarypenrose.code.tex}{\from{\jobname.dtx}{penrosedep}}
+}
+%</install>
+%<install>\endbatchfile
+%<*internal>
+\usedir{source/latex/penrose}
+\generate{
+ \file{\jobname.ins}{\from{\jobname.dtx}{install}}
+}
+\nopreamble\nopostamble
+\usedir{doc/latex/penrose}
+\generate{
+ \file{README.txt}{\from{\jobname.dtx}{readme}}
+}
+\ifx\fmtname\nameofplainTeX
+ \expandafter\endbatchfile
+\else
+ \expandafter\endgroup
+\fi
+%</internal>
+%<*driver>
+\documentclass{l3doc}
+\usepackage[scale=.8]{geometry}
+\usepackage[T1]{fontenc}
+\usepackage{lmodern}
+\usepackage{tikz}
+\usepackage{amsmath}
+%\usepackage{trace}
+\usetikzlibrary{penrose}
+%\traceoff
+%\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}
+
+\newenvironment{example}
+ {\VerbatimEnvironment
+ \begin{VerbatimOut}[gobble=2]{example.out}}
+ {\end{VerbatimOut}
+ \begin{center}
+% \setlength{\parindent}{0pt}
+ \fbox{\begin{minipage}{.9\linewidth}
+ \lstset{breakatwhitespace=true,breaklines=true,language=TeX,basicstyle=\small}
+ \lstinputlisting[]{example.out}
+ \end{minipage}}
+
+ \fbox{\begin{minipage}{.9\linewidth}
+ \input{example.out}
+ \end{minipage}}
+\end{center}
+}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{2944}
+%
+% \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}{2014/05/07}{Converted to DTX file}
+% \changes{1.2}{2019/02/23}{Added general tile creation code}
+% \changes{1.4}{2021/01/22}{Adapted to latest version of spath3}
+% \changes{1.6}{2023/03/22}{Included aperiodical hat}
+% \changes{1.8}{2023/05/11}{LMS systems for aperiodical tiles}
+% \changes{2.0}{2023/06/01}{Major version change for CTAN}
+%
+% \DoNotIndex
+% {
+% \begingroup,
+% \catcode,
+% \active,
+% \csname,
+% \endcsname,
+% }%
+%
+%
+% \providecommand*{\url}{\texttt}
+% \GetFileInfo{tikzlibrarytilings.code.tex}
+% \title{The \textsf{Tilings} package: code}
+% \author{Andrew Stacey\texorpdfstring{\\ \url{loopspace@mathforge.org}}{}}
+% \date{\fileversion~from \filedate}
+%
+%
+% \maketitle
+%
+% \tableofcontents
+%
+% \begin{documentation}
+%
+% \section{Introduction}
+%
+% This is a TikZ library for drawing tiles, such as Penrose tiles (kite/dart, rhombus, and pentagon versions) and the aperiodical polykite tiles.
+% It provides two methods of drawing: one in which an automatic pattern is built, and one where the tiles can be placed ``by hand''.
+% The tiles can be shaped and (hopefully!) still fit together.
+% For full user documentation, see the \Verb+tilings.pdf+ file.
+%
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{Implementation}
+%
+%
+% \iffalse
+%<*tilings>
+% \fi
+%
+% \begin{macrocode}
+%<@@=tilings>
+% \end{macrocode}
+%
+% \subsection{Initialisation}
+%
+%
+% We use the \Verb+spath3+ library for manipulating the paths that will make up the tiles.
+%
+% \begin{macrocode}
+\ProvidesExplFile
+ {tikzlibrarytilings.code.tex}
+ {2023/06/01}
+ {2.0}
+ {TikZ pics for tilings such as Penrose tiles}
+\RequirePackage{tikz}
+\usetikzlibrary{spath3}
+% \end{macrocode}
+% Now we move in to the realm of \LaTeX3.
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% Start with some basic paths (lines) for the sides of the tiles so that we know that we have well-defined tiles at the outset.
+% These are globally defined as we will frequently want to define them in one tikzpicture and use them in another.
+%
+% \begin{macrocode}
+\tl_new:N \g_@@_side_a_tl
+\tl_new:N \g_@@_side_b_tl
+\tl_new:N \g_@@_side_c_tl
+\tl_new:N \g_@@_side_d_tl
+\tl_new:N \g_@@_side_e_tl
+\tl_new:N \g_@@_side_A_tl
+\tl_new:N \g_@@_side_B_tl
+\tl_new:N \g_@@_side_C_tl
+\tl_new:N \g_@@_side_D_tl
+\tl_new:N \g_@@_side_E_tl
+\tl_new:c {g_@@_side_1_tl}
+\tl_new:c {g_@@_side_2_tl}
+\tl_new:c {g_@@_side_3_tl}
+\tl_gset:Nn \g_@@_side_a_tl
+{
+ \pgfsyssoftpath@movetotoken{0pt}{0pt}
+ \pgfsyssoftpath@linetotoken{1pt}{0pt}
+}
+\tl_gset_eq:NN \g_@@_side_b_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_c_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_d_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_e_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_A_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_B_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_C_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_D_tl \g_@@_side_a_tl
+\tl_gset_eq:NN \g_@@_side_E_tl \g_@@_side_a_tl
+\tl_gset_eq:cN {g_@@_side_1_tl} \g_@@_side_a_tl
+\tl_gset_eq:cN {g_@@_side_2_tl} \g_@@_side_a_tl
+\tl_gset_eq:cN {g_@@_side_3_tl} \g_@@_side_a_tl
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_tmpa_fp, \l_@@_tmpb_fp, \l_@@_tmpc_fp, \l_@@_saved_x_fp, \l_@@_saved_y_fp, \l_@@_tmpa_str, \l_@@_tmpb_str, \l_@@_tmpa_seq, \l_@@_tmpa_tl, \l_@@_tmpb_tl, \l_@@_tmpc_tl, \l_@@_tmpd_tl, \l_@@_tmpa_int, \l_@@_tmpb_int, \l_@@_xa_dim, \l_@@_ya_dim, \l_@@_xb_dim, \l_@@_yb_dim, \g_@@_xa_dim, \g_@@_ya_dim, \g_@@_xb_dim, \g_@@_yb_dim, \l_@@_tmpa_prop, \l_@@_cw_bool, \l_@@_update_saved_bool, \l_@@_relative_bool, \g_@@_output_tl}
+% We need a few temporary variables to hold intermediate calculations.
+%
+% \begin{macrocode}
+\fp_new:N \l_@@_tmpa_fp
+\fp_new:N \l_@@_tmpb_fp
+\fp_new:N \l_@@_tmpc_fp
+\fp_new:N \l_@@_saved_x_fp
+\fp_new:N \l_@@_saved_y_fp
+\str_new:N \l_@@_tmpa_str
+\str_new:N \l_@@_tmpb_str
+\seq_new:N \l_@@_tmpa_seq
+\tl_new:N \l_@@_tmpa_tl
+\tl_new:N \l_@@_tmpb_tl
+\tl_new:N \l_@@_tmpc_tl
+\tl_new:N \l_@@_tmpd_tl
+\tl_new:N \l_@@_tmp_tile_path_tl
+\tl_new:N \l_@@_action_lms_tl
+\tl_new:N \l_@@_parameters_lms_tl
+\int_new:N \l_@@_tmpa_int
+\int_new:N \l_@@_tmpb_int
+\fp_new:N \l_@@_xa_fp
+\fp_new:N \l_@@_ya_fp
+\fp_new:N \l_@@_xb_fp
+\fp_new:N \l_@@_yb_fp
+\dim_new:N \l_@@_xa_dim
+\dim_new:N \l_@@_ya_dim
+\dim_new:N \l_@@_xb_dim
+\dim_new:N \l_@@_yb_dim
+\dim_new:N \g_@@_xa_dim
+\dim_new:N \g_@@_ya_dim
+\dim_new:N \g_@@_xb_dim
+\dim_new:N \g_@@_yb_dim
+\prop_new:N \l_@@_tmpa_prop
+\bool_new:N \l_@@_cw_bool
+\bool_new:N \l_@@_update_saved_bool
+\bool_new:N \l_@@_relative_bool
+\bool_new:N \l_@@_edge_bool
+\str_const:Nn \c_@@_colon_str {:}
+\str_const:Nn \c_@@_comma_str {,}
+\fp_const:Nn \c_@@_cm_fp {\dim_to_fp:n {1cm}}
+\tl_new:N \g_@@_output_tl
+\fp_new:N \g_@@_output_a_fp
+\fp_new:N \g_@@_output_b_fp
+\prop_new:N \g_@@_tilenames_prop
+\regex_const:Nn \c_@@_anchor_regex {\s\w+\Z}
+\cs_generate_variant:Nn \seq_set_split:Nnn {NVV}
+\cs_generate_variant:Nn \regex_extract_once:NnNTF {NVNTF}
+\cs_generate_variant:Nn \tl_if_eq:nnT {nVT}
+\cs_generate_variant:Nn \tl_if_in:NnT {NVT}
+\cs_generate_variant:Nn \prop_item:Nn {cV}
+\cs_generate_variant:Nn \tl_if_head_is_group_p:n {V}
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Helpful Error Messages}
+%
+% \begin{macrocode}
+\msg_new:nnn { tilings }{ not baked }
+{ Tile~ #1~ has~ not~ been~ baked. }
+\msg_new:nnn { tilings }{ no tile }
+{ Tile~ #1~ has~ not~ been~ defined. }
+\msg_new:nnn { tilings }{ no side }
+{ Tile~ side~ #1~ has~ not~ been~ defined,~ using~ default. }
+\msg_new:nnn { tilings }{ tile no edge }
+{ Tile~ #1~ doesn't~ have~ an~ edge~ labelled~ #2;
+ ~ available~ edges~ are~ #3.}
+\msg_new:nnn { tilings }{ no edge }
+{ Either~ tile~ #1~ doesn't~ exist
+ ~ or~ it~ doesn't~ have~ an~ edge~ labelled~ #2.}
+% \end{macrocode}
+%
+% \subsection{Creating the Tiles}
+%
+% \begin{macro}[internal]{\@@_normalise_path:Nn}
+% When defining the path for a side, we normalise so that it starts at the origin and ends at \Verb+(1pt,0pt)+.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_normalise_path:Nn #1#2
+{
+% \end{macrocode}
+% Get the initial point of the path and convert to floating point.
+% \begin{macrocode}
+ \group_begin:
+ \spath_initialpoint:Nn \l_@@_tmpa_tl {#2}
+ \fp_set:Nn \l_@@_tmpa_fp {\tl_head:N \l_@@_tmpa_tl}
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+ \fp_set:Nn \l_@@_tmpb_fp {\tl_head:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Get the final point of the path, and compute the difference of the final and initial points.
+%
+% The resulting numbers, say \(a\) and \(b\), will be put into a matrix to rotate and scale the path.
+% The formula for the matrix is:
+%^^A
+% \[
+% \frac{1}{a^2 + b^2}
+% \begin{bmatrix} a & b \\ -b & a \end{bmatrix}
+% \]
+%
+% \begin{macrocode}
+ \spath_finalpoint:Nn \l_@@_tmpa_tl {#2}
+ \fp_set:Nn \l_@@_tmpa_fp
+ {\tl_head:N \l_@@_tmpa_tl - \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+ \fp_set:Nn \l_@@_tmpb_fp
+ {\tl_head:N \l_@@_tmpa_tl - \l_@@_tmpb_fp}
+% \end{macrocode}
+% Now compute the square of the length of the path for scaling.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_tmpc_fp
+ {\l_@@_tmpa_fp^2 + \l_@@_tmpb_fp^2}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_tmpa_fp/\l_@@_tmpc_fp}
+ \fp_set:Nn \l_@@_tmpb_fp {\l_@@_tmpb_fp/\l_@@_tmpc_fp}
+ \fp_set:Nn \l_@@_tmpc_fp {-\l_@@_tmpb_fp}
+% \end{macrocode}
+% Now construct the matrix.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpb_tl
+ {
+ {\fp_use:N \l_@@_tmpa_fp}
+ {\fp_use:N \l_@@_tmpc_fp} % swapped
+ {\fp_use:N \l_@@_tmpb_fp} % swapped
+ {\fp_use:N \l_@@_tmpa_fp}
+ }
+% \end{macrocode}
+% Get the initial point back again for the translation part.
+% \begin{macrocode}
+ \spath_initialpoint:Nn \l_@@_tmpa_tl {#2}
+% \end{macrocode}
+% But we need to premultiply by the matrix because of how the transformations are applied.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_tmpa_fp
+ {
+ (-1) * \l_@@_tmpa_fp * \tl_head:N \l_@@_tmpa_tl
+ + (-1) * \l_@@_tmpb_fp * \tl_tail:N \l_@@_tmpa_tl
+ }
+ \fp_set:Nn \l_@@_tmpb_fp
+ {
+ (-1) * \l_@@_tmpa_fp * \tl_tail:N \l_@@_tmpa_tl
+ + \l_@@_tmpb_fp * \tl_head:N \l_@@_tmpa_tl
+ }
+% \end{macrocode}
+% Finally, we apply the transformation to the path.
+% \begin{macrocode}
+ \tl_put_right:Nx \l_@@_tmpb_tl {
+ {\fp_to_dim:N \l_@@_tmpa_fp}
+ {\fp_to_dim:N \l_@@_tmpb_fp}
+ }
+ \spath_transform:NnV \l_@@_tmpa_tl {#2} \l_@@_tmpb_tl
+ \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmpa_tl
+ \group_end:
+ \tl_set_eq:NN #1 \g_@@_output_tl
+ \tl_gclear:N \g_@@_output_tl
+}
+\cs_generate_variant:Nn \@@_normalise_path:Nn {NV, cn, cV}
+\cs_new_protected_nopar:Npn \@@_normalise_path:N #1
+{
+ \@@_normalise_path:NV #1#1
+}
+\cs_generate_variant:Nn \@@_normalise_path:N {c}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{function}{\SetTilingPath}
+% This sets the path corresponding to a particular side to the current path, and normalises it.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_set_tiling_path:n #1
+{
+ \group_begin:
+ \pgfsyssoftpath@getcurrentpath\l_@@_tmpa_tl
+ \@@_normalise_path:N \l_@@_tmpa_tl
+ \tl_gset_eq:cN {g_@@_side_#1_tl} \l_@@_tmpa_tl
+ \group_end:
+}
+
+\NewDocumentCommand \SetTilingPath { m }
+{
+ \@@_set_tiling_path:n {#1}
+}
+% \end{macrocode}
+% \end{function}
+%
+% \begin{macro}[internal]{\tikz_scan_point:n}
+% This is a wrapper around \Verb+\tikz@scan@one@point+ to make it easier to use with \LaTeX3 variables.
+% \begin{macrocode}
+\cs_new_nopar:Npn \tikz_scan_point:n #1
+{
+ \tikz@scan@one@point\pgfutil@firstofone#1\relax
+}
+\cs_generate_variant:Nn \tikz_scan_point:n {V}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\tikz_node_if_defined:TF}
+% This extracts the code that tests if a node is defined.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \tikz_node_if_defined:n #1 {p,T,F,TF}
+{
+ \tl_if_exist:cTF {pgf@sh@ns@\use:c{tikz@pp@name}{#1}}
+ {
+ \prg_return_true:
+ }{
+ \tl_if_exist:cTF
+ {pgf@sh@ns@not yet positionedPGFINTERNAL\use:c{tikz@pp@name}{#1}}
+ {
+ \pgf_return_true:
+ }
+ {
+ \prg_return_false:
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_keys_get:Nn,\pgfkeys_get:n}
+% This is a wrapper around \Verb+\pgfkeysgetvalue+ to make it easier to use with \LaTeX3 variables.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_keys_get:Nn #1#2
+{
+ \pgfkeysgetvalue{/tikz/tiling/#2}{#1}
+}
+\cs_new_nopar:Npn \@@_keys_get:n #1
+{
+ \pgfkeysvalueof{/tikz/tiling/#1}
+}
+\cs_new_nopar:Npn \@@_tikz_keys_get:Nn #1#2
+{
+ \pgfkeysgetvalue{/tikz/#2}{#1}
+}
+\cs_new_nopar:Npn \@@_tikz_keys_get:n #1
+{
+ \pgfkeysvalueof{/tikz/#1}
+}
+\cs_new_nopar:Npn \@@_pgf_keys_get:Nn #1#2
+{
+ \pgfkeysgetvalue{#2}{#1}
+}
+\cs_new_nopar:Npn \@@_pgf_keys_get:n #1
+{
+ \pgfkeysvalueof{#1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_make_tile:nnn}
+% This builds the tile path from its pieces.
+% The arguments are the name of the tile, the descriptions of the sides, and a token list of the coordinates.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_make_tile:nnn #1#2#3
+{
+% \end{macrocode}
+% Get the first coordinate and initialise the path with a move to this point.
+% \begin{macrocode}
+ \group_begin:
+ \tl_set:Nn \l_@@_tmpa_tl {#3}
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+ \tl_set:Nn \l_@@_tmpa_tl {\pgfsyssoftpath@movetotoken}
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ {
+ \fp_to_dim:n
+ {(\tl_item:Nn \l_@@_tmpb_tl {1}) * \c_@@_cm_fp}
+ }
+ {
+ \fp_to_dim:n
+ {(\tl_item:Nn \l_@@_tmpb_tl {2}) * \c_@@_cm_fp}
+ }
+ }
+ \tl_set_eq:NN \l_@@_tmp_tile_path_tl \l_@@_tmpa_tl
+% \end{macrocode}
+% Now we have our path initialised, we can start appending the side paths according to the specification in the second argument.
+%
+% We append the initial coordinate to the end of the list to make a closed cycle.
+% \begin{macrocode}
+ \tl_set:Nn \l_@@_tmpa_tl {#3}
+ \tl_put_right:Nx \l_@@_tmpa_tl {{\tl_head:N \l_@@_tmpa_tl}}
+% \end{macrocode}
+% Now we walk through the description of the sides, adding the specified paths to our tile path.
+% \begin{macrocode}
+ \tl_map_inline:nn {#2} {
+% \end{macrocode}
+% Clone the path for this side.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_head:n {##1}}
+ \tl_if_exist:cF {g_@@_side_ \tl_use:N \l_@@_tmpc_tl _tl}
+ {
+ \msg_error:nnx { tilings }{ no side } { \tl_use:N \l_@@_tmpc_tl }
+ \tl_gset_eq:cc
+ {g_@@_side_ \tl_use:N \l_@@_tmpc_tl _tl}
+ {g_@@_side_a_tl}
+ }
+ \tl_set_eq:Nc \l_@@_tmpd_tl
+ {g_@@_side_ \tl_use:N \l_@@_tmpc_tl _tl}
+% \end{macrocode}
+% Strip off the next coordinate, and convert it to a point.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Store the resulting coordinate.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_tmpa_fp
+ { \tl_item:Nn \l_@@_tmpb_tl {1} }
+ \fp_set:Nn \l_@@_tmpb_fp
+ { \tl_item:Nn \l_@@_tmpb_tl {2} }
+% \end{macrocode}
+% Now get the next coordinate.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% We want the difference between the two coordinates.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_tmpa_fp
+ {\tl_item:Nn \l_@@_tmpb_tl {1} - \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpb_fp
+ {\tl_item:Nn \l_@@_tmpb_tl {2} - \l_@@_tmpb_fp}
+% \end{macrocode}
+% This is converted into a transformation matrix.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_tmpc_fp {-\l_@@_tmpb_fp}
+ \tl_set:Nx \l_@@_tmpb_tl
+ {
+ {\fp_to_dim:n { \l_@@_tmpa_fp * \c_@@_cm_fp }}
+ {\fp_to_dim:n { \l_@@_tmpb_fp * \c_@@_cm_fp }}% not swapped
+ {\fp_to_dim:n { \l_@@_tmpc_fp * \c_@@_cm_fp }}% not swapped
+ {\fp_to_dim:n { \l_@@_tmpa_fp * \c_@@_cm_fp }}
+ {0}
+ {0}
+ }
+% \end{macrocode}
+% The transformation is applied to the cloned path.
+% \begin{macrocode}
+ \spath_transform:NV \l_@@_tmpd_tl \l_@@_tmpb_tl
+% \end{macrocode}
+% And this is welded to the tile path.
+% \begin{macrocode}
+ \spath_weld:NV \l_@@_tmp_tile_path_tl \l_@@_tmpd_tl
+ }
+% \end{macrocode}
+% At the end we close the path.
+% \begin{macrocode}
+ \spath_close:N \l_@@_tmp_tile_path_tl
+ \tl_gset_eq:NN \g_@@_output_tl \l_@@_tmp_tile_path_tl
+ \group_end:
+ \tl_gclear_new:c {g_@@_tile_#1_tl}
+ \tl_gset_eq:cN {g_@@_tile_#1_tl} \g_@@_output_tl
+ \tl_gclear:N \g_@@_output_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_make_tile:nn}
+% A wrapper around the above which allows us to specify the second two arguments as two items in a token list.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_make_tile:nn #1#2
+{
+ \@@_make_tile:nnn {#1} #2
+}
+\cs_generate_variant:Nn \@@_make_tile:nn {nV}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Specifying the Tiles}
+%
+% The tile specifications are contained in a \Verb+prop+.
+% \begin{macrocode}
+\prop_new:N \g_@@_tiles_prop
+% \end{macrocode}
+%
+% \begin{macro}[internal]{\@@_add_coordinate:Nnn, \@@_add_coordinate:w}
+% Process a coordinate through \Verb+fp+ and adds it to a token list.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_add_coordinate:Nnn #1#2#3 {
+ \group_begin:
+ \fp_set:Nn \l_@@_tmpa_fp {#2}
+ \fp_set:Nn \l_@@_tmpb_fp {#3}
+ \bool_if:NT \l_@@_relative_bool
+ {
+ \fp_add:Nn \l_@@_tmpa_fp {\l_@@_saved_x_fp}
+ \fp_add:Nn \l_@@_tmpb_fp {\l_@@_saved_y_fp}
+ }
+ \fp_gset_eq:NN \g_@@_output_a_fp \l_@@_tmpa_fp
+ \fp_gset_eq:NN \g_@@_output_b_fp \l_@@_tmpb_fp
+ \group_end:
+ \tl_put_right:Nx #1
+ {
+ {{\fp_use:N \g_@@_output_a_fp}{\fp_use:N \g_@@_output_b_fp}}
+ }
+ \bool_if:NT \l_@@_update_saved_bool
+ {
+ \fp_set_eq:NN \l_@@_saved_x_fp \g_@@_output_a_fp
+ \fp_set_eq:NN \l_@@_saved_y_fp \g_@@_output_b_fp
+ }
+ \fp_gzero:N \g_@@_output_a_fp
+ \fp_gzero:N \g_@@_output_b_fp
+}
+% \end{macrocode}
+% Wrapper around the add coordinate command to split at a comma.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_add_xy_coordinate:w #1#2,#3 \q_stop
+{
+ \@@_add_coordinate:Nnn #1 {#2}{#3}
+}
+% \end{macrocode}
+%
+% Wrapper around the add coordinate command to split at a colon.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_add_rth_coordinate:w #1#2:#3 \q_stop
+{
+ \@@_add_coordinate:Nnn #1 {(#3) * cosd(#2)}{(#3) * sind(#2)}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_transform_side_to_axis:Nnn}
+% Apply a transformation to make a given side lie on the x-axis.
+% Second argument is the tile, third is the side, first is whether to reverse the side.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_transform_side_to_axis:Nnn #1#2#3
+{
+% \end{macrocode}
+% Get our tile data, checking if the tile exists.
+% \begin{macrocode}
+ \group_begin:
+ \prop_get:NnNTF \g_@@_tiles_prop {#2} \l_@@_tmpa_tl
+ {
+% \end{macrocode}
+% Start with the edge list.
+%
+% Initialise the counter.
+% \begin{macrocode}
+ \int_zero:N \l_@@_tmpb_int
+ \int_incr:N \l_@@_tmpb_int
+% \end{macrocode}
+% Get the path type list.
+%
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+% \end{macrocode}
+%
+% Iterate through the path type list, looking for the requested path.
+% \begin{macrocode}
+ \bool_set_false:N \l_@@_edge_bool
+ \tl_map_inline:Nn \l_@@_tmpc_tl {
+ \str_if_eq:nnT {##1} {#3} {
+ \bool_set_true:N \l_@@_edge_bool
+ \tl_map_break:
+ }
+ \int_incr:N \l_@@_tmpb_int
+ }
+ \bool_if:NTF \l_@@_edge_bool
+ {
+% \end{macrocode}
+% Get the coordinate list.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Strip off the outer braces.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_item:Nn \l_@@_tmpc_tl {1}}
+% \end{macrocode}
+% Add the first coordinate at the end.
+% \begin{macrocode}
+ \tl_put_right:Nx \l_@@_tmpc_tl
+ {{\tl_item:Nn \l_@@_tmpc_tl {1}}}
+% \end{macrocode}
+% Get the coordinates for this edge.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpa_tl
+ {\tl_item:Nn \l_@@_tmpc_tl {\int_use:N \l_@@_tmpb_int}}
+ \tl_set:Nx \l_@@_tmpb_tl
+ {\tl_item:Nn \l_@@_tmpc_tl {\int_use:N \l_@@_tmpb_int + 1}}
+% \end{macrocode}
+% Possibly swap the ends.
+% \begin{macrocode}
+ \bool_if:NT #1
+ {
+ \tl_set:NV \l_@@_tmpc_tl \l_@@_tmpa_tl
+ \tl_set:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
+ \tl_set:NV \l_@@_tmpb_tl \l_@@_tmpc_tl
+ }
+% \end{macrocode}
+% Get the coordinates of the first point, which will be the origin of the transformation.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_xa_fp {\tl_item:Nn \l_@@_tmpb_tl {1}}
+ \fp_set:Nn \l_@@_ya_fp {\tl_item:Nn \l_@@_tmpb_tl {2}}
+% \end{macrocode}
+% Get the coordinates of the second point and adjust relative to the first.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_xb_fp
+ {\tl_item:Nn \l_@@_tmpa_tl {1} - \l_@@_xa_fp}
+ \fp_set:Nn \l_@@_yb_fp
+ {\tl_item:Nn \l_@@_tmpa_tl {2} - \l_@@_ya_fp}
+% \end{macrocode}
+% And normalise the vector along it.
+% \begin{macrocode}
+% \fp_set:Nn \l_@@_xb_fp {\l_@@_xb_fp / \c_@@_cm_fp}
+% \fp_set:Nn \l_@@_yb_fp {\l_@@_yb_fp / \c_@@_cm_fp}
+ \fp_set:Nn \l_@@_tmpa_fp
+ {(\l_@@_xb_fp)^2 + (\l_@@_yb_fp)^2}
+ \fp_set:Nn \l_@@_xb_fp { \l_@@_xb_fp / \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_yb_fp { \l_@@_yb_fp / \l_@@_tmpa_fp}
+% \end{macrocode}
+% Now rotate so that the \(x\)--axis lies along the edge.
+% \begin{macrocode}
+ \tl_gset:Nx \g_@@_output_tl
+ {
+ \exp_not:N \pgftransformtriangle
+ {
+ \exp_not:N \pgfpoint{0pt}{0pt}
+ }
+ {
+ \exp_not:N \pgfpoint
+ {\fp_to_dim:N \l_@@_xb_fp}{\fp_to_dim:n {-\l_@@_yb_fp}}
+ }
+ {
+ \exp_not:N \pgfpoint
+ {\fp_to_dim:N \l_@@_yb_fp}{\fp_to_dim:N \l_@@_xb_fp}
+ }
+ \exp_not:N \pgftransformshift
+ {
+ \exp_not:N \pgfpoint
+ {
+ \fp_to_dim:n {-\l_@@_xa_fp * \c_@@_cm_fp}
+ }
+ {
+ \fp_to_dim:n {-\l_@@_ya_fp * \c_@@_cm_fp}
+ }
+ }
+ }
+ }
+ {
+ \msg_error:nnxxx {tilings} {tile no edge} {#2} {#3}
+ {\tl_use:N \l_@@_tmpc_tl }
+ \tl_gclear:N \g_@@_output_tl
+ }
+ }
+ {
+ \msg_error:nnn {tilings} {no tile} {#2}
+ \tl_gclear:N \g_@@_output_tl
+ }
+ \group_end:
+ \tl_use:N \g_@@_output_tl
+ \tl_gclear:N \g_@@_output_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\cs_generate_variant:Nn
+\@@_transform_side_to_axis:Nnn {Nnx,NnV,NVV}
+% \end{macrocode}
+%
+% \begin{macro}[internal]{\@@_translate_vertex_to_origin:Nnn}
+% Apply a transformation to make a given vertex sit at the origin.
+% Second argument is the tile, third is the side, first is a boolean to determine whether to use the start or end.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_translate_vertex_to_origin:Nnn #1#2#3
+{
+% \end{macrocode}
+% Get our tile data, checking if the tile exists.
+% \begin{macrocode}
+ \group_begin:
+ \prop_get:NnNTF \g_@@_tiles_prop {#2} \l_@@_tmpa_tl
+ {
+% \end{macrocode}
+% Start with the edge list.
+%
+% Initialise the counter.
+% \begin{macrocode}
+ \int_zero:N \l_@@_tmpb_int
+ \int_incr:N \l_@@_tmpb_int
+% \end{macrocode}
+% Get the path type list.
+%
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+% \end{macrocode}
+%
+% Iterate through the path type list, looking for the requested path.
+% \begin{macrocode}
+ \bool_set_false:N \l_@@_edge_bool
+ \tl_map_inline:Nn \l_@@_tmpc_tl {
+ \str_if_eq:nnT {##1} {#3} {
+ \bool_set_true:N \l_@@_edge_bool
+ \tl_map_break:
+ }
+ \int_incr:N \l_@@_tmpb_int
+ }
+ \bool_if:NTF \l_@@_edge_bool
+ {
+% \end{macrocode}
+% Get the coordinate list.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Strip off the outer braces.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_item:Nn \l_@@_tmpc_tl {1}}
+% \end{macrocode}
+% Add the first coordinate at the end.
+% \begin{macrocode}
+ \tl_put_right:Nx \l_@@_tmpc_tl
+ {{\tl_item:Nn \l_@@_tmpc_tl {1}}}
+% \end{macrocode}
+% Get the coordinates for this edge.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpa_tl
+ {\tl_item:Nn \l_@@_tmpc_tl {\int_use:N \l_@@_tmpb_int}}
+ \tl_set:Nx \l_@@_tmpb_tl
+ {\tl_item:Nn \l_@@_tmpc_tl {\int_use:N \l_@@_tmpb_int + 1}}
+% \end{macrocode}
+% Possibly swap the ends.
+% \begin{macrocode}
+ \bool_if:NT #1
+ {
+ \tl_set:NV \l_@@_tmpc_tl \l_@@_tmpa_tl
+ \tl_set:NV \l_@@_tmpa_tl \l_@@_tmpb_tl
+ \tl_set:NV \l_@@_tmpb_tl \l_@@_tmpc_tl
+ }
+% \end{macrocode}
+% Get the coordinates of the first point, which will be the origin of the transformation.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_xa_fp {\tl_item:Nn \l_@@_tmpb_tl {1}}
+ \fp_set:Nn \l_@@_ya_fp {\tl_item:Nn \l_@@_tmpb_tl {2}}
+% \end{macrocode}
+% Shift to place the selected vertex at the origin.
+% \begin{macrocode}
+ \tl_gset:Nx \g_@@_output_tl
+ {
+ \exp_not:N \pgftransformshift
+ {
+ \exp_not:N \pgfpoint
+ {
+ \fp_to_dim:n {-\l_@@_xa_fp * \c_@@_cm_fp}
+ }
+ {
+ \fp_to_dim:n {-\l_@@_ya_fp * \c_@@_cm_fp}
+ }
+ }
+ }
+ }
+ {
+ \msg_error:nnxxx {tilings} {tile no edge} {#2} {#3}
+ {\tl_use:N \l_@@_tmpc_tl }
+ \tl_gclear:N \g_@@_output_tl
+ }
+ }
+ {
+ \msg_error:nnn {tilings} {no tile} {#2}
+ \tl_gclear:N \g_@@_output_tl
+ }
+ \group_end:
+ \tl_use:N \g_@@_output_tl
+ \tl_gclear:N \g_@@_output_tl
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\cs_generate_variant:Nn
+\@@_translate_vertex_to_origin:Nnn {Nnx,NnV,NVV}
+% \end{macrocode}
+%
+% \begin{macro}[internal]{\TransformAlongSide}
+% Make this available outside the \LaTeX3 environment.
+% The starred version allows for reversing the side.
+% \begin{macrocode}
+\DeclareDocumentCommand \TransformAlongSide {s m m}
+{
+% \end{macrocode}
+% Store the star
+% \begin{macrocode}
+ \IfBooleanTF {#1}
+ {
+ \bool_set_true:N \l_@@_cw_bool
+ }
+ {
+ \bool_set_false:N \l_@@_cw_bool
+ }
+ \@@_transform_side_to_axis:Nnx \l_@@_cw_bool {#2}{#3}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_coordinates_at_vertices:n}
+% This places TikZ coordinates at the vertices of the tile.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_coordinates_at_vertices:n #1
+{
+ \group_begin:
+% \end{macrocode}
+% Get our tile data
+% \begin{macrocode}
+ \prop_get:NnN \g_@@_tiles_prop {#1} \l_@@_tmpa_tl
+% \end{macrocode}
+% Start with the edge list
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Get the coordinate list
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpa_tl}
+% \end{macrocode}
+% Strip off the outer braces
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {\tl_item:Nn \l_@@_tmpc_tl {1}}
+% \end{macrocode}
+% Add the first coordinate at the end
+% \begin{macrocode}
+ \tl_put_right:Nx \l_@@_tmpc_tl
+ {{\tl_item:Nn \l_@@_tmpc_tl {1}}}
+% \end{macrocode}
+% Get the first coordinate
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_head:N \l_@@_tmpc_tl}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
+% \end{macrocode}
+% Iterate through the edge list, placing coordinates
+% \begin{macrocode}
+ \tl_map_inline:Nn \l_@@_tmpb_tl {
+ \tl_set:Nx \l_@@_tmpd_tl {
+ \exp_not:N \coordinate
+ (-edge~ ##1~ start)~
+ at (
+ \tl_item:Nn \l_@@_tmpa_tl {1},
+ \tl_item:Nn \l_@@_tmpa_tl {2}
+ );
+ }
+ \tl_use:N \l_@@_tmpd_tl
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_head:N \l_@@_tmpc_tl}
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_tail:N \l_@@_tmpc_tl}
+ \tl_set:Nx \l_@@_tmpd_tl {
+ \exp_not:N \coordinate
+ (-edge~ ##1~ end)~
+ at (
+ \tl_item:Nn \l_@@_tmpa_tl {1},
+ \tl_item:Nn \l_@@_tmpa_tl {2}
+ );
+ }
+ \tl_use:N \l_@@_tmpd_tl
+ }
+ \group_end:
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\CoordinatesAtVertices}
+% User-accessible wrapper around the above.
+% \begin{macrocode}
+\DeclareDocumentCommand \CoordinatesAtVertices {m}
+{
+ \@@_coordinates_at_vertices:n {#1}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+\tikzset{
+ transform~ to~ tile/.code~ args={#1~ along~ #2}{%
+ \group_begin:
+ \tl_if_in:nnTF {#1} {back}
+ {
+ \tikzset{
+ tiling/alignment~ set~ location=#1,
+ tiling/alignment~ direction={backwards}
+ }
+ }
+ {
+ \tikzset{
+ tiling/alignment~ location=#1,
+ tiling/alignment~ direction={forewards}
+ }
+ }
+ \tl_if_in:nnTF {#2} {using}
+ {
+ \tikzset{
+ tiling/alignment~ set~ edges=#2,
+ }
+ }
+ {
+ \tikzset{
+ tiling/alignment~ edge=#2,
+ }
+ }
+ \tikz_scan_point:n {
+ (\@@_keys_get:n {alignment~ location}
+ -edge~ \@@_keys_get:n {alignment~ edge}~ start)
+ }
+ \dim_set_eq:Nc \l_@@_xa_dim {pgf@x}
+ \dim_set_eq:Nc \l_@@_ya_dim {pgf@y}
+ \tikz_scan_point:n {
+ (\@@_keys_get:n {alignment~ location}
+ -edge~ \@@_keys_get:n {alignment~ edge}~ end)
+ }
+ \dim_set_eq:Nc \l_@@_xb_dim {pgf@x}
+ \dim_set_eq:Nc \l_@@_yb_dim {pgf@y}
+ \@@_keys_get:Nn \l_@@_tmpb_tl {alignment~ direction}
+ \tl_if_eq:NnTF \l_@@_tmpb_tl {forewards}
+ {
+ \dim_gset_eq:NN \g_@@_xa_dim \l_@@_xa_dim
+ \dim_gset_eq:NN \g_@@_ya_dim \l_@@_ya_dim
+ \dim_gset_eq:NN \g_@@_xb_dim \l_@@_xb_dim
+ \dim_gset_eq:NN \g_@@_yb_dim \l_@@_yb_dim
+ }
+ {
+ \dim_gset_eq:NN \g_@@_xa_dim \l_@@_xb_dim
+ \dim_gset_eq:NN \g_@@_ya_dim \l_@@_yb_dim
+ \dim_gset_eq:NN \g_@@_xb_dim \l_@@_xa_dim
+ \dim_gset_eq:NN \g_@@_yb_dim \l_@@_ya_dim
+ }
+ \dim_gsub:Nn \g_@@_xb_dim {\g_@@_xa_dim}
+ \dim_gsub:Nn \g_@@_yb_dim {\g_@@_ya_dim}
+ \dim_gset:Nn \g_@@_xb_dim
+ {\g_@@_xb_dim * \dim_ratio:nn {1pt}{1cm}}
+ \dim_gset:Nn \g_@@_yb_dim
+ {\g_@@_yb_dim * \dim_ratio:nn {1pt}{1cm}}
+ \group_end:
+% \end{macrocode}
+% We store the initial points in \Verb+\pgf@xa+ and \Verb+\pgf@ya+ but we want \Verb+\pgf@xb+ and \Verb+\pgf@yb+ to be a vector along the edge.
+% \begin{macrocode}
+% \end{macrocode}
+% We shift to the start of the edge.
+% \begin{macrocode}
+ \pgftransformshift{\pgfpoint{\g_@@_xa_dim}{\g_@@_ya_dim}}
+% \end{macrocode}
+% Now rotate so that the \(x\)--axis lies along the edge.
+% \begin{macrocode}
+ \pgftransformtriangle
+ {\pgfpoint{0pt}{0pt}}
+ {\pgfpoint{\g_@@_xb_dim}{\g_@@_yb_dim}}
+ {\pgfpoint{-\g_@@_yb_dim}{\g_@@_xb_dim}}
+ },
+ align~ with/.code~ args={#1~ along~ #2}{%
+ \tl_if_in:nnTF {#1} {back}
+ {
+ \tikzset{
+ tiling/alignment~ set~ location=#1,
+ tiling/alignment~ direction={backwards}
+ }
+ }
+ {
+ \tikzset{
+ tiling/alignment~ location=#1,
+ tiling/alignment~ direction={forewards}
+ }
+ }
+ \tl_if_in:nnTF {#2} {using}
+ {
+ \tikzset{
+ tiling/alignment~ set~ edges=#2,
+ }
+ }
+ {
+ \tikzset{
+ tiling/alignment~ edge=#2,
+ }
+ }
+ \tikz_node_if_defined:nTF
+ {
+ \@@_keys_get:n {alignment~ location}
+ -edge~ \@@_keys_get:n {alignment~ edge}~ start
+ }
+ {
+ \tikzset{
+ tiling/alignment~ start/.expanded={
+ (\@@_keys_get:n {alignment~ location}
+ -edge~ \@@_keys_get:n {alignment~ edge}~ start)
+ },
+ tiling/alignment~ end/.expanded={
+ (\@@_keys_get:n {alignment~ location}
+ -edge~ \@@_keys_get:n {alignment~ edge}~ end)
+ },
+ }
+ }
+ {
+ \@@_keys_get:Nn \l_@@_tmpa_tl {alignment~ location}
+ \tl_set:Nx \l_@@_tmpa_tl {\tl_use:N \l_@@_tmpa_tl}
+ \prop_get:NVNTF \g_@@_tilenames_prop
+ \l_@@_tmpa_tl \l_@@_tmpb_tl
+ {
+ \prop_get:NVN \g_@@_tiles_prop
+ \l_@@_tmpb_tl \l_@@_tmpc_tl
+ \msg_error:nnxxx { tilings }{ tile no edge }
+ {
+ \tl_use:N \l_@@_tmpa_tl \c_space_tl
+ (type~ \tl_use:N \l_@@_tmpb_tl)
+ }
+ {\@@_keys_get:n {alignment~ edge} }
+ { \tl_item:Nn \l_@@_tmpc_tl {1} }
+ }
+ {
+ \msg_error:nnx { tilings }{ no tile }
+ {\@@_keys_get:n {alignment~ location} }
+ }
+ }
+ },
+ tiling/.is~ family,
+ tiling/alignment~ set~ location/.code~ args={#1~ back}{
+ \tikzset{
+ tiling/alignment~ location=#1,
+ }
+ },
+ tiling/alignment~ set~ edges/.code~ args={#1~ using~ #2}{
+ \tikzset{
+ tiling/alignment~ edge=#1,
+ tiling/alignment~ new~ edge=#2
+ }
+ },
+ align~ between/.code~ args={#1~ and~ #2~ using~ #3}{
+ \tikzset{
+ tiling/alignment~ start={#1},
+ tiling/alignment~ end={#2},
+ }
+ \str_set:Nn \l_@@_tmpa_str {#3}
+ \str_set:Nx \l_@@_tmpb_str {\str_tail:N \l_@@_tmpa_str}
+ \tikzset{
+ tiling/alignment~ new~ edge/.expanded={\str_use:N \l_@@_tmpb_str}
+ }
+ \str_set:Nx \l_@@_tmpa_str {\str_head:N \l_@@_tmpa_str}
+ \str_set:Nx \l_@@_tmpb_str {\str_lowercase:f { \l_@@_tmpa_str}}
+ \str_if_eq:NNT \l_@@_tmpa_str \l_@@_tmpb_str
+ {
+ \str_set:Nx \l_@@_tmpb_str
+ {\str_uppercase:f { \l_@@_tmpa_str}}
+ }
+ \tikzset{
+ tiling/alignment~ edge/.expanded={\str_use:N \l_@@_tmpb_str},
+ }
+ },
+ tiling/alignment~ location/.initial={},
+ tiling/alignment~ edge/.initial=a,
+ tiling/alignment~ new~ edge/.initial={},
+ tiling/alignment~ direction/.initial={forewards},
+ tiling/alignment~ start/.initial={},
+ tiling/alignment~ end/.initial={},
+ tiling/anchor/.initial={},
+% \end{macrocode}
+% Default clipping style.
+% \begin{macrocode}
+ every~ tile~ clip/.style={clip}
+}
+% \end{macrocode}
+%
+% \begin{function}{\DefineTile}
+% This is the user function for defining a tile.
+% \begin{macrocode}
+\DeclareDocumentCommand \DefineTile { s m m m }
+{
+% \end{macrocode}
+% Clear the temporary variable.
+% \begin{macrocode}
+ \tl_clear:N \l_@@_tmpa_tl
+% \end{macrocode}
+% The 3rd parameter is a list of coordinates at vertices, iterate through them and add them to the list.
+% \begin{macrocode}
+ \int_zero:N \l_@@_tmpa_int
+ \fp_zero:N \l_@@_saved_x_fp
+ \fp_zero:N \l_@@_saved_y_fp
+ \tl_map_inline:nn {#4} {
+ \str_set:Nn \l_@@_tmpa_str {##1}
+ \str_if_eq:VnTF \l_@@_tmpa_str {+}
+ {
+ \int_incr:N \l_@@_tmpa_int
+ }
+ {
+ \int_case:nn {\l_@@_tmpa_int}
+ {
+ {0} {
+ \bool_set_false:N \l_@@_relative_bool
+ \bool_set_true:N \l_@@_update_saved_bool
+ }
+ {1} {
+ \bool_set_true:N \l_@@_relative_bool
+ \bool_set_false:N \l_@@_update_saved_bool
+ }
+ {2} {
+ \bool_set_true:N \l_@@_relative_bool
+ \bool_set_true:N \l_@@_update_saved_bool
+ }
+
+ }
+ \str_if_in:NnTF \l_@@_tmpa_str {:}
+ {
+ \seq_set_split:NVV \l_@@_tmpa_seq \c_@@_colon_str \l_@@_tmpa_str
+ \@@_add_coordinate:Nnn \l_@@_tmpa_tl
+ {
+ (\seq_item:Nn \l_@@_tmpa_seq {2}) * cosd (\seq_item:Nn \l_@@_tmpa_seq {1})
+ }
+ {
+ (\seq_item:Nn \l_@@_tmpa_seq {2}) * sind (\seq_item:Nn \l_@@_tmpa_seq {1})
+ }
+ }
+ {
+ \seq_set_split:NVV \l_@@_tmpa_seq \c_@@_comma_str \l_@@_tmpa_str
+ \@@_add_coordinate:Nnn \l_@@_tmpa_tl
+ {
+ (\seq_item:Nn \l_@@_tmpa_seq {1})
+ }
+ {
+ (\seq_item:Nn \l_@@_tmpa_seq {2})
+ }
+ }
+ \int_zero:N \l_@@_tmpa_int
+ }
+ }
+% \end{macrocode}
+% Now we make a list of the edge types (from the 2nd parameter), using a prop to keep track of whether an edge is repeated.
+% \begin{macrocode}
+ \prop_clear:N \l_@@_tmpa_prop
+ \tl_map_inline:nn {#3} {
+ \prop_if_in:NnTF \l_@@_tmpa_prop {##1}
+ {
+ \prop_put:Nnn \l_@@_tmpa_prop {##1} {1}
+ }
+ {
+ \prop_put:Nnn \l_@@_tmpa_prop {##1} {0}
+ }
+ }
+% \end{macrocode}
+% Having established their multiplicity, we now create the edges with their names, appending numbers to their names if used more than once.
+% \begin{macrocode}
+ \tl_clear:N \l_@@_tmpb_tl
+ \tl_map_inline:nn {#3}
+ {
+ \tl_clear:N \l_@@_tmpc_tl
+ \tl_put_right:Nn \l_@@_tmpc_tl {##1}
+ \int_compare:nF {\prop_item:Nn \l_@@_tmpa_prop {##1} == 0} {
+ \tl_put_right:Nx \l_@@_tmpc_tl
+ {\prop_item:Nn \l_@@_tmpa_prop {##1}}
+ \prop_put:Nnx \l_@@_tmpa_prop {##1}
+ {\int_eval:n {\prop_item:Nn \l_@@_tmpa_prop {##1} + 1}}
+ }
+ \tl_put_right:Nx \l_@@_tmpb_tl {{ \l_@@_tmpc_tl }}
+ }
+% \end{macrocode}
+% Finally, we can create our tile and add it to the global tile prop.
+% \begin{macrocode}
+ \prop_gput:Nnx \g_@@_tiles_prop {#2}
+ {{\tl_use:N \l_@@_tmpb_tl} {\tl_use:N \l_@@_tmpa_tl}}
+% \end{macrocode}
+% Having created the tile, we make a TikZ pic to place it on the page.
+% \begin{macrocode}
+ \tikzset{
+ #2/.pic={
+ \begin{scope}[
+ every~ tile~ scope/.try,
+ every~ #2~ scope/.try,
+ this~ tile~ scope/.try
+ ]
+% \end{macrocode}
+% Save the name and tile type
+% \begin{macrocode}
+ \tikz@fig@mustbenamed
+ \prop_gput:NVn \g_@@_tilenames_prop \tikz@fig@name {#2}
+% \end{macrocode}
+% Were we given coordinates to align ourselves against?
+% \begin{macrocode}
+ \@@_keys_get:Nn \l_@@_tmpa_tl {alignment~ start}
+ \tl_if_empty:NTF \l_@@_tmpa_tl
+ {
+% \end{macrocode}
+% No alignment information was given, was an anchor specified?
+% \begin{macrocode}
+ \prop_get:NnN \g_@@_tiles_prop {#2} \l_@@_tmpa_tl
+ \tl_set:Nx \l_@@_tmpc_tl {\tl_head:N \l_@@_tmpa_tl}
+ \@@_keys_get:Nn \l_@@_tmpa_tl {anchor}
+ \tl_if_empty:NTF \l_@@_tmpa_tl
+ {
+% \end{macrocode}
+% No positioning information given, but we might have been asked to flip the tile
+% \begin{macrocode}
+ \bool_if:NT \l_@@_cw_bool
+ {
+ \pgftransformxscale {-1}
+ }
+ }
+ {
+ \regex_extract_once:NVNTF
+ \c_@@_anchor_regex \l_@@_tmpa_tl \l_@@_tmpb_tl
+ {
+ \regex_replace_once:NnN \c_@@_anchor_regex {} \l_@@_tmpa_tl
+ \tl_if_eq:NnTF \l_@@_tmpb_tl {~end}
+ {
+ \bool_set_true:N \l_@@_cw_bool
+ }
+ {
+ \bool_set_false:N \l_@@_cw_bool
+ }
+ }
+ {
+ \bool_set_false:N \l_@@_cw_bool
+ }
+ \tl_set:Nx \l_@@_tmpb_tl {{\tl_use:N \l_@@_tmpa_tl}}
+ \tl_if_in:NVT \l_@@_tmpc_tl \l_@@_tmpb_tl
+ {
+ \@@_translate_vertex_to_origin:NnV
+ \l_@@_cw_bool {#2} \l_@@_tmpa_tl
+ }
+ }
+ }
+ {
+% \end{macrocode}
+% Yes, we were.
+% So we adjust our position accordingly.
+% The first job is to transform so that we're aligned with the specified coordinates.
+% \begin{macrocode}
+ \group_begin:
+% \end{macrocode}
+% We get the locations of the start and ending coordinates.
+% \begin{macrocode}
+ \tikzset{
+ name~ prefix~ ..
+ }
+ \tikz_scan_point:n {
+ \@@_keys_get:n {alignment~ start}
+ }
+ \dim_set_eq:Nc \l_@@_xa_dim {pgf@x}
+ \dim_set_eq:Nc \l_@@_ya_dim {pgf@y}
+ \tikz_scan_point:n {
+ \@@_keys_get:n {alignment~ end}
+ }
+ \dim_set_eq:Nc \l_@@_xb_dim {pgf@x}
+ \dim_set_eq:Nc \l_@@_yb_dim {pgf@y}
+ \@@_keys_get:Nn \l_@@_tmpb_tl {alignment~ direction}
+ \tl_if_eq:NnTF \l_@@_tmpb_tl {forewards}
+ {
+ \dim_gset_eq:NN \g_@@_xa_dim \l_@@_xa_dim
+ \dim_gset_eq:NN \g_@@_ya_dim \l_@@_ya_dim
+ \dim_gset_eq:NN \g_@@_xb_dim \l_@@_xb_dim
+ \dim_gset_eq:NN \g_@@_yb_dim \l_@@_yb_dim
+ }
+ {
+ \dim_gset_eq:NN \g_@@_xa_dim \l_@@_xb_dim
+ \dim_gset_eq:NN \g_@@_ya_dim \l_@@_yb_dim
+ \dim_gset_eq:NN \g_@@_xb_dim \l_@@_xa_dim
+ \dim_gset_eq:NN \g_@@_yb_dim \l_@@_ya_dim
+ }
+ \dim_gsub:Nn \g_@@_xb_dim {\g_@@_xa_dim}
+ \dim_gsub:Nn \g_@@_yb_dim {\g_@@_ya_dim}
+ \dim_gset:Nn \g_@@_xb_dim {\g_@@_xb_dim * \dim_ratio:nn {1pt}{1cm}}
+ \dim_gset:Nn \g_@@_yb_dim {\g_@@_yb_dim * \dim_ratio:nn {1pt}{1cm}}
+ \group_end:
+% \end{macrocode}
+% We shift to the start of the edge.
+% \begin{macrocode}
+ \pgftransformshift{\pgfpoint{\g_@@_xa_dim}{\g_@@_ya_dim}}
+% \end{macrocode}
+% And normalise the vector along it.
+% \begin{macrocode}
+% \pgfpointnormalised{\pgfpoint{\g_@@_xb_dim}{\g_@@_yb_dim}}
+% \dim_gset_eq:Nc \g_@@_xb_dim {pgf@x}
+% \dim_gset_eq:Nc \g_@@_yb_dim {pgf@y}
+% \end{macrocode}
+% Now rotate so that the \(x\)--axis lies along the edge.
+% \begin{macrocode}
+ \pgftransformtriangle
+ {\pgfpoint{0pt}{0pt}}
+ {\pgfpoint{\g_@@_xb_dim}{\g_@@_yb_dim}}
+ {\pgfpoint{-\g_@@_yb_dim}{\g_@@_xb_dim}}
+% \end{macrocode}
+% The next job is to shift and rotate the current tile so that the correct edge ends up against the receiving tile.
+% \begin{macrocode}
+ \str_set:Nx \l_@@_tmpa_str
+ {\@@_keys_get:n {alignment~ edge}}
+ \str_set:Nx \l_@@_tmpa_str {\str_head:N \l_@@_tmpa_str}
+ \str_put_right:Nx \l_@@_tmpa_str
+ {\@@_keys_get:n {alignment~ new~ edge}}
+ \str_set:Nx \l_@@_tmpb_str {\str_lowercase:f { \l_@@_tmpa_str}}
+ \str_if_eq:NNT \l_@@_tmpa_str \l_@@_tmpb_str
+ {
+ \str_set:Nx \l_@@_tmpb_str
+ {\str_uppercase:f { \l_@@_tmpa_str}}
+ }
+
+ \IfBooleanT {#1}
+ {
+ \bool_set:Nn \l_@@_cw_bool {!\l_@@_cw_bool}
+ }
+ \bool_if:NT \l_@@_cw_bool
+ {
+ \pgftransformyscale {-1}
+ }
+ \@@_transform_side_to_axis:NnV \l_@@_cw_bool {#2} \l_@@_tmpb_str
+ }
+% \end{macrocode}
+% Now that the transformation is finalised, we can render the tile.
+% We clip against the tile path so that the tiles don't ``bleed''.
+% If we didn't do this, drawing the tile would result in overlaps which can look a bit ugly.
+% On the other hand, tight clipping can lead to ``gaps'' between the tiles so we make this optional by enclosing it in a style.
+%
+% We start by putting coordinates at each vertex, labelled by which edge they are.
+% \begin{macrocode}
+ \@@_coordinates_at_vertices:n {#2}
+% \end{macrocode}
+% And one at the origin of the pic
+% \begin{macrocode}
+ \coordinate[alias=-center] (-centre) at (0,0);
+% \end{macrocode}
+%
+% The first action is to clip against the tile path.
+% \begin{macrocode}
+ \UseTile[
+ every~ tile~ clip/.try,
+ every~ #2~ clip/.try,
+ this~ tile~ clip/.try
+ ]{#2}
+% \end{macrocode}
+% Any pre-actions?
+% \begin{macrocode}
+ \tikzset{
+ every~ tile~ before~ path/.try,
+ every~ #2~ before~ path/.try,
+ this~ tile~ before~ path/.try
+ }
+% \end{macrocode}
+% Now we render the tile path
+% \begin{macrocode}
+ \UseTile[
+ every~ tile/.try,
+ every~ #2/.try,
+ this~ tile/.try,
+ pic~ actions
+ ]{#2}
+% \end{macrocode}
+% After drawing the tile and placing the coordinates,
+% \begin{macrocode}
+ \tikzset{
+ every~ tile~ after~ path/.try,
+ every~ #2~ after~ path/.try,
+ this~ tile~ after~ path/.try
+ }
+ \end{scope}
+ },
+% \end{macrocode}
+% This is a shortcut for installing the \Verb+pic+ type.
+% \begin{macrocode}
+ #2/.style={
+ every~ tile~ pic/.try,
+ every~ #2~ pic/.try,
+ pic~ type=#2,
+ }
+ }
+}
+% \end{macrocode}
+% \end{function}
+%
+% \begin{function}{\BakeTile}
+% This is the user wrapper around the tile creation macros.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_bake_tile:n #1
+{
+ \prop_get:NnN \g_@@_tiles_prop {#1} \l_@@_tmpa_tl
+ \@@_make_tile:nV {#1} \l_@@_tmpa_tl
+}
+
+\NewDocumentCommand \BakeTile {m}
+{
+ \@@_bake_tile:n {#1}
+}
+% \end{macrocode}
+% \end{function}
+%
+% \begin{function}{\UseTile}
+% This is the command that actually places a tile on the page.
+% The first argument is optional and is for styling.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_use_tile:nn #1#2
+{
+% \end{macrocode}
+% We need to transform the tile to correspond to the current transformation matrix.
+% To ensure that we only transform the current tile, we clone it first.
+% \begin{macrocode}
+ \tl_if_exist:cTF {g_@@_tile_#2_tl}
+ {
+ \tl_set_eq:Nc \l_@@_tmp_tile_path_tl {g_@@_tile_#2_tl}
+% \end{macrocode}
+% We get the current transformation to apply to this path.
+% \begin{macrocode}
+ \pgfgettransform \l_@@_tmpa_tl
+% \end{macrocode}
+% Apply the transformation, protocol the path, and render it.
+% \begin{macrocode}
+ \spath_transform:NV \l_@@_tmp_tile_path_tl \l_@@_tmpa_tl
+ \spath_tikz_path:nV {#1} \l_@@_tmp_tile_path_tl
+ }
+ {
+ \msg_error:nnn { tilings }{ not baked }{#2}
+ }
+}
+
+\NewDocumentCommand \UseTile {O{} m}
+{
+ \@@_use_tile:nn {#1}{#2}
+}
+% \end{macrocode}
+% \end{function}
+%
+% \begin{macro}{save tiling path}
+% This is a style for a user to take a path and make it into the path for one of the sides.
+% It needs to store both that side and the reverse.
+% \begin{macrocode}
+\tikzset{
+ save~ tiling~ path/.code={
+ \tikz@addmode{
+% \end{macrocode}
+% Get the current path.
+% \begin{macrocode}
+ \pgfsyssoftpath@getcurrentpath\l_@@_tmpa_tl
+% \end{macrocode}
+% Normalise the path and save.
+% \begin{macrocode}
+ \@@_normalise_path:N \l_@@_tmpa_tl
+ \tl_gclear_new:c {g_@@_side_#1_tl}
+ \tl_gset_eq:cN {g_@@_side_#1_tl} \l_@@_tmpa_tl
+% \end{macrocode}
+% Now create the reverse path.
+% The name is the upper case version.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpb_tl {\str_uppercase:n {#1}}
+% \end{macrocode}
+% Reverse the path, and relocate to the interval \([0,1]\).
+% \begin{macrocode}
+ \spath_reverse:N \l_@@_tmpa_tl
+ \spath_transform:Nnnnnnn \l_@@_tmpa_tl {-1} {0} {0} {-1} {1} {0}
+ \tl_gclear_new:c {g_@@_side_ \tl_use:N \l_@@_tmpb_tl _tl}
+ \tl_gset_eq:cN {g_@@_side_ \tl_use:N \l_@@_tmpb_tl _tl} \l_@@_tmpa_tl
+ }
+ },
+ clone~ tiling~ side~ path/.style~ 2~ args={
+ spath/set~ name=tiling~ side,
+ spath/clone~ global={#1}{#2}
+ },
+ flip~ tile/.code={
+ \tl_set:Nn \l_@@_tmpa_tl {#1}
+ \tl_set:Nn \l_@@_tmpb_tl {true}
+ \bool_set:Nn \l_@@_cw_bool {\tl_if_eq_p:NN \l_@@_tmpa_tl \l_@@_tmpb_tl}
+ },
+ flip~ tile/.default={true},
+ spath/prefix/tiling~side/.style={
+ spath/set~ prefix=g_@@_side_,
+ },
+ spath/suffix/tiling~side/.style={
+ spath/set~ suffix=_tl,
+ },
+ clone~ tile~ path/.style~ 2~ args={
+ spath/set~ name=tiling~tile,
+ spath/clone~ global={#1}{#2}
+ },
+ spath/prefix/tiling~tile/.style={
+ spath/set~ prefix=g_@@_tile_,
+ },
+ spath/suffix/tiling~tile/.style={
+ spath/set~ suffix=_tl,
+ },
+ expand~ key/.code={
+ \exp_args:NV \pgfkeysalso #1
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Lindenmayer System}
+%
+% This is an implementation of the Lindenmayer System description of Penrose and other tilings as a way of generating tilings from a specific starting seed.
+%
+% The implementation uses \Verb+prop+s to store \emph{rules} and \emph{actions}.
+% The rules are used to expand the starting seed to a certain level, after which the actions are carried out.
+% The syntax is based on the PGF library, but as we're already using \LaTeX3 it is reimplemented in that.
+%
+% \begin{macro}[internal]{\@@_make_lms:Nnnn}
+% This creates the token list of actions, starting with the seed.
+% The arguments are: a token list to store the result in, the name of the system, the number of iterations, and the initial state.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_make_lms:Nnnn #1#2#3#4
+{
+ \group_begin:
+% \end{macrocode}
+% On the first time round, we start with the given seed.
+% \begin{macrocode}
+ \tl_set:Nn \l_@@_tmpb_tl {#4}
+% \end{macrocode}
+% We repeat the specified number of times.
+% \begin{macrocode}
+ \prg_replicate:nn {#3} {
+% \end{macrocode}
+% Duplicate the current state.
+% \begin{macrocode}
+ \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_tmpb_tl
+% \end{macrocode}
+% Clear the receiving token list.
+% \begin{macrocode}
+ \tl_clear:N \l_@@_tmpb_tl
+% \end{macrocode}
+% Walk through the current list, appending to the receiving list according to the rules.
+% \begin{macrocode}
+ \tl_map_inline:Nn \l_@@_tmpa_tl
+ {
+% \end{macrocode}
+% If a rule exists, copy that.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_action_lms_tl {\tl_head:n {##1}}
+ \tl_set:Nx \l_@@_parameters_lms_tl {\tl_tail:n {##1}}
+ \prop_if_in:cVTF {g_@@_#2_lms_rule_prop} \l_@@_action_lms_tl
+ {
+ \prop_get:cVN {g_@@_#2_lms_rule_prop} \l_@@_action_lms_tl \l_@@_tmpc_tl
+ \tl_put_right:Nx \l_@@_tmpb_tl {\tl_use:N \l_@@_tmpc_tl}
+% {\prop_item:cn {g_@@_#2_lms_rule_prop} {##1} }
+ }
+ {
+% \end{macrocode}
+% Otherwise, just copy the token.
+% \begin{macrocode}
+ \tl_if_single:nTF {##1}
+ {
+ \tl_put_right:Nn \l_@@_tmpb_tl {##1}
+ }
+ {
+ \tl_put_right:Nn \l_@@_tmpb_tl {{##1}}
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% We've done all this inside a group, now pass the result outside.
+% \begin{macrocode}
+ \tl_set:Nn \l_@@_tmpa_tl {
+ \group_end:
+ \tl_set:Nn #1
+ }
+ \tl_put_right:Nx \l_@@_tmpa_tl {{\tl_use:N \l_@@_tmpb_tl}}
+ \tl_use:N \l_@@_tmpa_tl
+}
+\cs_generate_variant:Nn \@@_make_lms:Nnnn {Nnnx}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\@@_invoke_lms:nn}
+% This carries out the actions specified by the resulting rules.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_invoke_lms:nn #1#2
+{
+ \group_begin:
+% \end{macrocode}
+% Walk through the given list, carrying out the corresponding action if it exists.
+% If not, look at the default.
+% Otherwise, just do nothing.
+% \begin{macrocode}
+ \tl_map_inline:nn {#1} {
+ \tl_set:Nx \l_@@_action_lms_tl {\tl_head:n {##1}}
+ \tl_set:Nx \l_@@_parameters_lms_tl {\tl_tail:n {##1}}
+ \prop_if_in:cVTF {g_@@_#2_lms_action_prop} \l_@@_action_lms_tl
+ {
+ \prop_item:cV {g_@@_#2_lms_action_prop} \l_@@_action_lms_tl
+ }
+ {
+ \prop_if_in:cVT {g_@@_default_lms_action_prop} \l_@@_action_lms_tl
+ {
+ \prop_item:cV {g_@@_default_lms_action_prop} \l_@@_action_lms_tl
+ }
+ }
+ }
+ \group_end:
+}
+\cs_generate_variant:Nn \@@_invoke_lms:nn {Vn}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% We need some parameters.
+% \begin{macrocode}
+\dim_new:N \l_@@_step_dim
+\dim_set:Nn \l_@@_step_dim {1cm}
+% \end{macrocode}
+%
+% These are the defaults, which will be used in all the rule sets.
+% \begin{macrocode}
+\prop_new:N \g_@@_default_lms_action_prop
+\prop_gput:Nnn \g_@@_default_lms_action_prop {[} {\group_begin:}
+\prop_gput:Nnn \g_@@_default_lms_action_prop {]} {\group_end:}
+\prop_gput:Nnn \g_@@_default_lms_action_prop {f}
+{\pgftransformxshift{\l_@@_step_dim}}
+\prop_gput:Nnn \g_@@_default_lms_action_prop {b}
+{\pgftransformxshift{-\l_@@_step_dim}}
+% \end{macrocode}
+%
+% Holds a list of the tiles that actually draw for each tile set
+% \begin{macrocode}
+\prop_new:N \g_@@_drawables_lms_prop
+% \end{macrocode}
+%
+% We keep track of the number of tiles.
+% \begin{macrocode}
+\int_new:N \g_@@_tile_int
+\int_new:N \g_@@_tiles_int
+% \end{macrocode}
+%
+% \begin{function}{\TilingDecomposition}
+% This is the user macro to invoke the decomposition.
+% The arguments are: optional styles, the name, number of iterations, and starting seed.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_tiling_decomposition:nnnn #1#2#3#4
+{
+ \group_begin:
+ \tikzset{
+ every~ #2~ decomposition/.try,
+ #1
+ }
+ \@@_make_lms:Nnnx \l_@@_tmpa_tl {#2} {#3} {#4}
+ \@@_count_lms:Vn \l_@@_tmpa_tl {#2}
+ \int_gzero:N \g_@@_tile_int
+ \@@_invoke_lms:Vn \l_@@_tmpa_tl {#2}
+ \group_end:
+}
+\cs_new_protected_nopar:Npn \@@_tiling_decomposition:nnn #1#2#3
+{
+ \@@_tiling_decomposition:nnnn {}{#1}{#2}{#3}
+}
+\cs_generate_variant:Nn \@@_tiling_decomposition:nnn {VVV}
+
+\NewDocumentCommand \TilingDecomposition { O{} m m m }
+{
+ \@@_tiling_decomposition:nnnn {#1}{#2}{#3}{#4}
+}
+
+\tikzset{
+ pics/decomposition/.style~ n~ args={3}{
+ code={
+ \@@_tiling_decomposition:nnn {#1}{#2}{#3}
+ }
+ }
+}
+% \end{macrocode}
+% \end{function}
+%
+% \begin{macro}[internal]{\@@_count_lms:nn}
+% This counts the number of tiles in the string.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_count_lms:nn #1#2
+{
+ \group_begin:
+ \int_gzero:N \g_@@_tiles_int
+ \prop_get:NnNT \g_@@_drawables_lms_prop {#2} \l_@@_tmpa_tl
+ {
+ \tl_map_variable:nNn {#1} \l_@@_tmpb_tl
+ {
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpb_tl}
+ \bool_do_while:nn
+ {
+ !\tl_if_empty_p:N \l_@@_tmpb_tl
+ &&
+ \tl_if_head_is_group_p:V \l_@@_tmpb_tl
+ }
+ {
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpb_tl}
+ }
+ \tl_if_in:NVT \l_@@_tmpa_tl \l_@@_tmpb_tl
+ {
+ \int_gincr:N \g_@@_tiles_int
+ }
+ }
+ }
+ \group_end:
+}
+\cs_generate_variant:Nn \@@_count_lms:nn {Vn}
+% \end{macrocode}
+% \end{macro}
+%
+% This is a \Verb+\tikzset+ mechanism for setting the dimensions of the tiling.
+% \begin{macrocode}
+\tikzset{
+ tiling~ step/.code={
+ \dim_set:Nn \l_@@_step_dim {#1}
+ }
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \iffalse
+%</tilings>
+% \fi
+%
+%
+% \iffalse
+%<*penrose>
+% \fi
+%
+% \begin{macrocode}
+\RequirePackage{tikz}
+\usetikzlibrary{tilings}
+\ProvidesFile {tikzlibrarytilings.penrose.code.tex}
+[2023/06/01 v2.0 TikZ pics for Penrose tiles]
+% \end{macrocode}
+%
+%
+% Create the pre-defined tile shapes.
+%
+% \begin{itemize}
+% \item Thin Rhombus.
+% \begin{macrocode}
+\DefineTile{thin rhombus}{a A B b}
+{
+ {0 , 0}
+ {cosd(18) , sind(18)}
+ {2*cosd(18) , 0}
+ {cosd(18) , -sind(18)}
+}
+% \end{macrocode}
+%
+% \item Thick Rhombus.
+% \begin{macrocode}
+\DefineTile{thick rhombus}{B a A b}
+{
+ {0 , 0}
+ {cosd(36) , sind(36)}
+ {2*cosd(36) , 0}
+ {cosd(36) , -sind(36)}
+}
+% \end{macrocode}
+%
+% \item Dart.
+% \begin{macrocode}
+\DefineTile{dart}{c a A C}
+{
+ {0 , 0}
+ {2*sind(18)*cosd(108) , 2*sind(18)*sind(108)}
+ {2*sind(18) , 0}
+ {2*sind(18)*cosd(108) , -2*sind(18)*sind(108)}
+}
+% \end{macrocode}
+%
+% \item Kite.
+% \begin{macrocode}
+\DefineTile{kite}{a c C A}
+{
+ {0 , 0}
+ {cosd(36) , sind(36)}
+ {1 , 0}
+ {cosd(36) , -sind(36)}
+}
+% \end{macrocode}
+%
+% \item Golden Triangle.
+% \begin{macrocode}
+\DefineTile{golden triangle}{a c b}
+{
+ {0 , 0}
+ {cosd(18) , sind(18)}
+ {cosd(18) , -sind(18)}
+}
+% \end{macrocode}
+%
+% \item Reverse Golden Triangle.
+% \begin{macrocode}
+\DefineTile {reverse golden triangle}{B C A}
+{
+ {0 , 0}
+ {cosd(18) , sind(18)}
+ {cosd(18) , -sind(18)}
+}
+% \end{macrocode}
+%
+% \item Golden Gnomon
+% \begin{macrocode}
+\DefineTile {golden gnomon}{C b A}
+{
+ {0 , 0}
+ {cosd(36) , sind(36)}
+ {2*cosd(36) , 0}
+}
+% \end{macrocode}
+%
+% \item Reverse Golden Gnomon
+% \begin{macrocode}
+\DefineTile {reverse golden gnomon}{a B c}
+{
+ {0 , 0}
+ {2*cosd(36) , 0}
+ {cosd(36) , -sind(36)}
+}
+% \end{macrocode}
+%
+% \item Primary Pentagon (pentagon 5)
+% \begin{macrocode}
+\DefineTile {pentagon 5}{a a a a a}
+{
+ {0 , 0}
+ {cosd(108) , sind(108)}
+ {1+cosd(72)+cosd(144) , sind(72)+sind(144)}
+ {1+cosd(72) , sind(72)}
+ {1 , 0}
+}
+% \end{macrocode}
+%
+% \item Secondary Pentagon (pentagon 3)
+% \begin{macrocode}
+\DefineTile {pentagon 3}{A b a a b}
+{
+ {0 , 0}
+ {cosd(108) , sind(108)}
+ {1+cosd(72)+cosd(144) , sind(72)+sind(144)}
+ {1+cosd(72) , sind(72)}
+ {1 , 0}
+}
+% \end{macrocode}
+%
+% \item Tertiary Pentagon (pentagon 2)
+% \begin{macrocode}
+\DefineTile {pentagon 2}{d A e c A}
+{
+ {0 , 0}
+ {cosd(108) , sind(108)}
+ {1+cosd(72)+cosd(144) , sind(72)+sind(144)}
+ {1+cosd(72) , sind(72)}
+ {1 , 0}
+}
+% \end{macrocode}
+%
+% \item Pentagram
+% \begin{macrocode}
+\DefineTile {pentagram}{C E C E C E C E C E}
+{
+ {1 , 0}
+ {1-cosd(36) , -sind(36)}
+ {1-cosd(36)-cosd(108) , -sind(36)-sind(108)}
+ {cosd(108) , -sind(108)}
+ {-1+3*cosd(108)+cosd(36) , -sind(36)-sind(108)}
+ {-1+2*cosd(108)+cosd(36) , -sind(36)}
+ {-1+2*cosd(108) , 0}
+ {2*cosd(108) , 0}
+ {cosd(108) , sind(108)}
+ {0 , 0}
+}
+% \end{macrocode}
+%
+% \item Boat
+% \begin{macrocode}
+\DefineTile {boat}{C E C E B D B}
+{
+ {-1+2*cosd(108) , 0}
+ {2*cosd(108) , 0}
+ {cosd(108) , sind(108)}
+ {0 , 0}
+ {1 , 0}
+ {1-cosd(36) , -sind(36)}
+ {-1+2*cosd(108)+cosd(36) , -sind(36)}
+}
+% \end{macrocode}
+%
+% \item Diamond.
+% \begin{macrocode}
+\DefineTile {diamond}{D B B D}
+{
+ {0 , 0}
+ {cosd(18) , sind(18)}
+ {2*cosd(18) , 0}
+ {cosd(18) , -sind(18)}
+}
+% \end{macrocode}
+% \end{itemize}
+%
+%
+% Place the arcs
+% \begin{macrocode}
+\tikzset{
+ every thin rhombus before path/.code={
+ \path[every circle arc/.try] (-edge a end) circle[radius=1/4];
+ \path[every long arc/.try] (-edge b start) circle[radius=1/4];
+ },
+ every thick rhombus before path/.code={
+ \path[every circle arc/.try] (-edge a end) circle[radius=1/4];
+ \path[every long arc/.try] (-edge B start) circle[radius=3/4];
+ },
+ every kite before path/.code={
+ \path[every circle arc/.try] (-edge a start) circle[radius=2/(sqrt(5)+1)];
+ \path[every long arc/.try] (-edge c end) circle[radius=2/(3+sqrt(5))];
+ },
+ every dart before path/.code={
+ \path[every circle arc/.try] (-edge a end) circle[radius=1 - 2/(sqrt(5)+1)];
+ \path[every long arc/.try] (-edge c start) circle[radius=2/(sqrt(5)+1) - 2/(3+sqrt(5))];
+ }
+}
+% \end{macrocode}
+%
+% Now bake the tiles.
+%
+% \begin{macrocode}
+\BakeTile {thin rhombus}
+\BakeTile {thick rhombus}
+\BakeTile {dart}
+\BakeTile {kite}
+\BakeTile {golden triangle}
+\BakeTile {reverse golden triangle}
+\BakeTile {golden gnomon}
+\BakeTile {reverse golden gnomon}
+\BakeTile {pentagon 5}
+\BakeTile {pentagon 3}
+\BakeTile {pentagon 2}
+\BakeTile {pentagram}
+\BakeTile {boat}
+\BakeTile {diamond}
+% \end{macrocode}
+%
+%
+% \subsection{Lindenmayer System}
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% These are the rules for generating rhombus tilings with the Lindenmayer System procedure.
+%
+% \begin{macrocode}
+\prop_new:N \g_@@_rhombus_lms_rule_prop
+\prop_gput:Nnn \g_@@_rhombus_lms_rule_prop {T} {[f*sT][f>g]}
+\prop_gput:Nnn \g_@@_rhombus_lms_rule_prop {t} {[f_st][f>G]}
+\prop_gput:Nnn \g_@@_rhombus_lms_rule_prop {G} {[f+sG][sf>g][sf*sT]}
+\prop_gput:Nnn \g_@@_rhombus_lms_rule_prop {g} {[f-sg][sf>G][sf_st]}
+% \end{macrocode}
+%
+% These are the rules for generating kite and dart tilings.
+% \begin{macrocode}
+\prop_new:N \g_@@_kite_lms_rule_prop
+\prop_gput:Nnn \g_@@_kite_lms_rule_prop {T} {[f*sT][f>st][+sg]}
+\prop_gput:Nnn \g_@@_kite_lms_rule_prop {t} {[f_st][f>sT][-sG]}
+\prop_gput:Nnn \g_@@_kite_lms_rule_prop {G} {[f*+sG][sT]}
+\prop_gput:Nnn \g_@@_kite_lms_rule_prop {g} {[f-_sg][st]}
+% \end{macrocode}
+%
+% These are the rules for generating pentagon tilings.
+% \begin{macrocode}
+\prop_new:N \g_@@_pentagon_lms_rule_prop
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {P}
+{[s>P][1sF+Q][1+sF+Q][1*sF+Q][1-sF+Q][1_sF+Q]} % pentagon 5
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {Q}
+{[s>P][1+sFR][1*sF*R][1-sF+Q][1_sF+Q][1sF+Q][->fsD]} % pentagon 3
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {R}
+{[s>P][1-sF+Q][1+sF*R][1*sFR][1_sF*R][1sFR][_>fsD][>fsD]} % pentagon 2
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {G}
+{
+ [s>G]
+ [se[>d+R][e1B]]
+ [+se[>d+R][e1B]]
+ [-se[>d+R][e1B]]
+ [*se[>d+R][e1B]]
+ [_se[>d+R][e1B]]
+} % pentagram
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {B}
+{
+ [s>G]
+ [se[>d+R][e1B]]
+ [+se[>d+R][e1B]]
+ [-se[>d+R][e1B]]
+} % boat
+\prop_gput:Nnn \g_@@_pentagon_lms_rule_prop {D}
+{[s>d+R][s>eG][se1B]} % diamond
+% \end{macrocode}
+%
+% Each of the standard tilings can also be drawn using triangles using the same rules.
+% \begin{macrocode}
+\prop_gset_eq:NN \g_@@_rtriangle_lms_rule_prop
+\g_@@_rhombus_lms_rule_prop
+\prop_gset_eq:NN \g_@@_ktriangle_lms_rule_prop
+\g_@@_kite_lms_rule_prop
+% \end{macrocode}
+%
+% These are the lists of tokens that actually draw things
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {rhombus} {TG}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {kite} {Tg}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {rtriangle} {TtGg}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {ktriangle} {TtGg}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {pentagon} {PQRGBD}
+% \end{macrocode}
+%
+%
+% These hold the various actions.
+% \begin{macrocode}
+\prop_new:N \g_@@_rhombus_lms_action_prop
+\prop_new:N \g_@@_kite_lms_action_prop
+\prop_new:N \g_@@_rtriangle_lms_action_prop
+\prop_new:N \g_@@_ktriangle_lms_action_prop
+\prop_new:N \g_@@_pentagon_lms_action_prop
+% \end{macrocode}
+%
+% The rhombus rules need a variety of turns.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {+}
+{\pgftransformrotate{144}}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {*}
+{\pgftransformrotate{108}}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {-}
+{\pgftransformrotate{216}}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {_}
+{\pgftransformrotate{252}}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {>}
+{\pgftransformrotate{180}}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {s} {
+ \fp_set:Nn \l_@@_tmpa_fp { 2 * sind(18) * \l_@@_step_dim }
+ \dim_set:Nn \l_@@_step_dim {\fp_to_dim:N \l_@@_tmpa_fp}
+}
+% \end{macrocode}
+%
+% Up to now, the actions for the rhombus and its triangle replacement are the same.
+% \begin{macrocode}
+\prop_gset_eq:NN \g_@@_rtriangle_lms_action_prop
+\g_@@_rhombus_lms_action_prop
+% \end{macrocode}
+%
+% Now we do the actions that actually draw something.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {T} {
+ \group_begin:
+% \end{macrocode}
+% As we go through, we keep track of how many tiles we've drawn.
+% \begin{macrocode}
+ \int_gincr:N \g_@@_tile_int
+% \end{macrocode}
+% Set up the position, size, and angle correctly.
+% \begin{macrocode}
+ \pgftransformrotate{198}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*2*cosd(18)}
+ \pgftransformxshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+% \end{macrocode}
+% Now we draw the thin rhombus, applying every style we can possibly imagine.
+% The \Verb+tile+ style gets the current tile and total tile numbers passed to it.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ thin~ rhombus/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{thin~rhombus}
+ \group_end:
+}
+% \end{macrocode}
+%
+% Same for the thick rhombus.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rhombus_lms_action_prop {G} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)/(2*cosd(36))}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ thick~ rhombus/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{thick~rhombus}
+ \group_end:
+}
+% \end{macrocode}
+%
+% Now we do the same for the kite and dart tiling.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {+} {\pgftransformrotate{36}}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {*} {\pgftransformrotate{108}}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {-} {\pgftransformrotate{-36}}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {_}
+{\pgftransformrotate{-108}}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {>} {\pgftransformrotate{180}}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {s} {
+ \fp_set:Nn \l_@@_tmpa_fp { 2 * sind(18) * \l_@@_step_dim }
+ \dim_set:Nn \l_@@_step_dim {\fp_to_dim:N \l_@@_tmpa_fp}
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gset_eq:NN \g_@@_ktriangle_lms_action_prop
+\g_@@_kite_lms_action_prop
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {T} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{36}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ kite/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{kite}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_kite_lms_action_prop {g} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{144}
+ \pgftransformxshift{-\l_@@_step_dim * 2 * sin(18)}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ dart/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{dart}
+ \group_end:
+}
+% \end{macrocode}
+%
+% Now we set up the actions for the triangle variations.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rtriangle_lms_action_prop {T} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{18}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ reverse~ golden~ triangle/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{reverse~ golden~ triangle}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rtriangle_lms_action_prop {t} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{-18}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ golden~ triangle/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{golden~ triangle}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rtriangle_lms_action_prop {G} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{180}
+ \pgftransformxshift{-\l_@@_step_dim}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)/(2*cosd(36))}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ reverse~ golden~ gnomon/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{reverse~ golden~ gnomon}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_rtriangle_lms_action_prop {g} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{180}
+ \pgftransformxshift{-\l_@@_step_dim}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)/(2*cosd(36))}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ golden~ gnomon/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{golden~ gnomon}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_ktriangle_lms_action_prop {T} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{18}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ reverse~ golden~ triangle/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{reverse~ golden~ triangle}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_ktriangle_lms_action_prop {t} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{-18}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ golden~ triangle/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{golden~ triangle}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_ktriangle_lms_action_prop {G} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{180}
+ \pgftransformxshift{-\l_@@_step_dim}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)/(2*cosd(36))}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ reverse~ golden~ gnomon/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{reverse~ golden~ gnomon}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_ktriangle_lms_action_prop {g} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{180}
+ \pgftransformxshift{-\l_@@_step_dim}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)/(2*cosd(36))}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ golden~ gnomon/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{golden~ gnomon}
+ \group_end:
+}
+% \end{macrocode}
+%
+% Now we do the same for the pentagonal tilings.
+%
+% The rules need a variety of turns.
+% \begin{macrocode}
+\int_new:N \l_@@_pentagon_parity_int
+\seq_new:N \l_@@_pentagon_parity_seq
+\seq_set_from_clist:Nn \l_@@_pentagon_parity_seq {odd,even}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {1} {
+ \int_set:Nn \l_@@_pentagon_parity_int
+ {3 - \l_@@_pentagon_parity_int}
+}
+\tikzset{
+ every~ pentagon~ decomposition/.code={%
+ \int_set:Nn \l_@@_pentagon_parity_int {2}
+ }
+}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {+}
+{\pgftransformrotate{72}}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {*}
+{\pgftransformrotate{144}}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {-}
+{\pgftransformrotate{288}}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {_}
+{\pgftransformrotate{216}}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {>}
+{\pgftransformrotate{180}}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {|}
+{\pgftransformxscale{-1}}
+% \end{macrocode}
+% The scale factor is different.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {s} {
+ \fp_set:Nn \l_@@_tmpa_fp
+ {
+ 1/(2 + 2 * cosd(72) ) * \l_@@_step_dim
+ }
+ \dim_set:Nn \l_@@_step_dim {\fp_to_dim:N \l_@@_tmpa_fp}
+}
+% \end{macrocode}
+% And we tend to work better vertically.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {f} {
+ \fp_set:Nn \l_@@_tmpa_fp { tand(54)/2 * \l_@@_step_dim }
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {F} {
+ \fp_set:Nn \l_@@_tmpa_fp { tand(54) * \l_@@_step_dim }
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {d} {
+ \fp_set:Nn \l_@@_tmpa_fp
+ {
+ (tand(54)/2 - tand(72)/2 + sind(36) ) * \l_@@_step_dim
+ }
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {e} {
+ \fp_set:Nn \l_@@_tmpa_fp
+ {
+ tand(54) * cosd(36) * \l_@@_step_dim
+ }
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {P} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/2}
+ \pgftransformxshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*tand(54)/2}
+ \pgftransformyshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ pentagon/.try,
+ every~
+ \seq_item:Nn \l_@@_pentagon_parity_seq
+ {\l_@@_pentagon_parity_int}
+ \space pentagon/.try,
+ every~ pentagon~ 5/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{pentagon~5}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {Q} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/2}
+ \pgftransformxshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*tand(54)/2}
+ \pgftransformyshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ pentagon/.try,
+ every~
+ \seq_item:Nn \l_@@_pentagon_parity_seq
+ {\l_@@_pentagon_parity_int}
+ \space pentagon/.try,
+ every~ pentagon~ 3/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{pentagon~3}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {R} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/2}
+ \pgftransformxshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*tand(54)/2}
+ \pgftransformyshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ pentagon/.try,
+ every~
+ \seq_item:Nn \l_@@_pentagon_parity_seq
+ {\l_@@_pentagon_parity_int}
+ \space pentagon/.try,
+ every~ pentagon~ 2/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{pentagon~2}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {G} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+% \pgftransformrotate{198}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*cosd(72)}
+ \pgftransformxshift{\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*tand(54)*cosd(72)}
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ pentagram/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{pentagram}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {B} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+% \pgftransformrotate{198}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*cosd(72)}
+ \pgftransformxshift{\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*tand(54)*cosd(72)}
+ \pgftransformyshift{\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ boat/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{boat}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_pentagon_lms_action_prop {D} {
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \pgftransformrotate{90}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim*cosd(18)}
+ \pgftransformxshift{-\fp_to_dim:N \l_@@_tmpa_fp}
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ diamond/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{diamond}
+ \group_end:
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \iffalse
+%</penrose>
+% \fi
+%
+% \iffalse
+%<*polykite>
+% \fi
+%
+% \begin{macrocode}
+\RequirePackage{tikz}
+\usetikzlibrary{tilings}
+\ProvidesFile {tikzlibrarytilings.polykite.code.tex}
+ [2023/06/01 v2.0 TikZ pics for Aperiodical Polykite tiles]
+% \end{macrocode}
+%
+% \begin{function}{\DefinePolykiteTile}
+% Define one of the family of polykite tiles.
+% Needs a name and length parameters.
+% A star option switches the side labels to enable the hat-turtle pairing of a tile with its ``opposite''.
+% \begin{macrocode}
+\DeclareDocumentCommand \DefinePolykiteTile {s m m m}
+{
+ \IfBooleanTF {#1}
+ {
+ \DefineTile {#2} {2 2 1 1 2 2 1 1 1 1 2 2 1 1}
+ }
+ {
+ \DefineTile {#2} {1 1 2 2 1 1 2 2 2 2 1 1 2 2}
+ }
+ {
+ {0 : #4}
+ ++{90 : #3}
+ ++{150 : #3}
+ ++{240 : #4}
+ ++{180 : #4}
+ ++{-90 : #3}
+ ++{210 : #3}
+ ++{-60 : #4}
+ ++{0 : #4}
+ ++{0 : #4}
+ ++{60 : #4}
+ ++{-30 : #3}
+ ++{30 : #3}
+ ++{120 : #4}
+ }
+}
+% \end{macrocode}
+% \end{function}
+%
+% Some predefined tiles.
+% The aperiodical hat and turtle can be swapped in for each other as they use the same edge definitions.
+% The spectral hat and turtle are designed to be used in the same diagram.
+% Technically, the spectral and aperiodical hats are the same, but I figured it better to have two names for the two uses.
+% The spectre uses the alternating edge scheme.
+%
+% \begin{itemize}
+% \item Aperiodical and Spectral Hat.
+% \begin{macrocode}
+\DefinePolykiteTile{aperiodical hat}{sqrt(3)/2}{1/2}
+\DefinePolykiteTile{spectral hat}{sqrt(3)/2}{1/2}
+% \end{macrocode}
+% \item Aperiodical and Spectral Turtles.
+% \begin{macrocode}
+\DefinePolykiteTile{aperiodical turtle}{1/2}{sqrt(3)/2}
+\DefinePolykiteTile*{spectral turtle}{1/2}{sqrt(3)/2}
+% \end{macrocode}
+% \item Aperiodical Spectre.
+% \begin{macrocode}
+\DefineTile {spectre} {a A a A a A a A a A a A a A}
+ {
+ {0 : .75}
+ ++{90 : .75}
+ ++{150 : .75}
+ ++{240 : .75}
+ ++{180 : .75}
+ ++{-90 : .75}
+ ++{210 : .75}
+ ++{-60 : .75}
+ ++{0 : .75}
+ ++{0 : .75}
+ ++{60 : .75}
+ ++{-30 : .75}
+ ++{30 : .75}
+ ++{120 : .75}
+ }
+% \end{macrocode}
+%
+% \item Meta Clusters
+%
+% The mapping between the notation in the \href{preprint}{https://arxiv.org/abs/2303.10798} is:
+%
+% \begin{align*}
+% A^+, A^- &\mapsto a, A \\
+% B^+, B^- &\mapsto b, B\\
+% F^+, F^- &\mapsto c, C\\
+% X^+, X^- &\mapsto d, D\\
+% L &\mapsto 1
+% \end{align*}
+%
+% \begin{macrocode}
+\DefineTile{meta cluster T}{A A b}
+{
+{ -1.5 , -sqrt(3)/2 }
+{ 1.5 , -sqrt(3)/2 }
+{ 0 , sqrt(3) }
+}
+\DefineTile{meta cluster P}{1 D d A 1 D d b}
+{
+{ -2.5, sqrt(3)/2 }
+{ -2, 0 }
+{ -1.5, -sqrt(3)/2 }
+{ -0.5 , -sqrt(3)/2 }
+{ 2.5 , -sqrt(3)/2 }
+{ 2 , 0 }
+{ 1.5 , sqrt(3)/2 }
+{ .5 , sqrt(3)/2 }
+}
+\DefineTile{meta cluster F}{1 D d 1 D c C d b}
+{
+{ -2.5, sqrt(3)/2 }
+{ -2, 0 }
+{ -1.5, -sqrt(3)/2 }
+{ -0.5 , -sqrt(3)/2 }
+{ .5 , -sqrt(3)/2 }
+{ 1.5 , -sqrt(3)/2 }
+{ 2 , 0 }
+{ 1.5 , sqrt(3)/2 }
+{ .5 , sqrt(3)/2 }
+}
+\DefineTile{meta cluster H}{B D d B D d a D d}
+{
+{ -2, -sqrt(3) }
+{ 1, -sqrt(3) }
+{ 2, -sqrt(3) }
+{ 2.5, -sqrt(3)/2 }
+{ 1, sqrt(3)}
+{ .5 , 3*sqrt(3)/2 }
+{ -.5 , 3*sqrt(3)/2 }
+{ -2, 0 }
+{ -2.5, -sqrt(3)/2 }
+}
+% \end{macrocode}
+% \item Super Clusters
+%
+% \begin{macrocode}
+\DefineTile{super cluster T}{A A b}
+{
+{ -30 : 3 * (1 + sqrt(5))/2 / sqrt(3) }
+{ 90 : 3 * (1 + sqrt(5))/2 / sqrt(3) }
+{ 210 : 3 * (1 + sqrt(5))/2 / sqrt(3) }
+}
+% 1 + 3phi, 1 + 2phi
+\DefineTile{super cluster P}{1 D d A 1 D d b}
+{
+{ - 1.75 - sqrt(5), (sqrt(5)/2 + 1) * sqrt(3)/2 }
+++{ -60 : 1 + sqrt(5) }
+++{ -60 : 1}
+++{ 1, 0}
+++{ 3*(1 + sqrt(5))/2, 0 }
+++{ 120 : 1 + sqrt(5) }
+++{ 120 : 1 }
+++{ -1, 0 }
+}
+\DefineTile{super cluster F}{1 D d 1 D c C d b}
+{
+{ - 1.75 - sqrt(5), (sqrt(5)/2 + 1) * sqrt(3)/2 }
+++{ -60 : 1 + sqrt(5) }
+++{ -60 : 1}
+++{ 1, 0}
+++{ 1 + sqrt(5), 0 }
+++{ 1, 0 }
++{ -.75 + (2 + sqrt(5)) * sqrt(3)/4 * sqrt(3)/3,
+ (2 + sqrt(5)) * sqrt(3)/4 + 3/4 * sqrt(3)/3 }
+++{ -1.5, (2 + sqrt(5)) * sqrt(3)/2 }
+++{ -1, 0 }
+}
+\DefineTile{super cluster H}{B D d B D d a D d}
+{
+{1.75 + 3*sqrt(5)/4, -(1 + sqrt(5))*sqrt(3)/4}
+++{120 : 3*(1+sqrt(5))/2 }
+++{120 : 1 }
+++{-1,0}
+++{240 : 3*(1+sqrt(5))/2}
+++{240 : 1}
+++{300 : 1}
+++{ 3*(1+sqrt(5))/2, 0 }
+++{1, 0}
+++{60 : 1}
+}
+% \end{macrocode}
+% \item Subclusters
+%
+% \begin{macrocode}
+\DefineTile{subcluster H}{B B a}
+{
+ { 0, 0 }
+ { 3, 0 }
+ { 60 : 3 }
+}
+\DefineTile{subcluster T}{A A b}
+{
+ { 0, 0 }
+ { 3, 0 }
+ { 60 : 3 }
+}
+\DefineTile{subcluster P}{ 1 A 1 b }
+{
+ { 0, 0 }
+ { 1, 0 }
+ { 4, 0 }
+ { 3, 0 }
+}
+\DefineTile{subcluster F}{ 1 1 f F b }
+{
+ { 0, 0 }
+ { 1, 0 }
+ +{ 60 : 1 }
+ { 2, 0 }
+ { 3, 0 }
+}
+% \end{macrocode}
+% \end{itemize}
+%
+% The P and F subclusters have no area, so clipping against them is not helpful.
+% \begin{macrocode}
+\tikzset{
+ no clip/.code={%
+ \tikz@addmode{\tikz@mode@clipfalse}%
+ },
+ every subcluster P clip/.style={no clip},
+ every subcluster F clip/.style={no clip},
+}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\BakeTile {aperiodical hat}
+\BakeTile {aperiodical turtle}
+\BakeTile {spectral hat}
+\BakeTile {spectral turtle}
+\BakeTile {spectre}
+\BakeTile {meta cluster T}
+\BakeTile {meta cluster P}
+\BakeTile {meta cluster F}
+\BakeTile {meta cluster H}
+\BakeTile {super cluster T}
+\BakeTile {super cluster P}
+\BakeTile {super cluster F}
+\BakeTile {super cluster H}
+% \end{macrocode}
+%
+% The subclusters are deformed by default.
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\clist_map_inline:nn {a,A,b,B,f,F}
+{
+ \tl_new:c {g_@@_side_polykite_#1_tl}
+ \tl_if_exist:cF {g_@@_side_#1_tl}
+ {
+ \tl_new:c {g_@@_side_#1_tl}
+ }
+}
+
+\tl_gset:cn {g_@@_side_polykite_A_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{-0.3333332942822268pt}
+ \pgfsyssoftpath@linetotoken {0.0833331478405773pt}{-0.1889954840909892pt}
+ \pgfsyssoftpath@linetotoken {0.3333332942822268pt}{-0.3333332942822268pt}
+ \pgfsyssoftpath@linetotoken {0.5833333235705567pt}{-0.1889954840909892pt}
+ \pgfsyssoftpath@linetotoken {0.6666667057177732pt}{-0.3333332942822268pt}
+ \pgfsyssoftpath@linetotoken {1pt}{-0.3333332942822268pt}
+}
+\tl_gset:cn {g_@@_side_polykite_a_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{0.33333pt}
+ \pgfsyssoftpath@linetotoken {0.33333pt}{0.33333pt}
+ \pgfsyssoftpath@linetotoken {0.41667pt}{0.189pt}
+ \pgfsyssoftpath@linetotoken {0.66667pt}{0.33333pt}
+ \pgfsyssoftpath@linetotoken {0.91667pt}{0.189pt}
+ \pgfsyssoftpath@linetotoken {1pt}{0.33333pt}
+}
+\tl_gset:cn {g_@@_side_polykite_B_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{0pt}
+ \pgfsyssoftpath@linetotoken {0.3333332942822268pt}{0pt}
+ \pgfsyssoftpath@linetotoken {0.4166665592761237pt}{0.1443378101912376pt}
+ \pgfsyssoftpath@linetotoken {0.6666667057177732pt}{0pt}
+ \pgfsyssoftpath@linetotoken {0.9166666178527835pt}{0.1443378101912376pt}
+ \pgfsyssoftpath@linetotoken {1pt}{0pt}
+}
+\tl_gset:cn {g_@@_side_polykite_b_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{0pt}
+ \pgfsyssoftpath@linetotoken {0.08333pt}{-0.14433pt}
+ \pgfsyssoftpath@linetotoken {0.33333pt}{0pt}
+ \pgfsyssoftpath@linetotoken {0.58333pt}{-0.14433pt}
+ \pgfsyssoftpath@linetotoken {0.66667pt}{0pt}
+ \pgfsyssoftpath@linetotoken {1pt}{0pt}
+}
+\tl_gset:cn {g_@@_side_polykite_F_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{-2.00000070292pt}
+ \pgfsyssoftpath@linetotoken {0.74999982427pt}{-1.566987221617321pt}
+ \pgfsyssoftpath@linetotoken {1pt}{-2.00000070292pt}
+}
+\tl_gset:cn {g_@@_side_polykite_f_tl}
+{
+ \pgfsyssoftpath@movetotoken {0pt}{2pt}
+ \pgfsyssoftpath@linetotoken {0.25pt}{1.56699pt}
+ \pgfsyssoftpath@linetotoken {1pt}{2pt}
+}
+
+\clist_map_inline:nn {a,A,b,B,f,F}
+{
+ \tl_gclear_new:c {g_@@_side_backup_#1_tl}
+ \tl_gset_eq:cc {g_@@_side_backup_#1_tl} {g_@@_side_#1_tl}
+ \tl_gclear_new:c {g_@@_side_#1_tl}
+ \tl_gset_eq:cc {g_@@_side_#1_tl}{g_@@_side_polykite_#1_tl}
+}
+
+\BakeTile{subcluster~ H}
+\BakeTile{subcluster~ T}
+\BakeTile{subcluster~ P}
+\BakeTile{subcluster~ F}
+
+\clist_map_inline:nn {a,A,b,B,f,F}
+{
+ \tl_gset_eq:cc {g_@@_side_#1_tl} {g_@@_side_backup_#1_tl}
+}
+% \end{macrocode}
+%
+% \subsection{Lindenmayer System}
+%
+% These are the rules for generating the super cluster tilings with the Lindenmayer System procedure.
+%
+% \begin{macro}[internal]{\@@_place_cluster_tile:nn}
+% Useful auxiliary for placing a cluster tile from a particular set
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_place_cluster_tile:nn #1#2
+{
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \pgftransformscale{\fp_use:N \l_@@_tmpa_fp}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \UseTile[
+ every~ tile/.try,
+ every~ #1~#2/.try,
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try/.expand~ once=\l_@@_tmpc_tl
+ ]{#1~ #2}
+ \group_end:
+}
+\cs_generate_variant:Nn \@@_place_cluster_tile:nn {Vn}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+\prop_new:N \g_@@_supercluster_lms_rule_prop
+\prop_gput:Nnn \g_@@_supercluster_lms_rule_prop {T}
+{
+ [s H]
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_rule_prop {H}
+{
+ [s {r{-60}} T]
+ [s {x{\fp_to_decimal:n{1}}} {y{\fp_to_decimal:n{(1+2*\c_@@_phi_fp)}}} H]
+ [s
+ {x{\fp_to_decimal:n{-2-3*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-\c_@@_phi_fp}}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{1+3*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-1-\c_@@_phi_fp}}}
+ {r{-120}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{-1.5-3.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{2.5*\c_@@_phi_fp+1.5}}}
+ {r{-120}}
+ P]
+ [s
+ {x{\fp_to_decimal:n{-1.5-2*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-1.5-3*\c_@@_phi_fp}}}
+ {r{180}}
+ P]
+ [s
+ {x{\fp_to_decimal:n{3+5.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5*\c_@@_phi_fp}}}
+ {r{120}}
+ P]
+ [s
+ {x{\fp_to_decimal:n{-4.5-6.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5-.5*\c_@@_phi_fp}}}
+ {r{-120}}
+ F]
+ [s
+ {x{\fp_to_decimal:n{1.5+4*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-2.5-3*\c_@@_phi_fp}}}
+ F]
+ [s
+ {x{\fp_to_decimal:n{3+2.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{2+3.5*\c_@@_phi_fp}}}
+ {r{120}}
+ F]
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_rule_prop {P}
+{
+ [s {r{60}} P]
+ [s
+ {x{\fp_to_decimal:n{2.5+3.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-.5-.5*\c_@@_phi_fp}}}
+ {r{-120}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{-2.5-3.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5+.5*\c_@@_phi_fp}}}
+ {r{180}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{4.5+6*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5+\c_@@_phi_fp}}}
+ {r{120}}
+ F]
+ [s
+ {x{\fp_to_decimal:n{-4.5-6*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-.5-\c_@@_phi_fp}}}
+ {r{-60}}
+ F]
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_rule_prop {F}
+{
+ [s {r{60}} P]
+ [s
+ {x{\fp_to_decimal:n{2.5+3.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-.5-.5*\c_@@_phi_fp}}}
+ {r{-120}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{-2.5-3.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5+.5*\c_@@_phi_fp}}}
+ {r{180}}
+ H]
+ [s
+ {x{\fp_to_decimal:n{4.5+6*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{.5+\c_@@_phi_fp}}}
+ {r{120}}
+ F]
+ [s
+ {x{\fp_to_decimal:n{-4.5-6*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-.5-\c_@@_phi_fp}}}
+ {r{-60}}
+ F]
+ [s
+ {x{\fp_to_decimal:n{3+4.5*\c_@@_phi_fp}}}
+ {y{\fp_to_decimal:n{-2-2.5*\c_@@_phi_fp}}}
+ F]
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {supercluster} {HTPF}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\fp_const:Nn \c_@@_phi_fp {(1 + sqrt(5))/2}
+\prop_new:N \g_@@_supercluster_lms_action_prop
+
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {r}
+{
+ \pgftransformrotate{\l_@@_parameters_lms_tl}
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {x}
+{
+ \pgftransformxshift{
+ \fp_to_dim:n
+ {.5 * (\l_@@_parameters_lms_tl) * \l_@@_step_dim}
+ }
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {y}
+{
+ \pgftransformyshift{
+ \fp_to_dim:n
+ {.5 * sqrt(3) * (\l_@@_parameters_lms_tl) * \l_@@_step_dim}
+ }
+}
+
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {s}
+{
+ \fp_set:Nn \l_@@_tmpa_fp {
+ \l_@@_step_dim
+ /
+ \c_@@_phi_fp
+ /
+ \c_@@_phi_fp
+ }
+ \dim_set:Nn \l_@@_step_dim {\fp_to_dim:N \l_@@_tmpa_fp}
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {H}
+{
+ \@@_place_cluster_tile:nn {super~ cluster}{H}
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {T}
+{
+ \@@_place_cluster_tile:nn {super~ cluster}{T}
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {P}
+{
+ \@@_place_cluster_tile:nn {super~ cluster}{P}
+}
+\prop_gput:Nnn \g_@@_supercluster_lms_action_prop {F}
+{
+ \@@_place_cluster_tile:nn {super~ cluster}{F}
+}
+% \end{macrocode}
+%
+%
+% Parameters:
+% \begin{enumerate}
+% \item Cluster type (super cluster, meta cluster, subcluster)
+% \item This tile type (H, T, P, F)
+% \item This tile's name
+% \item Alignment tile's name
+% \item Edge to align along
+% \item Edge to align with
+% \end{enumerate}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_place_cluster_tile_as_pic:nnnnnn #1#2#3#4#5#6
+{
+ \group_begin:
+ \int_gincr:N \g_@@_tile_int
+ \fp_set:Nn \l_@@_tmpa_fp {\l_@@_step_dim/(1cm)}
+ \tl_set:Nx \l_@@_tmpc_tl
+ {
+ {\int_use:N \g_@@_tile_int}
+ {\int_use:N \g_@@_tiles_int}
+ }
+ \tl_clear:N \l_@@_tmpa_tl
+ \tl_put_right:Nn \l_@@_tmpa_tl
+ {
+ \pic[
+ every~ tile/.try,
+ every~ #1~#2/.try,
+ }
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ tile~ \int_use:N \g_@@_tile_int/.try,
+ tile/.try=\l_@@_tmpc_tl,
+ scale=\fp_use:N \l_@@_tmpa_fp,
+ }
+ \tl_put_right:Nn \l_@@_tmpa_tl
+ {
+ name=#3,
+ }
+ \tl_if_empty:nTF {#4}
+ {
+ \tl_put_right:Nn \l_@@_tmpa_tl
+ {
+ first~ tile/.try,
+ }
+ }
+ {
+ \tl_put_right:Nn \l_@@_tmpa_tl
+ {
+ align~ with=#4~along~#5
+ }
+ \tl_if_single:nF {#6}
+ {
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ \c_space_tl using~\tl_tail:n {#6}
+ }
+ }
+ \tl_put_right:Nn \l_@@_tmpa_tl {,}
+ }
+ \tl_put_right:Nn \l_@@_tmpa_tl
+ {
+ #1~ #2
+ ];
+ }
+ \tl_use:N \l_@@_tmpa_tl
+ \group_end:
+}
+\cs_generate_variant:Nn \@@_place_cluster_tile_as_pic:nnnnnn {
+ Vnnnnn, VnVnnn, VnVVnn
+}
+\tikzset{
+ cluster~ type/.initial=super~ cluster,
+ first~ file/.style={transform~ shape}
+}
+\prop_new:N \g_@@_cluster_lms_rule_prop
+% \end{macrocode}
+%
+% The first set of rules govern when the tile being replaced is a root tile, in which case one of the new tiles becomes the new root and all others are placed with respect to them.
+%
+% It's convenient for code readability to have aliases for the labels for the parent and adjoining tiles, which are stored in the \Verb!\l_@@_parameters_lms_tl! token list.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_tile_label:
+{
+ \tl_item:Nn \l_@@_parameters_lms_tl {1}
+}
+\cs_new_nopar:Npn \@@_adjoint_label:
+{
+ \tl_item:Nn \l_@@_parameters_lms_tl {2}
+}
+% \end{macrocode}
+%
+% A single \(T\) tile is replaced by a single \(H\) tile
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {T}
+{
+ [s {H{\@@_tile_label:0}{}}]
+}
+% \end{macrocode}
+%
+% An \(H\) tile is replaced by \(10\) tiles, consisting of a \(T\) tile and \(3\) each of \(H\), \(P\), and \(F\).
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {H}
+{
+ [s {r{-60}} {T{\@@_tile_label:0}{}}]
+ [{ {HTa{A1}} {\@@_tile_label:1} {\@@_tile_label:0} }]
+ [{ {HTa{A2}} {\@@_tile_label:2} {\@@_tile_label:0} }]
+ [{ {HT{B1}b} {\@@_tile_label:3} {\@@_tile_label:0} }]
+ [{ {PHb{B2}} {\@@_tile_label:4} {\@@_tile_label:1} }]
+ [{ {PHb{B2}} {\@@_tile_label:5} {\@@_tile_label:2} }]
+ [{ {PHAa} {\@@_tile_label:6} {\@@_tile_label:3} }]
+ [{ {FHb{B1}} {\@@_tile_label:7} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:8} {\@@_tile_label:2} }]
+ [{ {FHb{B2}} {\@@_tile_label:9} {\@@_tile_label:3} }]
+}
+% \end{macrocode}
+%
+% Lastly, the \(P\) and \(F\) tile substitutions.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {P}
+{
+ [s {r{60}} {P{\@@_tile_label:0}{}}]
+ [{ {HPaA} {\@@_tile_label:1} {\@@_tile_label:0} }]
+ [{ {HP{B2}b} {\@@_tile_label:2} {\@@_tile_label:0} }]
+ [{ {FHb{B2}} {\@@_tile_label:3} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:4} {\@@_tile_label:2} }]
+}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {F}
+{
+ [s {r{60}} {P{\@@_tile_label:0}{}}]
+ [{ {HPaA} {\@@_tile_label:1} {\@@_tile_label:0} }]
+ [{ {HP{B2}b} {\@@_tile_label:2} {\@@_tile_label:0} }]
+ [{ {FHb{B2}} {\@@_tile_label:3} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:4} {\@@_tile_label:2} }]
+ [{ {FHb{B1}} {\@@_tile_label:5} {\@@_tile_label:1} }]
+}
+% \end{macrocode}
+%
+% The rest of the rules are for when the tile being replaced was itself positioned by aligning it with another tile.
+% For these tiles, one of its edge tiles will be its root and positioned alongside one of the edge tiles of the replacement of the original tile's alignment tile.
+% Then all the other tiles are positioned out from that root.
+% The labelling has to be the same regardless of the order of drawing the tiles.
+%
+% Not every edge pairing is necessary to generate a pattern as the edges that can be created are all between \(A^\pm\) edges and between \(B^\pm\) edges.
+% However, to avoid errors in case they are part of the seed then for now we create blank substitution rules that will effectively remove any such rogue elements.
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {TH{A1}a} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {TH{A2}a} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {THb{B1}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {THb{B2}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HTa{A1}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HTa{A2}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HT{B1}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HT{B2}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HPaA} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HP{B1}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HP{B2}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HF{B1}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {HF{B2}b} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PHAa} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PHb{B1}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PHb{B2}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PF{11}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PF{12}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PF{11}{12}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {PF{12}{12}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FHb{B1}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FHb{B2}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FP{11}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FP{12}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FP{11}{12}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FP{12}{12}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FFfF} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FFFf} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FF{11}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FF{12}{11}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FF{11}{12}} {}
+\prop_gput:Nnn \g_@@_cluster_lms_rule_prop {FF{12}{12}} {}
+% \end{macrocode}
+%
+% To help create the rules then we start with some helper macros.
+% Each of these creates the substitution rule for a tile given certain information about where the parent tile is positioned.
+% Most of the substitution information consists of placing the tiles next to each other, so only the first tile needs to know about a tile from a different set.
+% This makes it relatively easy to set up some templates for the substitution rules.
+% \begin{macrocode}
+\cs_new_nopar:cpn {@@_T{A1}_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {T#1{A1}#2}
+ {
+ [{ {H#3{B1}#4} {\@@_tile_label:0} {\@@_adjoint_label:#5} }]
+ }
+}
+\cs_new_nopar:cpn {@@_T{A2}_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {T#1{A2}#2}
+ {
+ [{ {H#3{B2}#4} {\@@_tile_label:0} {\@@_adjoint_label:#5} }]
+ }
+}
+\cs_new_nopar:cpn {@@_Tb_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {T#1b#2}
+ {
+ [{ {H#3a#4} {\@@_tile_label:0} {\@@_adjoint_label:#5} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_H{B1}_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {H#1{B1}#2}
+ {
+ [{ {P#3A#4} {\@@_tile_label:4} {\@@_adjoint_label:#5} }]
+
+ [{ {HP{B2}b} {\@@_tile_label:1} {\@@_tile_label:4} }]
+ [{ {TH{A1}a} {\@@_tile_label:0} {\@@_tile_label:1} }]
+
+ [{ {HTa{A2}} {\@@_tile_label:2} {\@@_tile_label:0} }]
+ [{ {PHb{B2}} {\@@_tile_label:5} {\@@_tile_label:2} }]
+
+ [{ {HT{B1}b} {\@@_tile_label:3} {\@@_tile_label:0} }]
+ [{ {PHAa} {\@@_tile_label:6} {\@@_tile_label:3} }]
+
+ [{ {FHb{B1}} {\@@_tile_label:7} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:8} {\@@_tile_label:2} }]
+ [{ {FHb{B2}} {\@@_tile_label:9} {\@@_tile_label:3} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_H{B2}_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {H#1{B2}#2}
+ {
+ [{ {P#3A#4} {\@@_tile_label:5} {\@@_adjoint_label:#5} }]
+
+ [{ {HP{B2}b} {\@@_tile_label:2} {\@@_tile_label:5} }]
+ [{ {TH{A2}a} {\@@_tile_label:0} {\@@_tile_label:2} }]
+
+ [{ {HTa{A1}} {\@@_tile_label:1} {\@@_tile_label:0} }]
+ [{ {PHb{B2}} {\@@_tile_label:4} {\@@_tile_label:1} }]
+
+ [{ {HT{B1}b} {\@@_tile_label:3} {\@@_tile_label:0} }]
+ [{ {PHAa} {\@@_tile_label:6} {\@@_tile_label:3} }]
+
+ [{ {FHb{B1}} {\@@_tile_label:7} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:8} {\@@_tile_label:2} }]
+ [{ {FHb{B2}} {\@@_tile_label:9} {\@@_tile_label:3} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_Ha_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {H#1a#2}
+ {
+ [{ {P#3b#4} {\@@_tile_label:6} {\@@_adjoint_label:#5} }]
+
+ [{ {HPaA} {\@@_tile_label:3} {\@@_tile_label:6} }]
+ [{ {THb{B1}} {\@@_tile_label:0} {\@@_tile_label:3} }]
+
+ [{ {HTa{A1}} {\@@_tile_label:1} {\@@_tile_label:0} }]
+ [{ {PHb{B2}} {\@@_tile_label:4} {\@@_tile_label:1} }]
+
+ [{ {HTa{A2}} {\@@_tile_label:2} {\@@_tile_label:0} }]
+ [{ {PHb{B2}} {\@@_tile_label:5} {\@@_tile_label:2} }]
+
+ [{ {FHb{B1}} {\@@_tile_label:7} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:8} {\@@_tile_label:2} }]
+ [{ {FHb{B2}} {\@@_tile_label:9} {\@@_tile_label:3} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_PA_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {P#1A#2}
+ {
+ [{ {H#3{B1}#4} {\@@_tile_label:1} {\@@_adjoint_label:#5} }]
+ [{ {PHAa} {\@@_tile_label:0} {\@@_tile_label:1} }]
+ [{ {HP{B2}b} {\@@_tile_label:2} {\@@_tile_label:0} }]
+
+ [{ {FHb{B2}} {\@@_tile_label:3} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:4} {\@@_tile_label:2} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_Pb_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {P#1b#2}
+ {
+ [{ {H#3a#4} {\@@_tile_label:2} {\@@_adjoint_label:#5} }]
+ [{ {PHb{B2}} {\@@_tile_label:0}{\@@_tile_label:2} }]
+ [{ {HPaA} {\@@_tile_label:1} {\@@_tile_label:0} }]
+
+ [{ {FHb{B2}} {\@@_tile_label:3} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:4} {\@@_tile_label:2} }]
+ }
+}
+
+\cs_new_nopar:cpn {@@_Fb_creator:nnnnn} #1#2#3#4#5
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_rule_prop {F#1b#2}
+ {
+ [{ {H#3a#4} {\@@_tile_label:2} {\@@_adjoint_label:#5} }]
+ [{ {PHb{B2}} {\@@_tile_label:0}{\@@_tile_label:2} }]
+ [{ {HPaA} {\@@_tile_label:1} {\@@_tile_label:0} }]
+
+ [{ {FHb{B2}} {\@@_tile_label:3} {\@@_tile_label:1} }]
+ [{ {FHb{B1}} {\@@_tile_label:4} {\@@_tile_label:2} }]
+ [{ {FHb{B1}} {\@@_tile_label:5} {\@@_tile_label:1} }]
+ }
+}
+% \end{macrocode}
+%
+% Now that the creators are set up it is time to invoke them.
+% \begin{macrocode}
+\clist_map_inline:nn
+{
+ TH{{A1}}a HP{{{B1}}}b06,
+ TH{{A2}}a HP{{{B2}}}b06,
+ THb{{B1}} HPaA04,
+ THb{{B2}} HPaA05,
+ PHAa HP{{{B1}}}b16,
+ PHb{{B1}} HPaA24,
+ PHb{{B2}} HPaA25,
+ FHb{{B1}} HPaA24,
+ FHb{{B2}} HPaA25,
+}
+{
+ \tl_clear:N \l_@@_tmpa_tl
+ \tl_put_right:Nn \l_@@_tmpa_tl { \use:c }
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ {@@_ \tl_item:nn {#1}{2}\tl_item:nn {#1}{4} _creator:nnnnn}
+ {\tl_item:nn {#1}{1}}{\tl_item:nn{#1}{3}}
+ \tl_item:nn {#1}{5}\tl_item:nn{#1}{7}
+ \tl_item:nn {#1}{9}
+ }
+ \tl_use:N \l_@@_tmpa_tl
+ \tl_clear:N \l_@@_tmpa_tl
+ \tl_put_right:Nn \l_@@_tmpa_tl { \use:c }
+ \tl_put_right:Nx \l_@@_tmpa_tl
+ {
+ {@@_ \tl_item:nn {#1}{1}\tl_item:nn {#1}{3} _creator:nnnnn}
+ {\tl_item:nn {#1}{2}}{\tl_item:nn{#1}{4}}
+ \tl_item:nn {#1}{6}\tl_item:nn{#1}{8}
+ \tl_item:nn {#1}{10}
+ }
+ \tl_use:N \l_@@_tmpa_tl
+}
+
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_new:N \g_@@_cluster_lms_action_prop
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_drawables_lms_prop {cluster} {HTPF}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\prop_gput:Nnn \g_@@_cluster_lms_action_prop {r}
+{
+ \pgftransformrotate{\l_@@_parameters_lms_tl}
+}
+\prop_gput:Nnn \g_@@_cluster_lms_action_prop {x}
+{
+ \pgftransformxshift{
+ \fp_to_dim:n
+ {.5 * (\l_@@_parameters_lms_tl) * \l_@@_step_dim}
+ }
+}
+\prop_gput:Nnn \g_@@_cluster_lms_action_prop {y}
+{
+ \pgftransformyshift{
+ \fp_to_dim:n
+ {.5 * sqrt(3) * (\l_@@_parameters_lms_tl) * \l_@@_step_dim}
+ }
+}
+
+\prop_gput:Nnn \g_@@_cluster_lms_action_prop {s}
+{
+ \fp_set:Nn \l_@@_tmpa_fp {
+ \l_@@_step_dim
+ /
+ \c_@@_phi_fp
+ /
+ \c_@@_phi_fp
+ }
+ \dim_set:Nn \l_@@_step_dim {\fp_to_dim:N \l_@@_tmpa_fp}
+}
+% \end{macrocode}
+%
+% The first set of actions are for when this tile is the root so doesn't have a parent
+% \begin{macrocode}
+\clist_map_inline:nn {H,T,P,F}
+{
+
+ \prop_gput:Nnn \g_@@_cluster_lms_action_prop {#1}
+ {
+ \@@_tikz_keys_get:Nn \l_@@_tmpa_tl {cluster~type}
+ \tl_set:Nx \l_@@_tmpb_tl {\tl_item:Nn \l_@@_parameters_lms_tl {1}}
+ \@@_place_cluster_tile_as_pic:VnVnnn
+ \l_@@_tmpa_tl {#1} \l_@@_tmpb_tl {}{}{}
+ }
+}
+% \end{macrocode}
+%
+% The second set is for when there is an adjoining edge
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_place_cluster_tile_as_pic_aux:nnnn #1#2#3#4
+{
+ \@@_tikz_keys_get:Nn \l_@@_tmpa_tl {cluster~type}
+ \tl_set:Nx \l_@@_tmpb_tl {\@@_tile_label:}
+ \tl_set:Nx \l_@@_tmpc_tl {\@@_adjoint_label:}
+ \@@_place_cluster_tile_as_pic:VnVVnn
+ \l_@@_tmpa_tl {#1} \l_@@_tmpb_tl \l_@@_tmpc_tl {#4}{#3}
+}
+
+\clist_map_inline:nn {
+ TH{A1}a,
+ TH{A2}a,
+ THb{B1},
+ THb{B2},
+ HTa{A1},
+ HTa{A2},
+ HT{B1}b,
+ HT{B2}b,
+ HPaA,
+ HP{B1}b,
+ HP{B2}b,
+ HF{B1}b,
+ HF{B2}b,
+ PHAa,
+ PHb{B1},
+ PHb{B2},
+ PF{11}{11},
+ PF{12}{11},
+ PF{11}{12},
+ PF{12}{12},
+ FHb{B1},
+ FHb{B2},
+ FP{11}{11},
+ FP{12}{11},
+ FP{11}{12},
+ FP{12}{12},
+ FFfF,
+ FFFf,
+ FF{11}{11},
+ FF{12}{11},
+ FF{11}{12},
+ FF{12}{12}
+}
+{
+ \prop_gput:Nnn \g_@@_cluster_lms_action_prop {#1}
+ {
+ \@@_place_cluster_tile_as_pic_aux:nnnn #1
+ }
+}
+
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \iffalse
+%</polykite>
+% \fi
+%
+% \iffalse
+%<*penrosedep>
+% \fi
+%
+% \begin{macrocode}
+\ProvidesFile {tikzlibrarypenrose.code.tex}
+ [2023/06/01 v2.0 TikZ pics for Penrose tiles]
+\usetikzlibrary{tilings.penrose}
+% \end{macrocode}
+%
+% Backwards compatibility mode:
+%
+% \begin{itemize}
+% \item \Verb+\SetPenrosePath+ is \Verb+\SetTilingPath+
+% \item \Verb+\BakePenroseTile+ and \Verb+\MakePenroseTile+ are \Verb+\BakeTile+
+% \item \Verb+\UsePenroseTile+ is \Verb+\UseTile+
+% \item \Verb+\PenroseDecomposition+ is \Verb+\TilingDecomposition+
+% \end{itemize}
+% \begin{macrocode}
+\ExplSyntaxOn
+\NewDocumentCommand \SetPenrosePath { m }
+{
+ \@@_set_tiling_path:n {#1}
+}
+\NewDocumentCommand \BakePenroseTile {m}
+{
+ \@@_bake_tile:n {#1}
+}
+\NewDocumentCommand \MakePenroseTile {m}
+{
+ \@@_bake_tile:n {#1}
+}
+\NewDocumentCommand \UsePenroseTile {O{} m}
+{
+ \@@_use_tile:nn {#1}{#2}
+}
+\NewDocumentCommand \PenroseDecomposition { O{} m m m }
+{
+ \@@_tiling_decomposition:nnnn {#1}{#2}{#3}{#4}
+}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \begin{macrocode}
+\tikzset{
+ save Penrose path/.forward to=/tikz/save tiling path,
+ clone Penrose side path/.forward to=/tikz/clone tiling side path,
+ spath/prefix/Penrose side/.forward to=/tikz/spath/prefix/tiling side,
+ spath/suffix/Penrose side/.forward to=/tikz/spath/suffix/tiling side,
+ clone Penrose tile path/.forward to=/tikz/clone tiling tile path,
+ spath/prefix/Penrose tile/.forward to=/tikz/spath/prefix/tiling tile,
+ spath/suffix/Penrose tile/.forward to=/tikz/spath/suffix/tiling tile,
+ Penrose step/.forward to=/tikz/tiling step,
+ every tile/.append style={
+ every Penrose tile/.try
+ },
+ every tile clip/.append style={
+ every Penrose tile clip/.try
+ },
+ every tile pic/.append style={
+ every Penrose pic/.try
+ },
+ tile/.append style={
+ Penrose tile #1/.try,
+ Penrose tile/.try=#1
+ }
+}
+% \end{macrocode}
+%
+% \iffalse
+%</penrosedep>
+% \fi
+%
+% \end{implementation}
+%\Finale
+\endinput