Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edition = "2024"
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ path = "tools/streamline.rs"
name = "snap"
path = "tools/snap.rs"

[[bin]]
name = "attractor"
path = "tools/attractor.rs"

[[bin]]
name = "geom2graph"
path = "tools/geom2graph.rs"
Expand All @@ -79,6 +83,7 @@ cxx = { version = "1.0", optional = true }
delaunator = "1.0"
eyre = "0.6.12"
geo = "0.31"
image = { version = "0.25.8", default-features = false, features = ["png"] }
itertools = "0.14"
kdtree = "0.7"
noise = "0.9"
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
* [How to build](#how-to-build)
* [Philosophy](#philosophy)
* [Examples](#examples)
* [Chaotic attractors](#chaotic-attractors)
* [Asemic writing](#asemic-writing)
* [Random L-Systems](#random-l-systems)
* [The tools](#the-tools)
Expand All @@ -29,6 +30,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
* [streamline](#streamline)
* [traverse](#traverse)
* [urquhart](#urquhart)
* [attractor](#attractor)
* [Transformations](#transformations)
* [project.py](#projectpy)
* [geom2graph](#geom2graph)
Expand Down Expand Up @@ -96,6 +98,24 @@ to produce/consume a standard textual interface.
* Graphs are in [TGF](https://en.wikipedia.org/wiki/Trivial_Graph_Format) format

# Examples

## Chaotic attractors
See the [`attractor`](#attractor) tool for more details on how to generate these attractor images.

![](examples/attractor/clifford.png)

![](examples/attractor/ikeda.png)

![](examples/attractor/johnny-svensson.png)

![](examples/attractor/peter-de-jong.png)

![](examples/attractor/tinkerbell.png)

![](examples/attractor/fractal-dreams-ssss.png)

![](examples/attractor/gumowski-mira.png)

## Asemic writing
The following snippet generates random asemic writing glyphs
```sh
Expand Down Expand Up @@ -553,6 +573,27 @@ point-cloud --seed 11878883030565683752 --points 20 --scale 200 |
```
![](examples/urquhart/urquhart.svg)

### attractor
The `attractor` tool is very similar to the [`streamline`](#streamline) tool. It takes a Rune script
defining a 2D dynamical system, and traces the trajectories of points in that system.

For example the [tinkerbell.rn](examples/attractor/tinkerbell.rn) script defines the Tinkerbell
attractor:

```sh
attractor \
--script ./examples/attractor/tinkerbell.rn \
--output ./examples/attractor/tinkerbell.png \
--output-format image \
-x=-0.72 \
-y=-0.64 \
--iterations 500000
```
![](examples/attractor/tinkerbell.png)

You may use `--output-format` to get WKT POINTs or LINESTRINGs instead of a PNG image, but the PGN
image looks better than an SVG rendering of the WKT geometries.

## Transformations
### project.py
The `project.py` tool can be used to project 3D geometries to 2D. It supports several projection
Expand Down
35 changes: 35 additions & 0 deletions README.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
* [How to build](#how-to-build)
* [Philosophy](#philosophy)
* [Examples](#examples)
* [Chaotic attractors](#chaotic-attractors)
* [Asemic writing](#asemic-writing)
* [Random L-Systems](#random-l-systems)
* [The tools](#the-tools)
Expand All @@ -29,6 +30,7 @@ A polyglot collection of composable generative art tools, with a focus on 2D com
* [streamline](#streamline)
* [traverse](#traverse)
* [urquhart](#urquhart)
* [attractor](#attractor)
* [Transformations](#transformations)
* [project.py](#projectpy)
* [geom2graph](#geom2graph)
Expand Down Expand Up @@ -96,6 +98,24 @@ to produce/consume a standard textual interface.
* Graphs are in [TGF](https://en.wikipedia.org/wiki/Trivial_Graph_Format) format

# Examples

## Chaotic attractors
See the [`attractor`](#attractor) tool for more details on how to generate these attractor images.

![](examples/attractor/clifford.png)

![](examples/attractor/ikeda.png)

![](examples/attractor/johnny-svensson.png)

![](examples/attractor/peter-de-jong.png)

![](examples/attractor/tinkerbell.png)

![](examples/attractor/fractal-dreams-ssss.png)

![](examples/attractor/gumowski-mira.png)

## Asemic writing
The following snippet generates random asemic writing glyphs
```sh
Expand Down Expand Up @@ -347,6 +367,21 @@ triangulation.
```
![](examples/urquhart/urquhart.svg)

### attractor
The `attractor` tool is very similar to the [`streamline`](#streamline) tool. It takes a Rune script
defining a 2D dynamical system, and traces the trajectories of points in that system.

For example the [tinkerbell.rn](examples/attractor/tinkerbell.rn) script defines the Tinkerbell
attractor:

```sh
@TINKERBELL_SNIPPET@
```
![](examples/attractor/tinkerbell.png)

You may use `--output-format` to get WKT POINTs or LINESTRINGs instead of a PNG image, but the PGN
image looks better than an SVG rendering of the WKT geometries.

## Transformations
### project.py
The `project.py` tool can be used to project 3D geometries to 2D. It supports several projection
Expand Down
Binary file added examples/attractor/clifford.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/attractor/clifford.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let a = -2.0;
let b = -2.4;
let c = 1.1;
let d = -0.9;

let x_new = f64::sin(a * y) + c * f64::cos(a * x);
let y_new = f64::sin(b * x) + d * f64::cos(b * y);
Binary file added examples/attractor/fractal-dreams-ssss.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions examples/attractor/fractal-dreams-ssss.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// From Chaos in Wonderland, version SSSS

let a = 1.468;
let b = 2.407;
let c = 0.194;
let d = 1.438;

let x_new = f64::sin(y * b) + c * f64::sin(x * b);
let y_new = f64::sin(x * a) + d * f64::sin(y * a);
71 changes: 71 additions & 0 deletions examples/attractor/generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
set -o noclobber

debug "Generating clifford ..."
attractor \
--seed 1193803725491079949 \
--script ./examples/attractor/clifford.rn \
--output ./examples/attractor/clifford.png \
--output-format image \
--num-points 400 \
--iterations 800

debug "Generating ikeda ..."
attractor \
--seed 14245741203239691500 \
--script ./examples/attractor/ikeda.rn \
--output ./examples/attractor/ikeda.png \
--output-format image \
--num-points 500 \
--iterations 500

debug "Generating johnny-svensson ..."
attractor \
--seed 2310402659768744900 \
--script ./examples/attractor/johnny-svensson.rn \
--output ./examples/attractor/johnny-svensson.png \
--output-format image \
--num-points 200 \
--iterations 800

debug "Generating peter-de-jong ..."
attractor \
--seed 10329922707181609977 \
--script ./examples/attractor/peter-de-jong.rn \
--output ./examples/attractor/peter-de-jong.png \
--output-format image \
--num-points 200 \
--iterations 800

debug "Generating tinkerbell ..."
# BEGIN TINKERBELL_SNIPPET
attractor \
--script ./examples/attractor/tinkerbell.rn \
--output ./examples/attractor/tinkerbell.png \
--output-format image \
-x=-0.72 \
-y=-0.64 \
--iterations 500000
# END TINKERBELL_SNIPPET
extract_snippet TINKERBELL_SNIPPET

debug "Generating fractal-dreams-ssss ..."
attractor \
--seed 4392994853744049110 \
--script ./examples/attractor/fractal-dreams-ssss.rn \
--output ./examples/attractor/fractal-dreams-ssss.png \
--output-format image \
--num-points 1000 \
--iterations 2000

debug "Generating gumowski-mira ..."
attractor \
--seed 6844197751594810350 \
--script ./examples/attractor/gumowski-mira.rn \
--output ./examples/attractor/gumowski-mira.png \
--output-format image \
--num-points 1000 \
--iterations 5000
Binary file added examples/attractor/gumowski-mira.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions examples/attractor/gumowski-mira.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
let a = 0.192;
let b = 0.982;

fn f(x) {
let a = 0.192;
let b = 0.982;

a * x + 2.0 * (1.0 - a) * x.powi(2) / (1.0 + x.powi(2)).powi(2)
}

let x_new = b * y + f(x);
let y_new = f(x_new) - x;
Binary file added examples/attractor/ikeda.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions examples/attractor/ikeda.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// ikeda is a chaotic attractor for u>=0.6
let u = 0.9;

let t_n = 0.4 - 6.0 / (1.0 + x.powi(2) + y.powi(2));
let x_new = 1.0 + u * (x * f64::cos(t_n) - y * f64::sin(t_n));
let y_new = u * (x * f64::sin(t_n) + y * f64::cos(t_n));
Binary file added examples/attractor/johnny-svensson.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/attractor/johnny-svensson.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let a = 1.4;
let b = 1.56;
let c = 1.4;
let d = -6.56;

let x_new = d * f64::sin(a * x) - f64::sin(b * y);
let y_new = c * f64::cos(a * x) + f64::cos(b * y);
Binary file added examples/attractor/peter-de-jong.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/attractor/peter-de-jong.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let a = 0.970;
let b = -1.899;
let c = 1.381;
let d = -1.506;

let x_new = f64::sin(a * y) - f64::cos(b * x);
let y_new = f64::sin(c * x) - f64::cos(d * y);
Binary file added examples/attractor/tinkerbell.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/attractor/tinkerbell.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let a = 0.9;
let b = -0.6013;
let c = 2.0;
let d = 0.5;

let x_new = x.powi(2) - y.powi(2) + a * x + b * y;
let y_new = 2.0 * x * y + c * x + d * y;
Loading
Loading