-
Notifications
You must be signed in to change notification settings - Fork 8
/
main.rs
114 lines (105 loc) · 2.92 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::f64::consts::PI;
use clap::*;
use gre::*;
use noise::*;
use svg::node::element::path::Data;
use svg::node::element::*;
#[derive(Parser)]
#[clap()]
struct Opts {
#[clap(short, long, default_value = "55.0")]
seed: f64,
#[clap(short, long, default_value = "200")]
samples: usize,
}
fn art(opts: Opts) -> Vec<Group> {
let (width, height) = (297., 210.);
let precision = 0.2;
let pad = 20.;
let w = (width as f64 / precision) as u32;
let h = (height as f64 / precision) as u32;
let perlin = Perlin::new();
let bounds = (pad, pad, width - pad, height - pad);
let colors = vec!["black"];
fn length(l: (f64, f64)) -> f64 {
(l.0 * l.0 + l.1 * l.1).sqrt()
}
let f = |(x, y): (f64, f64)| {
let c = ((x - 0.5) * width / height, y - 0.5);
let f1 = 2.;
let f2 = 4.;
let f3 = 8.;
let a1 = 0.2;
let a2 = 0.4;
let a3 = 1.2;
let n1 = a1
* perlin.get([
f1 * c.0,
f1 * c.1,
opts.seed
+ a2
* perlin.get([
opts.seed - 10.,
f2 * c.0 + a3 * perlin.get([f3 * c.0, f3 * c.1, 20. + opts.seed]),
f2 * c.1 + a3 * perlin.get([f3 * c.0, f3 * c.1, 30. + opts.seed]),
]),
]);
0.4 + 0.5 * sdf_box2(c, (0.2, 0.2)) + n1
};
let samples = opts.samples;
colors
.iter()
.enumerate()
.map(|(ci, &color)| {
let pattern = (3., 10.);
let thresholds: Vec<f64> = (0..samples)
.map(|i| {
(i as f64 + pattern.1 * (i as f64 / pattern.0).floor())
/ (samples as f64 * (pattern.0 + pattern.1) / pattern.0).floor()
})
.collect();
let res = contour(w, h, f, &thresholds);
let mut routes = features_to_routes(res, precision);
routes = crop_routes(&routes, bounds);
let mut data = Data::new();
let csamples = 64;
let radius = 80.;
let in_circle = |p| euclidian_dist(p, (width / 2., height / 2.)) < radius;
let mut circle: Vec<(f64, f64)> = (0..csamples)
.map(|i| {
let a = PI * 2. * i as f64 / csamples as f64;
(
width / 2. + radius * a.cos(),
height / 2. + radius * a.sin(),
)
})
.collect();
circle.push(circle[0]);
let collider = |a, b| {
if !in_circle(a) && !in_circle(b) {
return Some(a);
}
collide_route_segment(&circle, a, b)
};
for route in routes {
data = render_route_collide(data, route, &collider);
}
if ci == 0 {
data = render_route(data, circle);
}
let mut l = layer(color);
l = l.add(base_path(color, 0.35, data));
l = l.add(signature(1.0, (200., 180.), color));
l
})
.collect()
}
fn main() {
let opts: Opts = Opts::parse();
let groups = art(opts);
let mut document = base_a4_landscape("white");
for g in groups {
document = document.add(g);
}
svg::save("image.svg", &document).unwrap();
}