dopairb 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +41 -9
- data/lib/dopairb/cli.rb +4 -6
- data/lib/dopairb/config.rb +6 -4
- data/lib/dopairb/demo.rb +9 -2
- data/lib/dopairb/director.rb +35 -5
- data/lib/dopairb/fx.rb +23 -0
- data/lib/dopairb/gallery/impressionism.rb +818 -0
- data/lib/dopairb/gallery/japan.rb +693 -0
- data/lib/dopairb/gallery/modern_ancient.rb +774 -0
- data/lib/dopairb/gallery/renaissance.rb +829 -0
- data/lib/dopairb/gallery/romantic.rb +703 -0
- data/lib/dopairb/gallery.rb +349 -0
- data/lib/dopairb/game.rb +84 -7
- data/lib/dopairb/input_fx.rb +63 -9
- data/lib/dopairb/irb_adapter.rb +8 -0
- data/lib/dopairb/profile.rb +106 -0
- data/lib/dopairb/reline_adapter.rb +1 -0
- data/lib/dopairb/scene.rb +5 -0
- data/lib/dopairb/scenes/bonus.rb +279 -0
- data/lib/dopairb/scenes/failure.rb +1 -0
- data/lib/dopairb/scenes/finale.rb +42 -2
- data/lib/dopairb/scenes/session.rb +21 -3
- data/lib/dopairb/scenes/success.rb +11 -4
- data/lib/dopairb/session.rb +50 -6
- data/lib/dopairb/sound.rb +57 -2
- data/lib/dopairb/term.rb +3 -1
- data/lib/dopairb/tour.rb +89 -0
- data/lib/dopairb/version.rb +1 -1
- data/lib/dopairb.rb +57 -1
- data/spec.md +3 -3
- metadata +10 -1
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dopairb
|
|
4
|
+
module Gallery
|
|
5
|
+
# Impressionists and Post-Impressionists. Painters live in Paint as
|
|
6
|
+
# imp_* methods so they can use early returns.
|
|
7
|
+
module Paint
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# Distance from (u, v) to the segment a-b (sx scales the u axis).
|
|
11
|
+
def imp_seg(u, v, ax, ay, bx, by, sx = 1.0)
|
|
12
|
+
dx = (bx - ax) * sx
|
|
13
|
+
dy = by - ay
|
|
14
|
+
px = (u - ax) * sx
|
|
15
|
+
py = v - ay
|
|
16
|
+
t = ((px * dx + py * dy) / (dx * dx + dy * dy + 1e-12)).clamp(0.0, 1.0)
|
|
17
|
+
Math.hypot(px - dx * t, py - dy * t)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# A standing figure: :head, :body or nil. top = top of the head, h = height, w = hem width.
|
|
21
|
+
def imp_figure(u, v, cx, top, h, w)
|
|
22
|
+
hr = h * 0.09
|
|
23
|
+
return :head if ellipse(u, v, cx, top + hr, hr * 0.8, hr) < 1
|
|
24
|
+
t = (v - top - hr * 1.8) / (h - hr * 1.8)
|
|
25
|
+
return nil unless t.between?(0.0, 1.0)
|
|
26
|
+
(u - cx).abs < w * (0.3 + 0.7 * t) * 0.5 ? :body : nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Thin dark line just outside a polygon.
|
|
30
|
+
def imp_outline?(u, v, pts, e = 0.014)
|
|
31
|
+
inside?(u + e, v, pts) || inside?(u - e, v, pts) || inside?(u, v + e, pts) || inside?(u, v - e, pts)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Monet, Impression, Sunrise
|
|
35
|
+
def imp_impression_sunrise(u, v)
|
|
36
|
+
sx = 0.44
|
|
37
|
+
sy = 0.34
|
|
38
|
+
horizon = 0.50
|
|
39
|
+
ds = dist(u, v, sx, sy, 1.31)
|
|
40
|
+
return rgb(0xff6020) if ds < 0.030
|
|
41
|
+
# boats: hull + standing rower
|
|
42
|
+
[[0.36, 0.76, 0.075, 0.022, 0.0], [0.20, 0.64, 0.045, 0.015, 0.35], [0.53, 0.62, 0.04, 0.013, 0.45]].each do |bx, by, rx, ry, fade|
|
|
43
|
+
dark = mix([25, 35, 50], [90, 110, 125], fade)
|
|
44
|
+
return dark if ellipse(u, v, bx, by, rx, ry) < 1 && v > by - ry * 0.3
|
|
45
|
+
return dark if (u - bx - rx * 0.2).abs < rx * 0.16 && v < by && v > by - ry * 3.2
|
|
46
|
+
end
|
|
47
|
+
if v > horizon
|
|
48
|
+
# broken orange reflection streaks
|
|
49
|
+
row = (v * 42).floor
|
|
50
|
+
frac = v * 42 - row
|
|
51
|
+
off = (noise(row, 3) - 0.5) * 0.05
|
|
52
|
+
w = (0.02 + (v - horizon) * 0.12) * (noise(row, 7) > 0.2 ? 1 : 0)
|
|
53
|
+
if (u - sx - off).abs < w && frac.between?(0.15, 0.8) && v < 0.97
|
|
54
|
+
return mix([255, 120, 40], [230, 80, 30], noise(row, 9))
|
|
55
|
+
end
|
|
56
|
+
base = mix([95, 125, 135], [60, 90, 105], (v - horizon) * 2)
|
|
57
|
+
stroke = brush(u, v, angle: 0.05, freq: 30.0, wobble: 0.6)
|
|
58
|
+
base = mix(base, [140, 160, 160], 0.35) if stroke > 0.6
|
|
59
|
+
base = mix(base, [50, 75, 90], 0.3) if stroke < -0.7
|
|
60
|
+
return jitter(base, u, v, 10)
|
|
61
|
+
end
|
|
62
|
+
# cranes, masts and chimneys, faint in the haze
|
|
63
|
+
[[0.06, 0.12, 0.004], [0.10, 0.22, 0.004], [0.62, 0.18, 0.005], [0.70, 0.10, 0.004], [0.83, 0.22, 0.004], [0.90, 0.16, 0.004]].each do |mx, top, half|
|
|
64
|
+
return mix([110, 125, 135], [140, 150, 155], 0.3) if (u - mx).abs < half + 0.003 && v > top
|
|
65
|
+
end
|
|
66
|
+
return mix([110, 125, 135], [135, 145, 150], 0.4) if v > 0.40 && (u < 0.30 || u > 0.66) && vnoise(u, v, 10) > 0.4
|
|
67
|
+
sky = mix([125, 145, 155], [160, 165, 160], v * 1.5)
|
|
68
|
+
glow = Math.exp(-ds * 7)
|
|
69
|
+
sky = mix(sky, [235, 150, 100], glow * 0.8)
|
|
70
|
+
sky = mix(sky, [210, 150, 125], 0.25) if v < 0.25 && brush(u, v, angle: -0.15, freq: 12.0) > 0.6 && u > 0.3
|
|
71
|
+
jitter(sky, u, v, 10)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Monet, Water Lilies
|
|
75
|
+
def imp_water_lilies(u, v)
|
|
76
|
+
clusters = [[0.22, 0.10, 0.20, 0.035], [0.75, 0.16, 0.22, 0.04], [0.48, 0.36, 0.28, 0.055],
|
|
77
|
+
[0.14, 0.58, 0.20, 0.07], [0.78, 0.62, 0.24, 0.08], [0.42, 0.88, 0.32, 0.09]]
|
|
78
|
+
clusters.each_with_index do |(cx, cy, rx, ry), i|
|
|
79
|
+
e = ellipse(u, v, cx, cy, rx, ry) + (vnoise(u, v, 14.0) - 0.5) * 0.9
|
|
80
|
+
next unless e < 1
|
|
81
|
+
# flowers
|
|
82
|
+
return [250, 245, 245] if dist(u, v, cx + rx * 0.25, cy - ry * 0.1, 1.1) < 0.022 + ry * 0.15 && i.even?
|
|
83
|
+
return [240, 140, 170] if dist(u, v, cx - rx * 0.35, cy, 1.1) < 0.02 + ry * 0.2
|
|
84
|
+
return [250, 220, 230] if dist(u, v, cx + rx * 0.05, cy + ry * 0.2, 1.1) < 0.012 + ry * 0.15 && i.odd?
|
|
85
|
+
pad = brush(u, v, angle: 0.0, freq: 70.0, wobble: 0.8) > 0 ? [90, 150, 70] : [130, 175, 80]
|
|
86
|
+
pad = mix(pad, [200, 200, 90], 0.4) if vnoise(u, v, 25.0) > 0.7
|
|
87
|
+
return pad
|
|
88
|
+
end
|
|
89
|
+
# pond: blue-violet sky reflections with green vertical willow reflections
|
|
90
|
+
base = ramp(v, [90, 110, 170], [120, 140, 200], [100, 120, 180], [70, 90, 150])
|
|
91
|
+
refl = Math.sin(u * 22 + vnoise(u, v, 4.0) * 4)
|
|
92
|
+
base = mix(base, [60, 110, 90], 0.55) if refl > 0.5
|
|
93
|
+
base = mix(base, [190, 190, 220], 0.4) if vnoise(u * 0.3, v * 3, 6.0) > 0.68
|
|
94
|
+
base = mix(base, [150, 120, 190], 0.3) if brush(u, v, angle: 0.0, freq: 45.0) > 0.7
|
|
95
|
+
jitter(base, u, v, 12)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Monet, Woman with a Parasol
|
|
99
|
+
def imp_woman_with_a_parasol(u, v)
|
|
100
|
+
ground = 0.83 + 0.04 * Math.sin(u * 4 + 0.5)
|
|
101
|
+
# grass in the foreground
|
|
102
|
+
if v > ground
|
|
103
|
+
g = brush(u, v, angle: 1.1, freq: 40.0, wobble: 0.8) > 0.2 ? [120, 160, 60] : [70, 120, 50]
|
|
104
|
+
g = mix(g, [210, 200, 90], 0.5) if vnoise(u, v, 18.0) > 0.65
|
|
105
|
+
return g
|
|
106
|
+
end
|
|
107
|
+
# the boy at right, half hidden by the slope
|
|
108
|
+
return [235, 230, 200] if ellipse(u, v, 0.82, 0.715, 0.03, 0.018) < 1
|
|
109
|
+
return [200, 160, 130] if ellipse(u, v, 0.82, 0.745, 0.022, 0.025) < 1
|
|
110
|
+
return [220, 210, 180] if (u - 0.82).abs < 0.035 && v > 0.77
|
|
111
|
+
# parasol, tilted (its right side lower)
|
|
112
|
+
pv = v - (u - 0.42) * 0.22
|
|
113
|
+
if pv < 0.245 && ellipse(u, pv, 0.42, 0.245, 0.27, 0.17) < 1
|
|
114
|
+
shade = smooth(0.15, 0.68, u)
|
|
115
|
+
return mix([110, 170, 90], [40, 90, 60], shade) if brush(u, v, angle: 0.8, freq: 30.0) > -0.3
|
|
116
|
+
return [70, 120, 70]
|
|
117
|
+
end
|
|
118
|
+
return mix([200, 180, 90], [100, 110, 60], u) if pv >= 0.245 && ellipse(u, pv, 0.42, 0.245, 0.27, 0.045) < 1
|
|
119
|
+
# handle
|
|
120
|
+
return [70, 60, 50] if imp_seg(u, v, 0.43, 0.25, 0.47, 0.44) < 0.008
|
|
121
|
+
# head with hat and blowing veil
|
|
122
|
+
return [190, 160, 110] if ellipse(u, v, 0.48, 0.355, 0.035, 0.035) < 1
|
|
123
|
+
return [235, 240, 245] if ellipse(u, v, 0.40, 0.38, 0.08, 0.018 + (0.48 - u).abs * 0.05) < 1 && u < 0.47
|
|
124
|
+
# white dress, blown to the left
|
|
125
|
+
dress = [[0.45, 0.385], [0.52, 0.39], [0.57, 0.52], [0.61, 0.90], [0.36, 0.90], [0.33, 0.70], [0.40, 0.52]]
|
|
126
|
+
if inside?(u, v, dress)
|
|
127
|
+
side = smooth(0.38, 0.58, u)
|
|
128
|
+
c = mix([170, 190, 225], [250, 245, 220], side)
|
|
129
|
+
c = mix(c, [235, 225, 160], 0.4) if brush(u, v, angle: 0.4, freq: 35.0) > 0.6 && u > 0.5
|
|
130
|
+
return c
|
|
131
|
+
end
|
|
132
|
+
# sky with wind-blown clouds
|
|
133
|
+
sky = mix([90, 145, 210], [175, 205, 235], smooth(0.0, 0.85, v))
|
|
134
|
+
cloud = vnoise(u * 1.4 + v * 0.6, v, 4.0) + brush(u, v, angle: -0.6, freq: 18.0) * 0.12
|
|
135
|
+
sky = mix(sky, [245, 245, 240], smooth(0.56, 0.74, cloud))
|
|
136
|
+
jitter(sky, u, v, 8)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Monet, The Water Lily Pond (Japanese Footbridge)
|
|
140
|
+
def imp_japanese_footbridge(u, v)
|
|
141
|
+
deck = 0.44 - 0.12 * Math.sin(Math::PI * u)
|
|
142
|
+
# the arched green bridge with its railing
|
|
143
|
+
return mix([160, 190, 110], [100, 150, 80], u) if v > deck && v < deck + 0.04
|
|
144
|
+
return [80, 130, 70] if v > deck + 0.04 && v < deck + 0.065
|
|
145
|
+
top = deck - 0.12
|
|
146
|
+
return [190, 210, 140] if (v - top).abs < 0.013
|
|
147
|
+
return [150, 185, 110] if (v - (deck - 0.06)).abs < 0.01
|
|
148
|
+
return [130, 175, 100] if v > top && v < deck && ((u * 12.5) % 1.0) < 0.18
|
|
149
|
+
if v > 0.50 + 0.04 * Math.sin(u * 6)
|
|
150
|
+
# pond with rows of lily pads
|
|
151
|
+
row = ((v - 0.5) * 22).floor
|
|
152
|
+
rh = (v - 0.5) * 22 - row
|
|
153
|
+
cw = 0.10 + row * 0.01
|
|
154
|
+
cell = ((u + noise(row, 1) * 0.3) / cw).floor
|
|
155
|
+
cu = (u + noise(row, 1) * 0.3) / cw - cell
|
|
156
|
+
if noise(cell, row) > 0.3 && ((cu - 0.5) / 0.45)**2 + ((rh - 0.5) / 0.4)**2 < 1
|
|
157
|
+
return [235, 150, 170] if noise(cell, row + 50) > 0.85 && (cu - 0.5).abs < 0.15
|
|
158
|
+
return [250, 245, 240] if noise(cell, row + 70) > 0.85 && (cu - 0.5).abs < 0.15
|
|
159
|
+
return mix([140, 180, 70], [90, 150, 60], noise(cell, row + 9))
|
|
160
|
+
end
|
|
161
|
+
water = mix([40, 80, 60], [70, 110, 90], vnoise(u, v, 6.0))
|
|
162
|
+
water = mix(water, [150, 170, 120], 0.4) if Math.sin(u * 40 + vnoise(u, v, 5.0) * 3) > 0.75
|
|
163
|
+
return water
|
|
164
|
+
end
|
|
165
|
+
# dense willow and bamboo foliage
|
|
166
|
+
f = vnoise(u, v, 16.0)
|
|
167
|
+
stroke = brush(u, v, angle: 1.5, freq: 50.0, wobble: 0.6)
|
|
168
|
+
c = ramp(f, [30, 60, 35], [60, 110, 50], [110, 160, 70], [180, 200, 90])
|
|
169
|
+
c = mix(c, [40, 80, 70], 0.4) if stroke > 0.6
|
|
170
|
+
jitter(c, u, v, 14)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Monet, Poppy Field
|
|
174
|
+
def imp_poppy_field(u, v)
|
|
175
|
+
horizon = 0.30 + 0.20 * u
|
|
176
|
+
# foreground pair: woman with blue parasol and child
|
|
177
|
+
return [60, 80, 130] if ellipse(u, v, 0.70, 0.50, 0.065, 0.045) < 1 && v < 0.52
|
|
178
|
+
case imp_figure(u, v, 0.71, 0.53, 0.30, 0.13)
|
|
179
|
+
when :head then return [200, 160, 130]
|
|
180
|
+
when :body then return [45, 45, 60]
|
|
181
|
+
end
|
|
182
|
+
case imp_figure(u, v, 0.79, 0.66, 0.18, 0.08)
|
|
183
|
+
when :head then return [220, 200, 140]
|
|
184
|
+
when :body then return [230, 225, 205]
|
|
185
|
+
end
|
|
186
|
+
# background pair high on the hill
|
|
187
|
+
return [70, 100, 160] if ellipse(u, v, 0.30, 0.37, 0.035, 0.025) < 1 && v < 0.38
|
|
188
|
+
case imp_figure(u, v, 0.30, 0.38, 0.14, 0.06)
|
|
189
|
+
when :head then return [200, 170, 140]
|
|
190
|
+
when :body then return [50, 50, 60]
|
|
191
|
+
end
|
|
192
|
+
case imp_figure(u, v, 0.36, 0.44, 0.08, 0.04)
|
|
193
|
+
when :head, :body then return [210, 200, 180]
|
|
194
|
+
end
|
|
195
|
+
if v > horizon
|
|
196
|
+
ground = mix([140, 170, 80], [90, 140, 60], (v - horizon) * 1.5)
|
|
197
|
+
ground = mix(ground, [190, 190, 110], 0.35) if vnoise(u, v, 8.0) > 0.65
|
|
198
|
+
poppy_zone = u < 0.70 - (v - 0.4) * 0.6 + (vnoise(u, v, 5.0) - 0.5) * 0.2
|
|
199
|
+
cell = noise((u * 64).floor, (v * 48).floor)
|
|
200
|
+
return mix([230, 60, 30], [190, 30, 25], noise((u * 64).floor + 7, (v * 48).floor)) if poppy_zone && cell > 0.6
|
|
201
|
+
return [220, 60, 35] if cell > 0.95
|
|
202
|
+
return jitter(ground, u, v, 12)
|
|
203
|
+
end
|
|
204
|
+
# row of trees and a red-roofed house on the horizon
|
|
205
|
+
tree_top = horizon - 0.07 - vnoise(u, 0.0, 12.0) * 0.08
|
|
206
|
+
if u > 0.35 && u < 0.97 && v > tree_top
|
|
207
|
+
return [210, 120, 80] if (u - 0.62).abs < 0.025 && v > horizon - 0.04
|
|
208
|
+
return mix([40, 70, 50], [80, 110, 70], vnoise(u, v, 20.0))
|
|
209
|
+
end
|
|
210
|
+
sky = mix([110, 150, 210], [190, 210, 230], v * 2)
|
|
211
|
+
sky = mix(sky, [245, 245, 240], smooth(0.5, 0.7, vnoise(u * 1.3, v, 5.0)))
|
|
212
|
+
jitter(sky, u, v, 8)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Renoir, Bal du moulin de la Galette
|
|
216
|
+
def imp_bal_du_moulin(u, v)
|
|
217
|
+
light = vnoise(u, v, 13.0) > 0.66
|
|
218
|
+
dapple = ->(c) { light ? mix(c, [250, 235, 200], 0.45) : c }
|
|
219
|
+
# foreground: woman in pink-and-blue stripes
|
|
220
|
+
return [60, 40, 30] if ellipse(u, v, 0.30, 0.45, 0.035, 0.045) < 1 && v < 0.44
|
|
221
|
+
return [235, 195, 170] if ellipse(u, v, 0.30, 0.47, 0.03, 0.04) < 1
|
|
222
|
+
stripe_dress = [[0.27, 0.51], [0.33, 0.51], [0.37, 0.70], [0.42, 1.0], [0.18, 1.0], [0.24, 0.70]]
|
|
223
|
+
if inside?(u, v, stripe_dress)
|
|
224
|
+
return dapple.(Math.sin(u * 160 + v * 20) > 0 ? [235, 190, 200] : [80, 100, 170])
|
|
225
|
+
end
|
|
226
|
+
# seated group at right: a man in dark coat, a striped woman, the table
|
|
227
|
+
return [225, 210, 120] if ellipse(u, v, 0.78, 0.53, 0.06, 0.02) < 1
|
|
228
|
+
return [225, 190, 160] if ellipse(u, v, 0.78, 0.58, 0.03, 0.04) < 1
|
|
229
|
+
return dapple.([30, 30, 45]) if inside?(u, v, [[0.72, 0.62], [0.84, 0.62], [0.92, 1.0], [0.66, 1.0]])
|
|
230
|
+
return [235, 195, 175] if ellipse(u, v, 0.58, 0.60, 0.028, 0.036) < 1
|
|
231
|
+
if inside?(u, v, [[0.55, 0.64], [0.62, 0.64], [0.66, 1.0], [0.50, 1.0]])
|
|
232
|
+
return dapple.(Math.sin(u * 160) > 0 ? [240, 220, 225] : [90, 110, 180])
|
|
233
|
+
end
|
|
234
|
+
return [235, 235, 220] if ellipse(u, v, 0.95, 0.80, 0.08, 0.03) < 1
|
|
235
|
+
# lamps on posts under the trees
|
|
236
|
+
[[0.16, 0.10], [0.40, 0.06], [0.62, 0.12], [0.86, 0.07]].each do |lx, ly|
|
|
237
|
+
d = dist(u, v, lx, ly, 1.33)
|
|
238
|
+
return [250, 245, 220] if d < 0.025
|
|
239
|
+
return [235, 220, 170] if d < 0.035
|
|
240
|
+
end
|
|
241
|
+
# the dancing crowd
|
|
242
|
+
if v > 0.20 && v < 0.80
|
|
243
|
+
# two staggered rows of dancers: nearer (bigger) first
|
|
244
|
+
[[11.0, 0.34, 0.032, 0.37], [19.0, 0.23, 0.02, 0.0]].each_with_index do |(cols, base, hr, shift), row|
|
|
245
|
+
col = (u * cols + shift).floor
|
|
246
|
+
next if noise(col, row + 20) < 0.25
|
|
247
|
+
cx = (col + 0.5 - shift) / cols + (noise(col, row + 30) - 0.5) * 0.3 / cols
|
|
248
|
+
hy = base + noise(col, row + 1) * 0.06
|
|
249
|
+
return [230, 190, 160] if ellipse(u, v, cx, hy, hr * 0.65, hr) < 1
|
|
250
|
+
return [225, 205, 120] if noise(col, row + 4) > 0.6 && ellipse(u, v, cx, hy - hr * 0.9, hr * 1.2, hr * 0.45) < 1
|
|
251
|
+
return [35, 30, 30] if ellipse(u, v, cx, hy - hr * 0.7, hr * 0.7, hr * 0.5) < 1
|
|
252
|
+
next unless v > hy + hr && (u - cx).abs < hr * 1.3 + (v - hy) * 0.12
|
|
253
|
+
n = noise(col, row + 2)
|
|
254
|
+
cloth = if n < 0.45 then [30, 30, 45]
|
|
255
|
+
elsif n < 0.65 then [60, 80, 150]
|
|
256
|
+
elsif n < 0.8 then [230, 200, 210]
|
|
257
|
+
else [40, 60, 90]
|
|
258
|
+
end
|
|
259
|
+
return dapple.(cloth)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
if v < 0.30
|
|
263
|
+
leaves = mix([40, 70, 60], [90, 120, 90], vnoise(u, v, 18.0))
|
|
264
|
+
return dapple.(leaves)
|
|
265
|
+
end
|
|
266
|
+
jitter(dapple.(mix([150, 145, 150], [175, 155, 140], v)), u, v, 14)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
DANCERS = [
|
|
270
|
+
[0.06, 0.28, 1.0, [60, 150, 90]], [0.15, 0.30, 1.0, [70, 110, 200]], [0.24, 0.28, 0.95, [230, 190, 60]],
|
|
271
|
+
[0.70, 0.28, 0.9, [210, 60, 50]], [0.80, 0.30, 0.9, [80, 120, 200]], [0.90, 0.27, 0.9, [230, 150, 170]],
|
|
272
|
+
[0.84, 0.56, 1.5, [70, 160, 110]], [0.14, 0.58, 1.45, [230, 110, 50]]
|
|
273
|
+
].freeze
|
|
274
|
+
|
|
275
|
+
# Degas, The Dance Class
|
|
276
|
+
def imp_the_dance_class(u, v)
|
|
277
|
+
DANCERS.reverse_each do |cx, hy, s, sash|
|
|
278
|
+
return [70, 45, 30] if ellipse(u, v, cx, hy, 0.022 * s, 0.022 * s) < 1 && v < hy - 0.005
|
|
279
|
+
return [235, 200, 175] if ellipse(u, v, cx, hy + 0.01 * s, 0.02 * s, 0.026 * s) < 1
|
|
280
|
+
return sash if (v - hy - 0.085 * s).abs < 0.012 * s && (u - cx).abs < 0.03 * s
|
|
281
|
+
return [245, 245, 240] if (u - cx).abs < 0.02 * s && v > hy + 0.03 * s && v < hy + 0.09 * s
|
|
282
|
+
return mix([250, 250, 245], [210, 215, 220], ((u - cx) / (0.07 * s)).abs) if ellipse(u, v, cx, hy + 0.115 * s, 0.07 * s, 0.035 * s) < 1
|
|
283
|
+
return [235, 190, 180] if ((u - cx).abs - 0.012 * s).abs < 0.006 * s && v > hy + 0.12 * s && v < hy + 0.23 * s
|
|
284
|
+
end
|
|
285
|
+
# the dance master leaning on his cane
|
|
286
|
+
return [235, 235, 230] if ellipse(u, v, 0.55, 0.30, 0.025, 0.03) < 1 && v < 0.29
|
|
287
|
+
return [225, 185, 155] if ellipse(u, v, 0.55, 0.315, 0.023, 0.03) < 1
|
|
288
|
+
return [70, 55, 45] if imp_seg(u, v, 0.585, 0.45, 0.62, 0.74) < 0.006
|
|
289
|
+
case imp_figure(u, v, 0.555, 0.33, 0.40, 0.11)
|
|
290
|
+
when :body then return mix([110, 95, 80], [80, 70, 60], (u - 0.5) * 8)
|
|
291
|
+
end
|
|
292
|
+
floor_line = 0.47
|
|
293
|
+
if v > floor_line
|
|
294
|
+
a = Math.atan2(v - 0.20, u - 0.62)
|
|
295
|
+
base = mix([205, 165, 120], [175, 125, 85], (v - floor_line) * 1.6)
|
|
296
|
+
return Color.scale(base, 0.85) if Math.sin(a * 46) > 0.8
|
|
297
|
+
return jitter(base, u, v, 8, 60.0)
|
|
298
|
+
end
|
|
299
|
+
# pilaster and doorway with mirror
|
|
300
|
+
return [205, 205, 185] if u > 0.31 && u < 0.37
|
|
301
|
+
return [215, 215, 195] if u > 0.29 && u < 0.39 && v < 0.05
|
|
302
|
+
return mix([130, 145, 140], [160, 170, 160], vnoise(u, v, 10.0)) if u > 0.77 && u < 0.97 && v > 0.05
|
|
303
|
+
jitter(mix([180, 190, 170], [160, 170, 150], v * 2), u, v, 10)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Seurat, A Sunday on La Grande Jatte (scene before pointillist dots)
|
|
307
|
+
def imp_grande_jatte_scene(u, v)
|
|
308
|
+
dark = [35, 40, 50]
|
|
309
|
+
# couple in profile at right: woman with bustle and parasol, man in top hat
|
|
310
|
+
return [150, 60, 50] if ellipse(u, v, 0.79, 0.28, 0.06, 0.035) < 1 && v < 0.29
|
|
311
|
+
return [60, 40, 40] if imp_seg(u, v, 0.79, 0.28, 0.80, 0.40) < 0.006
|
|
312
|
+
return [230, 190, 160] if ellipse(u, v, 0.80, 0.36, 0.012, 0.02) < 1
|
|
313
|
+
return dark if inside?(u, v, [[0.79, 0.39], [0.82, 0.39], [0.83, 0.55], [0.88, 0.60], [0.86, 0.96], [0.74, 0.96], [0.77, 0.55]])
|
|
314
|
+
return [20, 20, 25] if (u - 0.905).abs < 0.014 && v > 0.22 && v < 0.29
|
|
315
|
+
return [20, 20, 25] if (u - 0.905).abs < 0.025 && (v - 0.29).abs < 0.006
|
|
316
|
+
return [230, 190, 160] if ellipse(u, v, 0.905, 0.32, 0.013, 0.025) < 1
|
|
317
|
+
return [30, 30, 40] if inside?(u, v, [[0.89, 0.35], [0.93, 0.35], [0.95, 0.96], [0.87, 0.96]])
|
|
318
|
+
# woman with child in white, center
|
|
319
|
+
return [245, 245, 240] if (case imp_figure(u, v, 0.52, 0.48, 0.20, 0.07) when :head, :body then true end)
|
|
320
|
+
case imp_figure(u, v, 0.47, 0.38, 0.34, 0.11)
|
|
321
|
+
when :head then return [230, 190, 160]
|
|
322
|
+
when :body then return [120, 50, 70]
|
|
323
|
+
end
|
|
324
|
+
# seated woman with orange parasol, reclining man at lower left
|
|
325
|
+
return [230, 120, 50] if ellipse(u, v, 0.22, 0.52, 0.06, 0.035) < 1 && v < 0.53
|
|
326
|
+
return dark if ellipse(u, v, 0.23, 0.63, 0.05, 0.08) < 1
|
|
327
|
+
return [45, 35, 30] if ellipse(u, v, 0.11, 0.80, 0.10, 0.045) < 1
|
|
328
|
+
return [235, 200, 170] if ellipse(u, v, 0.04, 0.76, 0.02, 0.03) < 1
|
|
329
|
+
# small distant strollers
|
|
330
|
+
[[0.35, 0.30, 0.12], [0.62, 0.26, 0.11], [0.68, 0.33, 0.13], [0.42, 0.25, 0.08], [0.58, 0.40, 0.12]].each do |fx, fy, fh|
|
|
331
|
+
return dark if imp_figure(u, v, fx, fy, fh, fh * 0.35)
|
|
332
|
+
end
|
|
333
|
+
# trees: canopy at top, trunks
|
|
334
|
+
return [40, 70, 40] if v < 0.10 + 0.05 * vnoise(u, 0.0, 9.0)
|
|
335
|
+
return [70, 60, 45] if ((u - 0.30).abs < 0.012 || (u - 0.70).abs < 0.014) && v < 0.42
|
|
336
|
+
# the river at top left
|
|
337
|
+
if v < 0.42 - u * 0.75
|
|
338
|
+
return [250, 250, 245] if ellipse(u, v, 0.12, 0.20, 0.03, 0.03) < 1 && v < 0.21
|
|
339
|
+
return [140, 175, 210]
|
|
340
|
+
end
|
|
341
|
+
# grass: shade in front, sun behind
|
|
342
|
+
shade = v > 0.70 - 0.08 * u + 0.04 * Math.sin(u * 7)
|
|
343
|
+
shade ? [40, 95, 55] : [160, 200, 80]
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def imp_grande_jatte(u, v)
|
|
347
|
+
c = imp_grande_jatte_scene(u, v)
|
|
348
|
+
cx = (u * 100).floor
|
|
349
|
+
cy = (v * 68).floor
|
|
350
|
+
n = noise(cx, cy)
|
|
351
|
+
if n < 0.2 then mix(c, [240, 150, 60], 0.3)
|
|
352
|
+
elsif n > 0.82 then mix(c, [70, 110, 210], 0.3)
|
|
353
|
+
elsif n > 0.65 then mix(c, [255, 250, 220], 0.2)
|
|
354
|
+
else jitter(c, u, v, 12, 90.0)
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Manet, A Bar at the Folies-Bergere
|
|
359
|
+
def imp_bar_folies(u, v)
|
|
360
|
+
skin = [240, 215, 195]
|
|
361
|
+
# bottles on the marble counter
|
|
362
|
+
[[0.05, [40, 70, 40]], [0.09, [120, 40, 30]], [0.13, [40, 70, 40]], [0.18, [200, 120, 40]], [0.84, [40, 70, 40]], [0.89, [120, 40, 30]]].each do |bx, bc|
|
|
363
|
+
next unless v > 0.52 && v < 0.72
|
|
364
|
+
return [230, 190, 80] if (u - bx).abs < 0.009 && v < 0.56
|
|
365
|
+
return bc if (u - bx).abs < (v < 0.60 ? 0.008 : 0.016)
|
|
366
|
+
end
|
|
367
|
+
return [240, 140, 40] if ellipse(u, v, 0.67, 0.69, 0.06, 0.03) < 1 && v < 0.70
|
|
368
|
+
# barmaid: hair, face, dark bodice with lace, hands on the counter
|
|
369
|
+
return [190, 140, 80] if ellipse(u, v, 0.50, 0.26, 0.05, 0.05) < 1 && v < 0.27
|
|
370
|
+
return skin if ellipse(u, v, 0.50, 0.30, 0.04, 0.06) < 1
|
|
371
|
+
return skin if (u - 0.5).abs < 0.022 && v > 0.34 && v < 0.40
|
|
372
|
+
body = [[0.42, 0.40], [0.58, 0.40], [0.62, 0.68], [0.38, 0.68]]
|
|
373
|
+
if inside?(u, v, body)
|
|
374
|
+
return [240, 150, 160] if ellipse(u, v, 0.53, 0.46, 0.02, 0.02) < 1
|
|
375
|
+
return [235, 230, 225] if v < 0.47 && (u - 0.5).abs < (0.47 - v) * 0.9
|
|
376
|
+
return [35, 35, 55]
|
|
377
|
+
end
|
|
378
|
+
return skin if ellipse(u, v, 0.39, 0.68, 0.025, 0.02) < 1 || ellipse(u, v, 0.61, 0.68, 0.025, 0.02) < 1
|
|
379
|
+
# marble counter
|
|
380
|
+
if v > 0.68
|
|
381
|
+
return [120, 110, 100] if v > 0.73 && v < 0.745
|
|
382
|
+
return mix([235, 225, 210], [200, 190, 180], v > 0.745 ? 0.6 : 0.0)
|
|
383
|
+
end
|
|
384
|
+
# in the mirror: her back and the man in a top hat
|
|
385
|
+
return [190, 150, 100] if ellipse(u, v, 0.80, 0.33, 0.035, 0.045) < 1
|
|
386
|
+
return [55, 50, 65] if inside?(u, v, [[0.76, 0.37], [0.84, 0.37], [0.87, 0.68], [0.73, 0.68]])
|
|
387
|
+
return [25, 25, 30] if (u - 0.93).abs < 0.03 && v > 0.17 && v < 0.27
|
|
388
|
+
return [210, 180, 150] if ellipse(u, v, 0.93, 0.31, 0.03, 0.045) < 1
|
|
389
|
+
return [40, 40, 45] if u > 0.89 && v > 0.35 && v < 0.68
|
|
390
|
+
# chandeliers and lamps
|
|
391
|
+
[[0.27, 0.13, 0.06], [0.63, 0.10, 0.05], [0.08, 0.30, 0.025], [0.40, 0.24, 0.025]].each do |lx, ly, r|
|
|
392
|
+
d = dist(u, v, lx, ly, 1.35)
|
|
393
|
+
return [255, 250, 230] if d < r * 0.5
|
|
394
|
+
return mix([255, 240, 190], [200, 180, 140], (d - r * 0.5) / (r * 0.5)) if d < r
|
|
395
|
+
end
|
|
396
|
+
return [80, 160, 70] if dist(u, v, 0.03, 0.06, 1.35) < 0.02
|
|
397
|
+
return [190, 160, 90] if (v - 0.22).abs < 0.01
|
|
398
|
+
crowd = ramp(vnoise(u, v, 14.0), [120, 105, 90], [175, 160, 140], [215, 205, 185], [235, 225, 200])
|
|
399
|
+
crowd = mix(crowd, [60, 55, 60], 0.5) if v > 0.30 && noise((u * 30).floor, (v * 20).floor) > 0.7
|
|
400
|
+
jitter(crowd, u, v, 12)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Manet, Luncheon on the Grass
|
|
404
|
+
def imp_luncheon(u, v)
|
|
405
|
+
pale = [235, 220, 195]
|
|
406
|
+
suit = [30, 30, 35]
|
|
407
|
+
# still life at lower left: fruit, basket, blue dress
|
|
408
|
+
return [210, 60, 40] if dist(u, v, 0.15, 0.80, 1.27) < 0.018
|
|
409
|
+
return [235, 160, 50] if dist(u, v, 0.20, 0.81, 1.27) < 0.018
|
|
410
|
+
return [150, 110, 50] if ellipse(u, v, 0.17, 0.86, 0.07, 0.035) < 1
|
|
411
|
+
return [110, 140, 190] if ellipse(u, v, 0.07, 0.86, 0.08, 0.06) < 1
|
|
412
|
+
return [230, 200, 110] if ellipse(u, v, 0.08, 0.76, 0.05, 0.02) < 1
|
|
413
|
+
# reclining man at right with black cap
|
|
414
|
+
return [20, 20, 25] if ellipse(u, v, 0.64, 0.42, 0.035, 0.022) < 1 && v < 0.43
|
|
415
|
+
return [220, 180, 150] if ellipse(u, v, 0.64, 0.46, 0.028, 0.04) < 1
|
|
416
|
+
return suit if ellipse(u, v, 0.68, 0.60, 0.09, 0.10) < 1
|
|
417
|
+
return suit if imp_seg(u, v, 0.70, 0.66, 0.92, 0.78, 1.27) < 0.04
|
|
418
|
+
return [230, 190, 160] if ellipse(u, v, 0.57, 0.58, 0.02, 0.02) < 1
|
|
419
|
+
# middle man
|
|
420
|
+
return [120, 90, 60] if ellipse(u, v, 0.47, 0.40, 0.03, 0.025) < 1 && v < 0.40
|
|
421
|
+
return [220, 180, 150] if ellipse(u, v, 0.47, 0.43, 0.027, 0.038) < 1
|
|
422
|
+
return suit if ellipse(u, v, 0.48, 0.58, 0.07, 0.11) < 1
|
|
423
|
+
return suit if imp_seg(u, v, 0.48, 0.66, 0.44, 0.86, 1.27) < 0.035
|
|
424
|
+
# pale seated figure at left
|
|
425
|
+
return [40, 30, 25] if ellipse(u, v, 0.33, 0.42, 0.035, 0.03) < 1 && v < 0.43
|
|
426
|
+
return pale if ellipse(u, v, 0.33, 0.45, 0.03, 0.04) < 1
|
|
427
|
+
return pale if ellipse(u, v, 0.31, 0.60, 0.06, 0.11) < 1
|
|
428
|
+
return pale if ellipse(u, v, 0.39, 0.72, 0.09, 0.045) < 1
|
|
429
|
+
# bathing woman in the clearing
|
|
430
|
+
return [235, 235, 225] if ellipse(u, v, 0.50, 0.30, 0.03, 0.05) < 1
|
|
431
|
+
if ellipse(u, v, 0.50, 0.26, 0.16, 0.26) + (vnoise(u, v, 9.0) - 0.5) * 0.9 < 1 && v > 0.04
|
|
432
|
+
return mix([100, 130, 100], [140, 160, 120], vnoise(u, v, 8.0)) if v > 0.30
|
|
433
|
+
return mix([120, 150, 90], [170, 185, 130], vnoise(u, v, 9.0))
|
|
434
|
+
end
|
|
435
|
+
if v > 0.70 + 0.04 * Math.sin(u * 9)
|
|
436
|
+
return jitter(mix([60, 80, 40], [40, 55, 30], v), u, v, 14)
|
|
437
|
+
end
|
|
438
|
+
woods = ramp(vnoise(u, v, 10.0), [15, 30, 20], [35, 60, 35], [60, 90, 50], [90, 110, 60])
|
|
439
|
+
jitter(woods, u, v, 10)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
SUNFLOWERS = [
|
|
443
|
+
[0.36, 0.56, 0.07, 1], [0.58, 0.55, 0.075, 0], [0.18, 0.58, 0.07, 1], [0.78, 0.62, 0.07, 0],
|
|
444
|
+
[0.44, 0.36, 0.10, 0], [0.24, 0.40, 0.085, 0], [0.64, 0.40, 0.09, 1], [0.84, 0.42, 0.08, 0],
|
|
445
|
+
[0.30, 0.20, 0.09, 0], [0.52, 0.14, 0.085, 1], [0.72, 0.22, 0.09, 0], [0.12, 0.24, 0.07, 1],
|
|
446
|
+
[0.88, 0.25, 0.065, 1], [0.64, 0.06, 0.06, 0]
|
|
447
|
+
].freeze
|
|
448
|
+
|
|
449
|
+
# van Gogh, Sunflowers
|
|
450
|
+
def imp_sunflowers(u, v)
|
|
451
|
+
# vase with the blue line
|
|
452
|
+
if v > 0.62 && v < 0.93
|
|
453
|
+
half = 0.11 + 0.035 * Math.sin(Math::PI * (v - 0.62) / 0.31)
|
|
454
|
+
if (u - 0.48).abs < half
|
|
455
|
+
return [60, 90, 170] if (v - 0.72).abs < 0.009
|
|
456
|
+
return v < 0.72 ? mix([245, 210, 90], [215, 170, 60], (u - 0.48) / half) : mix([230, 175, 60], [190, 130, 40], (u - 0.48) / half)
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
SUNFLOWERS.each do |fx, fy, r, kind|
|
|
460
|
+
d = dist(u, v, fx, fy, 0.79)
|
|
461
|
+
next if d > r
|
|
462
|
+
a = Math.atan2(v - fy, (u - fx) * 0.79)
|
|
463
|
+
return (kind == 1 ? [190, 110, 30] : [150, 80, 25]) if d < r * 0.45 && noise((u * 90).floor, (v * 70).floor) > 0.25
|
|
464
|
+
return [110, 60, 20] if d < r * 0.45
|
|
465
|
+
return (Math.sin(a * 13) > 0 ? [245, 185, 30] : [230, 150, 30]) if d < r * (0.78 + 0.22 * Math.sin(a * 13))
|
|
466
|
+
end
|
|
467
|
+
# stems
|
|
468
|
+
return [110, 130, 40] if [[0.36, 0.56], [0.58, 0.55], [0.44, 0.36], [0.64, 0.40]].any? { |sx, sy| imp_seg(u, v, sx, sy, 0.48, 0.63) < 0.007 } && v < 0.63
|
|
469
|
+
# table and wall
|
|
470
|
+
return [195, 130, 40] if (v - 0.78).abs < 0.007
|
|
471
|
+
if v > 0.78
|
|
472
|
+
return jitter(mix([225, 170, 60], [210, 150, 50], brush(u, v, angle: 0.1, freq: 40.0) * 0.5 + 0.5), u, v, 8)
|
|
473
|
+
end
|
|
474
|
+
wall = brush(u, v, angle: 0.9, freq: 30.0, wobble: 0.5) > 0.3 ? [240, 215, 110] : [230, 200, 90]
|
|
475
|
+
jitter(wall, u, v, 8)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# van Gogh, Cafe Terrace at Night
|
|
479
|
+
def imp_cafe_terrace(u, v)
|
|
480
|
+
# yellow awning in perspective
|
|
481
|
+
awn_top = 0.02 + u * 0.45
|
|
482
|
+
awn_bot = 0.36 - u * 0.05
|
|
483
|
+
if u < 0.48 && v > awn_top && v < awn_bot
|
|
484
|
+
return Math.sin(u * 50) > 0.7 ? [235, 160, 40] : [250, 210, 60]
|
|
485
|
+
end
|
|
486
|
+
# building above the awning
|
|
487
|
+
return mix([50, 70, 90], [80, 90, 100], vnoise(u, v, 10.0)) if u < 0.48 && v <= awn_top
|
|
488
|
+
terrace_edge = 0.86 - u * 0.5
|
|
489
|
+
if u < 0.50 && v >= awn_bot && v < terrace_edge
|
|
490
|
+
# tables and patrons on the lit terrace
|
|
491
|
+
[[0.10, 0.62, 0.06], [0.24, 0.58, 0.05], [0.36, 0.53, 0.04], [0.20, 0.72, 0.07], [0.42, 0.48, 0.03]].each do |tx, ty, r|
|
|
492
|
+
return [235, 235, 200] if ellipse(u, v, tx, ty, r, r * 0.35) < 1
|
|
493
|
+
return [60, 50, 40] if (u - tx).abs < 0.006 && v > ty && v < ty + r * 1.2
|
|
494
|
+
end
|
|
495
|
+
return [50, 50, 60] if imp_figure(u, v, 0.30, 0.44, 0.12, 0.05)
|
|
496
|
+
return mix([240, 180, 60], [220, 140, 40], vnoise(u, v, 12.0)) if v < 0.48
|
|
497
|
+
return mix([240, 190, 90], [225, 160, 60], vnoise(u, v, 14.0))
|
|
498
|
+
end
|
|
499
|
+
# dark buildings at right
|
|
500
|
+
if u > 0.80 - v * 0.05 && v < 0.82
|
|
501
|
+
return [240, 190, 80] if ((u * 18) % 1.0) < 0.35 && ((v * 14) % 1.0) < 0.3 && v > 0.25 && noise((u * 18).floor, (v * 14).floor) > 0.5
|
|
502
|
+
return mix([30, 55, 70], [55, 75, 70], vnoise(u, v, 9.0))
|
|
503
|
+
end
|
|
504
|
+
# starry corridor of sky
|
|
505
|
+
if v < 0.38 + 0.02 * Math.sin(u * 30)
|
|
506
|
+
[[0.55, 0.08], [0.67, 0.05], [0.76, 0.14], [0.60, 0.21], [0.71, 0.27], [0.53, 0.30], [0.66, 0.35]].each do |sx, sy|
|
|
507
|
+
d = dist(u, v, sx, sy, 0.81)
|
|
508
|
+
return [255, 250, 220] if d < 0.014
|
|
509
|
+
return [220, 220, 170] if d < 0.024
|
|
510
|
+
end
|
|
511
|
+
return mix([20, 40, 120], [40, 70, 160], v * 2.2 + (brush(u, v, angle: 0.5, freq: 25.0) * 0.1))
|
|
512
|
+
end
|
|
513
|
+
# distant street and walkers
|
|
514
|
+
return [40, 40, 50] if imp_figure(u, v, 0.62, 0.42, 0.10, 0.04) || imp_figure(u, v, 0.70, 0.44, 0.09, 0.035)
|
|
515
|
+
return [45, 60, 90] if v < 0.48
|
|
516
|
+
# cobblestones
|
|
517
|
+
sv = 1.0 / (v - 0.38)
|
|
518
|
+
su = (u - 0.62) * sv
|
|
519
|
+
cell_x = (su * 4).floor
|
|
520
|
+
cell_y = (sv * 5).floor
|
|
521
|
+
fx = su * 4 - cell_x
|
|
522
|
+
fy = sv * 5 - cell_y
|
|
523
|
+
return [40, 40, 70] if fx < 0.15 || fy < 0.15
|
|
524
|
+
stone = noise(cell_x, cell_y)
|
|
525
|
+
return [230, 160, 120] if stone > 0.75 && u < 0.7
|
|
526
|
+
mix([90, 100, 160], [130, 120, 170], stone)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
CROWS = [[0.30, 0.18, 0.035], [0.42, 0.10, 0.03], [0.55, 0.22, 0.04], [0.64, 0.12, 0.03], [0.72, 0.28, 0.035],
|
|
530
|
+
[0.80, 0.16, 0.03], [0.48, 0.35, 0.04], [0.60, 0.42, 0.035], [0.86, 0.33, 0.03], [0.22, 0.30, 0.03],
|
|
531
|
+
[0.38, 0.44, 0.03]].freeze
|
|
532
|
+
|
|
533
|
+
# van Gogh, Wheatfield with Crows
|
|
534
|
+
def imp_wheatfield_with_crows(u, v)
|
|
535
|
+
aspect = 2.04
|
|
536
|
+
CROWS.each do |cx, cy, s|
|
|
537
|
+
du = (u - cx) * aspect
|
|
538
|
+
next if du.abs > s
|
|
539
|
+
return [15, 15, 20] if (v - (cy - du.abs * 0.6)).abs < 0.022
|
|
540
|
+
end
|
|
541
|
+
horizon = 0.42 + 0.03 * Math.sin(u * 5)
|
|
542
|
+
if v < horizon
|
|
543
|
+
sky = mix([15, 30, 90], [40, 80, 160], vnoise(u, v, 6.0) + v)
|
|
544
|
+
sky = mix(sky, [80, 130, 200], 0.6) if brush(u, v, angle: 0.3 + vnoise(u, v, 3.0), freq: 25.0, wobble: 0.8) > 0.5
|
|
545
|
+
[[0.25, 0.20], [0.78, 0.14]].each do |cx, cy|
|
|
546
|
+
sky = mix(sky, [170, 205, 215], 0.85) if dist(u, v, cx, cy, aspect) < 0.08 + 0.03 * brush(u, v, freq: 30.0)
|
|
547
|
+
end
|
|
548
|
+
return sky
|
|
549
|
+
end
|
|
550
|
+
# the red-brown paths with green verges
|
|
551
|
+
if v > horizon + 0.03
|
|
552
|
+
t = (v - horizon) / (1.0 - horizon)
|
|
553
|
+
center = 0.52 - t * 0.02
|
|
554
|
+
w = 0.01 + t * 0.10
|
|
555
|
+
off = (u - center).abs
|
|
556
|
+
return mix([190, 80, 40], [150, 60, 30], vnoise(u, v, 20.0)) if off < w
|
|
557
|
+
return [60, 140, 60] if off < w + 0.015 + t * 0.03
|
|
558
|
+
[[0.0, 0.70, 0.26, 0.50], [1.0, 0.66, 0.76, 0.48]].each do |ax, ay, bx, by|
|
|
559
|
+
d = imp_seg(u, v, ax, ay, bx, by, aspect)
|
|
560
|
+
return [180, 80, 40] if d < 0.03 && v > by
|
|
561
|
+
return [70, 140, 60] if d < 0.055 && v > by
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
# agitated wheat
|
|
565
|
+
ang = 1.2 + (vnoise(u, v, 5.0) - 0.5) * 2.0
|
|
566
|
+
st = brush(u, v, angle: ang, freq: 35.0, wobble: 0.8)
|
|
567
|
+
wheat = if st > 0.5 then [245, 205, 80]
|
|
568
|
+
elsif st < -0.6 then [170, 110, 20]
|
|
569
|
+
else [220, 165, 40]
|
|
570
|
+
end
|
|
571
|
+
wheat = mix(wheat, [100, 140, 50], 0.5) if v < horizon + 0.05 && vnoise(u, v, 20.0) > 0.55
|
|
572
|
+
wheat
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
# van Gogh, Bedroom in Arles
|
|
576
|
+
def imp_bedroom_in_arles(u, v)
|
|
577
|
+
bed_yellow = [230, 170, 60]
|
|
578
|
+
# footboard at front right
|
|
579
|
+
return mix(bed_yellow, [190, 130, 40], (u - 0.70) * 3) if u > 0.70 && v > 0.66 && v < 0.94 && v > 0.66 + (u - 0.70) * 0.05
|
|
580
|
+
# mattress, red blanket, white pillows
|
|
581
|
+
mattress = [[0.60, 0.44], [0.86, 0.44], [1.0, 0.66], [0.70, 0.68]]
|
|
582
|
+
if inside?(u, v, mattress)
|
|
583
|
+
return [245, 240, 205] if v < 0.50
|
|
584
|
+
return mix([220, 60, 40], [180, 40, 30], vnoise(u, v, 12.0))
|
|
585
|
+
end
|
|
586
|
+
return bed_yellow if u > 0.60 && u < 0.86 && v > 0.27 && v < 0.46
|
|
587
|
+
# chair by the bed and chair at front left
|
|
588
|
+
[[0.52, 0.60, 0.8], [0.15, 0.80, 1.3]].each do |cx, cy, s|
|
|
589
|
+
return [215, 175, 90] if ellipse(u, v, cx, cy, 0.06 * s, 0.025 * s) < 1
|
|
590
|
+
return [200, 140, 50] if ((u - cx).abs - 0.05 * s).abs < 0.008 * s && v < cy && v > cy - 0.14 * s
|
|
591
|
+
return [200, 140, 50] if (v - (cy - 0.12 * s)).abs < 0.008 * s && (u - cx).abs < 0.05 * s
|
|
592
|
+
return [180, 120, 40] if ((u - cx).abs - 0.05 * s).abs < 0.008 * s && v > cy && v < cy + 0.09 * s
|
|
593
|
+
end
|
|
594
|
+
# small table with jug
|
|
595
|
+
return [80, 110, 170] if ellipse(u, v, 0.28, 0.47, 0.012, 0.025) < 1
|
|
596
|
+
return [210, 170, 100] if u > 0.20 && u < 0.36 && (v - 0.50).abs < 0.015
|
|
597
|
+
return [180, 130, 70] if ((u - 0.22).abs < 0.006 || (u - 0.34).abs < 0.006) && v > 0.50 && v < 0.66
|
|
598
|
+
# floor in tilted perspective
|
|
599
|
+
floor_v = u < 0.22 ? 0.82 - u * 1.2 : 0.556 + (u > 0.72 ? (u - 0.72) * 0.6 : 0.0)
|
|
600
|
+
if v > floor_v
|
|
601
|
+
a = Math.atan2(v - 0.20, u - 0.45)
|
|
602
|
+
base = mix([200, 120, 90], [170, 100, 80], v)
|
|
603
|
+
return Math.sin(a * 40) > 0.75 ? [150, 150, 100] : base
|
|
604
|
+
end
|
|
605
|
+
# pictures on the walls
|
|
606
|
+
[[0.66, 0.08, 0.04, 0.06], [0.78, 0.12, 0.04, 0.06], [0.90, 0.10, 0.05, 0.07], [0.25, 0.14, 0.03, 0.06]].each do |px, py, rx, ry|
|
|
607
|
+
next unless (u - px).abs < rx && (v - py).abs < ry
|
|
608
|
+
return [190, 150, 60] if (u - px).abs > rx * 0.7 || (v - py).abs > ry * 0.75
|
|
609
|
+
return [200, 160, 110] if dist(u, v, px, py - ry * 0.2, 1.25) < rx * 0.5
|
|
610
|
+
return [90, 140, 120]
|
|
611
|
+
end
|
|
612
|
+
# window with green shutters
|
|
613
|
+
if u > 0.34 && u < 0.50 && v > 0.05 && v < 0.40
|
|
614
|
+
return [70, 120, 60] if (u - 0.42).abs < 0.008 || (v - 0.20).abs < 0.008
|
|
615
|
+
return [150, 190, 110]
|
|
616
|
+
end
|
|
617
|
+
return [70, 130, 80] if u > 0.30 && u < 0.54 && v > 0.03 && v < 0.42
|
|
618
|
+
# left wall door, back wall, right wall
|
|
619
|
+
return [100, 110, 170] if u < 0.13 && u > 0.03 && v > 0.12 && v < 0.75
|
|
620
|
+
return [140, 150, 210] if u < 0.22
|
|
621
|
+
return [120, 130, 195] if u > 0.72
|
|
622
|
+
jitter([150, 165, 215], u, v, 6)
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
ALMOND_BRANCHES = [
|
|
626
|
+
[0.00, 0.98, 0.28, 0.58, 0.035], [0.28, 0.58, 0.45, 0.36, 0.028], [0.45, 0.36, 0.63, 0.20, 0.022],
|
|
627
|
+
[0.63, 0.20, 0.86, 0.04, 0.016], [0.28, 0.58, 0.14, 0.26, 0.018], [0.14, 0.26, 0.08, 0.02, 0.012],
|
|
628
|
+
[0.14, 0.26, 0.32, 0.10, 0.011], [0.45, 0.36, 0.72, 0.46, 0.016], [0.72, 0.46, 0.97, 0.38, 0.011],
|
|
629
|
+
[0.72, 0.46, 0.84, 0.78, 0.012], [0.84, 0.78, 0.92, 0.98, 0.010], [0.63, 0.20, 0.56, 0.02, 0.011]
|
|
630
|
+
].freeze
|
|
631
|
+
ALMOND_BLOSSOMS = ALMOND_BRANCHES.each_with_index.flat_map do |(ax, ay, bx, by, _), i|
|
|
632
|
+
[0.25, 0.55, 0.85].each_with_index.map do |t, j|
|
|
633
|
+
side = (i + j).even? ? 1 : -1
|
|
634
|
+
nx = -(by - ay)
|
|
635
|
+
ny = bx - ax
|
|
636
|
+
len = Math.hypot(nx, ny)
|
|
637
|
+
[ax + (bx - ax) * t + side * nx / len * 0.035, ay + (by - ay) * t + side * ny / len * 0.035, (i * 3 + j) % 4]
|
|
638
|
+
end
|
|
639
|
+
end.freeze
|
|
640
|
+
|
|
641
|
+
# van Gogh, Almond Blossoms
|
|
642
|
+
def imp_almond_blossoms(u, v)
|
|
643
|
+
aspect = 1.25
|
|
644
|
+
ALMOND_BLOSSOMS.each do |bx, by, kind|
|
|
645
|
+
d = dist(u, v, bx, by, aspect)
|
|
646
|
+
next if d > 0.05
|
|
647
|
+
a = Math.atan2(v - by, (u - bx) * aspect)
|
|
648
|
+
r = (kind.zero? ? 0.025 : 0.04) * (0.75 + 0.25 * Math.cos(a * 5))
|
|
649
|
+
next if d > r
|
|
650
|
+
return [200, 70, 90] if d < r * 0.3
|
|
651
|
+
return kind == 3 ? [245, 215, 220] : mix([255, 255, 250], [225, 235, 230], d / r)
|
|
652
|
+
end
|
|
653
|
+
ALMOND_BRANCHES.each do |ax, ay, bx, by, w|
|
|
654
|
+
d = imp_seg(u, v, ax, ay, bx, by, aspect)
|
|
655
|
+
return d < w * 0.4 ? [70, 80, 50] : [40, 50, 35] if d < w
|
|
656
|
+
end
|
|
657
|
+
sky = brush(u, v, angle: 0.6 + vnoise(u, v, 3.0), freq: 30.0) > 0.4 ? [140, 205, 210] : [100, 175, 195]
|
|
658
|
+
jitter(sky, u, v, 8)
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
# van Gogh, Self-Portrait (1889)
|
|
662
|
+
def imp_van_gogh_self_portrait(u, v)
|
|
663
|
+
hair = [205, 110, 45]
|
|
664
|
+
# blue suit with swirling strokes, white collar
|
|
665
|
+
coat = [[0.12, 1.0], [0.16, 0.72], [0.32, 0.58], [0.50, 0.55], [0.68, 0.58], [0.84, 0.70], [0.90, 1.0]]
|
|
666
|
+
if inside?(u, v, coat)
|
|
667
|
+
return [235, 235, 220] if v < 0.66 && (u - 0.50).abs < (0.66 - v) * 0.7 && v > 0.55
|
|
668
|
+
return [40, 60, 100] if ((u - 0.5).abs - (v - 0.55) * 0.3).abs < 0.012
|
|
669
|
+
return brush(u, v, angle: 0.8 + vnoise(u, v, 4.0) * 2, freq: 35.0) > 0.3 ? [90, 120, 170] : [55, 80, 130]
|
|
670
|
+
end
|
|
671
|
+
return [200, 160, 110] if (u - 0.50).abs < 0.06 && v > 0.47 && v < 0.58
|
|
672
|
+
# face in three-quarter view, beard and hair
|
|
673
|
+
face = ellipse(u, v, 0.48, 0.34, 0.14, 0.17)
|
|
674
|
+
if face < 1
|
|
675
|
+
return [70, 90, 60] if ((u - 0.43).abs < 0.025 || (u - 0.55).abs < 0.022) && (v - 0.31).abs < 0.012
|
|
676
|
+
return mix(hair, [170, 80, 35], vnoise(u, v, 30.0)) if v < 0.24 + (u - 0.48).abs * 0.2
|
|
677
|
+
return mix(hair, [230, 140, 60], vnoise(u, v, 30.0)) if v > 0.41 - (u - 0.48).abs * 0.15
|
|
678
|
+
return [170, 120, 80] if (u - 0.47).abs < 0.008 && v > 0.32 && v < 0.38
|
|
679
|
+
return mix([230, 190, 130], [170, 150, 100], smooth(0.40, 0.62, u))
|
|
680
|
+
end
|
|
681
|
+
return [205, 160, 110] if ellipse(u, v, 0.625, 0.34, 0.02, 0.04) < 1
|
|
682
|
+
# swirling pale blue background
|
|
683
|
+
r = dist(u, v, 0.5, 0.35, 0.83)
|
|
684
|
+
a = Math.atan2(v - 0.35, (u - 0.5) * 0.83)
|
|
685
|
+
swirl = Math.sin(r * 60 + a * 4 + vnoise(u, v, 5.0) * 3)
|
|
686
|
+
base = swirl > 0.3 ? [175, 205, 210] : [130, 175, 190]
|
|
687
|
+
jitter(base, u, v, 8)
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
VICTOIRE_RIDGE = [[0.0, 0.45], [0.25, 0.38], [0.45, 0.30], [0.60, 0.20], [0.66, 0.22], [0.78, 0.36], [0.90, 0.40], [1.0, 0.43]].freeze
|
|
691
|
+
|
|
692
|
+
# Cezanne, Mont Sainte-Victoire
|
|
693
|
+
def imp_mont_sainte_victoire(u, v)
|
|
694
|
+
ridge = VICTOIRE_RIDGE.each_cons(2).each do |(x0, y0), (x1, y1)|
|
|
695
|
+
break y0 + (y1 - y0) * (u - x0) / (x1 - x0) if u <= x1
|
|
696
|
+
end
|
|
697
|
+
ridge = 0.43 unless ridge.is_a?(Float)
|
|
698
|
+
px = u * 13 + v * 4
|
|
699
|
+
py = v * 15 - u * 2
|
|
700
|
+
n = noise(px.floor, py.floor)
|
|
701
|
+
if v < ridge
|
|
702
|
+
pal = [[120, 170, 175], [175, 205, 200], [100, 145, 180], [150, 190, 170], [200, 215, 210]]
|
|
703
|
+
return pal[(n * pal.size).floor]
|
|
704
|
+
end
|
|
705
|
+
return [80, 90, 140] if v < ridge + 0.015
|
|
706
|
+
if v < ridge + 0.13 - u * 0.04 && u > 0.35
|
|
707
|
+
pal = [[130, 140, 175], [170, 160, 175], [190, 175, 170], [115, 125, 160]]
|
|
708
|
+
return pal[(n * pal.size).floor]
|
|
709
|
+
end
|
|
710
|
+
# houses in the valley
|
|
711
|
+
if v > 0.55 && v < 0.78 && noise(px.floor + 11, py.floor) > 0.82
|
|
712
|
+
return py - py.floor < 0.35 ? [190, 90, 50] : [230, 190, 120]
|
|
713
|
+
end
|
|
714
|
+
pal = if v > 0.86 then [[40, 80, 50], [60, 100, 60], [90, 120, 70], [50, 70, 60]]
|
|
715
|
+
else [[90, 140, 80], [130, 160, 80], [200, 165, 95], [110, 150, 110], [175, 150, 80], [70, 120, 80]]
|
|
716
|
+
end
|
|
717
|
+
pal[(n * pal.size).floor]
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
# Cezanne, The Card Players
|
|
721
|
+
def imp_the_card_players(u, v)
|
|
722
|
+
skin = [210, 150, 100]
|
|
723
|
+
# bottle in the middle
|
|
724
|
+
if (u - 0.5).abs < (v < 0.40 ? 0.012 : 0.03) && v > 0.28 && v < 0.58
|
|
725
|
+
return [230, 230, 210] if (u - 0.49).abs < 0.006 && v > 0.40
|
|
726
|
+
return [40, 50, 40]
|
|
727
|
+
end
|
|
728
|
+
# cards and hands
|
|
729
|
+
return [240, 235, 215] if ellipse(u, v, 0.38, 0.54, 0.025, 0.025) < 1 || ellipse(u, v, 0.63, 0.54, 0.025, 0.025) < 1
|
|
730
|
+
return skin if ellipse(u, v, 0.40, 0.58, 0.03, 0.022) < 1 || ellipse(u, v, 0.61, 0.58, 0.03, 0.022) < 1
|
|
731
|
+
# table top and front
|
|
732
|
+
if u > 0.30 && u < 0.70 && v > 0.58
|
|
733
|
+
return [205, 155, 90] if v < 0.64
|
|
734
|
+
return mix([170, 80, 40], [130, 60, 35], vnoise(u, v, 10.0))
|
|
735
|
+
end
|
|
736
|
+
# left man with pipe, blue-violet jacket
|
|
737
|
+
return [245, 245, 235] if imp_seg(u, v, 0.31, 0.31, 0.37, 0.34) < 0.008
|
|
738
|
+
return [55, 50, 50] if ellipse(u, v, 0.26, 0.17, 0.07, 0.05) < 1 && v < 0.19
|
|
739
|
+
return [55, 50, 50] if (v - 0.185).abs < 0.012 && (u - 0.26).abs < 0.10
|
|
740
|
+
return mix(skin, [160, 100, 60], (u - 0.20) * 6) if ellipse(u, v, 0.27, 0.26, 0.055, 0.075) < 1
|
|
741
|
+
if inside?(u, v, [[0.13, 0.34], [0.33, 0.34], [0.42, 0.56], [0.40, 1.0], [0.04, 1.0], [0.08, 0.50]])
|
|
742
|
+
return brush(u, v, angle: 1.2, freq: 30.0) > 0.4 ? [110, 105, 160] : [75, 70, 120]
|
|
743
|
+
end
|
|
744
|
+
# right man, hat and ochre jacket
|
|
745
|
+
return [110, 95, 75] if ellipse(u, v, 0.75, 0.15, 0.06, 0.06) < 1 && v < 0.18
|
|
746
|
+
return [110, 95, 75] if (v - 0.175).abs < 0.012 && (u - 0.75).abs < 0.09
|
|
747
|
+
return mix([160, 100, 60], skin, (u - 0.70) * 6) if ellipse(u, v, 0.74, 0.25, 0.055, 0.075) < 1
|
|
748
|
+
return [210, 200, 180] if (v - 0.32).abs < 0.012 && (u - 0.75).abs < 0.06
|
|
749
|
+
if inside?(u, v, [[0.66, 0.33], [0.88, 0.33], [0.95, 0.50], [0.98, 1.0], [0.60, 1.0], [0.58, 0.56]])
|
|
750
|
+
return brush(u, v, angle: 1.0, freq: 30.0) > 0.4 ? [200, 165, 100] : [165, 130, 80]
|
|
751
|
+
end
|
|
752
|
+
# warm brown wall
|
|
753
|
+
wall = mix([160, 115, 70], [110, 95, 80], u)
|
|
754
|
+
wall = mix(wall, [90, 70, 50], 0.35) if brush(u, v, angle: 0.9, freq: 25.0) > 0.6
|
|
755
|
+
jitter(wall, u, v, 8)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
TAHITI_LEFT = [[0.18, 0.40], [0.38, 0.40], [0.46, 0.66], [0.48, 0.86], [0.12, 0.88], [0.14, 0.62]].freeze
|
|
759
|
+
TAHITI_RIGHT = [[0.60, 0.40], [0.80, 0.40], [0.88, 0.62], [0.96, 0.96], [0.52, 0.96], [0.56, 0.62]].freeze
|
|
760
|
+
|
|
761
|
+
# Gauguin, Tahitian Women on the Beach
|
|
762
|
+
def imp_tahitian_women(u, v)
|
|
763
|
+
skin = [190, 120, 70]
|
|
764
|
+
outline = [50, 35, 30]
|
|
765
|
+
# left woman in profile: black hair, white top, red pareo with white flowers
|
|
766
|
+
return [20, 15, 15] if ellipse(u, v, 0.29, 0.25, 0.07, 0.08) < 1 && u > 0.25
|
|
767
|
+
return skin if ellipse(u, v, 0.26, 0.29, 0.045, 0.06) < 1
|
|
768
|
+
return [250, 250, 240] if dist(u, v, 0.30, 0.20, 1.32) < 0.02
|
|
769
|
+
return skin if imp_seg(u, v, 0.18, 0.45, 0.10, 0.70, 1.32) < 0.025
|
|
770
|
+
if inside?(u, v, TAHITI_LEFT)
|
|
771
|
+
return [240, 235, 220] if v < 0.56
|
|
772
|
+
return [250, 245, 230] if noise((u * 30).floor, (v * 24).floor) > 0.72
|
|
773
|
+
return [205, 40, 40]
|
|
774
|
+
end
|
|
775
|
+
return outline if imp_outline?(u, v, TAHITI_LEFT)
|
|
776
|
+
# right woman, frontal, pink dress, weaving palm fronds
|
|
777
|
+
return [20, 15, 15] if ellipse(u, v, 0.70, 0.24, 0.075, 0.08) < 1 && v < 0.27
|
|
778
|
+
return skin if ellipse(u, v, 0.70, 0.29, 0.05, 0.07) < 1
|
|
779
|
+
return skin if (u - 0.70).abs < 0.025 && v > 0.34 && v < 0.42
|
|
780
|
+
if inside?(u, v, TAHITI_RIGHT)
|
|
781
|
+
return [240, 210, 120] if ellipse(u, v, 0.70, 0.70, 0.10, 0.04) < 1
|
|
782
|
+
return skin if ellipse(u, v, 0.70, 0.64, 0.07, 0.025) < 1
|
|
783
|
+
return [250, 240, 230] if v < 0.45 && (u - 0.70).abs < 0.05
|
|
784
|
+
return Math.sin(u * 50 + v * 10) > 0.6 ? [200, 100, 130] : [230, 140, 160]
|
|
785
|
+
end
|
|
786
|
+
return outline if imp_outline?(u, v, TAHITI_RIGHT)
|
|
787
|
+
# flat sea band with a white wave line, then pink-ochre sand
|
|
788
|
+
wave = 0.30 + 0.015 * Math.sin(u * 18)
|
|
789
|
+
return [30, 70, 80] if v < 0.12
|
|
790
|
+
return [60, 140, 130] if v < wave - 0.02
|
|
791
|
+
return [225, 235, 225] if v < wave + 0.01
|
|
792
|
+
sand = mix([225, 170, 140], [200, 130, 110], vnoise(u, v, 5.0))
|
|
793
|
+
sand = mix(sand, [170, 100, 90], 0.4) if v > 0.80 && vnoise(u, v, 8.0) > 0.6
|
|
794
|
+
sand
|
|
795
|
+
end
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
piece(:impression_sunrise, "Impression, Sunrise", "Claude Monet", "1872", aspect: 1.31) { |u, v| imp_impression_sunrise(u, v) }
|
|
799
|
+
piece(:water_lilies, "Water Lilies", "Claude Monet", "1906", aspect: 1.1) { |u, v| imp_water_lilies(u, v) }
|
|
800
|
+
piece(:woman_with_a_parasol, "Woman with a Parasol", "Claude Monet", "1875", aspect: 0.81) { |u, v| imp_woman_with_a_parasol(u, v) }
|
|
801
|
+
piece(:japanese_footbridge, "The Water Lily Pond (Japanese Footbridge)", "Claude Monet", "1899", aspect: 1.0) { |u, v| imp_japanese_footbridge(u, v) }
|
|
802
|
+
piece(:poppy_field, "Poppy Field", "Claude Monet", "1873", aspect: 1.3) { |u, v| imp_poppy_field(u, v) }
|
|
803
|
+
piece(:bal_du_moulin_de_la_galette, "Bal du moulin de la Galette", "Pierre-Auguste Renoir", "1876", aspect: 1.33) { |u, v| imp_bal_du_moulin(u, v) }
|
|
804
|
+
piece(:the_dance_class, "The Dance Class", "Edgar Degas", "1874", aspect: 0.88) { |u, v| imp_the_dance_class(u, v) }
|
|
805
|
+
piece(:sunday_on_la_grande_jatte, "A Sunday on La Grande Jatte", "Georges Seurat", "1886", aspect: 1.49) { |u, v| imp_grande_jatte(u, v) }
|
|
806
|
+
piece(:bar_at_the_folies_bergere, "A Bar at the Folies-Bergère", "Édouard Manet", "1882", aspect: 1.35) { |u, v| imp_bar_folies(u, v) }
|
|
807
|
+
piece(:luncheon_on_the_grass, "Luncheon on the Grass", "Édouard Manet", "1863", aspect: 1.27) { |u, v| imp_luncheon(u, v) }
|
|
808
|
+
piece(:sunflowers, "Sunflowers", "Vincent van Gogh", "1888", aspect: 0.79) { |u, v| imp_sunflowers(u, v) }
|
|
809
|
+
piece(:cafe_terrace_at_night, "Café Terrace at Night", "Vincent van Gogh", "1888", aspect: 0.81) { |u, v| imp_cafe_terrace(u, v) }
|
|
810
|
+
piece(:wheatfield_with_crows, "Wheatfield with Crows", "Vincent van Gogh", "1890", aspect: 2.04) { |u, v| imp_wheatfield_with_crows(u, v) }
|
|
811
|
+
piece(:bedroom_in_arles, "Bedroom in Arles", "Vincent van Gogh", "1888", aspect: 1.25) { |u, v| imp_bedroom_in_arles(u, v) }
|
|
812
|
+
piece(:almond_blossoms, "Almond Blossoms", "Vincent van Gogh", "1890", aspect: 1.25) { |u, v| imp_almond_blossoms(u, v) }
|
|
813
|
+
piece(:van_gogh_self_portrait, "Self-Portrait", "Vincent van Gogh", "1889", aspect: 0.83) { |u, v| imp_van_gogh_self_portrait(u, v) }
|
|
814
|
+
piece(:mont_sainte_victoire, "Mont Sainte-Victoire", "Paul Cézanne", "c. 1904", aspect: 1.26) { |u, v| imp_mont_sainte_victoire(u, v) }
|
|
815
|
+
piece(:the_card_players, "The Card Players", "Paul Cézanne", "c. 1893", aspect: 1.21) { |u, v| imp_the_card_players(u, v) }
|
|
816
|
+
piece(:tahitian_women_on_the_beach, "Tahitian Women on the Beach", "Paul Gauguin", "1891", aspect: 1.32) { |u, v| imp_tahitian_women(u, v) }
|
|
817
|
+
end
|
|
818
|
+
end
|