Penrose tiling: Difference between revisions

Added Fōrmulæ entry
(added Penrose tiling draft task)
 
(Added Fōrmulæ entry)
 
(42 intermediate revisions by 18 users not shown)
Line 3:
 
There are many tile sets that can create non-periodic tilings, but those can typically also be used to create a periodic
tiling. What makes Penrose tiles special is that they ''can only be used to produce non-periodic tilings''.
<br><br>
[[File:Penrose_tilesets.png]]
Line 10:
 
These so-called prototiles are usually depicted with smooth edges, but in reality Penrose tiles have interlocking tabs
and cut-outs like the pieces of a Jigsawjigsaw puzzle. For convenience these deformations are often replaced
with ''matching rules'', which ensure that the tiles are only connected in ways that guarantee
a non-periodic tiling. (Otherwise, for instance, you could combine the kite and dart to form a rhombus,
Line 20:
have a self-similarity on different levels. When zooming out it can be observed that groups of tiles are enclosed in areas that
form exactly the same pattern as the tiles on the lower level. Departing from an inflated level, the prototiles can be
subdivided into smaller tiles, always observing the matching rules. IfThe donesubdivision correctlymay ithave willto alwaysbe fitrepeated several times, before the desired level of detail is reached. This process is called deflation.
The subdivision may have to repeated several times, before you reach the desired level of detail.
This process is called deflation.
 
More information can be found through the links below.
 
'''The task''': fill a rectangular area with a Penrose tiling.
<br><br>
 
;See also:
* [http://www.ams.org/samplings/feature-column/fcarc-penrose| A good introduction (ams.org)]
* [http://tartarus.org/simon/20110412-penrose/penrose.xhtml| Deflation explained for both sets (tartarus.org)]
* [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}}
<syntaxhighlight lang="go">package main
 
import (
"github.com/fogleman/gg"
"math"
)
 
type tiletype int
 
const (
kite tiletype = iota
dart
)
 
type tile struct {
tt tiletype
x, y float64
angle, size float64
}
 
var gr = (1 + math.Sqrt(5)) / 2 // golden ratio
 
const theta = math.Pi / 5 // 36 degrees in radians
 
func setupPrototiles(w, h int) []tile {
var proto []tile
// sun
for a := math.Pi/2 + theta; a < 3*math.Pi; a += 2 * theta {
ww := float64(w / 2)
hh := float64(h / 2)
proto = append(proto, tile{kite, ww, hh, a, float64(w) / 2.5})
}
return proto
}
 
func distinctTiles(tls []tile) []tile {
tileset := make(map[tile]bool)
for _, tl := range tls {
tileset[tl] = true
}
distinct := make([]tile, len(tileset))
for tl, _ := range tileset {
distinct = append(distinct, tl)
}
return distinct
}
 
func deflateTiles(tls []tile, gen int) []tile {
if gen <= 0 {
return tls
}
var next []tile
for _, tl := range tls {
x, y, a, size := tl.x, tl.y, tl.angle, tl.size/gr
var nx, ny float64
if tl.tt == dart {
next = append(next, tile{kite, x, y, a + 5*theta, size})
for i, sign := 0, 1.0; i < 2; i, sign = i+1, -sign {
nx = x + math.Cos(a-4*theta*sign)*gr*tl.size
ny = y - math.Sin(a-4*theta*sign)*gr*tl.size
next = append(next, tile{dart, nx, ny, a - 4*theta*sign, size})
}
} else {
for i, sign := 0, 1.0; i < 2; i, sign = i+1, -sign {
next = append(next, tile{dart, x, y, a - 4*theta*sign, size})
nx = x + math.Cos(a-theta*sign)*gr*tl.size
ny = y - math.Sin(a-theta*sign)*gr*tl.size
next = append(next, tile{kite, nx, ny, a + 3*theta*sign, size})
}
}
}
// remove duplicates
tls = distinctTiles(next)
return deflateTiles(tls, gen-1)
}
 
func drawTiles(dc *gg.Context, tls []tile) {
dist := [2][3]float64{{gr, gr, gr}, {-gr, -1, -gr}}
for _, tl := range tls {
angle := tl.angle - theta
dc.MoveTo(tl.x, tl.y)
ord := tl.tt
for i := 0; i < 3; i++ {
x := tl.x + dist[ord][i]*tl.size*math.Cos(angle)
y := tl.y - dist[ord][i]*tl.size*math.Sin(angle)
dc.LineTo(x, y)
angle += theta
}
dc.ClosePath()
if ord == kite {
dc.SetHexColor("FFA500") // orange
} else {
dc.SetHexColor("FFFF00") // yellow
}
dc.FillPreserve()
dc.SetHexColor("A9A9A9") // dark gray
dc.SetLineWidth(1)
dc.Stroke()
}
}
 
func main() {
w, h := 700, 450
dc := gg.NewContext(w, h)
dc.SetRGB(1, 1, 1)
dc.Clear()
tiles := deflateTiles(setupPrototiles(w, h), 5)
drawTiles(dc, tiles)
dc.SavePNG("penrose_tiling.png")
}</syntaxhighlight>
 
{{out}}
<pre>
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}}
<syntaxhighlight lang="java">import java.awt.*;
import java.util.List;
import java.awt.geom.Path2D;
import java.util.*;
import javax.swing.*;
import static java.lang.Math.*;
import static java.util.stream.Collectors.toList;
 
public class PenroseTiling extends JPanel {
// ignores missing hash code
class Tile {
double x, y, angle, size;
Type type;
 
Tile(Type t, double x, double y, double a, double s) {
type = t;
this.x = x;
this.y = y;
angle = a;
size = s;
}
 
@Override
public boolean equals(Object o) {
if (o instanceof Tile) {
Tile t = (Tile) o;
return type == t.type && x == t.x && y == t.y && angle == t.angle;
}
return false;
}
}
 
enum Type {
Kite, Dart
}
 
static final double G = (1 + sqrt(5)) / 2; // golden ratio
static final double T = toRadians(36); // theta
 
List<Tile> tiles = new ArrayList<>();
 
public PenroseTiling() {
int w = 700, h = 450;
setPreferredSize(new Dimension(w, h));
setBackground(Color.white);
 
tiles = deflateTiles(setupPrototiles(w, h), 5);
}
 
List<Tile> setupPrototiles(int w, int h) {
List<Tile> proto = new ArrayList<>();
 
// sun
for (double a = PI / 2 + T; a < 3 * PI; a += 2 * T)
proto.add(new Tile(Type.Kite, w / 2, h / 2, a, w / 2.5));
 
return proto;
}
 
List<Tile> deflateTiles(List<Tile> tls, int generation) {
if (generation <= 0)
return tls;
 
List<Tile> next = new ArrayList<>();
 
for (Tile tile : tls) {
double x = tile.x, y = tile.y, a = tile.angle, nx, ny;
double size = tile.size / G;
 
if (tile.type == Type.Dart) {
next.add(new Tile(Type.Kite, x, y, a + 5 * T, size));
 
for (int i = 0, sign = 1; i < 2; i++, sign *= -1) {
nx = x + cos(a - 4 * T * sign) * G * tile.size;
ny = y - sin(a - 4 * T * sign) * G * tile.size;
next.add(new Tile(Type.Dart, nx, ny, a - 4 * T * sign, size));
}
 
} else {
 
for (int i = 0, sign = 1; i < 2; i++, sign *= -1) {
next.add(new Tile(Type.Dart, x, y, a - 4 * T * sign, size));
 
nx = x + cos(a - T * sign) * G * tile.size;
ny = y - sin(a - T * sign) * G * tile.size;
next.add(new Tile(Type.Kite, nx, ny, a + 3 * T * sign, size));
}
}
}
// remove duplicates
tls = next.stream().distinct().collect(toList());
 
return deflateTiles(tls, generation - 1);
}
 
void drawTiles(Graphics2D g) {
double[][] dist = {{G, G, G}, {-G, -1, -G}};
for (Tile tile : tiles) {
double angle = tile.angle - T;
Path2D path = new Path2D.Double();
path.moveTo(tile.x, tile.y);
 
int ord = tile.type.ordinal();
for (int i = 0; i < 3; i++) {
double x = tile.x + dist[ord][i] * tile.size * cos(angle);
double y = tile.y - dist[ord][i] * tile.size * sin(angle);
path.lineTo(x, y);
angle += T;
}
path.closePath();
g.setColor(ord == 0 ? Color.orange : Color.yellow);
g.fill(path);
g.setColor(Color.darkGray);
g.draw(path);
}
}
 
@Override
public void paintComponent(Graphics og) {
super.paintComponent(og);
Graphics2D g = (Graphics2D) og;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawTiles(g);
}
 
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Penrose Tiling");
f.setResizable(false);
f.add(new PenroseTiling(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}</syntaxhighlight>
 
=={{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}}
<syntaxhighlight lang="julia">using Printf
 
function drawpenrose()
lindenmayer_rules = Dict("A" => "",
"M" => "OA++PA----NA[-OA----MA]++", "N" => "+OA--PA[---MA--NA]+",
"O" => "-MA++NA[+++OA++PA]-", "P" => "--OA++++MA[+PA++++NA]--NA")
 
rul(x) = lindenmayer_rules[x]
 
penrose = replace(replace(replace(replace("[N]++[N]++[N]++[N]++[N]",
r"[AMNOP]" => rul), r"[AMNOP]" => rul), r"[AMNOP]" => rul), r"[AMNOP]" => rul)
 
x, y, theta, r, svglines, stack = 160, 160, π / 5, 20.0, String[], Vector{Real}[]
 
for c in split(penrose, "")
if c == "A"
xx, yy = x + r * cos(theta), y + r * sin(theta)
line = @sprintf("<line x1='%.1f' y1='%.1f' x2='%.1f' y2='%.1f' style='stroke:rgb(255,165,0)'/>\n", x, y, xx, yy)
x, y = xx, yy
push!(svglines, line)
elseif c == "+"
theta += π / 5
elseif c == "-"
theta -= π / 5
elseif c == "["
push!(stack, [x, y, theta])
elseif c == "]"
x, y, theta = pop!(stack)
end
end
 
svg = join(unique(svglines), "\n")
fp = open("penrose_tiling.svg", "w")
write(fp, """<svg xmlns="http://www.w3.org/2000/svg" height="350" width="350"> <rect height="100%" """ *
"""width="100%" style="fill:black" />""" * "\n$svg</svg>")
close(fp)
end
 
drawpenrose()
</syntaxhighlight>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">// version 1.1.2
 
import java.awt.*
import java.awt.geom.Path2D
import javax.swing.*
 
class PenroseTiling(w: Int, h: Int) : JPanel() {
private enum class Type {
KITE, DART
}
 
private class Tile(
val type: Type,
val x: Double,
val y: Double,
val angle: Double,
val size: Double
) {
override fun equals(other: Any?): Boolean {
if (other == null || other !is Tile) return false
return type == other.type && x == other.x && y == other.y &&
angle == other.angle && size == other.size
}
}
 
private companion object {
val G = (1.0 + Math.sqrt(5.0)) / 2.0 // golden ratio
val T = Math.toRadians(36.0) // theta
}
 
private val tiles: List<Tile>
 
init {
preferredSize = Dimension(w, h)
background = Color.white
tiles = deflateTiles(setupPrototiles(w, h), 5)
}
 
private fun setupPrototiles(w: Int, h: Int): List<Tile> {
val proto = mutableListOf<Tile>()
var a = Math.PI / 2.0 + T
while (a < 3.0 * Math.PI) {
proto.add(Tile(Type.KITE, w / 2.0, h / 2.0, a, w / 2.5))
a += 2.0 * T
}
return proto
}
 
private fun deflateTiles(tls: List<Tile>, generation: Int): List<Tile> {
if (generation <= 0) return tls
val next = mutableListOf<Tile>()
for (tile in tls) {
val x = tile.x
val y = tile.y
val a = tile.angle
var nx: Double
var ny: Double
val size = tile.size / G
if (tile.type == Type.DART) {
next.add(Tile(Type.KITE, x, y, a + 5.0 * T, size))
var sign = 1
for (i in 0..1) {
nx = x + Math.cos(a - 4.0 * T * sign) * G * tile.size
ny = y - Math.sin(a - 4.0 * T * sign) * G * tile.size
next.add(Tile(Type.DART, nx, ny, a - 4.0 * T * sign, size))
sign *= -1
}
}
else {
var sign = 1
for (i in 0..1) {
next.add(Tile(Type.DART, x, y, a - 4.0 * 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(Type.KITE, nx, ny, a + 3.0 * T * sign, size))
sign *= -1
}
}
}
// remove duplicates and deflate
return deflateTiles(next.distinct(), generation - 1)
}
 
private fun drawTiles(g: Graphics2D) {
val dist = arrayOf(
doubleArrayOf(G, G, G),
doubleArrayOf(-G, -1.0, -G)
)
for (tile in tiles) {
var angle = tile.angle - T
val path = Path2D.Double()
path.moveTo(tile.x, tile.y)
val ord = tile.type.ordinal
for (i in 0..2) {
val x = tile.x + dist[ord][i] * tile.size * Math.cos(angle)
val y = tile.y - dist[ord][i] * tile.size * Math.sin(angle)
path.lineTo(x, y)
angle += T
}
path.closePath()
with(g) {
color = if (ord == 0) Color.pink else Color.red
fill(path)
color = Color.darkGray
draw(path)
}
}
}
 
override fun paintComponent(og: Graphics) {
super.paintComponent(og)
val g = og as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON)
drawTiles(g)
}
}
 
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
with (f) {
defaultCloseOperation = JFrame.EXIT_ON_CLOSE
title = "Penrose Tiling"
isResizable = false
add(PenroseTiling(700, 450), BorderLayout.CENTER)
pack()
setLocationRelativeTo(null)
isVisible = true
}
}
}</syntaxhighlight>
 
=={{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}}==
<syntaxhighlight lang="perl">use constant pi => 2 * atan2(1, 0);
 
# Generated with a P3 tile set using a Lindenmayer system.
%rules = (
A => '',
M => 'OA++PA----NA[-OA----MA]++',
N => '+OA--PA[---MA--NA]+',
O => '-MA++NA[+++OA++PA]-',
P => '--OA++++MA[+PA++++NA]--NA'
);
$penrose = '[N]++[N]++[N]++[N]++[N]';
$penrose =~ s/([AMNOP])/$rules{$1}/eg for 1..4;
 
# Draw the curve in SVG
($x, $y) = (160, 160);
$theta = pi/5;
$r = 20;
 
for (split //, $penrose) {
if (/A/) {
$line = sprintf "<line x1='%.1f' y1='%.1f' ", $x, $y;
$line .= sprintf "x2='%.1f' ", $x += $r * cos($theta);
$line .= sprintf "y2='%.1f' ", $y += $r * sin($theta);
$line .= "style='stroke:rgb(255,165,0)'/>\n";
$SVG{$line} = 1;
} elsif (/\+/) { $theta += pi/5
} elsif (/\-/) { $theta -= pi/5
} elsif (/\[/) { push @stack, [$x, $y, $theta]
} elsif (/\]/) { ($x, $y, $theta) = @{pop @stack} }
}
$svg .= $_ for keys %SVG;
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;</syntaxhighlight>
[https://github.com/SqrtNegInf/Rosettacode-Perl5-Smoke/blob/master/ref/penrose_tiling.svg Penrose tiling] (offsite image)
 
=={{header|Phix}}==
Translation of the original Python code. Output can be toggled to look like the java or perl output.
{{libheader|Phix/pGUI}}
{{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 ===
{{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}}==
===LSystem===
<syntaxhighlight lang="java">
class LSystem
{
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) {
while (getAge() < gen) {
production = iterate(production, rule);
}
}
 
String iterate(String prod_, String rule_) {
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;
float somestep = 0.1;
String ruleW;
String ruleX;
String ruleY;
String ruleZ;
 
PenroseLSystem() {
axiom = "[X]++[X]++[X]++[X]++[X]";
ruleW = "YF++ZF4-XF[-YF4-WF]++";
ruleX = "+YF--ZF[3-WF--XF]+";
ruleY = "-WF++XF[+++YF++ZF]-";
ruleZ = "--YF++++WF[+ZF++++XF]--XF";
startLength = 460.0;
theta = radians(36);
reset();
}
 
void useRule(String r_) {
rule = r_;
}
 
void useAxiom(String a_) {
axiom = a_;
}
 
void useLength(float l_) {
startLength = l_;
}
 
void useTheta(float t_) {
theta = radians(t_);
}
 
void reset() {
production = axiom;
drawLength = startLength;
generations = 0;
}
 
int getAge() {
return generations;
}
 
void render() {
translate(width/2, height/2);
int pushes = 0;
int repeats = 1;
steps += 12;
if (steps > production.length()) {
steps = production.length();
}
 
for (int i = 0; i < steps; i++) {
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
while (pushes > 0) {
popMatrix();
pushes--;
}
}
 
String iterate(String prod_, String rule_) {
String newProduction = "";
for (int i = 0; i < prod_.length(); i++) {
char step = production.charAt(i);
if (step == 'W') {
newProduction = newProduction + ruleW;
}
else if (step == 'X') {
newProduction = newProduction + ruleX;
}
else if (step == 'Y') {
newProduction = newProduction + ruleY;
}
else if (step == 'Z') {
newProduction = newProduction + ruleZ;
}
else {
if (step != 'F') {
newProduction = newProduction + step;
}
}
}
 
drawLength = drawLength * 0.5;
generations++;
return newProduction;
}
 
}
</syntaxhighlight>
===PenroseTile===
<syntaxhighlight lang="java">
PenroseLSystem ds;
 
void setup() {
size(1000, 1000);
ds = new PenroseLSystem();
ds.simulate(5);
}
 
void draw() {
background(0);
ds.render();
}
</syntaxhighlight>
 
=={{header|Python}}==
Not much of a python program: majority of this code is string literals that dumps an SVG on output.
<syntaxhighlight lang="python">def 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" />''')
 
for d in range(depth):
print(f''' <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(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}}==
 
{{trans|Perl}}
 
<syntaxhighlight lang="racket">#lang racket
(require racket/draw)
(define rules '([M . (O A + + P A - - - - N A < - O A - - - - M A > + +)]
[N . (+ O A - - P A < - - - M A - - N A > +)]
[O . (- M A + + N A < + + + O A + + P A > -)]
[P . (- - O A + + + + M A < + P A + + + + N A > - - N A)]
[S . (< N > + + < N > + + < N > + + < N > + + < N >)]))
(define (get-cmds n cmd)
(cond
[(= 0 n) (list cmd)]
[else (append-map (curry get-cmds (sub1 n))
(dict-ref rules cmd (list cmd)))]))
(define (make-curve DIM N R OFFSET COLOR BACKGROUND-COLOR)
(define target (make-bitmap DIM DIM))
(define dc (new bitmap-dc% [bitmap target]))
(send dc set-background BACKGROUND-COLOR)
(send dc set-pen COLOR 1 'solid)
(send dc clear)
(for/fold ([x 160] [y 160] [θ (/ pi 5)] [S '()])
([cmd (in-list (get-cmds N 'S))])
(define (draw/values x* y* θ* S*)
(send/apply dc draw-line (map (curry + OFFSET) (list x y x* y*)))
(values x* y* θ* S*))
(match cmd
['A (draw/values (+ x (* R (cos θ))) (+ y (* R (sin θ))) θ S)]
['+ (values x y (+ θ (/ pi 5)) S)]
['- (values x y (- θ (/ pi 5)) S)]
['< (values x y θ (cons (list x y θ) S))]
['> (match-define (cons (list x y θ) S*) S)
(values x y θ S*)]
[_ (values x y θ S)]))
target)
(make-curve 500 4 20 80 (make-color 255 255 0) (make-color 0 0 0))</syntaxhighlight>
 
=={{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}}==
===Java Swing Interoperability===
{{libheader|Scala Java Swing interoperability}}
{{works with|Scala|2.13}}
<syntaxhighlight lang="scala">import java.awt.{BorderLayout, Color, Dimension, Graphics, Graphics2D, RenderingHints}
import java.awt.geom.Path2D
 
import javax.swing.{JFrame, JPanel}
 
import scala.math._
 
object PenroseTiling extends App {
private val (φ, ϑ) = ((1 + sqrt(5)) / 2, toRadians(36)) // golden ratio and 36 degrees
private val dist: Array[Array[Double]] = Array(Array(φ, φ, φ), Array(-φ, -1, -φ))
 
class PenroseTiling extends JPanel {
private val (w, h) = (700, 450)
private val tiles: Set[Tile] = deflateTiles(setupPrototiles(w, h), 5)
 
override def paintComponent(og: Graphics): Unit = {
def drawTiles(g: Graphics2D): Unit =
for (tile <- tiles) {
val path: Path2D = new Path2D.Double()
val distL = dist(tile.tileType.id)
 
path.moveTo(tile.x, tile.y)
for {i <- 0 until 3
ω = tile.α + (i - 1) * ϑ}
path.lineTo(
tile.x + distL(i) * tile.size * cos(ω),
tile.y - distL(i) * tile.size * sin(ω))
 
path.closePath()
g.setColor(if (tile.tileType == Type.Kite) Color.orange else Color.yellow)
g.fill(path)
g.setColor(Color.darkGray)
g.draw(path)
}
 
super.paintComponent(og)
val g: Graphics2D = og.asInstanceOf[Graphics2D]
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
drawTiles(g)
}
 
private def setupPrototiles(w: Int, h: Int): Set[Tile] = (0 to 5).map(n =>
Tile(Type.Kite, (w / 2).toDouble, (h / 2).toDouble, Pi / 2 + ϑ + n * 2 * ϑ, w / 2.5)).toSet
 
@scala.annotation.tailrec
private def deflateTiles(tls: Set[Tile], generation: Int): Set[Tile] =
if (generation > 0) {
val next = for {
tile <- tls
size = tile.size / φ
} yield {
 
def nx(factor: Int) = tile.x + cos(tile.α - factor * ϑ) * φ * tile.size
def ny(factor: Int) = tile.y - sin(tile.α - factor * ϑ) * φ * tile.size
 
tile.tileType match {
case Type.Dart =>
Seq(Tile(Type.Kite, tile.x, tile.y, tile.α + 5 * ϑ, size)) ++
(for (sign <- -1 to 1 by 2)
yield Tile(Type.Dart, nx(sign * 4), ny(sign * 4), tile.α - 4 * ϑ * sign, size))
 
case Type.Kite => (for (sign <- 1 to -1 by -2) yield {
Seq(Tile(Type.Dart, tile.x, tile.y, tile.α - 4 * ϑ * sign, size),
Tile(Type.Kite, nx(sign), ny(sign), tile.α + 3 * ϑ * sign, size))
}).flatten
}
}
deflateTiles(next.flatten, generation - 1)
} else tls
 
private case class Tile(tileType: Type.Type, x: Double, y: Double, α: Double, size: Double)
 
private object Type extends Enumeration {
type Type = Value
val Kite, Dart = Value
}
 
setPreferredSize(new Dimension(w, h))
setBackground(Color.white)
}
 
new JFrame("Penrose Tiling") {
add(new PenroseTiling(), BorderLayout.CENTER)
pack()
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
setLocationRelativeTo(null)
setResizable(false)
setVisible(true)
}
 
}</syntaxhighlight>
 
=={{header|Sidef}}==
Using the LSystem class defined at [https://rosettacode.org/wiki/Hilbert_curve#Sidef Hilbert curve].
<syntaxhighlight lang="ruby">var rules = Hash(
a => 'cE++dE----bE[-cE----aE]++',
b => '+cE--dE[---aE--bE]+',
c => '-aE++bE[+++cE++dE]-',
d => '--cE++++aE[+dE++++bE]--bE',
E => '',
)
 
var lsys = LSystem(
width: 1000,
height: 1000,
 
scale: 1,
xoff: -500,
yoff: -500,
 
len: 40,
angle: 36,
color: 'dark blue',
)
 
lsys.execute('[b]++[b]++[b]++[b]++[b]', 5, "penrose_tiling.png", rules)</syntaxhighlight>
 
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