Skip to content

Commit 009c1f5

Browse files
authored
Attractor (#192)
Closes #160
2 parents 0d83d7e + 37b4599 commit 009c1f5

22 files changed

Lines changed: 678 additions & 0 deletions

.rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
edition = "2024"

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ path = "tools/streamline.rs"
6767
name = "snap"
6868
path = "tools/snap.rs"
6969

70+
[[bin]]
71+
name = "attractor"
72+
path = "tools/attractor.rs"
73+
7074
[[bin]]
7175
name = "geom2graph"
7276
path = "tools/geom2graph.rs"
@@ -79,6 +83,7 @@ cxx = { version = "1.0", optional = true }
7983
delaunator = "1.0"
8084
eyre = "0.6.12"
8185
geo = "0.31"
86+
image = { version = "0.25.8", default-features = false, features = ["png"] }
8287
itertools = "0.14"
8388
kdtree = "0.7"
8489
noise = "0.9"

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
1212
* [How to build](#how-to-build)
1313
* [Philosophy](#philosophy)
1414
* [Examples](#examples)
15+
* [Chaotic attractors](#chaotic-attractors)
1516
* [Asemic writing](#asemic-writing)
1617
* [Random L-Systems](#random-l-systems)
1718
* [The tools](#the-tools)
@@ -29,6 +30,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
2930
* [streamline](#streamline)
3031
* [traverse](#traverse)
3132
* [urquhart](#urquhart)
33+
* [attractor](#attractor)
3234
* [Transformations](#transformations)
3335
* [project.py](#projectpy)
3436
* [geom2graph](#geom2graph)
@@ -96,6 +98,24 @@ to produce/consume a standard textual interface.
9698
* Graphs are in [TGF](https://en.wikipedia.org/wiki/Trivial_Graph_Format) format
9799

98100
# Examples
101+
102+
## Chaotic attractors
103+
See the [`attractor`](#attractor) tool for more details on how to generate these attractor images.
104+
105+
![](examples/attractor/clifford.png)
106+
107+
![](examples/attractor/ikeda.png)
108+
109+
![](examples/attractor/johnny-svensson.png)
110+
111+
![](examples/attractor/peter-de-jong.png)
112+
113+
![](examples/attractor/tinkerbell.png)
114+
115+
![](examples/attractor/fractal-dreams-ssss.png)
116+
117+
![](examples/attractor/gumowski-mira.png)
118+
99119
## Asemic writing
100120
The following snippet generates random asemic writing glyphs
101121
```sh
@@ -553,6 +573,27 @@ point-cloud --seed 11878883030565683752 --points 20 --scale 200 |
553573
```
554574
![](examples/urquhart/urquhart.svg)
555575
576+
### attractor
577+
The `attractor` tool is very similar to the [`streamline`](#streamline) tool. It takes a Rune script
578+
defining a 2D dynamical system, and traces the trajectories of points in that system.
579+
580+
For example the [tinkerbell.rn](examples/attractor/tinkerbell.rn) script defines the Tinkerbell
581+
attractor:
582+
583+
```sh
584+
attractor \
585+
--script ./examples/attractor/tinkerbell.rn \
586+
--output ./examples/attractor/tinkerbell.png \
587+
--output-format image \
588+
-x=-0.72 \
589+
-y=-0.64 \
590+
--iterations 500000
591+
```
592+
![](examples/attractor/tinkerbell.png)
593+
594+
You may use `--output-format` to get WKT POINTs or LINESTRINGs instead of a PNG image, but the PGN
595+
image looks better than an SVG rendering of the WKT geometries.
596+
556597
## Transformations
557598
### project.py
558599
The `project.py` tool can be used to project 3D geometries to 2D. It supports several projection

README.md.in

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
1212
* [How to build](#how-to-build)
1313
* [Philosophy](#philosophy)
1414
* [Examples](#examples)
15+
* [Chaotic attractors](#chaotic-attractors)
1516
* [Asemic writing](#asemic-writing)
1617
* [Random L-Systems](#random-l-systems)
1718
* [The tools](#the-tools)
@@ -29,6 +30,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
2930
* [streamline](#streamline)
3031
* [traverse](#traverse)
3132
* [urquhart](#urquhart)
33+
* [attractor](#attractor)
3234
* [Transformations](#transformations)
3335
* [project.py](#projectpy)
3436
* [geom2graph](#geom2graph)
@@ -96,6 +98,24 @@ to produce/consume a standard textual interface.
9698
* Graphs are in [TGF](https://en.wikipedia.org/wiki/Trivial_Graph_Format) format
9799

98100
# Examples
101+
102+
## Chaotic attractors
103+
See the [`attractor`](#attractor) tool for more details on how to generate these attractor images.
104+
105+
![](examples/attractor/clifford.png)
106+
107+
![](examples/attractor/ikeda.png)
108+
109+
![](examples/attractor/johnny-svensson.png)
110+
111+
![](examples/attractor/peter-de-jong.png)
112+
113+
![](examples/attractor/tinkerbell.png)
114+
115+
![](examples/attractor/fractal-dreams-ssss.png)
116+
117+
![](examples/attractor/gumowski-mira.png)
118+
99119
## Asemic writing
100120
The following snippet generates random asemic writing glyphs
101121
```sh
@@ -347,6 +367,21 @@ triangulation.
347367
```
348368
![](examples/urquhart/urquhart.svg)
349369

370+
### attractor
371+
The `attractor` tool is very similar to the [`streamline`](#streamline) tool. It takes a Rune script
372+
defining a 2D dynamical system, and traces the trajectories of points in that system.
373+
374+
For example the [tinkerbell.rn](examples/attractor/tinkerbell.rn) script defines the Tinkerbell
375+
attractor:
376+
377+
```sh
378+
@TINKERBELL_SNIPPET@
379+
```
380+
![](examples/attractor/tinkerbell.png)
381+
382+
You may use `--output-format` to get WKT POINTs or LINESTRINGs instead of a PNG image, but the PGN
383+
image looks better than an SVG rendering of the WKT geometries.
384+
350385
## Transformations
351386
### project.py
352387
The `project.py` tool can be used to project 3D geometries to 2D. It supports several projection

examples/attractor/clifford.png

428 KB
Loading

examples/attractor/clifford.rn

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
let a = -2.0;
2+
let b = -2.4;
3+
let c = 1.1;
4+
let d = -0.9;
5+
6+
let x_new = f64::sin(a * y) + c * f64::cos(a * x);
7+
let y_new = f64::sin(b * x) + d * f64::cos(b * y);
342 KB
Loading
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// From Chaos in Wonderland, version SSSS
2+
3+
let a = 1.468;
4+
let b = 2.407;
5+
let c = 0.194;
6+
let d = 1.438;
7+
8+
let x_new = f64::sin(y * b) + c * f64::sin(x * b);
9+
let y_new = f64::sin(x * a) + d * f64::sin(y * a);

examples/attractor/generate.sh

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/bash
2+
set -o errexit
3+
set -o pipefail
4+
set -o nounset
5+
set -o noclobber
6+
7+
debug "Generating clifford ..."
8+
attractor \
9+
--seed 1193803725491079949 \
10+
--script ./examples/attractor/clifford.rn \
11+
--output ./examples/attractor/clifford.png \
12+
--output-format image \
13+
--num-points 400 \
14+
--iterations 800
15+
16+
debug "Generating ikeda ..."
17+
attractor \
18+
--seed 14245741203239691500 \
19+
--script ./examples/attractor/ikeda.rn \
20+
--output ./examples/attractor/ikeda.png \
21+
--output-format image \
22+
--num-points 500 \
23+
--iterations 500
24+
25+
debug "Generating johnny-svensson ..."
26+
attractor \
27+
--seed 2310402659768744900 \
28+
--script ./examples/attractor/johnny-svensson.rn \
29+
--output ./examples/attractor/johnny-svensson.png \
30+
--output-format image \
31+
--num-points 200 \
32+
--iterations 800
33+
34+
debug "Generating peter-de-jong ..."
35+
attractor \
36+
--seed 10329922707181609977 \
37+
--script ./examples/attractor/peter-de-jong.rn \
38+
--output ./examples/attractor/peter-de-jong.png \
39+
--output-format image \
40+
--num-points 200 \
41+
--iterations 800
42+
43+
debug "Generating tinkerbell ..."
44+
# BEGIN TINKERBELL_SNIPPET
45+
attractor \
46+
--script ./examples/attractor/tinkerbell.rn \
47+
--output ./examples/attractor/tinkerbell.png \
48+
--output-format image \
49+
-x=-0.72 \
50+
-y=-0.64 \
51+
--iterations 500000
52+
# END TINKERBELL_SNIPPET
53+
extract_snippet TINKERBELL_SNIPPET
54+
55+
debug "Generating fractal-dreams-ssss ..."
56+
attractor \
57+
--seed 4392994853744049110 \
58+
--script ./examples/attractor/fractal-dreams-ssss.rn \
59+
--output ./examples/attractor/fractal-dreams-ssss.png \
60+
--output-format image \
61+
--num-points 1000 \
62+
--iterations 2000
63+
64+
debug "Generating gumowski-mira ..."
65+
attractor \
66+
--seed 6844197751594810350 \
67+
--script ./examples/attractor/gumowski-mira.rn \
68+
--output ./examples/attractor/gumowski-mira.png \
69+
--output-format image \
70+
--num-points 1000 \
71+
--iterations 5000
74.7 KB
Loading

0 commit comments

Comments
 (0)