Penrose tiling: Difference between revisions

Added Fōrmulæ entry
(Scala contribution added.)
(Added Fōrmulæ entry)
 
(21 intermediate revisions by 12 users not shown)
Line 31:
* [http://preshing.com/20110831/penrose-tiling-explained/ Deflation explained for Kite and Dart, includes Python code (preshing.com)]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">
F penrose(depth)
print(‘<svg viewBox="-100 -100 200 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="A0" d="M 80.90169943749474 58.778525229247315 L 0 0 100 0" stroke="black" fill="#8bc" />
<path id="B0" d="M 0 0 80.90169943749474 58.778525229247315 161.80339887498948 0" stroke="black" fill="#97e" />’)
 
L(d) 0 .< depth
print(‘ <g id="A’(d + 1)‘" transform="translate(100, 0) scale(0.6180339887498949)">
<use href="#A’d‘" transform="rotate(108)" />
<use href="#B’d‘" transform="scale(-1, 1)" />
</g>
<g id="B’(d + 1)‘">
<use href="#A’(d + 1)‘" />
<use href="#B’d‘" transform="translate(100, 0) scale(0.6180339887498949) rotate(144) translate(-80.90169943749474,-58.778525229247315)"/>
</g>’)
 
print(‘ <g id="G">
<use href="#A’depth‘"/>
<use href="#A’depth‘" transform="scale(1, -1)" />
</g>
</defs>
<g transform="scale(2, 2)">
<use href="#G" transform="rotate(-144)" />
<use href="#G" transform="rotate(-72)" />
<use href="#G" transform="rotate(0)" />
<use href="#G" transform="rotate(72)" />
<use href="#G" transform="rotate(144)" />
</g>
</svg>’)
 
penrose(6)
</syntaxhighlight>
 
=={{header|C++}}==
{{trans|Nim}}
<syntaxhighlight lang="cpp">#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
 
int main() {
std::ofstream out("penrose_tiling.svg");
if (!out) {
std::cerr << "Cannot open output file.\n";
return EXIT_FAILURE;
}
std::string penrose("[N]++[N]++[N]++[N]++[N]");
for (int i = 1; i <= 4; ++i) {
std::string next;
for (char ch : penrose) {
switch (ch) {
case 'A':
break;
case 'M':
next += "OA++PA----NA[-OA----MA]++";
break;
case 'N':
next += "+OA--PA[---MA--NA]+";
break;
case 'O':
next += "-MA++NA[+++OA++PA]-";
break;
case 'P':
next += "--OA++++MA[+PA++++NA]--NA";
break;
default:
next += ch;
break;
}
}
penrose = std::move(next);
}
const double r = 30;
const double pi5 = 0.628318530717959;
double x = r * 8, y = r * 8, theta = pi5;
std::set<std::string> svg;
std::stack<std::tuple<double, double, double>> stack;
for (char ch : penrose) {
switch (ch) {
case 'A': {
double nx = x + r * std::cos(theta);
double ny = y + r * std::sin(theta);
std::ostringstream line;
line << std::fixed << std::setprecision(3) << "<line x1='" << x
<< "' y1='" << y << "' x2='" << nx << "' y2='" << ny << "'/>";
svg.insert(line.str());
x = nx;
y = ny;
} break;
case '+':
theta += pi5;
break;
case '-':
theta -= pi5;
break;
case '[':
stack.push({x, y, theta});
break;
case ']':
std::tie(x, y, theta) = stack.top();
stack.pop();
break;
}
}
out << "<svg xmlns='http://www.w3.org/2000/svg' height='" << r * 16
<< "' width='" << r * 16 << "'>\n"
<< "<rect height='100%' width='100%' fill='black'/>\n"
<< "<g stroke='rgb(255,165,0)'>\n";
for (const auto& line : svg)
out << line << '\n';
out << "</g>\n</svg>\n";
return EXIT_SUCCESS;
}</syntaxhighlight>
 
{{out}}
[[Media:Penrose tiling cpp.svg]]
 
=={{header|EasyLang}}==
[https://easylang.online/show/#cod=jVTLbqQwELz7K0oWymFbRpnMbm4c/RXIBwOexIoDCJMM8/er5jXOzKy0EkKmqlztbgr6oasR4iW6qUdw3y4gh51895lh+AouZqVBLgCcugEBY7eoGAFg2wwFpFwfWVNn8C3iONTvdoir18qvEo8CB8TR9XhZHNu92FUJwJ823BsUqLMfLMDFil0CwsHcKqrB2Q8cfsC5eLTkXp6SIhsVz7bfRmLbmc1FLuJo64+Sj1XCiH6bYzPY86aecIFt3xDaN+SLX/CtO/tmfMdzfmTgs/t2LBT/MT5/WhqWWl6PPYEK1F1E4wf84lpX7sJc9O0jjk+yFQbgwu6uEnfeqAru4l5HNzr6h65MdNvUngpMD9HLQ7Txw72vSXwDijlG6550PMUKBii8mHQ4KZMmh5vZuQRPCkAdr3j6DrfgcETWGPAIKkN0f5Ni/8Y4RtJKyFoTNVoppSpdqnpeWW2IJGQlIYmhRpczzCLDTC0hldVElS6JaDExSkI2zCgGiKwuqZlXlTa8V3KWICWM2H4Cr7efv7iN9Z9nvo6v+C3EXw== Run it]
 
<syntaxhighlight>
proc lsysexp level . axiom$ rules$[] .
for l to level
an$ = ""
for c$ in strchars axiom$
for i = 1 step 2 to len rules$[]
if rules$[i] = c$
c$ = rules$[i + 1]
break 1
.
.
an$ &= c$
.
swap axiom$ an$
.
.
stack[] = [ ]
proc lsysdraw axiom$ x y ang lng . .
linewidth 0.3
move x y
for c$ in strchars axiom$
if c$ = "E"
x += cos dir * lng
y += sin dir * lng
line x y
elif c$ = "-"
dir -= ang
elif c$ = "+"
dir += ang
elif c$ = "["
stack[] &= x
stack[] &= y
stack[] &= dir
elif c$ = "]"
l = len stack[]
x = stack[l - 2]
y = stack[l - 1]
dir = stack[l]
len stack[] -3
move x y
.
.
.
axiom$ = "[b]++[b]++[b]++[b]++[b]"
rules$[] = [ "a" "cE++dE----bE[-cE----aE]++" "b" "+cE--dE[---aE--bE]+" "c" "-aE++bE[+++cE++dE]-" "d" "--cE++++aE[+dE++++bE]--bE" "E" "" ]
lsysexp 6 axiom$ rules$[]
lsysdraw axiom$ 50 50 36 4
</syntaxhighlight>
 
=={{header|FreeBASIC}}==
{{trans|Phython}}
Not much of a FreeBASIC program: majority of this code is string literals that dumps an SVG on output.
<syntaxhighlight lang="vb">Sub penrose(depth As Integer)
Dim As String svg
svg = "<svg viewBox=""-100 -100 200 200"" xmlns=""http://www.w3.org/2000/svg"">" + !"\n"
svg &= " <defs>" + !"\n"
svg &= " <path id=""A0"" d=""M 80.90169943749474 58.778525229247315 L 0 0 100 0"" stroke=""black"" fill=""#8bc"" />" + !"\n"
svg &= " <path id=""B0"" d=""M 0 0 80.90169943749474 58.778525229247315 161.80339887498948 0"" stroke=""black"" fill=""#97e"" />" + !"\n"
For d As Integer = 0 To 5
svg &= " <g id=""A" : svg &= (d+1) : svg &= """ transform=""translate(100, 0) scale(0.6180339887498949)"">" + !"\n"
svg += " <use href=" & """" & "#A" & d & """ transform=""rotate(108)"" />" + !"\n"
svg &= " <use href=" & """" & "#B" & d & """ transform=""scale(-1, 1)"" />" + !"\n"
svg &= " </g>" + !"\n"
svg &= " <g id=""B" & d+1 & """>" + !"\n"
svg &= " <use href=" & """" & "#A" & d+1 & """ />" + !"\n"
svg &= " <use href=" & """" & "#B" & d & """ transform=""translate(100, 0) scale(0.6180339887498949) rotate(144) translate(-80.90169943749474,-58.778525229247315)""/>" + !"\n"
svg &= " </g>" + !"\n"
Next
svg &= " <g id=""G"">" + !"\n"
svg &= " <use href=""#A6""/>" + !"\n"
svg &= " <use href=""#A6"" transform=""scale(1, -1)"" />" + !"\n"
svg &= " </g>" + !"\n"
svg &= " </defs>" + !"\n"
svg &= " <g transform=""scale(2, 2)"">" + !"\n"
svg &= " <use href=""#G"" transform=""rotate(-144)"" />" + !"\n"
svg &= " <use href=""#G"" transform=""rotate(-72)"" />" + !"\n"
svg &= " <use href=""#G"" transform=""rotate(0)"" />" + !"\n"
svg &= " <use href=""#G"" transform=""rotate(72)"" />" + !"\n"
svg &= " <use href=""#G"" transform=""rotate(144)"" />" + !"\n"
svg &= " </g>" + !"\n"
svg &= "</svg>"
Print #1, svg
End Sub
 
Open "Penrose_tiling.svg" For Output As #1
penrose(6)
Close #1</syntaxhighlight>
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/L-system}}
 
'''Solution'''
 
It can be done using an [[wp:L-system|L-system]]. There are generic functions written in Fōrmulæ to compute an L-system in the page [[L-system#Fōrmulæ | L-system]].
 
The program that creates a Penrose tiling is:
 
[[File:Fōrmulæ - L-system - Penrose tiling 01.png]]
 
[[File:Fōrmulæ - L-system - Penrose tiling 02.png]]
 
=={{header|Go}}==
{{libheader|Go Graphics}}
{{trans|Java}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 143 ⟶ 379:
drawTiles(dc, tiles)
dc.SavePNG("penrose_tiling.png")
}</langsyntaxhighlight>
 
{{out}}
Line 149 ⟶ 385:
Image same as Java entry.
</pre>
 
=={{header|J}}==
{{trans|perl}}
<syntaxhighlight lang="j">require'format/printf'
penrosesvg=: {{
penrose=. rplc&(".{{)n
'A';'';
'M';'OA++PA----NA(-OA----MA)++';
'N';'+OA--PA(---MA--NA)+';
'O';'-MA++NA(+++OA++PA)-';
'P';'--OA++++MA(+PA++++NA)--NA'
}}-.LF)^:y '(N)++(N)++(N)++(N)++(N)'
LINE=. 2 2$0
A=. a=. o.%5
R=. 20
LINES=. STACK=. EMPTY
for_ch. penrose do.
select. ch
case. 'A' do. LINES=. LINES,,LINE=. (R*0,:2 1 o. A)+"1 {:LINE
case. '+' do. A=. A+a
case. '-' do. A=. A-a
case. '(' do. STACK=. STACK, A;LINE
case. ')' do. STACK=. }: STACK [ 'A LINE'=. {: STACK
end.
end.
OFF=. 25+>.>./,LINES=. ~.LINES
assert 1<(F=.'penrose_tiling_%d.svg' sprintf y) fwrite~ {{)n
<svg xmlns="http://www.w3.org/2000/svg" height="%d" width="%d">
<rect height="100%%" width="100%%" style="fill:black" />
%s
</svg>
}} sprintf (2#<2*OFF),<}:,{{)n
<line x1="%.1f" y1="%.1f" x2="%.1f" y2="%.1f" style="stroke:rgb(255,165,0)"/>
}} sprintf"1 OFF+LINES
(jpathsep 1!:43''),'/',F
}}</syntaxhighlight>
 
Example images (linked): [[j:File:Penrose_tiling_1.svg|<code>penrosesvg 1</code>]], [[j:File:Penrose_tiling_2.svg|<code>penrosesvg 2</code>]], [[j:File:Penrose_tiling_3.svg|<code>penrosesvg 3</code>]], [[j:File:Penrose_tiling_4.svg|<code>penrosesvg 4</code>]], [[j:File:Penrose_tiling_5.svg|<code>penrosesvg 5</code>]]
 
=={{header|Java}}==
[[File:Penrose_java.png|300px|thumb|right]]
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.awt.*;
import java.util.List;
import java.awt.geom.Path2D;
Line 291 ⟶ 565:
});
}
}</langsyntaxhighlight>
 
=={{header|jq}}==
'''Adapted from [[#Perl|Perl]]'''
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
The SVG viewBox parameters are computed dynamically.
<syntaxhighlight lang="jq">def pi: 4 * (1|atan);
 
def rules:
{A : "",
M : "OA++PA----NA[-OA----MA]++",
N : "+OA--PA[---MA--NA]+",
O : "-MA++NA[+++OA++PA]-",
P : "--OA++++MA[+PA++++NA]--NA",
"": "[N]++[N]++[N]++[N]++[N]" } ;
 
# Apply the rules
def penrose($count):
rules as $rules
| def repeat($count):
if $count <= 0 then .
else gsub("M";"m") | gsub("N";"n") | gsub("O";"o") | gsub("P";"p")
| gsub("A"; $rules["A"])
| gsub("m"; $rules["M"])
| gsub("n"; $rules["N"])
| gsub("o"; $rules["O"])
| gsub("p"; $rules["P"])
| repeat($count-1)
end;
$rules[""] | repeat($count) ;
 
# Update {svg, x, y, theta, stack, minx, maxx, miny, maxy}
def interpret($z):
def rnd: 1000*.|round/1000;
def minmax:
.minx = ([.minx, .x]|min)
| .miny = ([.miny, .y]|min)
| .maxx = ([.maxx, .x]|max)
| .maxy = ([.maxy, .y]|max) ;
 
if $z == "+" then .theta += pi/5
elif $z == "-" then .theta -= pi/5
elif $z == "[" then .stack += [ {x, y, theta} ]
elif $z == "]" then .stack[-1] as {$x, $y, $theta}
| .x = $x | .y = $y | .theta = $theta
| .stack |= .[:-1]
elif $z == "A"
then minmax
| .r as $r
|.svg += "<line x1='\(.x|rnd)' y1='\(.y|rnd)' "
| .x += $r * (.theta|cos)
| .y += $r * (.theta|sin)
| .svg += "x2='\(.x|rnd)' y2='\(.y|rnd)' "
| .svg += "style='stroke:rgb(255,165,0)'/>\n"
| minmax
else .
end ;
 
def penrose_tiling($n):
penrose($n)
| split("")
| reduce .[] as $action (
{x:160, y:160, theta: (pi/5), r: 20,
minx: infinite, miny: infinite,
maxx: -infinite, maxy: -infinite,
svg: "", stack: []};
interpret($action) ) ;
 
# viewBox = <min-x> <min-y> <width> <height>
# Input: {svg, minx, miny, maxx, maxy}
def svg:
([.minx, .miny] | min - 2 | floor) as $min
| ([.maxx - .minx, .maxy - .miny] | max + 2 | ceil) as $size
| "<svg viewBox=\"\($min) \($min) \($size) \($size)\" xmlns=\"http://www.w3.org/2000/svg\">",
.svg,
"</svg>";
 
penrose_tiling(5)
| svg</syntaxhighlight>
{{out}}
See https://imgur.com/gallery/UflFbPw
 
=={{header|Julia}}==
{{trans|Perl}}
<langsyntaxhighlight lang="julia">using Printf
 
function drawpenrose()
Line 334 ⟶ 690:
 
drawpenrose()
</syntaxhighlight>
</lang>
 
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
import java.awt.*
Line 472 ⟶ 827:
}
}
}</langsyntaxhighlight>
 
=={{header|Nim}}==
{{trans|Phix}}
This is a translation of the Lindenmayer Phix version translated itself from Perl.
<syntaxhighlight lang="nim">import math, strformat, tables
 
const Lindenmayer = {'A': "",
'M': "OA++PA----NA[-OA----MA]++",
'N': "+OA--PA[---MA--NA]+",
'O': "-MA++NA[+++OA++PA]-",
'P': "--OA++++MA[+PA++++NA]--NA"}.toTable
 
var penrose = "[N]++[N]++[N]++[N]++[N]"
 
for _ in 1..4:
var next = ""
for ch in penrose:
next.add Lindenmayer.getOrDefault(ch, $ch)
penrose = move(next)
 
var
x, y = 160.0
theta = PI / 5
r = 20.0
 
var svg = ""
var stack: seq[(float, float, float)]
 
for ch in penrose:
case ch
of 'A':
let (nx, ny) = (x + r * cos(theta), y + r * sin(theta))
svg.add &"<line x1='{x:.1f}' y1='{y:.1f}' x2='{nx:.1f}' y2='{ny:.1f}'"
svg.add " style='stroke:rgb(255,165,0)'/>\n"
(x, y) = (nx, ny)
of '+':
theta += PI / 5
of '-':
theta -= PI / 5
of '[':
stack.add (x, y, theta)
of ']':
(x, y, theta) = stack.pop()
else:
discard
 
let svgFile = "penrose_tiling.svg".open(fmWrite)
svgFile.write """
<svg xmlns="http://www.w3.org/2000/svg" height="350" width="350">
<rect height="100%%" width="100%%" style="fill:black" />
"""
svgFile.write svg, "</svg>"
svgFile.close()</syntaxhighlight>
 
{{out}}
Same output as Perl.
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use constant pi => 2 * atan2(1, 0);
 
# Generated with a P3 tile set using a Lindenmayer system.
Line 508 ⟶ 919:
open $fh, '>', 'penrose_tiling.svg';
print $fh qq{<svg xmlns="http://www.w3.org/2000/svg" height="350" width="350"> <rect height="100%" width="100%" style="fill:black" />\n$svg</svg>};
close $fh;</langsyntaxhighlight>
[https://github.com/SqrtNegInf/Rosettacode-Perl5-Smoke/blob/master/ref/penrose_tiling.svg Penrose tiling] (offsite image)
 
=={{header|Perl 6Phix}}==
Translation of the original Python code. Output can be toggled to look like the java or perl output.
{{works with|Rakudo|2018.05}}
{{libheader|Phix/pGUI}}
Generated with a P3 tile set using a Lindenmayer system.
{{libheader|Phix/online}}
You can run this online [http://phix.x10.mx/p2js/Penrose_tiling.htm here].
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Penrose_tiling.exw
-- ===============================
--
-- Resizeable. Press space to iterate/subdivide, C to toggle colour scheme
--</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">yellow_orange</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span> <span style="color: #000080;font-style:italic;">-- false = magenta on black, outlines only</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Penrose tiling"</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">golden_ratio</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">))</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">subdivide</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">colour</span>
<span style="color: #004080;">complex</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Q</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">R</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">colour</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">triangles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">colour</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- Subdivide orange triangle</span>
<span style="color: #000000;">P</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">complex_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">,</span><span style="color: #000000;">A</span><span style="color: #0000FF;">),</span><span style="color: #000000;">golden_ratio</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">else</span>
<span style="color: #000080;font-style:italic;">-- Subdivide yellow triangle</span>
<span style="color: #000000;">Q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">complex_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">,</span><span style="color: #000000;">B</span><span style="color: #0000FF;">),</span><span style="color: #000000;">golden_ratio</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">R</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">complex_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">complex_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span><span style="color: #000000;">B</span><span style="color: #0000FF;">),</span><span style="color: #000000;">golden_ratio</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">R</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Q</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">R</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">R</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Q</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">initial_wheel</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">-- Create an initial wheel of yellow triangles around the origin</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">triangles</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">complex</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">phi</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">phi</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span>
<span style="color: #000000;">B</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">phi</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">phi</span><span style="color: #0000FF;">)}</span>
<span style="color: #000000;">phi</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span>
<span style="color: #000000;">C</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">phi</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">phi</span><span style="color: #0000FF;">)}</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- mirror every second triangle</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">triangles</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">subdivide</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ... and iterate once</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">triangles</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">initial_wheel</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">hw</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">draw_one</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">triangle</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">colour</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">yellow_orange</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">colour</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">cdCanvasBegin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">triangle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">cdCanvasVertex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">hw</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">h</span><span style="color: #0000FF;">+</span><span style="color: #000000;">hh</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">cdCanvasEnd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">hw</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hh</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_floor_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hw</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hh</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">yellow_orange</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_BLACK</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_MAGENTA</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">triangle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">triangles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">yellow_orange</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">colour</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]?</span><span style="color: #004600;">CD_ORANGE</span><span style="color: #0000FF;">:</span><span style="color: #004600;">CD_YELLOW</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">draw_one</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">colour</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_FILL</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">draw_one</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangle</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_DARK_GREY</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_CLOSED_LINES</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">6100</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- sane limit</span>
<span style="color: #000000;">triangles</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">subdivide</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">title</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" (sane limit reached)"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)=</span><span style="color: #008000;">'C'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">yellow_orange</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">yellow_orange</span>
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RASTERSIZE=600x600"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallbacks</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">),</span>
<span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">`TITLE="%s"`</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">title</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"KEY_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- release the minimum limitation</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
 
=== Lindenmayer/svg ===
<lang perl6>use SVG;
{{trans|Perl}} Same output, obviously the resulting file can be opened in a separate browser.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">Lindenmayer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">'M'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"OA++PA----NA[-OA----MA]++"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">'N'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+OA--PA[---MA--NA]+"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">'O'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-MA++NA[+++OA++PA]-"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">'P'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"--OA++++MA[+PA++++NA]--NA"</span><span style="color: #0000FF;">}})</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">penrose</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"[N]++[N]++[N]++[N]++[N]"</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">next</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">penrose</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">penrose</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Lindenmayer</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">next</span> <span style="color: #0000FF;">&=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">?</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">:</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">penrose</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">160</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">160</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">theta</span><span style="color: #0000FF;">=</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">20</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">svg</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"&lt;line x1='%.1f' y1='%.1f' x2='%.1f' y2='%.1f' style='stroke:rgb(255,165,0)'/&gt;\n"</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">penrose</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">penrose</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">ch</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'A'</span><span style="color: #0000FF;">:</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">nx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">theta</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ny</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">theta</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">svg</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">})</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'+'</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">theta</span> <span style="color: #0000FF;">+=</span> <span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'-'</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">theta</span> <span style="color: #0000FF;">-=</span> <span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'['</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">theta</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">']'</span><span style="color: #0000FF;">:</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">theta</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">svgfmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
&lt;svg xmlns="http://www.w3.org/2000/svg" height="350" width="350"&gt;
&lt;rect height="100%%" width="100%%" style="fill:black" /&gt;
%s
&lt;/svg&gt;"""</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"penrose_tiling.svg"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"w"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">svgfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">svg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|Processing}}==
role Lindenmayer {
===LSystem===
has %.rules;
<syntaxhighlight lang="java">
method succ {
class LSystem
self.comb.map( { %!rules{$^c} // $c } ).join but Lindenmayer(%!rules)
{
int steps = 0;
 
String axiom;
String rule;
String production;
 
float startLength;
float drawLength;
float theta;
 
int generations;
 
LSystem() {
axiom = "F";
rule = "F+F-F";
startLength = 190.0;
theta = radians(120.0);
reset();
}
 
void reset() {
production = axiom;
drawLength = startLength;
generations = 0;
}
 
int getAge() {
return generations;
}
 
void render() {
translate(width/2, height/2);
steps += 5;
if (steps > production.length()) {
steps = production.length();
}
for (int i = 0; i < steps; i++) {
}
char step = production.charAt(i);
if (step == 'F') {
rect(0, 0, -drawLength, -drawLength);
noFill();
translate(0, -drawLength);
}
else if (step == '+') {
rotate(theta);
}
else if (step == '-') {
rotate(-theta);
}
else if (step == '[') {
pushMatrix();
}
else if (step == ']') {
popMatrix();
}
}
}
 
void simulate(int gen) {
my $penrose = '[N]++[N]++[N]++[N]++[N]' but Lindenmayer(
while (getAge() < gen) {
{
Aproduction => ''iterate(production, rule);
M => 'OA++PA----NA[-OA----MA]++',
N => '+OA--PA[---MA--NA]+',
O => '-MA++NA[+++OA++PA]-',
P => '--OA++++MA[+PA++++NA]--NA'
}
}
);
 
String iterate(String prod_, String rule_) {
$penrose++ xx 4;
drawLength = drawLength * 0.6;
generations++;
String newProduction = prod_;
newProduction = newProduction.replaceAll("F", rule_);
return newProduction;
}
}
</syntaxhighlight>
===PenroseLSystem===
<syntaxhighlight lang="java">
class PenroseLSystem extends LSystem {
 
int steps = 0;
my @lines;
float somestep = 0.1;
my @stack;
String ruleW;
String ruleX;
String ruleY;
String ruleZ;
 
PenroseLSystem() {
for $penrose.comb {
axiom = "[X]++[X]++[X]++[X]++[X]";
state ($x, $y) = 300, 200;
state $druleW = 55 "YF+ 0i+ZF4-XF[-YF4-WF]++";
ruleX = "+YF--ZF[3-WF--XF]+";
when 'A' { @lines.push: 'line' => [:x1($x.round(.01)), :y1($y.round(.01)), :x2(($x += $d.re).round(.01)), :y2(($y += $d.im).round(.01))] }
ruleY = "-WF++XF[+++YF++ZF]-";
when '[' { @stack.push: ($x.clone, $y.clone, $d.clone) }
ruleZ = "--YF++++WF[+ZF++++XF]--XF";
when ']' { ($x, $y, $d) = @stack.pop }
startLength = 460.0;
when '+' { $d *= cis -π/5 }
whentheta '-' { $d *= cis radians(36); π/5 }
default { }reset();
}
 
void useRule(String r_) {
say SVG.serialize(
svgrule => [r_;
}
:600width, :400height, :style<stroke:rgb(250,12,210)>,
:rect[:width<100%>, :height<100%>, :fill<black>],
|@lines,
],
);</lang>
See: [https://github.com/thundergnat/rc/blob/master/img/penrose-perl6.svg Penrose tiling image]
 
void useAxiom(String a_) {
=={{header|Phix}}==
axiom = a_;
{{libheader|pGUI}}
}
Translation of the original Python code
<lang Phix>-- demo\rosetta\Penrose_tiling.exw
-- Resizeable. Press space to iterate/subdivide, C to toggle colour scheme
bool yellow_orange = true -- false = magenta on black, outlines only
 
void useLength(float l_) {
include pGUI.e
startLength = l_;
}
 
void useTheta(float t_) {
Ihandle dlg, canvas
theta = radians(t_);
cdCanvas cddbuffer, cdcanvas
}
 
void reset() {
include builtins\complex.e
production = axiom;
drawLength = startLength;
constant golden_ratio = (1 + sqrt(5)) / 2
generations = 0;
}
 
int getAge() {
function subdivide(sequence triangles)
return generations;
sequence result = {}
}
integer colour
complex A, B, C, P, Q, R
for i=1 to length(triangles) do
{colour, A, B, C} = triangles[i]
if colour == 0 then
-- Subdivide orange triangle
P = complex_add(A,complex_div(complex_sub(B,A),golden_ratio))
result &= {{0, C, P, B}, {1, P, C, A}}
else
-- Subdivide yellow triangle
Q = complex_add(B,complex_div(complex_sub(A,B),golden_ratio))
R = complex_add(B,complex_div(complex_sub(C,B),golden_ratio))
result &= {{1, R, C, A}, {1, Q, R, B}, {0, R, Q, A}}
end if
end for
return result
end function
 
void render() {
function initial_wheel()
translate(width/2, height/2);
-- Create an initial wheel of yellow triangles around the origin
sequenceint trianglespushes = {}0;
complexint B,repeats C= 1;
steps += 12;
atom phi
if (steps > production.length()) {
for i=0 to 9 do
phisteps = production.length(2*i-1)*PI/10;
}
B = {cos(phi),sin(phi)}
phi = (2*i+1)*PI/10
C = {cos(phi),sin(phi)}
if mod(i,2)==0 then
{B, C} = {C, B} -- mirror every second triangle
end if
triangles &= {{0, {0,0}, B, C}}
end for
return subdivide(triangles) -- ... and iterate once
end function
 
for (int i = 0; i < steps; i++) {
sequence triangles = initial_wheel()
char step = production.charAt(i);
if (step == 'F') {
stroke(255, 60);
for (int j = 0; j < repeats; j++) {
line(0, 0, 0, -drawLength);
noFill();
translate(0, -drawLength);
}
repeats = 1;
}
else if (step == '+') {
for (int j = 0; j < repeats; j++) {
rotate(theta);
}
repeats = 1;
}
else if (step == '-') {
for (int j =0; j < repeats; j++) {
rotate(-theta);
}
repeats = 1;
}
else if (step == '[') {
pushes++;
pushMatrix();
}
else if (step == ']') {
popMatrix();
pushes--;
}
else if ( (step >= 48) && (step <= 57) ) {
repeats = (int)step - 48;
}
}
 
// Unpush if we need too
integer hw, hh, h
while (pushes > 0) {
popMatrix();
pushes--;
}
}
 
String iterate(String prod_, String rule_) {
procedure draw_one(sequence triangle, integer colour, mode)
String newProduction = "";
if yellow_orange then
for (int i = 0; i < prod_.length(); i++) {
cdCanvasSetForeground(cddbuffer, colour)
char step = production.charAt(i);
end if
if (step == 'W') {
cdCanvasBegin(cddbuffer, mode)
newProduction = newProduction + ruleW;
for i=2 to 4 do
atom {x,y} = triangle[i]
else if cdCanvasVertex(cddbuffer,step x*h+hw,== y*h+hh'X') {
newProduction = newProduction + ruleX;
end for
}
cdCanvasEnd(cddbuffer)
else if (step == 'Y') {
end procedure
newProduction = newProduction + ruleY;
}
else if (step == 'Z') {
newProduction = newProduction + ruleZ;
}
else {
if (step != 'F') {
newProduction = newProduction + step;
}
}
}
 
drawLength = drawLength * 0.5;
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
generations++;
{hw, hh} = sq_floor_div(IupGetIntInt(canvas, "DRAWSIZE"),2)
return newProduction;
h = min(hw,hh)
}
if yellow_orange then
cdCanvasSetBackground(cddbuffer, CD_WHITE)
else
cdCanvasSetBackground(cddbuffer, CD_BLACK)
cdCanvasSetForeground(cddbuffer, CD_MAGENTA)
end if
cdCanvasActivate(cddbuffer)
cdCanvasClear(cddbuffer)
for i=1 to length(triangles) do
sequence triangle = triangles[i]
if yellow_orange then
integer colour = iff(triangle[1]?CD_ORANGE:CD_YELLOW)
draw_one(triangle,colour,CD_FILL)
end if
draw_one(triangle,CD_DARK_GREY,CD_CLOSED_LINES)
end for
cdCanvasFlush(cddbuffer)
return IUP_DEFAULT
end function
 
}
function map_cb(Ihandle ih)
</syntaxhighlight>
cdcanvas = cdCreateCanvas(CD_IUP, ih)
===PenroseTile===
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
<syntaxhighlight lang="java">
return IUP_DEFAULT
PenroseLSystem ds;
end function
 
void setup() {
function esc_close(Ihandle /*ih*/, atom c)
size(1000, 1000);
if c=K_ESC then return IUP_CLOSE end if
ds = new PenroseLSystem();
if c=' ' then
ds.simulate(5);
triangles = subdivide(triangles)
}
IupUpdate(canvas)
elsif upper(c)='C' then
yellow_orange = not yellow_orange
IupUpdate(canvas)
end if
return IUP_CONTINUE
end function
 
void draw() {
procedure main()
IupOpenbackground(0);
ds.render();
}
canvas = IupCanvas(NULL)
</syntaxhighlight>
IupSetAttribute(canvas, "RASTERSIZE", "600x600") -- initial size
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
 
=={{header|Python}}==
dlg = IupDialog(canvas)
Not much of a python program: majority of this code is string literals that dumps an SVG on output.
IupSetAttribute(dlg, "TITLE", "Penrose tiling")
<syntaxhighlight lang="python">def penrose(depth):
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
print('''<svg viewBox="-100 -100 200 200" xmlns="http://www.w3.org/2000/svg">
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
<defs>
<path id="A0" d="M 80.90169943749474 58.778525229247315 L 0 0 100 0" stroke="black" fill="#8bc" />
<path id="B0" d="M 0 0 80.90169943749474 58.778525229247315 161.80339887498948 0" stroke="black" fill="#97e" />''')
 
IupMapfor d in range(dlgdepth):
print(f''' <g id="A{d+1}" transform="translate(100, 0) scale(0.6180339887498949)">
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
<use href="#A{d}" transform="rotate(108)" />
IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
<use href="#B{d}" transform="scale(-1, 1)" />
IupMainLoop()
</g>
IupClose()
<g id="B{d+1}">
end procedure
<use href="#A{d+1}" />
main()</lang>
<use href="#B{d}" transform="translate(100, 0) scale(0.6180339887498949) rotate(144) translate(-80.90169943749474,-58.778525229247315)"/>
Output can be toggled to look like the java or perl output
</g>''')
 
print(f''' <g id="G">
<use href="#A{d+1}"/>
<use href="#A{d+1}" transform="scale(1, -1)" />
</g>
</defs>
<g transform="scale(2, 2)">
<use href="#G" transform="rotate(-144)" />
<use href="#G" transform="rotate(-72)" />
<use href="#G" transform="rotate(0)" />
<use href="#G" transform="rotate(72)" />
<use href="#G" transform="rotate(144)" />
</g>
</svg>''')
 
penrose(6)</syntaxhighlight>
 
=={{header|Racket}}==
Line 695 ⟶ 1,374:
{{trans|Perl}}
 
<langsyntaxhighlight lang="racket">#lang racket
(require racket/draw)
Line 732 ⟶ 1,411:
target)
(make-curve 500 4 20 80 (make-color 255 255 0) (make-color 0 0 0))</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.05}}
Generated with a P3 tile set using a Lindenmayer system.
 
<syntaxhighlight lang="raku" line>use SVG;
 
role Lindenmayer {
has %.rules;
method succ {
self.comb.map( { %!rules{$^c} // $c } ).join but Lindenmayer(%!rules)
}
}
 
my $penrose = '[N]++[N]++[N]++[N]++[N]' but Lindenmayer(
{
A => '',
M => 'OA++PA----NA[-OA----MA]++',
N => '+OA--PA[---MA--NA]+',
O => '-MA++NA[+++OA++PA]-',
P => '--OA++++MA[+PA++++NA]--NA'
}
);
 
$penrose++ xx 4;
 
my @lines;
my @stack;
 
for $penrose.comb {
state ($x, $y) = 300, 200;
state $d = 55 + 0i;
when 'A' { @lines.push: 'line' => [:x1($x.round(.01)), :y1($y.round(.01)), :x2(($x += $d.re).round(.01)), :y2(($y += $d.im).round(.01))] }
when '[' { @stack.push: ($x.clone, $y.clone, $d.clone) }
when ']' { ($x, $y, $d) = @stack.pop }
when '+' { $d *= cis -π/5 }
when '-' { $d *= cis π/5 }
default { }
}
 
say SVG.serialize(
svg => [
:600width, :400height, :style<stroke:rgb(250,12,210)>,
:rect[:width<100%>, :height<100%>, :fill<black>],
|@lines,
],
);</syntaxhighlight>
See: [https://github.com/thundergnat/rc/blob/master/img/penrose-perl6.svg Penrose tiling image]
 
=={{header|Scala}}==
Line 738 ⟶ 1,466:
{{libheader|Scala Java Swing interoperability}}
{{works with|Scala|2.13}}
<langsyntaxhighlight Scalalang="scala">import java.awt.{BorderLayout, Color, Dimension, Graphics, Graphics2D, RenderingHints}
import java.awt.geom.Path2D
 
Line 828 ⟶ 1,556:
}
 
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
Using the LSystem class defined at [https://rosettacode.org/wiki/Hilbert_curve#Sidef Hilbert curve].
<langsyntaxhighlight lang="ruby">var rules = Hash(
a => 'cE++dE----bE[-cE----aE]++',
b => '+cE--dE[---aE--bE]+',
Line 852 ⟶ 1,581:
)
 
lsys.execute('[b]++[b]++[b]++[b]++[b]', 5, "penrose_tiling.png", rules)</langsyntaxhighlight>
 
Output image: [https://github.com/trizen/rc/blob/master/img/penrose-tiling-sidef.png Penrose tiling]
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|DOME}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-set}}
{{libheader|Wren-polygon}}
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color
import "dome" for Window
import "math" for Math
import "./dynamic" for Enum, Tuple
import "./set" for Set
import "./polygon" for Polygon
 
var Type = Enum.create("Type", ["KITE", "DART"])
 
var Tile = Tuple.create("Tile", ["type", "x", "y", "angle", "size"])
 
var DistinctTiles = Fn.new { |tiles|
var tileStr = tiles.map { |t| t.toString }.toList
var tileSet = Set.new(tileStr)
var tileDst = []
for (tile in tiles) {
var str = tile.toString
if (tileSet.contains(str)) {
tileDst.add(tile)
tileSet.remove(str)
}
}
return tileDst
}
 
var Radians = Fn.new { |d| d * Num.pi / 180 }
 
var G = (1 + 5.sqrt) / 2 // golden ratio
var T = Radians.call(36) // theta
 
class PenroseTiling {
construct new(width, height) {
Window.title = "Penrose Tiling"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
}
 
init() {
var tiles = deflateTiles_(setupPrototiles_(_w, _h), 5)
drawTiles(tiles)
}
 
setupPrototiles_(w, h) {
var proto = []
var a = Num.pi / 2 + T
while (a < 3 * Num.pi) {
proto.add(Tile.new(Type.KITE, w / 2, h / 2, a, w / 2.5))
a = a + 2 * T
}
return proto
}
 
deflateTiles_(tiles, generation) {
if (generation <= 0) return tiles
var next = []
for (tile in tiles) {
var x = tile.x
var y = tile.y
var a = tile.angle
var nx
var ny
var size = tile.size / G
if (tile.type == Type.DART) {
next.add(Tile.new(Type.KITE, x, y, a + 5 * T, size))
var sign = 1
for (i in 0..1) {
nx = x + Math.cos(a - 4 * T * sign) * G * tile.size
ny = y - Math.sin(a - 4 * T * sign) * G * tile.size
next.add(Tile.new(Type.DART, nx, ny, a - 4 * T * sign, size))
sign = -sign
}
} else {
var sign = 1
for (i in 0..1) {
next.add(Tile.new(Type.DART, x, y, a - 4 * T * sign, size))
nx = x + Math.cos(a - T * sign) * G * tile.size
ny = y - Math.sin(a - T * sign) * G * tile.size
next.add(Tile.new(Type.KITE, nx, ny, a + 3 * T * sign, size))
sign = -sign
}
}
}
// remove duplicates and deflate
return deflateTiles_(DistinctTiles.call(next), generation - 1)
}
 
drawTiles(tiles) {
var dist = [ [G, G, G], [-G, -1, -G] ]
for (tile in tiles) {
var angle = tile.angle - T
var x0 = tile.x
var y0 = tile.y
var ord = tile.type
var vertices = [[x0, y0]]
for (i in 0..2) {
var x1 = tile.x + dist[ord][i] * tile.size * Math.cos(angle)
var y1 = tile.y - dist[ord][i] * tile.size * Math.sin(angle)
vertices.add([x1, y1])
angle = angle + T
x0 = x1
y0 = y1
}
var poly = Polygon.quick(vertices)
poly.drawfill((ord == 0) ? Color.orange : Color.yellow)
poly.draw(Color.darkgray)
}
}
 
update() {}
 
draw(alpha) {}
}
 
var Game = PenroseTiling.new(700, 450)</syntaxhighlight>
2,120

edits