diff options
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/latex/tilings/tilings_code.dtx | 3780 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/tilings/tilings_code.ins | 92 |
2 files changed, 3872 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 diff --git a/Master/texmf-dist/source/latex/tilings/tilings_code.ins b/Master/texmf-dist/source/latex/tilings/tilings_code.ins new file mode 100644 index 00000000000..462d08cc6ad --- /dev/null +++ b/Master/texmf-dist/source/latex/tilings/tilings_code.ins @@ -0,0 +1,92 @@ +%% +%% This is file `tilings_code.ins', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% tilings_code.dtx (with options: `install') +%% ---------------------------------------------------------------- +%% 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 +%% ---------------------------------------------------------------- +%% +\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}} +} +\endbatchfile +%% +%% 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 +%% +%% +%% End of file `tilings_code.ins'. |