-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinteractive_pattern.py
More file actions
156 lines (133 loc) · 5.09 KB
/
Copy pathinteractive_pattern.py
File metadata and controls
156 lines (133 loc) · 5.09 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import py5_tools
py5_tools.add_jars('./jars')
import py5
from controlP5 import ControlP5, Slider
import math
import hsluv
from data_dict import base_data
from data_generation import (
calculate_offsets, multiplier, steps, spacing,
compute_grid, sin_cos_table, sin_cos_rotate, shift,
calculate_intersection_points, calculate_colors,
calculate_color_palette
)
def setup():
global cp5, data
py5.size(1200, 900) # Reduced width since we only have tile view
# Initialize data from base_data
data = base_data.copy()
data['width'] = py5.width
data['height'] = py5.height - 100 # Reserve space for controls
# Create control panel
cp5 = ControlP5(py5.get_current_sketch())
# Add controls at the bottom
controls_y = py5.height - 80
spacing_x = 180 # Horizontal spacing between controls
current_x = 20
# Symmetry slider
(cp5.addSlider('symmetry')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(3, 12)
.setValue(data['symmetry'])
.onChange(lambda e: update_pattern()))
current_x += spacing_x
# Radius slider
(cp5.addSlider('radius')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(10, 150)
.setValue(data['radius'])
.onChange(lambda e: update_pattern()))
current_x += spacing_x
# Pattern slider
(cp5.addSlider('pattern')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(0, 1)
.setValue(data['pattern'])
.onChange(lambda e: update_pattern()))
current_x += spacing_x
# Disorder slider
(cp5.addSlider('disorder')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(0, 1)
.setValue(data['disorder'])
.onChange(lambda e: update_pattern()))
current_x += spacing_x
# Zoom slider
(cp5.addSlider('zoom')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(0.1, 2)
.setValue(data['zoom'])
.onChange(lambda e: update_pattern()))
current_x += spacing_x
# Hue slider
(cp5.addSlider('hue')
.setPosition(current_x, controls_y)
.setSize(150, 20)
.setRange(0, 360)
.setValue(data['hue'])
.onChange(lambda e: update_pattern()))
# Initial pattern generation
update_pattern()
def update_pattern():
"""Update the pattern based on current control values"""
# Update data from controls
data['symmetry'] = int(cp5.getController('symmetry').getValue())
data['radius'] = cp5.getController('radius').getValue()
data['pattern'] = cp5.getController('pattern').getValue()
data['disorder'] = cp5.getController('disorder').getValue()
data['zoom'] = cp5.getController('zoom').getValue()
data['hue'] = cp5.getController('hue').getValue()
# Calculate pattern data
data['steps'] = steps(data['radius'], data['symmetry'])
data['spacing'] = spacing(data['zoom'], data['width'], data['height'], data['steps'])
data['multiplier'] = multiplier(data['symmetry'])
sin_cos_table_val = sin_cos_table(data['symmetry'], data['multiplier'])
sin_cos_rotate_val = sin_cos_rotate(data['rotate'])
shift_val = shift(sin_cos_table_val, sin_cos_rotate_val)
data['offsets'] = calculate_offsets(
data['symmetry'], data['pattern'], data['disorder'],
data['randomSeed'], data['pan'], data['steps'], shift_val
)
# Calculate grid and intersections
grid = compute_grid(data['symmetry'], data['steps'], data['offsets'])
data['grid'] = grid
data['intersectionPoints'] = calculate_intersection_points(data, grid, sin_cos_table_val)
# Calculate colors
colors = calculate_colors(data['hue'], data['hueRange'], data['sat'], data['contrast'])
data['tiles'] = calculate_color_palette(
data['intersectionPoints'], data['orientationColoring'],
colors, data['reverseColors']
)
def draw():
py5.background(51)
# Draw tile view
with py5.push_matrix():
# Center and scale the tiles
py5.translate(py5.width/2, (py5.height-100)/2) # Account for control space
# Reduce the scale factor to make pattern smaller
scale_factor = min(py5.width / 2, (py5.height - 100) / 2) / (data['steps'] * 20)
py5.scale(scale_factor)
# Draw tiles
if data['colorTiles']:
for pt in data['intersectionPoints'].values():
color = next(tile for tile in data['tiles']
if tile['area'] == pt['area'])
py5.fill(color['fill'])
py5.no_stroke()
py5.begin_shape()
for dual_pt in pt['dualPts']:
py5.vertex(
dual_pt['x'] * data['spacing'],
dual_pt['y'] * data['spacing']
)
py5.end_shape(py5.CLOSE)
# Draw control area background
py5.fill(40)
py5.no_stroke()
py5.rect(0, py5.height-100, py5.width, 100)
py5.run_sketch()