diff options
author | Norbert Preining <norbert@preining.info> | 2023-06-07 03:04:09 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-06-07 03:04:09 +0000 |
commit | 5c99135c06494b236cce7fd76e346851cf8c4408 (patch) | |
tree | ddae5aa8cd5c5ebbd4bb7518958532bdf817125f /obsolete/graphics/pgf | |
parent | 81c6e34f9b4e2191ee45a1e3236d77914a7af519 (diff) |
CTAN sync 202306070304
Diffstat (limited to 'obsolete/graphics/pgf')
-rw-r--r-- | obsolete/graphics/pgf/contrib/penrose/README | 8 | ||||
-rw-r--r-- | obsolete/graphics/pgf/contrib/penrose/penrose.pdf | bin | 0 -> 557513 bytes | |||
-rw-r--r-- | obsolete/graphics/pgf/contrib/penrose/penrose.tex | 794 | ||||
-rw-r--r-- | obsolete/graphics/pgf/contrib/penrose/penrose_code.dtx | 3126 | ||||
-rw-r--r-- | obsolete/graphics/pgf/contrib/penrose/penrose_code.pdf | bin | 0 -> 464179 bytes |
5 files changed, 3928 insertions, 0 deletions
diff --git a/obsolete/graphics/pgf/contrib/penrose/README b/obsolete/graphics/pgf/contrib/penrose/README new file mode 100644 index 0000000000..43c2298f5f --- /dev/null +++ b/obsolete/graphics/pgf/contrib/penrose/README @@ -0,0 +1,8 @@ +---------------------------------------------------------------- +penrose --- TikZ library for producing Penrose 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 +---------------------------------------------------------------- + +This package is for the creation of Penrose tilings using either kite-and-dart or rhombuses, and either by manual placement or automatic generation. diff --git a/obsolete/graphics/pgf/contrib/penrose/penrose.pdf b/obsolete/graphics/pgf/contrib/penrose/penrose.pdf Binary files differnew file mode 100644 index 0000000000..67ea7a9309 --- /dev/null +++ b/obsolete/graphics/pgf/contrib/penrose/penrose.pdf diff --git a/obsolete/graphics/pgf/contrib/penrose/penrose.tex b/obsolete/graphics/pgf/contrib/penrose/penrose.tex new file mode 100644 index 0000000000..be44311844 --- /dev/null +++ b/obsolete/graphics/pgf/contrib/penrose/penrose.tex @@ -0,0 +1,794 @@ +%\immediate\write18{tex penrose_code.dtx} +\documentclass{ltxdoc} +\usepackage[T1]{fontenc} +\usepackage{trace} +\usepackage{lmodern} +\usepackage{morefloats} +\usepackage[svgnames]{xcolor} +\usepackage{tikz} +\usetikzlibrary{penrose} +\usepackage[numbered]{hypdoc} +\definecolor{lstbgcolor}{rgb}{0.9,0.9,0.9} + +\usepackage{listings} +\lstloadlanguages{[LaTeX]TeX} +\lstset{ + breakatwhitespace=true, + breaklines=true, + language=[LaTeX]TeX, + basicstyle=\small\ttfamily, + keepspaces=true, + columns=fullflexible +} + +\usepackage{fancyvrb} + +\newenvironment{example} + {\VerbatimEnvironment + \begin{VerbatimOut}{example.out}} + {\end{VerbatimOut} + \begin{center} + \setlength{\parindent}{0pt} + \fbox{\begin{minipage}{.9\linewidth} + \lstinputlisting[]{example.out} + \end{minipage}} + + \fbox{\begin{minipage}{.9\linewidth} + \centering + \input{example.out} + \end{minipage}} +\end{center} +} + +\newenvironment{justexample} + {\VerbatimEnvironment + \begin{VerbatimOut}{example.out}} + {\end{VerbatimOut} + \begin{center} + \setlength{\parindent}{0pt} + \fbox{\begin{minipage}{.9\linewidth} + \lstinputlisting[]{example.out} + \end{minipage}} +\end{center} +} + +\colorlet{thinRhombus}{DarkOrchid} +\colorlet{thickRhombus}{DarkSlateGray} +\colorlet{circleArc}{RosyBrown} +\colorlet{longArc}{LawnGreen} + +\colorlet{kite}{HotPink} +\colorlet{dart}{Fuchsia} + +\colorlet{goldenTriangle}{Gold} +\colorlet{reverseGoldenTriangle}{Magenta} +\colorlet{goldenGnomon}{Cyan} +\colorlet{reverseGoldenGnomon}{LimeGreen} + +\makeatletter +\tikzset{ + tint fill colour/.code={% + \edef\@temp{% + \def\noexpand\tikz@fillcolor{\tikz@fillcolor!#1}% + \noexpand\tikz@addoption{\noexpand\pgfsetfillcolor{\tikz@fillcolor!#1}}% + }% + \@temp + } +} +\makeatother + +\providecommand*{\url}{\texttt} +\GetFileInfo{tikzlibrarypenrose.code.tex} + +\title{The \textsf{Penrose} Package: Documentation} +\author{Andrew Stacey\texorpdfstring{\\ \url{loopspace@mathforge.org}}{}} + \date{\fileversion~from \filedate} + +\begin{document} +\maketitle + +\tableofcontents + +\section{Introduction} + +The \textsf{Penrose} package is a TikZ library for drawing Penrose tiles. +It currently supports natively the kite/dart, rhombus, and pentagon tile sets, but has provision for defining new tiles. +There are two main methods for their placement: one that automatically generates a tiling, and one that allows for ``by hand'' placement. +Furthermore, the tiles themselves can be deformed and will still (hopefully!) fit together in the correct fashion. + +\section{Initialisation} + +To use this package, load the \Verb+tikz+ package and load \Verb+penrose+ as a TikZ library. +Specifically, your preamble should contain: + +\begin{verbatim} +\usepackage{tikz} +\usetikzlibrary{penrose} +\end{verbatim} + +\section{Usage} + +Using this package splits into several components. +There are the two main ways of getting tiles on to the page, and then there are the ways of deforming or styling the tiles once they are there. + +\subsection{Placing Tiles ``By Hand''} + +It is possible to use the tiles as \Verb+pic+s. +These are mini-drawings introduced in TikZ3.0 that are node-like in style, but a little more geared towards repeatable \emph{drawings} than boxes containing text. +This package defines several \Verb+pic+ types: + +\tikzset{ + every Penrose pic/.style={draw,ultra thick}, + every circle arc/.style={draw,thin}, + every long arc/.style={draw,thin}, +} + +\begin{itemize} +\item Kite \tikz[baseline=-.5ex] \pic[draw,kite]; +\item Dart \tikz[baseline=-.5ex] \pic[draw,dart]; +\item Thin Rhombus \tikz[baseline=-.5ex] \pic[draw,thin rhombus]; +\item Thick Rhombus \tikz[baseline=-.5ex] \pic[draw,thick rhombus]; +\item Pentagon \tikz[baseline=-.5ex] \pic[draw, pentagon 5]; +(Actually, there are three pentagons: \Verb+pentagon 5+, \Verb+pentagon 3+, and \Verb+pentagon 2+. +The number signifies how many pentagons it goes next to.) +\item Pentagram \tikz[baseline=-.5ex] \pic[draw, pentagram]; +\item Boat \tikz[baseline=-.5ex] \pic[draw, boat]; +\item Diamond \tikz[baseline=-.5ex] \pic[draw, diamond]; +\item Golden Triangle \tikz[baseline=-.5ex] \pic[draw,golden triangle]; +\item Reverse Golden Triangle \tikz[baseline=-.5ex] \pic[draw,reverse golden triangle]; +\item Golden Gnomon \tikz[baseline=-.5ex] \pic[draw,golden gnomon]; +\item Reverse Golden Gnomon \tikz[baseline=-.5ex] \pic[draw,reverse golden gnomon]; +\end{itemize} + +The main tiles can have arcs drawn on them to illustrate the matching rules. +The triangles and gnomon are not true Penrose tiles but rather can be used to build tilings so they do not have the arcs. +The two types of each triangle and gnomon are actually different in that they have different matching rules. +This is best illustrated by deforming the paths (see Section~\ref{sec:pathdeform}). + +There are two ways in TikZ to specify the \Verb+pic+ type: either as the ``contents'' of the pic or as the argument to the \Verb+pic type+ key. +Each of the tiles comes with a shorthand key which specifies the \Verb+pic type+ and also invokes the key \Verb+every Penrose tile+. +That is, the key \Verb+dart+ calls the \Verb+every Penrose tile+ key and specifies the \Verb+pic type+ as \Verb+dart+. + +The tiles can be placed using standard TikZ methods. +One important thing to note is that by default, \Verb+pic+s are like \Verb+nodes+ in that they only respond to ambient translations, and not to rotations and scaling. +To make them notice this, use the key \Verb+transform shape+ or specify the transformation to the \Verb+pic+ directly. +If the shortcut keys are used to specify the tiles, this can be put in the \Verb+every Penrose pic+ style. + +TikZ \Verb+pic+s can be named, using the \Verb+name=<name>+ key. +When a Penrose tile has been named then it can be used for positioning other tiles. +Each edge is assigned a label from \Verb+a b c d e A B C D E+ and a new tile can be aligned with an old one along a matching edge (\Verb+a+ matches with \Verb+A+ and so on). + +The edge labels are as follows. +For the \Verb+pentagon 5+, for example, the edges are all the same and the numbers are used to distinguish between them. + +\foreach \tile/\edges in { + kite/{a,A,c,C}, + dart/{a,A,c,C}, + thin rhombus/{a,A,b,B}, + thick rhombus/{a,A,b,B}, + pentagon 5/{a1,a2,a3,a4,a5}, + pentagon 3/{A,b1,a1,a2,b2}, + pentagon 2/{d,A1,c1,c2,A2}, + pentagram/{C1,C2,C3,C4,C5,C6,C7,C8,C9,C10}, + boat/{C1,C2,C3,C4,B1,D,B2}, + diamond/{D1,B1,B2,D2}, + golden triangle/{a,b,c}, + reverse golden triangle/{A,B,C}, + golden gnomon/{A,b,C}, + reverse golden gnomon/{a,B,c}} { + +\begin{tikzpicture} +\pic[draw,\tile,name=tile]; +\foreach \e in \edges { + \path (tile-edge \e\space start) -- node {\e} (tile-edge \e\space end); +} +\end{tikzpicture} + +} + +To align a tile with an existing one, use the following key: +% +\begin{verbatim} +align with=<tile> along <edge> +\end{verbatim} +% +where \Verb+<tile>+ is the name given to an existing tile, and \Verb+<edge>+ is the label on the existing tile. +If the tile being placed has edges that are identical (for example, \Verb+pentagon 5+), this syntax extends to +% +\begin{verbatim} +align with=<tile> along <edge> using <number> +\end{verbatim} +% +to specify which of the edges on the new tile to use. + +\begin{example} +\begin{tikzpicture} +\pic[kite,name=tile]; +\pic[dart,align with=tile along c]; +\pic[pentagon 5,name=ptile,at={(3,0)}]; +\pic[pentagon 3,align with=ptile along a1 using 2]; +\end{tikzpicture} +\end{example} + +With judicious use of loops, quite complicated pictures can be rendered using simple code. +(Note that the \Verb+transform shape+ is \emph{not} needed to apply the transformations needed to place a tile using this syntax.) + +\begin{example} +\begin{tikzpicture}[ + every rhombus/.style={ + draw=black, + ultra thick, + }, + every thin rhombus/.style={ + every rhombus/.try, + fill=thinRhombus, + }, + every thick rhombus/.style={ + every rhombus/.try, + fill=thickRhombus, + }, + every circle arc/.style={ + draw=circleArc + }, + every long arc/.style={ + draw=longArc + } +] +\pic[rotate=18,thick rhombus,name=a0]; +\foreach[evaluate=\k as \kmo using int(\k-1)] \k in {1,...,4} +{ + \pic[thick rhombus,name=a\k,align with={a\kmo} along A]; +} +\foreach \k in {0,...,4} +{ + \pic[thin rhombus,name=b\k,align with={a\k} along B]; + \pic[thick rhombus,name=c\k,align with={b\k} along A]; + \pic[thick rhombus,name=d\k,align with={b\k} along a]; + \pic[thick rhombus,name=e\k,align with={c\k} along A]; + \foreach \l/\a in {{0/b},{1/B}} + \pic[thin rhombus,name=f\k\l,align with={e\k} along \a]; +} +\pic[thin rhombus,name=g0,align with={f10} along a]; +\pic[thin rhombus,name=g1,align with={f21} along A]; +\foreach \l/\a in {{0/a},{1/A}} + \pic[thick rhombus,name=h\l,align with={g\l} along \a]; +\pic[thick rhombus,name=i,align with=g0 along B]; +\foreach \l/\a in {{0/a},{1/A}} + \pic[thick rhombus,name=j\l,align with=i along \a]; +\end{tikzpicture} +\end{example} + +The tiles can be styled, either directly or using various keys. +Each tile has the following styles applied (in this order): +% +\begin{enumerate} +\item \Verb+every Penrose Tile+ +\item \Verb+every <name>+ +\item \Verb+pic actions+ +\end{enumerate} +% +The \Verb+pic actions+ are any actions given directly to the tile, as in \Verb+\pic[draw,thin rhombus];+. +The kite, dart, and rhombus tiles also have arcs drawn on them and these are styled as \Verb+every circle arc+ and \Verb+every long arc+. +The names come from the way the arcs look on the rhombus shapes. + +One other point is important to note about the tiles. +They are actually clipped against themselves. +This ensures that the tiles do not overstep their bounds and so when placed alongside each other then they do not go over each other. +In practical terms, this means that if drawn then the line width is half that which might be expected (but when placed next to another tile, the two halves combine to the expected width). + +\subsection{Placing Tiles Automatically} + +There is a way to specify a Penrose tiling using \emph{Lindenmayer systems}. +In brief, this takes a golden triangle or gnomon (or one of the reverse ones) and repeatedly decomposes it into smaller triangles and gnomon. +Once a desired level has been reached, the resulting triangles and gnomon are glued together in pairs to create either darts and kites or rhombuses (of both types). +This library contains an implementation of this for each of the tilings. + +The user command is: +% +\begin{verbatim} +\PenroseDecomposition{<type>}{<level>}{<seed>} +\end{verbatim} +% +where \Verb+<type>+ is one of: +% +\begin{itemize} +\item \Verb+kite+ for the kite and dart tiling, +\item \Verb+rhombus+ for the rhombus tiling, +\item \Verb+pentagon+ for the pentagon tiling. +\item \Verb+ktriangle+ for the triangular decomposition used to form the kite and dart tiling but with the individual triangles +\item \Verb+rtriangle+ for the triangular decomposition used to form the rhombus tiling but with the individual triangles. +\end{itemize} + +The \Verb+<seed>+ is a ``word'' that will be used to initiate the Lindenmayer system. +The key letters in the alphabet for the kite/darts and rhombuses are \Verb+T+, \Verb+t+, \Verb+G+, and \Verb+g+. +These actually correspond to the two triangles and two gnomons. +For the pentagons, the key letters are \Verb+P+, \Verb+Q+, \Verb+R+, \Verb+G+, \Verb+B+, \Verb+D+. +These correspond to the three pentagons, the pentagram, the boat, and the diamond. +Other permitted letters are \Verb+[+, \Verb+]+, \Verb+s+, \Verb+f+, \Verb!+!, \Verb+*+, \Verb+-+, \Verb+_+, \Verb+>+. +These refer to various transformations (for details, see the implementation). + +The \Verb+<level>+ controls how far to take the iteration. +The code is not particularly optimised for speed, and once \Verb+<level>+ gets to about \(5\) or \(6\) then we are at the ``make a cup of tea while compiling'' stage, depending on the processor. + +\begin{example} +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + Penrose step=2cm, +] +\PenroseDecomposition{kite}{0}{T} +\end{tikzpicture} +\end{example} + +The same styling keys as for the \Verb+pic+ tiles apply, together with some additional ones. +These allow styling the tiles by their number: a count is kept of the number of tiles and each tile knows its own number. +Specifically, two keys are tried: +% +\begin{enumerate} +\item \Verb+Penrose tile <number>+, and +\item \Verb+Penrose tile={<number>}{<total>}+ +\end{enumerate} +% +A word of warning is in order on the second of these. +The \Verb+<total>+ is not guaranteed to be correct. +It is done by a quick count at the start of the process and counts those letters which \emph{might} result in a rendered tile. +Not every letter in the resulting word actually does. +Nevertheless, this can be used to style a tile based on what proportion of tiles have been rendered. + +Lastly, \Verb+Penrose step+ is used to control the size of the resulting picture. + +\begin{example} +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + Penrose step=4cm, + Penrose tile/.code 2 args={ + \pgfmathsetmacro\tint{100*#1/#2} + \pgfkeysalso{fill=black!\tint} + } +] +\PenroseDecomposition{rhombus}{3}{T} +\end{tikzpicture} +\end{example} + +\section{Deforming Paths} +\label{sec:pathdeform} + +This package provides the ability to deform the various tiles. +The various tiles can be built from four paths (labelled \Verb+a+, \Verb+b+, \Verb+c+, and \Verb+d+) together with their reverses. +By changing these paths, one can get a wide variety of different tiles with the same fundamental matching rules. +Indeed, by using asymmetric paths, the matching rules can be enforced without the need for additional decoration. + +Internally, the \Verb+penrose+ library uses the \Verb+spath3+ package for storing and manipulating the paths. + +To create a new edge path, use the key \Verb+save Penrose path=<edge>+ where \Verb+<edge>+ is a symbol used in the edge description of a tile. +There are no constraints on the size of the path as all paths are scaled and transformed to fit the tiles. +Once the edge paths have been specified, they are welded together into the tiles using the following command: +% +\begin{verbatim} +\BakePenroseTile{<name>} +\end{verbatim} +% +Here, \Verb+<name>+ is one of the names of the tiles. +This has global effect, as does the definition of the edge paths. +Paths, both sides and tiles, can be cloned via: +% +\begin{verbatim} +\tikzset{clone Penrose side path={target}{source} +\tikzset{clone Penrose tile path={target}{source} +\end{verbatim} +% +and restored with the same command (but names switched). + +The initial version of this package used \Verb!\MakePenroseTile! for this command. +That command is still available for backwards compatibility. + +\begin{example} +\begin{tikzpicture} +\pic[draw,dart,name=dart]; +\pic[draw,kite,align with=dart along c]; +\pic[draw,kite,align with=dart along C]; +\tikzset{clone Penrose tile path={original kite}{kite}} +\tikzset{clone Penrose tile path={original dart}{dart}} +\path[save Penrose path=a] (0,0) to[out=-30,in=100] (1,0); +\path[save Penrose path=c] (0,0) to[out=-40,in=140] (1,0); +\BakePenroseTile{kite} +\BakePenroseTile{dart} +\pic[xshift=2cm,draw,dart,name=dart]; +\pic[draw,kite,align with=dart along c]; +\pic[draw,kite,align with=dart along C]; +\tikzset{clone Penrose tile path={kite}{original kite}} +\tikzset{clone Penrose tile path={dart}{original dart}} +\pic[xshift=4cm,draw,dart,name=dart]; +\pic[draw,kite,align with=dart along c]; +\pic[draw,kite,align with=dart along C]; +\end{tikzpicture} +\end{example} + +With deformed tiles, there is no guarantee that the inner arcs will match up perfectly. + +\section{Defining New Tiles} + +This package includes the capability to define new tiles. +The command to do this is: +% +\begin{verbatim} +\DefineTile{<name>}{<sides>}{<coordinates>} +\end{verbatim} +% +For example, +% +\begin{verbatim} +\DefineTile {square}{a A a A} +{ + {0,0} + {1,0} + {1,1} + {0,1} +} +\end{verbatim} +% +The \Verb!<sides>! is a list of sides for matching rules. +Each letter used matches against its opposite case (so it is possible to create a side that matches against itself by using a symbol that \TeX\ regards as having the same upper as lower case; not all symbols work, I've used \Verb+!+ successfully). +These are also used in path replacing, both a letter and its opposite case are replaced by the corresponding path (but in opposite directions) when the tile is ``baked''. +The coordinates are passed to the \Verb!fp! module of \LaTeX3 so can involve complicated expressions. +Note that the trigonometric functions for angles in degrees are \Verb!cosd!, \Verb!sind!, and \Verb!tand!. + +Note that the tile must be baked via the command \Verb!\BakePenroseTile! before it can be used. + +The new tile can be used with all the same features as the pre-defined Penrose tiles, except for the Lindenmayer systems. + +\begin{example} +\DefineTile {square}{a A a A} +{ + {0,0} + {1,0} + {1,1} + {0,1} +} + +\begin{tikzpicture} +\path[save Penrose path=a] (0,0) to[out=45,in=135] (1,0); +\BakePenroseTile{square} +\pic[square,name=A,fill=green]; +\pic[square,align with=A along a1 using 2,name=B,fill=red]; +\pic[square,align with=A along A1 using 2,fill=red]; +\pic[square,align with=A along A2 using 1,fill=red]; +\pic[square,align with=B along a1 using 2,fill=green]; +\pic[square,align with=B along a2 using 1,fill=green]; +\end{tikzpicture} +\end{example} + +\section{More Examples} + +Let's set some aesthetically pleasing shapes. + +\begin{justexample} +\begin{tikzpicture} +\path[save Penrose path=a] (0,0) to[out=-30,in=100] (1,0); +\path[save Penrose path=b] (0,0) to[out=0,in=140] (1,0); +\path[save Penrose path=c] (0,0) to[out=-40,in=140] (1,0); +\BakePenroseTile{thin rhombus} +\BakePenroseTile{thick rhombus} +\BakePenroseTile{golden triangle} +\BakePenroseTile{reverse golden triangle} +\BakePenroseTile{golden gnomon} +\BakePenroseTile{reverse golden gnomon} +\BakePenroseTile{kite} +\BakePenroseTile{dart} +\end{tikzpicture} +\end{justexample} + +\begin{tikzpicture} +\path[save Penrose path=a] (0,0) to[out=-30,in=100] (1,0); +\path[save Penrose path=b] (0,0) to[out=0,in=140] (1,0); +\path[save Penrose path=c] (0,0) to[out=-40,in=140] (1,0); +\BakePenroseTile{thin rhombus} +\BakePenroseTile{thick rhombus} +\BakePenroseTile{golden triangle} +\BakePenroseTile{reverse golden triangle} +\BakePenroseTile{golden gnomon} +\BakePenroseTile{reverse golden gnomon} +\BakePenroseTile{kite} +\BakePenroseTile{dart} +\end{tikzpicture} + + +Styling the first tile. +Note that as the pattern is formed by repeating two different initial seeds \(5\) times, there are \(10\) ``first tiles'' in each overall pattern. + +\begin{example} +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + Penrose tile 1/.style={fill=yellow}, +] +\foreach \tp/\pos in {rhombus/0cm,rtriangle/2.5cm,kite/5cm,ktriangle/7.5cm} +{ +\begin{scope}[xshift=\pos] +\foreach[evaluate=\k as \mk using {\k+Mod(\k,2)},evaluate=\k as \ax using {Mod(\k,2) == 0 ? "T" : "t"}] \k in {0,...,9} { + \begin{scope}[rotate=\mk*36] + \PenroseDecomposition{\tp}{1}{\ax} + \end{scope} +} +\end{scope} +} +\end{tikzpicture} +\end{example} + +A more detailed decomposition, with more and more tinting applied to teach tile. +Roughly half of the counted tiles are rendered, and the ordering in which they are rendered is not at first an obvious one (though it is in general from ``outside in''). + +Note that the key \Verb+tint fill colour+ is not a TikZ native. +It is defined as: + +\begin{verbatim} +\makeatletter +\tikzset{ + tint fill colour/.code={% + \edef\@temp{% + \def\noexpand\tikz@fillcolor{\tikz@fillcolor!#1}% + \noexpand\tikz@addoption{% + \noexpand\pgfsetfillcolor{\tikz@fillcolor!#1}% + }% + }% + \@temp + } +} +\makeatother +\end{verbatim} + +\begin{example} +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + every kite/.style={fill=reverseGoldenTriangle}, + every dart/.style={fill=goldenTriangle}, + Penrose tile/.code 2 args={ + \pgfmathsetmacro\tint{100*(1 - 1.5*#1/#2))} + \pgfkeysalso{tint fill colour=\tint} + } +] +\foreach[evaluate=\k as \mk using {\k+Mod(\k,2)},evaluate=\k as \ax using {Mod(\k,2) == 0 ? "T" : "t"}] \k in {0,...,9} { + \begin{scope}[rotate=\mk*36] + \PenroseDecomposition[Penrose step=5cm]{kite}{4}{\ax} + \end{scope} +} +\end{tikzpicture} +\end{example} + +An example with ``manual placement''. + +\begin{example} +\begin{tikzpicture}[ + every Penrose pic/.style={ + draw=black, + ultra thick, + }, + every kite/.style={ + fill=kite, + }, + every dart/.style={ + fill=dart, + }, + every circle arc/.style={ + draw=circleArc + }, + every long arc/.style={ + draw=longArc + } +] +\pic[dart,name=a0]; +\foreach[evaluate=\k as \kmo using int(\k-1)] \k in {1,...,4} { + \pic[dart,name=a\k,align with={a\kmo} along a]; +} +\foreach \k in {0,...,4} { + \foreach \l/\e/\ee in {0/c/a,1/C/A} { + \pic[kite,name=b\l\k,align with={a\k} along \e]; + \pic[dart,name=c\l\k,align with={b\l\k} along \ee]; + \pic[kite,name=d\l\k,align with={c\l\k} along \e]; + } + \pic[kite,name=e\k,align with={c0\k} along C]; + \pic[dart,name=f\k,align with={c0\k} along a]; + \foreach \e in {c,C} { + \pic[kite,name=g\k,align with={f\k} along \e]; + } +} +\end{tikzpicture} +\end{example} + + +The decomposition rules for the Lindenmayer system can be illustrated by drawing each tile together with the result of one decomposition superimposed on top. + +\begin{example} +\foreach \ax in {T,t,G,g} { + +\begin{tikzpicture} +\foreach \tp/\pos in {rhombus/0cm,rtriangle/2cm,kite/4cm,ktriangle/6cm} +{ +\begin{scope}[xshift=\pos] + \PenroseDecomposition[every path/.style={draw=red,ultra thick}]{\tp}{0}{\ax} + \PenroseDecomposition[every path/.style={fill=gray!50,fill opacity=.5,draw=black}]{\tp}{1}{\ax} +\end{scope} +} +\end{tikzpicture} + +} +\end{example} + +The tiles can make interesting forms by themselves. + +\begin{example} +\begin{tikzpicture}[ + scale=2, + every Penrose pic/.style={ + transform shape, + }, + every golden triangle/.style={ + draw=black, + ultra thick, + fill=goldenTriangle, + }, + every reverse golden triangle/.style={ + draw=black, + ultra thick, + fill=reverseGoldenTriangle, + }, + every golden gnomon/.style={ + draw=black, + ultra thick, + fill=goldenGnomon, + }, + every reverse golden gnomon/.style={ + draw=black, + ultra thick, + fill=reverseGoldenGnomon, + }, +] +\pic[golden triangle,name=a]; +\pic[reverse golden triangle,align with=a along a]; +\pic[reverse golden triangle,align with=a along b]; +\pic[reverse golden triangle,align with=a along c]; +\begin{scope}[xshift=2cm] +\pic[reverse golden triangle,name=a]; +\pic[golden triangle,align with=a along A]; +\pic[golden triangle,align with=a along B]; +\pic[golden triangle,align with=a along C]; +\end{scope} +\begin{scope}[yshift=-3cm] +\pic[golden gnomon,name=a]; +\pic[reverse golden gnomon,align with=a along C]; +\pic[reverse golden gnomon,align with=a along b]; +\pic[reverse golden gnomon,align with=a along A]; +\begin{scope}[xshift=2cm] +\pic[reverse golden gnomon,name=a]; +\pic[golden gnomon,align with=a along c]; +\pic[golden gnomon,align with=a along B]; +\pic[golden gnomon,align with=a along a]; +\end{scope} +\end{scope} +\end{tikzpicture} +\end{example} + +\begin{example} +\begin{tikzpicture}[ + every rhombus/.style={ + draw=black, + ultra thick, + }, + every thin rhombus/.style={ + every rhombus/.try, + fill=thinRhombus, + }, + every thick rhombus/.style={ + every rhombus/.try, + fill=thickRhombus, + }, + every circle arc/.style={ + draw=circleArc + }, + every long arc/.style={ + draw=longArc + } +] +\pic[rotate=18,thick rhombus,name=a0]; +\foreach[evaluate=\k as \kmo using int(\k-1)] \k in {1,...,4} +{ + \pic[thick rhombus,name=a\k,align with={a\kmo} along A]; +} +\foreach \k in {0,...,4} +{ + \pic[thin rhombus,name=b\k,align with={a\k} along B]; + \pic[thick rhombus,name=c\k,align with={b\k} along A]; + \pic[thick rhombus,name=d\k,align with={b\k} along a]; + \pic[thick rhombus,name=e\k,align with={c\k} along A]; + \foreach \l/\a in {{0/b},{1/B}} + \pic[thin rhombus,name=f\k\l,align with={e\k} along \a]; +} +\pic[thin rhombus,name=g0,align with={f10} along a]; +\pic[thin rhombus,name=g1,align with={f21} along A]; +\foreach \l/\a in {{0/a},{1/A}} + \pic[thick rhombus,name=h\l,align with={g\l} along \a]; +\pic[thick rhombus,name=i,align with=g0 along B]; +\foreach \l/\a in {{0/a},{1/A}} + \pic[thick rhombus,name=j\l,align with=i along \a]; +\end{tikzpicture} +\end{example} + +Lastly, here's an example that generates full page patterns. + +\begin{justexample} +\foreach \tp/\lvl in {rhombus/5,rhombus/6,kite/5,kite/6} +{ +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + remember picture, + overlay, + scale=20 +] +\coordinate (a) at (current page.center); +\begin{scope}[shift={(a)}] +\foreach[evaluate=\k as \mk using {\k+Mod(\k,2)},evaluate=\k as \ax using {Mod(\k,2) == 0 ? "T" : "t"}] \k in {0,...,9} { + \begin{scope}[rotate=\mk*36] + \PenroseDecomposition{\tp}{\lvl}{\ax} + \end{scope} +} +\end{scope} +\end{tikzpicture} +\newpage +} +\end{justexample} + +\begin{tikzpicture} +\path[save Penrose path=a] (0,0) -- (1,0); +\path[save Penrose path=b] (0,0) -- (1,0); +\path[save Penrose path=c] (0,0) -- (1,0); +\BakePenroseTile{thin rhombus} +\BakePenroseTile{thick rhombus} +\BakePenroseTile{golden triangle} +\BakePenroseTile{reverse golden triangle} +\BakePenroseTile{golden gnomon} +\BakePenroseTile{reverse golden gnomon} +\BakePenroseTile{kite} +\BakePenroseTile{dart} +\end{tikzpicture} + +\newpage + +\foreach \tp/\lvl in {rhombus/5,rhombus/6,kite/5,kite/6} +{ +\begin{tikzpicture}[ + every Penrose tile/.style={draw}, + remember picture, + overlay, + scale=20 +] +\coordinate (a) at (current page.center); +\begin{scope}[shift={(a)}] +\foreach[evaluate=\k as \mk using {\k+Mod(\k,2)},evaluate=\k as \ax using {Mod(\k,2) == 0 ? "T" : "t"}] \k in {0,...,9} { + \begin{scope}[rotate=\mk*36] + \PenroseDecomposition{\tp}{\lvl}{\ax} + \end{scope} +} +\end{scope} +\end{tikzpicture} +\newpage +} + + +%% \foreach \lvl in {5,6} +%% { +%% \begin{tikzpicture}[ +%% every Penrose tile/.style={draw}, +%% remember picture, +%% overlay, +%% scale=180 +%% ] +%% \coordinate (a) at (current page.center); +%% \PenroseDecomposition{pentagon}{\lvl}{D} +%% \end{tikzpicture} +%% \newpage +%% } + + +\end{document} + +% Local Variables: +% tex-output-type: "pdf18" +% End: diff --git a/obsolete/graphics/pgf/contrib/penrose/penrose_code.dtx b/obsolete/graphics/pgf/contrib/penrose/penrose_code.dtx new file mode 100644 index 0000000000..cdc6356965 --- /dev/null +++ b/obsolete/graphics/pgf/contrib/penrose/penrose_code.dtx @@ -0,0 +1,3126 @@ +% \iffalse meta-comment +%<*internal> +\iffalse +%</internal> +%<*readme> +---------------------------------------------------------------- +penrose --- TikZ library for producing Penrose 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 +---------------------------------------------------------------- + +This package is for the creation of Penrose tilings using either kite-and-dart or rhombuses, and either by manual placement or automatic generation. +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*install> +\input l3docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +---------------------------------------------------------------- +penrose --- TikZ library for producing Penrose 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-2019 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 + tikzlibrarypenrose.code.tex + README.txt + +\endpostamble +\usedir{tex/latex/penrose} +\generate{ + \file{tikzlibrarypenrose.code.tex}{\from{\jobname.dtx}{package}} +} +%</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[T1]{fontenc} +\usepackage{lmodern} +\usepackage{tikz} +%\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} +% +% \DoNotIndex +% { +% \begingroup, +% \catcode, +% \active, +% \csname, +% \endcsname, +% }% +% +% +% \providecommand*{\url}{\texttt} +% \GetFileInfo{tikzlibrarypenrose.code.tex} +% \title{The \textsf{Penrose} package} +% \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 Penrose tiles (kite/dart, rhombus, and pentagon versions). +% 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+penrose.pdf+ file. +% +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{Implementation} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \begin{macrocode} +%<@@=penrose> +% \end{macrocode} +% +% \subsection{Initialisation} +% +% +% We use the \Verb+spath3+ library for manipulating the paths that will make up the tiles. +% +% \begin{macrocode} +\ProvidesExplFile {tikzlibrarypenrose.code.tex} {2021/01/22} {1.4} {TikZ pics for Penrose and other tiles} +\RequirePackage{spath3} +\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_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 +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmpa_fp, \l_@@_tmpb_fp, \l_@@_tmpc_fp, \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, \l_@@_tmpa_prop} +% 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 +\str_new:N \l_@@_tmpa_str +\str_new:N \l_@@_tmpb_str +\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 \g_@@_smuggle_tl +\int_new:N \l_@@_tmpa_int +\int_new:N \l_@@_tmpb_int +\dim_new:N \l_@@_xa_dim +\dim_new:N \l_@@_ya_dim +\dim_new:N \l_@@_xb_dim +\dim_new:N \l_@@_yb_dim +\prop_new:N \l_@@_tmpa_prop +% \end{macrocode} +% \end{variable} +% +% \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_@@_smuggle_tl \l_@@_tmpa_tl + \group_end: + \tl_set_eq:NN #1 \g_@@_smuggle_tl + \tl_gclear:N \g_@@_smuggle_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}{\SetPenrosePath} +% This sets the path corresponding to a particular side to the current path, and normalises it. +% \begin{macrocode} +\NewDocumentCommand \SetPenrosePath { m } +{ + \pgfsyssoftpath@getcurrentpath\l_@@_tmpa_tl + \@@_normalise_path:N \l_@@_tmpa_tl + \tl_gset_eq:cN {g_@@_side_#1_tl} \l_@@_tmpa_tl +} +% \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]{\@@_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} + \tikz_scan_point:V \l_@@_tmpb_tl + \tl_put_right:Nx \l_@@_tmpa_tl + { + {\dim_use:N \pgf@x}{\dim_use:N \pgf@y} + } + \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_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} + \tikz_scan_point:V \l_@@_tmpb_tl +% \end{macrocode} +% Store the resulting coordinate. +% \begin{macrocode} + \fp_set:Nn \l_@@_tmpa_fp { \pgf@x } + \fp_set:Nn \l_@@_tmpb_fp { \pgf@y } +% \end{macrocode} +% Now get the next coordinate. +% \begin{macrocode} + \tl_set:Nx \l_@@_tmpb_tl {\tl_head:N \l_@@_tmpa_tl} + \tikz_scan_point:V \l_@@_tmpb_tl +% \end{macrocode} +% We want the difference between the two coordinates. +% \begin{macrocode} + \fp_set:Nn \l_@@_tmpa_fp {\pgf@x - \l_@@_tmpa_fp} + \fp_set:Nn \l_@@_tmpb_fp {\pgf@y - \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_use:N \l_@@_tmpa_fp} + {\fp_use:N \l_@@_tmpb_fp} % not swapped + {\fp_use:N \l_@@_tmpc_fp} % not swapped + {\fp_use:N \l_@@_tmpa_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_@@_smuggle_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_@@_smuggle_tl + \tl_gclear:N \g_@@_smuggle_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 { + \fp_set:Nn \l_@@_tmpa_fp{#2} + \fp_set:Nn \l_@@_tmpb_fp{#3} + \tl_put_right:Nx #1 + { + {(\fp_use:N \l_@@_tmpa_fp, \fp_use:N \l_@@_tmpb_fp)} + } +} +% \end{macrocode} +% Wrapper around the add coordinate command to split at a comma. +% \begin{macrocode} +\cs_new_nopar:Npn \@@_add_coordinate:w #1#2,#3 \q_stop +{ + \@@_add_coordinate:Nnn \l_@@_tmpa_tl {#2}{#3} +} +% \end{macrocode} +% \end{macro} +% +% Now we specify the tiles. +% The specification is a clockwise list of the vertices together with the labels of the corresponding sides. +% There are three basic paths, \Verb+a+, \Verb+b+, \Verb+c+, and their complements (which are capitalised). +% +% \begin{itemize} +% \item Thin Rhombus. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{sind(18)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(18)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{-sind(18)} + +\prop_gput:Nnx \g_@@_tiles_prop {thin~ rhombus} +{{a A B b} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Thick Rhombus. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(36)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{-sind(36)} + +\prop_gput:Nnx \g_@@_tiles_prop {thick~ rhombus} +{{B a A b} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Dart. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{2*sind(18)*cosd(108)}{2*sind(18)*sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*sind(18)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{2*sind(18)*cosd(108)}{-2*sind(18)*sind(108)} + +\prop_gput:Nnx \g_@@_tiles_prop {dart} +{{c a A C} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Kite. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{-sind(36)} + +\prop_gput:Nnx \g_@@_tiles_prop {kite} +{{a c C A} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Golden Triangle. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{sind(18)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{-sind(18)} + +\prop_gput:Nnx \g_@@_tiles_prop {golden~ triangle} +{{a c b} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Reverse Golden Triangle. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{sind(18)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{-sind(18)} + +\prop_gput:Nnx \g_@@_tiles_prop {reverse~ golden~ triangle} +{{B C A} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Golden Gnomon +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(36)}{0} + +\prop_gput:Nnx \g_@@_tiles_prop {golden~ gnomon} +{{C b A} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Reverse Golden Gnomon +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(36)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(36)}{-sind(36)} +\prop_gput:Nnx \g_@@_tiles_prop {reverse~ golden~ gnomon} +{{a B c} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Primary Pentagon (pentagon 5) +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(108)}{sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{1+cosd(72)+cosd(144)}{sind(72)+sind(144)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1+cosd(72)}{sind(72)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1}{0} +\prop_gput:Nnx \g_@@_tiles_prop {pentagon~ 5} +{{a a a a a} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Secondary Pentagon (pentagon 3) +% \begin{macrocode} +\prop_gput:Nnx \g_@@_tiles_prop {pentagon~ 3} +{{A b a a b} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Tertiary Pentagon (pentagon 2) +% \begin{macrocode} +\prop_gput:Nnx \g_@@_tiles_prop {pentagon~ 2} +{{d A e c A} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Pentagram +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1-cosd(36)}{-sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{1-cosd(36)-cosd(108)}{-sind(36)-sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(108)}{-sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{-1+3*cosd(108)+cosd(36)}{-sind(36)-sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{-1+2*cosd(108)+cosd(36)}{-sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {-1+2*cosd(108)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(108)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(108)}{sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\prop_gput:Nnx \g_@@_tiles_prop {pentagram} +{{C E C E C E C E C E} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Boat +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {-1+2*cosd(108)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(108)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(108)}{sind(108)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {1-cosd(36)}{-sind(36)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl +{-1+2*cosd(108)+cosd(36)}{-sind(36)} +\prop_gput:Nnx \g_@@_tiles_prop {boat} +{{C E C E B D B} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \item Diamond. +% \begin{macrocode} +\tl_clear:N \l_@@_tmpa_tl +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {0}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{sind(18)} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {2*cosd(18)}{0} +\@@_add_coordinate:Nnn \l_@@_tmpa_tl {cosd(18)}{-sind(18)} +\prop_gput:Nnx \g_@@_tiles_prop {diamond} +{{D B B D} {\tl_use:N \l_@@_tmpa_tl}} +% \end{macrocode} +% +% \end{itemize} +% +% \begin{function}{\BakePenroseTile} +% This is the user wrapper around the tile creation macros. +% \begin{macrocode} +\NewDocumentCommand \BakePenroseTile {m} +{ + \prop_get:NnN \g_@@_tiles_prop {#1} \l_@@_tmpa_tl + \@@_make_tile:nV {#1} \l_@@_tmpa_tl +} +% \end{macrocode} +% For backwards compatibility. +% \begin{macrocode} +\cs_set_eq:NN \MakePenroseTile \BakePenroseTile +% \end{macrocode} +% \end{function} +% +% \begin{function}{\UsePenroseTile} +% This is the command that actually places a tile on the page. +% The first argument is optional and is for styling. +% \begin{macrocode} +\NewDocumentCommand \UsePenroseTile {O{} m} +{ +% \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_set_eq:Nc \l_@@_tmp_tile_path_tl {g_@@_tile_#2_tl} +% \end{macrocode} +% The transformation matrix returned by PGF appears to be transposed from what it should be. +% (This needs a little more investigation, it might be that I've implemented the multiplication incorrectly here.) +% \begin{macrocode} + \pgfgettransform \l_@@_tmpa_tl +% \tl_clear:N \l_@@_tmpb_tl +% \tl_set:Nx \l_@@_tmpb_tl {{\tl_head:N \l_@@_tmpa_tl}} +% \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} +% \tl_put_right:Nx \l_@@_tmpb_tl +% { +% {\tl_item:Nn \l_@@_tmpa_tl {1}} +% } +% \tl_put_right:Nx \l_@@_tmpb_tl +% { +% {\tl_item:Nn \l_@@_tmpa_tl {2}} +% } +% \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} +% \tl_set:Nx \l_@@_tmpa_tl {\tl_tail:N \l_@@_tmpa_tl} +% \tl_put_right:NV \l_@@_tmpb_tl \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 +} +% \end{macrocode} +% \end{function} +% +% \begin{macro}{save Penrose 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~ Penrose~ 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~ Penrose~ side~ path/.style~ 2~ args={ + spath/set~ name=Penrose~side, + spath/clone~ global={#1}{#2} + }, + spath/prefix/Penrose~side/.style={ + spath/set~ prefix=g_@@_side_, + }, + spath/suffix/Penrose~side/.style={ + spath/set~ suffix=_tl, + }, + clone~ Penrose~ tile~ path/.style~ 2~ args={ + spath/set~ name=Penrose~tile, + spath/clone~ global={#1}{#2} + }, + spath/prefix/Penrose~tile/.style={ + spath/set~ prefix=g_@@_tile_, + }, + spath/suffix/Penrose~tile/.style={ + spath/set~ suffix=_tl, + }, + expand~ key/.code={ + \exp_args:NV \pgfkeysalso #1 + } +} +% \end{macrocode} +% \end{macro} +% +% Create the basic tile shapes. +% \begin{macrocode} +\BakePenroseTile {thin~ rhombus} +\BakePenroseTile {thick~ rhombus} +\BakePenroseTile {dart} +\BakePenroseTile {kite} +\BakePenroseTile {golden~ triangle} +\BakePenroseTile {reverse~ golden~ triangle} +\BakePenroseTile {golden~ gnomon} +\BakePenroseTile {reverse~ golden~ gnomon} +\BakePenroseTile {pentagon~ 5} +\BakePenroseTile {pentagon~ 3} +\BakePenroseTile {pentagon~ 2} +\BakePenroseTile {pentagram} +\BakePenroseTile {boat} +\BakePenroseTile {diamond} +% \end{macrocode} +% +% +% \subsection{User-Definable Tiles} +% +% The commands in this section are for enabling a user to define their own tile. +% +% +% \begin{macro}[internal]{\@@_transform_side:nn} +% Apply a transformation to make a given side lie on the x-axis. +% First argument is the tile, second is the side. +% \begin{macrocode} +\cs_new_nopar:Npn \@@_transform_side:nn #1#2 +{ +% \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. +% +% 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} + \tl_map_inline:Nn \l_@@_tmpc_tl { + \str_if_eq:nnT {##1} {#2} { + \tl_map_break: + } + \int_incr:N \l_@@_tmpb_int + } +% \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} +% Translate second to origin. +% \begin{macrocode} + \tikz_scan_point:V \l_@@_tmpb_tl + \dim_set_eq:Nc \l_@@_xa_dim {pgf@x} + \dim_set_eq:Nc \l_@@_ya_dim {pgf@y} +% \end{macrocode} +% Rotate and scale first to unit x-vector. +% \begin{macrocode} + \tikz_scan_point:V \l_@@_tmpa_tl + \dim_set_eq:Nc \l_@@_xb_dim {pgf@x} + \dim_set_eq:Nc \l_@@_yb_dim {pgf@y} + + \dim_sub:Nn \l_@@_xb_dim {\l_@@_xa_dim } + \dim_sub:Nn \l_@@_yb_dim {\l_@@_ya_dim } +% \end{macrocode} +% And normalise the vector along it. +% \begin{macrocode} + \pgfpointnormalised{\pgfpoint{\l_@@_xb_dim}{\l_@@_yb_dim}} + \dim_set_eq:Nc \l_@@_xb_dim {pgf@x} + \dim_set_eq:Nc \l_@@_yb_dim {pgf@y} +% \end{macrocode} +% Now rotate so that the \(x\)--axis lies along the edge. +% \begin{macrocode} + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\l_@@_xb_dim}{-\l_@@_yb_dim}} + {\pgfpoint{\l_@@_yb_dim}{\l_@@_xb_dim}} + + \pgftransformshift{\pgfpoint{-\l_@@_xa_dim}{-\l_@@_ya_dim}} + +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\cs_generate_variant:Nn \tl_if_eq:nnT {nVT} +\cs_generate_variant:Nn \@@_transform_side:nn {nx,nV} +% \end{macrocode} +% +% \begin{macro}[internal]{\TransformAlongSide} +% Make this available outside the \LaTeX3 environment. +% \begin{macrocode} +\DeclareDocumentCommand \TransformAlongSide {m m} +{ + \@@_transform_side:nx {#1}{#2} +} +% \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 +{ +% \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 path type list, looking for the requested path +% \begin{macrocode} + \tl_map_inline:Nn \l_@@_tmpb_tl { + \tl_set:Nx \l_@@_tmpd_tl { + \exp_not:N \coordinate + (-edge~ ##1~ start)~ at \tl_use:N \l_@@_tmpa_tl; + } + \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_use:N \l_@@_tmpa_tl; + } + \tl_use:N \l_@@_tmpd_tl + } +} +% \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{function}{\DefineTile} +% This is the user function for defining a tile. +% \begin{macrocode} +\DeclareDocumentCommand \DefineTile { 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} + \tl_map_inline:nn {#3} { + \@@_add_coordinate:w \l_@@_tmpa_tl ##1 \q_stop + } +% \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 {#2} { + \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 {#2} + { + \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 {#1} + {{\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{ + #1/.pic={ + \begin{scope} +% \end{macrocode} +% Were we given a tile to align ourselves against? +% \begin{macrocode} + \pgfkeysgetvalue{/tikz/Penrose/alignment~ location}{\prloc} + \ifx\prloc\pgfutil@empty + \else +% \end{macrocode} +% Yes, we were. +% So we adjust our position accordingly. +% The first job is to transform so that we're along the edge of the receiving tile. +% \begin{macrocode} + \begingroup +% \end{macrocode} +% We get the locations of the start and end of the receiving tile. +% As \Verb+pic+ sets the node prefix, we have to temporarily suspend that (hence working in a group). +% \begin{macrocode} + \tikzset{name~ prefix~ ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge~ \pgfkeysvalueof{/tikz/Penrose/alignment~ edge}~ start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge~ \pgfkeysvalueof{/tikz/Penrose/alignment~ edge}~ end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup +% \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} + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya +% \end{macrocode} +% We shift to the start of the edge. +% \begin{macrocode} + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% +% \end{macrocode} +% And normalise the vector along it. +% \begin{macrocode} + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y +% \end{macrocode} +% Now rotate so that the \(x\)--axis lies along the edge. +% \begin{macrocode} + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}} +% \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 + {\pgfkeysvalueof{/tikz/Penrose/alignment~ edge}} + \str_set:Nx \l_@@_tmpa_str {\str_head:N \l_@@_tmpa_str} + \str_put_right:Nx \l_@@_tmpa_str + {\pgfkeysvalueof{/tikz/Penrose/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}} + } + + \@@_transform_side:nV {#1} \l_@@_tmpb_str + \fi +% \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. +% \begin{macrocode} + \UsePenroseTile[ + every~ Penrose~ tile~ clip/.try, + every~ #1~ clip/.try + ]{#1} + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ #1/.try, + pic~ actions + ]{#1} +% Lastly, we put coordinates at each vertex, labelled by which edge they are. +% \begin{macrocode} + \@@_coordinates_at_vertices:n {#1} + \end{scope} + }, +% \end{macrocode} +% This is a shortcut for installing the \Verb+pic+ type. +% \begin{macrocode} + #1/.style={ + every~ Penrose~ pic/.try, + pic~ type=#1, + }, + } +} +% \end{macrocode} +% \end{function} +% +% +% \subsection{Lindenmayer System} +% +% This is an implementation of the Lindenmayer System description of Penrose 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. +% +% These are the rules for generating rhombus tilings. +% \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 hold the various actions. +% \begin{macrocode} +\prop_new:N \g_@@_default_lms_action_prop +\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} +% +% 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_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 {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} +% +% 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}} +% \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+Penrose 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ thin~ rhombus/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ thick~ rhombus/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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}} +% \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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ kite/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ dart/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ reverse~ golden~ triangle/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ golden~ triangle/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ reverse~ golden~ gnomon/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ golden~ gnomon/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ reverse~ golden~ triangle/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ golden~ triangle/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ reverse~ golden~ gnomon/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ golden~ gnomon/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } +\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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ pentagon/.try, + every~ + \seq_item:Nn \l_@@_pentagon_parity_seq + {\l_@@_pentagon_parity_int} + \space pentagon/.try, + every~ pentagon~ 5/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ pentagon/.try, + every~ + \seq_item:Nn \l_@@_pentagon_parity_seq + {\l_@@_pentagon_parity_int} + \space pentagon/.try, + every~ pentagon~ 3/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ pentagon/.try, + every~ + \seq_item:Nn \l_@@_pentagon_parity_seq + {\l_@@_pentagon_parity_int} + \space pentagon/.try, + every~ pentagon~ 2/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ pentagram/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ boat/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ 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} + } + \UsePenroseTile[ + every~ Penrose~ tile/.try, + every~ diamond/.try, + Penrose~ tile~ \int_use:N \g_@@_tile_int/.try, + Penrose~ tile/.try/.expand~ once=\l_@@_tmpc_tl + ]{diamond} + \group_end: +} +% \end{macrocode} +% +% \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} + \prop_if_in:cnTF {g_@@_#2_lms_rule_prop} {##1} + { + \tl_put_right:Nx \l_@@_tmpb_tl + {\prop_item:cn {g_@@_#2_lms_rule_prop} {##1} } + } + { +% \end{macrocode} +% Otherwise, just copy the token. +% \begin{macrocode} + \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 { + \prop_if_in:cnTF {g_@@_#2_lms_action_prop} {##1} + { + \prop_item:cn {g_@@_#2_lms_action_prop} {##1} + } + { + \prop_if_in:cnT {g_@@_default_lms_action_prop} {##1} + { + \prop_item:cn {g_@@_default_lms_action_prop} {##1} + } + } + } + \group_end: +} +% \end{macrocode} +% \end{macro} +% +% 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}{\PenroseDecomposition} +% This is the user macro to invoke the decomposition. +% The arguments are: optional styles, the name, number of iterations, and starting seed. +% \begin{macrocode} +\NewDocumentCommand \PenroseDecomposition { O{} m m m } +{ + \group_begin: + \tikzset{#1} + \@@_make_lms:Nnnx \l_@@_tmpa_tl {#2} {#3} {#4} + \@@_count_lms:N \l_@@_tmpa_tl + \int_gzero:N \g_@@_tile_int + \int_set:Nn \l_@@_pentagon_parity_int {2} + \@@_invoke_lms:Nn \l_@@_tmpa_tl {#2} + \group_end: +} +% \end{macrocode} +% \end{function} +% +% \begin{macro}[internal]{\@@_count_lms:N} +% This counts the number of tiles in the string. +% \begin{macrocode} +\cs_new_nopar:Npn \@@_count_lms:N #1 +{ + \int_gzero:N \g_@@_tiles_int + \tl_map_inline:Nn #1 + { + \tl_if_eq:nnT {##1} {T} + { + \int_gincr:N \g_@@_tiles_int + } + \tl_if_eq:nnT {##1} {t} + { + \int_gincr:N \g_@@_tiles_int + } + \tl_if_eq:nnT {##1} {G} + { + \int_gincr:N \g_@@_tiles_int + } + \tl_if_eq:nnT {##1} {g} + { + \int_gincr:N \g_@@_tiles_int + } + } +} +% \end{macrocode} +% \end{macro} +% +% This is a \Verb+\tikzset+ mechanism for setting the dimensions of the tiling. +% \begin{macrocode} +\tikzset{ + Penrose~ step/.code={ + \dim_set:Nn \l_@@_step_dim {#1} + } +} +% \end{macrocode} +% +% We're done with \LaTeX3, so turn off the syntax. +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% +% \subsection{TikZ Pictures} +% +% New in TikZ3.0 is the ability to make pictures that can be reused. +% Penrose tiles seems an obvious use for this. +% These pictures can be placed alongside other tiles, matching by edge type. +% +% There are a variety of constants that are frequently used and reused, so we define them all here. +% These are the PGF versions. +% +% \begin{macrocode} +\pgfmathsetmacro\pr@chphi{cos(18)} +\pgfmathsetmacro\pr@shphi{sin(18)} +\pgfmathsetmacro\pr@cphi{cos(36)} +\pgfmathsetmacro\pr@sphi{sin(36)} +\pgfmathsetmacro\pr@invphi{2/(sqrt(5)+1)} +\pgfmathsetmacro\pr@phi{(sqrt(5)+1)/2} +\pgfmathsetmacro\pr@invphisq{\pr@invphi*\pr@invphi} +\pgfmathsetmacro\pr@ominvphisq{\pr@invphi - \pr@invphisq} +\pgfmathsetmacro\pr@ominvphi{1 - \pr@invphi} +% \end{macrocode} +% +% \begin{macrocode} +\newif\if@edgealign +\def\pr@getfirst#1#2\pr@stop{#1}% +\def\test@edgealign#1{% + \pgfkeysgetvalue{/tikz/Penrose/alignment edge}{\@penrose@tmpa}% + \edef\@penrose@tmpb{#1}% + \edef\@penrose@tmpa{\expandafter\pr@getfirst\@penrose@tmpa.\pr@stop}% + \ifx\@penrose@tmpa\@penrose@tmpb + \@edgealigntrue + \else + \@edgealignfalse + \fi +}% +% \end{macrocode} +% +% \begin{macrocode} +\newif\if@newedge +\def\test@newedge#1{% + \pgfkeysgetvalue{/tikz/Penrose/alignment new edge}{\@penrose@tmpa}% + \edef\@penrose@tmpb{#1}% + \edef\@penrose@tmpa{\@penrose@tmpa}% + \ifx\@penrose@tmpa\@penrose@tmpb + \@newedgetrue + \else + \@newedgefalse + \fi +}% +% \end{macrocode} +% +% The implementation is essentially the same for each, so only the first will be commented. +% \begin{macrocode} +\tikzset{ +% \end{macrocode} +% The key \Verb+align with=<tile> along <edge>+ is used to set the parameters for placing a tile next to an existing one. +% For most tiles, that's enough to specify how the new tile should be placed. +% Some, though, need more information. +% For those, use \Verb+align with=<tile> along <edge> using <number>+. +% \begin{macrocode} + align with/.code args={#1 along #2}{% + \pgfutil@in@{ using }{#2} + \ifpgfutil@in@% + \tikzset{ + Penrose/alignment location=#1, + Penrose/alignment set edges=#2, + }% + \else + \tikzset{ + Penrose/alignment location=#1, + Penrose/alignment edge=#2, + }% + \fi + }, + Penrose/alignment set edges/.code args={#1 using #2}{% + \tikzset{ + Penrose/alignment edge=#1, + Penrose/alignment new edge=#2 + }, + }, + Penrose/alignment location/.initial={}, + Penrose/alignment edge/.initial=a, + Penrose/alignment new edge/.initial={}, +% \end{macrocode} +% Default clipping style. +% \begin{macrocode} + every Penrose tile clip/.style={clip}, +% \end{macrocode} +% This is the code for setting up a \Verb+pic+. +% \begin{macrocode} + thin rhombus/.pic={ + \begin{scope} +% \end{macrocode} +% Were we given a tile to align ourselves against? +% \begin{macrocode} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else +% \end{macrocode} +% Yes, we were. +% So we adjust our position accordingly. +% The first job is to transform so that we're along the edge of the receiving tile. +% \begin{macrocode} + \begingroup +% \end{macrocode} +% We get the locations of the start and end of the receiving tile. +% As \Verb+pic+ sets the node prefix, we have to temporarily suspend that (hence working in a group). +% \begin{macrocode} + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup +% \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} + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya +% \end{macrocode} +% We shift to the start of the edge. +% \begin{macrocode} + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% +% \end{macrocode} +% And normalise the vector along it. +% \begin{macrocode} + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y +% \end{macrocode} +% Now rotate so that the \(x\)--axis lies along the edge. +% \begin{macrocode} + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}} +% \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} + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}b\relax + \pgftransformrotate{-18}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{\pr@shphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}B\relax + \pgftransformrotate{18}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \pgftransformrotate{198}% + \pgftransformshift{\pgfpoint{-2*\pr@chphi cm}{0 cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{162}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{-\pr@shphi cm}}% + \fi\fi\fi\fi + \fi +% \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. +% \begin{macrocode} + \UsePenroseTile[ + every Penrose tile clip/.try, + every thin rhombus clip/.try + ]{thin rhombus} + \UsePenroseTile[ + every Penrose tile/.try, + every thin rhombus/.try, + pic actions + ]{thin rhombus} +% \end{macrocode} +% These draw the arcs that designate the joining rules. +% We draw full circles so that it doesn't matter what shape the tiles are. +% \begin{macrocode} + \UsePenroseTile[ + every Penrose arc clip/.try, + every thin rhombus arc clip/.try + ]{thin rhombus} + \path[every circle arc/.try] (18:1) circle[radius=1/4]; + \path[every long arc/.try] (-18:1) circle[radius=1/4]; +% \end{macrocode} +% Lastly, we put coordinates at each vertex, labelled by which edge they are. +% \begin{macrocode} +\coordinate (-edge a start) at (0,0); +\coordinate (-edge a end) at (18:1); +\coordinate (-edge A start) at (18:1); +\coordinate (-edge A end) at (2*\pr@chphi,0); +\coordinate (-edge B start) at (2*\pr@chphi,0); +\coordinate (-edge B end) at (-18:1); +\coordinate (-edge b start) at (-18:1); +\coordinate (-edge b end) at (0,0); + \end{scope} + }, +% \end{macrocode} +% This is a shortcut for installing the \Verb+pic+ type. +% \begin{macrocode} + thin rhombus/.style={ + every Penrose pic/.try, + pic type=thin rhombus, + }, +% \end{macrocode} +% Same again, but for the thick rhombus. +% \begin{macrocode} + thick rhombus/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}} + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}b\relax + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{-\pr@sphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}B\relax + \pgftransformrotate{36}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \pgftransformrotate{-36}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{\pr@sphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{216}% + \pgftransformshift{\pgfpoint{-2*\pr@cphi cm}{0 cm}}% + \fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every thick rhombus clip/.try + ]{thick rhombus} + \UsePenroseTile[ + every Penrose tile/.try, + every thick rhombus/.try, + pic actions + ]{thick rhombus} + \UsePenroseTile[ + every Penrose arc clip/.try, + every thick rhombus arc clip/.try + ]{thick rhombus} +\path[every circle arc/.try] (2*\pr@cphi,0) circle[radius=1/4]; +\path[every long arc/.try] (0,0) circle[radius=3/4]; +\coordinate (-edge B start) at (0,0); +\coordinate (-edge B end) at (36:1); +\coordinate (-edge a start) at (36:1); +\coordinate (-edge a end) at (2*\pr@cphi,0); +\coordinate (-edge A start) at (2*\pr@cphi,0); +\coordinate (-edge A end) at (-36:1); +\coordinate (-edge b start) at (-36:1); +\coordinate (-edge b end) at (0,0); + \end{scope} + }, + thick rhombus/.style={ + every Penrose pic/.try, + pic type=thick rhombus, + }, +% \end{macrocode} +% Now the kite. +% \begin{macrocode} + kite/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}c\relax + \pgftransformrotate{-72}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{\pr@sphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}C\relax + \pgftransformrotate{-108}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \pgftransformrotate{36}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{-\pr@sphi cm}}% + \fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every kite clip/.try + ]{kite} + \UsePenroseTile[ + every Penrose tile/.try, + every kite/.try, + pic actions + ]{kite} + \UsePenroseTile[ + every Penrose arc clip/.try, + every kite arc clip/.try + ]{kite} +\path[every circle arc/.try] (0,0) circle[radius=\pr@invphi]; +\path[every long arc/.try] (1,0) circle[radius=\pr@invphisq]; +\coordinate (-edge a start) at (0,0); +\coordinate (-edge a end) at (36:1); +\coordinate (-edge c start) at (36:1); +\coordinate (-edge c end) at (1,0); +\coordinate (-edge C start) at (1,0); +\coordinate (-edge C end) at (-36:1); +\coordinate (-edge A start) at (-36:1); +\coordinate (-edge A end) at (0,0); + \end{scope} + }, +% \end{macrocode} +% The dart is next. +% \begin{macrocode} + dart/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}c\relax + \pgftransformrotate{108}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}C\relax + \pgftransformrotate{72}% + \pgftransformshift% + {\pgfpoint{\pr@invphi*\pr@shphi cm}{-\pr@invphi*\pr@chphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \pgftransformrotate{-36}% + \pgftransformshift% + {\pgfpoint{\pr@invphi*\pr@shphi cm}{\pr@invphi*\pr@chphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{216}% + \pgftransformshift{\pgfpoint{-\pr@invphi cm}{0 cm}}% + \fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every dart clip/.try + ]{dart} + \UsePenroseTile[ + every Penrose tile/.try, + every dart/.try, + pic actions + ]{dart} + \UsePenroseTile[ + every Penrose arc clip/.try, + every dart arc clip/.try + ]{dart} +\path[every circle arc/.try] (\pr@invphi,0) circle[radius=\pr@ominvphi]; +\path[every long arc/.try] (0,0) circle[radius=\pr@ominvphisq]; +\coordinate (-edge c start) at (0,0); +\coordinate (-edge c end) at (108:\pr@invphi); +\coordinate (-edge a start) at (108:\pr@invphi); +\coordinate (-edge a end) at (\pr@invphi,0); +\coordinate (-edge A start) at (\pr@invphi,0); +\coordinate (-edge A end) at (-108:\pr@invphi); +\coordinate (-edge C start) at (-108:\pr@invphi); +\coordinate (-edge C end) at (0,0); + \end{scope} + }, + kite/.style={ + every Penrose pic/.try, + pic type=kite, + }, + dart/.style={ + every Penrose pic/.try, + pic type=dart, + }, +% \end{macrocode} +% The golden triangle. +% \begin{macrocode} + golden triangle/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}B\relax + \pgftransformrotate{18}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}C\relax + \pgftransformrotate{-90}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{\pr@shphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{162}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{-\pr@shphi cm}}% + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every golden triangle clip/.try + ]{golden triangle} + \UsePenroseTile[ + every Penrose tile/.try, + every golden triangle/.try, + pic actions + ]{golden triangle} +\coordinate (-edge a start) at (0,0); +\coordinate (-edge a end) at (18:1); +\coordinate (-edge c start) at (18:1); +\coordinate (-edge c end) at (-18:1); +\coordinate (-edge b start) at (-18:1); +\coordinate (-edge b end) at (0,0); + \end{scope} + }, + golden triangle/.style={ + every Penrose pic/.try, + pic type=golden triangle, + }, +% \end{macrocode} +% The reverse golden triangle (is there a better name?). +% \begin{macrocode} + reverse golden triangle/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}b\relax + \pgftransformrotate{162}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{-\pr@shphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}c\relax + \pgftransformrotate{-90}% + \pgftransformshift{\pgfpoint{-\pr@chphi cm}{\pr@shphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \pgftransformrotate{18}% + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every reverse golden triangle clip/.try + ]{reverse golden triangle} + \UsePenroseTile[ + every Penrose tile/.try, + every reverse golden triangle/.try, + pic actions + ]{reverse golden triangle} +\coordinate (-edge B start) at (0,0); +\coordinate (-edge B end) at (18:1); +\coordinate (-edge C start) at (18:1); +\coordinate (-edge C end) at (-18:1); +\coordinate (-edge A start) at (-18:1); +\coordinate (-edge A end) at (0,0); + \end{scope} + }, + reverse golden triangle/.style={ + every Penrose pic/.try, + pic type=reverse golden triangle, + }, +% \end{macrocode} +% The golden gnomon. +% \begin{macrocode} + golden gnomon/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}c\relax + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{-\pr@sphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}B\relax + \pgftransformrotate{-144}% + \pgftransformshift{\pgfpoint{-2*\pr@cphi cm}{0 cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}a\relax + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every golden gnomon clip/.try + ]{golden gnomon} + \UsePenroseTile[ + every Penrose tile/.try, + every golden gnomon/.try, + pic actions + ]{golden gnomon} +\coordinate (-edge C start) at (0,0); +\coordinate (-edge C end) at (36:1); +\coordinate (-edge b start) at (36:1); +\coordinate (-edge b end) at (2*\pr@cphi,0); +\coordinate (-edge A start) at (2*\pr@cphi,0); +\coordinate (-edge A end) at (0,0); + \end{scope} + }, + golden gnomon/.style={ + every Penrose pic/.try, + pic type=golden gnomon, + }, +% \end{macrocode} +% The reverse golden gnomon. +% \begin{macrocode} + reverse golden gnomon/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}C\relax + \pgftransformrotate{36}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}b\relax + \pgftransformrotate{-36}% + \pgftransformshift{\pgfpoint{-\pr@cphi cm}{\pr@sphi cm}}% + \else + \if\pgfkeysvalueof{/tikz/Penrose/alignment edge}A\relax + \pgftransformrotate{180}% + \pgftransformshift{\pgfpoint{-2*\pr@cphi cm}{0 cm}}% + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every reverse golden gnomon clip/.try + ]{reverse golden gnomon} + \UsePenroseTile[ + every Penrose tile/.try, + every reverse golden gnomon/.try, + pic actions + ]{reverse golden gnomon} +\coordinate (-edge a start) at (0,0); +\coordinate (-edge a end) at (2*\pr@cphi,0); +\coordinate (-edge B start) at (2*\pr@cphi,0); +\coordinate (-edge B end) at (-36:1); +\coordinate (-edge c start) at (-36:1); +\coordinate (-edge c end) at (0,0); + \end{scope} + }, + reverse golden gnomon/.style={ + every Penrose pic/.try, + pic type=reverse golden gnomon, + }, +% \end{macrocode} +% The primary pentagon. +% \begin{macrocode} + pentagon 5/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@newedge{1}% + \if@newedge + \pgftransformrotate{180}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \test@newedge{2}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm}{0 cm}}% + \pgftransformrotate{108}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \test@newedge{3}% + \if@newedge + \pgftransformshift% + {\pgfpoint{\pr@phi * \pr@shphi cm}{- \pr@phi * \pr@chphi cm}}% + \pgftransformrotate{36}% + \else + \test@newedge{4}% + \if@newedge + \pgftransformshift{\pgfpoint{- \pr@shphi cm}{-\pr@chphi cm}}% + \pgftransformrotate{-36}% + \else + \test@newedge{5}% + \if@newedge + \pgftransformrotate{-108}% + \fi\fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every pentagon clip/.try, + every pentagon 5 clip/.try + ]{pentagon 5} + \UsePenroseTile[ + every Penrose tile/.try, + every pentagon/.try, + every pentagon 5/.try, + pic actions + ]{pentagon 5} +\coordinate (-edge a1 start) at (0,0); +\coordinate (-edge a1 end) at (1,0); +\coordinate (-edge a2 start) at (1,0); +\coordinate (-edge a2 end) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge a3 start) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge a3 end) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge a4 start) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge a4 end) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge a5 start) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge a5 end) at (0,0); + \end{scope} + }, + pentagon 5/.style={ + every Penrose pic/.try, + pic type=pentagon 5, + }, +% \end{macrocode} +% The secondary pentagon. +% \begin{macrocode} + pentagon 3/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@edgealign{a}% + \if@edgealign + \pgftransformrotate{180}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \test@edgealign{B}% + \if@edgealign% + \test@newedge{1}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm}{0 cm}}% + \pgftransformrotate{108}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \pgftransformrotate{-108}% + \fi + \else + \test@newedge{1}% + \if@newedge + \pgftransformshift% + {\pgfpoint{\pr@phi * \pr@shphi cm}{- \pr@phi * \pr@chphi cm}}% + \pgftransformrotate{36}% + \else + \pgftransformshift{\pgfpoint{- \pr@shphi cm}{-\pr@chphi cm}}% + \pgftransformrotate{-36}% + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every pentagon clip/.try, + every pentagon 3 clip/.try + ]{pentagon 3} + \UsePenroseTile[ + every Penrose tile/.try, + every pentagon/.try, + every pentagon 3/.try, + pic actions + ]{pentagon 3} +\coordinate (-edge A start) at (0,0); +\coordinate (-edge A end) at (1,0); +\coordinate (-edge b1 start) at (1,0); +\coordinate (-edge b1 end) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge a1 start) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge a1 end) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge a2 start) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge a2 end) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge b2 start) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge b2 end) at (0,0); + \end{scope} + }, + pentagon 3/.style={ + every Penrose pic/.try, + pic type=pentagon 3, + }, +% \end{macrocode} +% The tertiary pentagon. +% \begin{macrocode} + pentagon 2/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@edgealign{D}% + \if@edgealign + \pgftransformrotate{180}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \test@edgealign{a}% + \if@edgealign% + \test@newedge{1}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm}{0 cm}}% + \pgftransformrotate{108}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \pgftransformrotate{-108}% + \fi + \else + \test@newedge{1}% + \if@newedge + \pgftransformshift% + {\pgfpoint{\pr@phi * \pr@shphi cm}{- \pr@phi * \pr@chphi cm}}% + \pgftransformrotate{36}% + \else + \pgftransformshift{\pgfpoint{- \pr@shphi cm}{-\pr@chphi cm}}% + \pgftransformrotate{-36}% + \fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every pentagon clip/.try, + every pentagon 2 clip/.try + ]{pentagon 2} + \UsePenroseTile[ + every Penrose tile/.try, + every pentagon/.try, + every pentagon 2/.try, + pic actions + ]{pentagon 2} +\coordinate (-edge d start) at (0,0); +\coordinate (-edge d end) at (1,0); +\coordinate (-edge A1 start) at (1,0); +\coordinate (-edge A1 end) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge c1 start) at (1+\pr@shphi,\pr@chphi); +\coordinate (-edge c1 end) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge c2 start) at (\pr@cphi-\pr@shphi,\pr@sphi+\pr@chphi); +\coordinate (-edge c2 end) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge A2 start) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge A2 end) at (0,0); + \end{scope} + }, + pentagon 2/.style={ + every Penrose pic/.try, + pic type=pentagon 2, + }, +% \end{macrocode} +% The pentagram. +% \begin{macrocode} + pentagram/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@newedge{2}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm}{0 cm}}% + \pgftransformrotate{72}% + \else + \test@newedge{3}% + \if@newedge + \pgftransformrotate{-72}% + \pgftransformshift{\pgfpoint{2 * \pr@shphi cm}{0 cm}}% + \else + \test@newedge{4}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm + 2 * \pr@shphi cm}{0 cm}}% + \else + \test@newedge{5}% + \if@newedge + \pgftransformrotate{216}% + \pgftransformshift{\pgfpoint{\pr@cphi cm}{\pr@sphi cm}}% + \else + \test@newedge{6}% + \if@newedge + \pgftransformshift{\pgfpoint{1cm}{0cm}}% + \pgftransformrotate{-72}% + \pgftransformshift{\pgfpoint{\pr@cphi cm}{\pr@sphi cm}}% + \else + \test@newedge{7}% + \if@newedge + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{\pr@shphi cm}{\pr@chphi cm}}% + \else + \test@newedge{8}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm + 2*\pr@shphi cm}{0cm}}% + \pgftransformrotate{216}% + \pgftransformshift{\pgfpoint{\pr@cphi cm}{\pr@sphi cm}}% + \else + \test@newedge{9}% + \if@newedge + \pgftransformshift{\pgfpoint{-2*\pr@shphi cm}{0cm}}% + \pgftransformrotate{72}% + \else + \test@newedge{10}% + \if@newedge + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every pentagram clip/.try + ]{pentagram} + \UsePenroseTile[ + every Penrose tile/.try, + every pentagram/.try, + pic actions + ]{pentagram} +\coordinate (-edge C1 start) at (1,0); +\coordinate (-edge C1 end) at (0,0); +\coordinate (-edge C2 start) at (0,0); +\coordinate (-edge C2 end) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge C3 start) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge C3 end) at (-2*\pr@shphi,0); +\coordinate (-edge C4 start) at (-2*\pr@shphi,0); +\coordinate (-edge C4 end) at (-1-2*\pr@shphi,0); +\coordinate (-edge C5 start) at (-1-2*\pr@shphi,0); +\coordinate (-edge C5 end) at (-\pr@cphi,-\pr@sphi); +\coordinate (-edge C6 start) at (-\pr@cphi,-\pr@sphi); +\coordinate (-edge C6 end) at (-\pr@cphi-\pr@shphi,-\pr@sphi-\pr@chphi); +\coordinate (-edge C7 start) at (-\pr@cphi-\pr@shphi,-\pr@sphi-\pr@chphi); +\coordinate (-edge C7 end) at (-\pr@shphi,-\pr@chphi); +\coordinate (-edge C8 start) at (-\pr@shphi,-\pr@chphi); +\coordinate (-edge C8 end) at (1-\pr@cphi+\pr@shphi,-\pr@sphi-\pr@chphi); +\coordinate (-edge C9 start) at (1-\pr@cphi+\pr@shphi,-\pr@sphi-\pr@chphi); +\coordinate (-edge C9 end) at (1-\pr@cphi,-\pr@sphi); +\coordinate (-edge C10 start) at (1-\pr@cphi,-\pr@sphi); +\coordinate (-edge C10 end) at (1,0); + \end{scope} + }, + pentagram/.style={ + every Penrose pic/.try, + pic type=pentagram, + }, +% \end{macrocode} +% The boat. +% \begin{macrocode} + boat/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@edgealign{d}% + \if@edgealign + \pgftransformrotate{180}% + \pgftransformshift{\pgfpoint{\pr@cphi cm - 1cm}{\pr@sphi cm}}% + \else + \test@edgealign{b}% + \if@edgealign% + \test@newedge{2}% + \if@newedge + \pgftransformrotate{144}% + \pgftransformshift{\pgfpoint{-1 cm}{0 cm}}% + \else + \pgftransformrotate{216}% + \pgftransformshift{\pgfpoint{\pr@cphi cm}{\pr@sphi cm}}% + \fi + \else + \test@edgealign{c}% + \if@edgealign% + \test@newedge{2}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm}{0 cm}}% + \pgftransformrotate{72}% + \else + \test@newedge{3}% + \if@newedge + \pgftransformrotate{-72}% + \pgftransformshift{\pgfpoint{2 * \pr@shphi cm}{0 cm}}% + \else + \test@newedge{4}% + \if@newedge + \pgftransformshift{\pgfpoint{1 cm + 2 * \pr@shphi cm}{0 cm}}% + \else + \fi\fi\fi\fi\fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every boat clip/.try + ]{boat} + \UsePenroseTile[ + every Penrose tile/.try, + every boat/.try, + pic actions + ]{boat} +\coordinate (-edge C1 start) at (1,0); +\coordinate (-edge C1 end) at (0,0); +\coordinate (-edge C2 start) at (0,0); +\coordinate (-edge C2 end) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge C3 start) at (-\pr@shphi,\pr@chphi); +\coordinate (-edge C3 end) at (-2*\pr@shphi,0); +\coordinate (-edge C4 start) at (-2*\pr@shphi,0); +\coordinate (-edge C4 end) at (-1-2*\pr@shphi,0); +\coordinate (-edge B1 start) at (-1-2*\pr@shphi,0); +\coordinate (-edge B1 end) at (-\pr@cphi,-\pr@sphi); +\coordinate (-edge D start) at (-\pr@cphi,-\pr@sphi); +\coordinate (-edge D end) at (1-\pr@cphi,-\pr@sphi); +\coordinate (-edge B2 start) at (1-\pr@cphi,-\pr@sphi); +\coordinate (-edge B2 end) at (1,0); + \end{scope} + }, + boat/.style={ + every Penrose pic/.try, + pic type=boat, + }, +% \end{macrocode} +% The diamond. +% \begin{macrocode} + diamond/.pic={ + \begin{scope} + \pgfkeysgetvalue{/tikz/Penrose/alignment location}{\prloc} + \ifx\prloc\pgfutil@empty + \else + \begingroup + \tikzset{name prefix ..}% + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} start)% + \global\pgf@xa=\pgf@x + \global\pgf@ya=\pgf@y + \tikz@scan@one@point\pgfutil@firstofone% + (\prloc-edge \pgfkeysvalueof{/tikz/Penrose/alignment edge} end)% + \global\pgf@xb=\pgf@x + \global\pgf@yb=\pgf@y + \endgroup + \advance\pgf@xb by -\pgf@xa + \advance\pgf@yb by -\pgf@ya + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfpointnormalised{\pgfpoint{\pgf@xb}{\pgf@yb}} + \pgf@xb=\pgf@x + \pgf@yb=\pgf@y + \pgftransformtriangle% + {\pgfpoint{0pt}{0pt}}% + {\pgfpoint{\pgf@xb}{\pgf@yb}}% + {\pgfpoint{-\pgf@yb}{\pgf@xb}}% + \test@edgealign{d}% + \if@edgealign% + \test@newedge{2}% + \if@newedge + \pgftransformshift{\pgfpoint{1cm}{0cm}}% + \pgftransformrotate{-162}% + \else + \pgftransformrotate{-18}% + \fi + \else + \test@newedge{2}% + \if@newedge + \pgftransformrotate{162}% + \pgftransformshift{\pgfpoint{- 2 * \pr@chphi cm}{0cm}}% + \else + \pgftransformshift{\pgfpoint{- \pr@cphi cm}{-\pr@sphi cm}}% + \pgftransformrotate{18}% + \fi\fi + \fi + \UsePenroseTile[ + every Penrose tile clip/.try, + every diamond clip/.try + ]{diamond} + \UsePenroseTile[ + every Penrose tile/.try, + every diamond/.try, + pic actions + ]{diamond} +\coordinate (-edge D1 start) at (0,0); +\coordinate (-edge D1 end) at (\pr@chphi,\pr@shphi); +\coordinate (-edge B1 start) at (\pr@chphi,\pr@shphi); +\coordinate (-edge B1 end) at (2*\pr@chphi,0); +\coordinate (-edge B2 start) at (2*\pr@chphi,0); +\coordinate (-edge B2 end) at (\pr@chphi,-\pr@shphi); +\coordinate (-edge D2 start) at (\pr@chphi,-\pr@shphi); +\coordinate (-edge D2 end) at (0,0); + \end{scope} + }, + diamond/.style={ + every Penrose pic/.try, + pic type=diamond, + }, +} +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +%\Finale +\endinput diff --git a/obsolete/graphics/pgf/contrib/penrose/penrose_code.pdf b/obsolete/graphics/pgf/contrib/penrose/penrose_code.pdf Binary files differnew file mode 100644 index 0000000000..59579b2524 --- /dev/null +++ b/obsolete/graphics/pgf/contrib/penrose/penrose_code.pdf |