def hilbert_gen(order, size, pos=vec2(0), heading=vec2(0, 1)): def draw_hilbert(symbols, order, size): if order == 0: return for symbol in symbols: op = operations[symbol] yield from op(order - 1, size) def forward(order, size): nonlocal pos pos += heading * size yield pos def right(order, size): nonlocal heading heading = heading.rotate(90) return yield def left(order, size): nonlocal heading heading = heading.rotate(-90) return yield operations = { 'A': partial(draw_hilbert, '-BF+AFA+FB-'), 'B': partial(draw_hilbert, '+AF-BFB-FA+'), 'F': forward, '+': right, '-': left, } yield from draw_hilbert('A', order, size)
def get_curl(p: vec2): delta = 0.1 dx = (get_noise(p + vec2(delta, 0)) - get_noise(p - vec2(delta, 0))) / (delta * 2) dy = (get_noise(p + vec2(0, delta)) - get_noise(p - vec2(0, delta))) / (delta * 2) return vec2(dy, -dx)
def interp(grid, pos): size = len(grid) pos = (size - 1) * pos / 100 topleft = vec2(math.floor(pos.x), math.floor(pos.y)) topright = topleft + vec2(1, 0) bottomright = topleft + vec2(1) bottomleft = topleft + vec2(0, 1) d = fract(pos) top = lerp(grid[topleft.y][topleft.x], grid[topright.y][topright.x], d.x) bottom = lerp(grid[bottomleft.y][bottomleft.x], grid[bottomright.y][bottomright.x], d.x) return lerp(top, bottom, d.y)
def main(p: Plot): p.setup() grid_size = 8 for r in range(grid_size + 1): for c in range(grid_size + 1): x = c * 100 / grid_size y = r * 100 / grid_size draw_blob(p, vec2(x, y), 25 / grid_size)
def main(p: Plot): p.plot_size = 2 p.setup() p.draw_bounding_box(True) num_lines = 100 for _ in range(num_lines): t = random.random() edge = get_point_on_circle(t, 10) tangent = (edge - vec2(50)).rotate(90).normalize() p.goto(*(edge - 70 * tangent)) p.lineto(*(edge + 70 * tangent))
def draw_blob(p: Plot, origin, radius): if random.choice([True, False]): p.circle(origin, 0.3) start = radius * vec2(0, 1) p.goto(*(origin + start)) angle = 0 while True: angle += random.uniform(20, 50) blob_angle = random.uniform(200, 300) if 360 - angle < 20: break p.arcto(*(origin + start.rotate(angle)), blob_angle) p.arcto(*(origin + start), blob_angle)
def main(p: Plot): p.plot_size = 11.69 p.set_canvas_size(210, 297) p.setup() p.draw_bounding_box() mat_range = (0, 24) # mat_range = (24, 47) num_cols = 4 spacing = 5 size = (210 - spacing * (num_cols + 1)) / num_cols vert_size = SQRT_3 * size / 2 text_size = vert_size / 8 for mat_num, mat in enumerate(MATS[mat_range[0]:mat_range[1]]): row = mat_num // num_cols col = mat_num % num_cols x = spacing + col * (size + spacing) y = vert_size + spacing + row * (vert_size + spacing) draw_mat(p, mat, vec2(x, y), size) draw_string(p, str(mat_range[0] + mat_num), vec2(x, y - vert_size), text_size)
def main(p: Plot): p.setup() p.draw_bounding_box() gridsize = 6 for r in range(gridsize + 1): for c in range(gridsize + 1): x = 100 * r / gridsize + random.uniform(-5, 5) y = 100 * c / gridsize + random.uniform(-5, 5) size = random.uniform(3, 8) angle = random.uniform(0, 360) p.right(angle) draw_star(p, vec2(x, y), size)
def main(p: Plot): p.setup() poly = Polygon([ vec2(30, 30), vec2(70, 30), vec2(70, 70), vec2(30, 70), ]) clip_poly = Polygon([ vec2(50, 50), vec2(80, 50), vec2(80, 80), vec2(50, 80), ]) # draw_poly(p, poly) # draw_poly(p, clip_poly) poly.clip(clip_poly) draw_poly(p, poly)
def main(p: Plot): p.options.speed_pendown = 90 p.plot_size = 6 p.setup() p.draw_bounding_box(True) min_dist = p.inches_to_units(0.04) # grid_size = 11 # for r in range(grid_size): # for c in range(grid_size): # x = c * 100/(grid_size-1) # y = r * 100/(grid_size-1) # pos = vec2(x, y) # pos2 = pos # p.goto(*pos) # for _ in range(50): # if pos.x < 0 or pos.y < 0 or pos.x > 100 or pos.y > 100: # break # step_size = 20 # d = get_curl(pos2) * step_size # pos2 += d # if (pos2 - pos).mag() < min_dist: # continue # pos = pos2 # p.lineto(*pos) num_lines = 120 for i in range(num_lines): print('line', f'{i+1}/{num_lines}') pos = vec2(random.uniform(1, 99), random.uniform(1, 99)) pos2 = pos p.goto(*pos) for _ in range(100): step_size = 20 d = get_curl(pos2) * step_size pos2 += d if (pos2 - pos).mag() < min_dist: continue pos = pos2 p.lineto(*pos)
def draw_mat(p, mat, origin, size): num_divisions = 10 grads = { pos: get_grad(pos, mat) for pos in gen_simplex_coords(num_divisions) } max_grad = max(grad.mag() for grad in grads.values()) linelength = (1 / num_divisions) # spacing between flow and border spacing = 1 draw_tri(p, origin, size) flow_origin = vec2(origin.x + spacing * SQRT_3, origin.y - spacing) flow_size = size - 2 * spacing * SQRT_3 for pos, grad in grads.items(): if max_grad != 0: grad /= max_grad start = simplex_to_cart(pos, flow_origin, flow_size) end = simplex_to_cart(pos + grad * linelength, flow_origin, flow_size) draw_arrow(p, start, end)
def main(p: Plot): p.plot_size = 4 # p.options.speed_pendown = 50 p.setup() p.draw_bounding_box(True) lo = vec2(0, 0) hi = vec2(1, 1) layers = [] grid_size = 4 spacing = 7 scale = (100-spacing*(grid_size+1))/grid_size inc = 0.2 min_space = p.inches_to_units(0.01)/scale while lo.x < hi.x and lo.y < hi.y: inc = max(inc - random.uniform(0.015, 0.025), min_space) r = random.random() if r > 0.75: lo += vec2(inc) layers.append( ( vec2(lo.x, hi.y), lo, vec2(hi.x, lo.y), ) ) elif r > 0.5: lo += vec2(inc, 0) hi -= vec2(0, inc) layers.append( ( lo, vec2(lo.x, hi.y), hi, ) ) elif r > 0.25: lo += vec2(0, inc) hi -= vec2(inc, 0) layers.append( ( lo, vec2(hi.x, lo.y), hi, ) ) else: hi -= vec2(inc) layers.append( ( vec2(lo.x, hi.y), hi, vec2(hi.x, lo.y), ) ) layers.pop() for r in range(grid_size): for c in range(grid_size): origin = vec2(spacing+c*(scale+spacing), spacing+r*(scale+spacing)) p.goto(*origin) p.lineto(*(origin+scale*vec2(1, 0))) p.lineto(*(origin+scale*vec2(1))) p.lineto(*(origin+scale*vec2(0, 1))) p.lineto(*origin) for s, m, e in layers: p.goto(*(origin+scale*s)) p.lineto(*(origin+scale*m)) p.lineto(*(origin+scale*e))
def get_point_on_circle(t, radius): return vec2(50 + radius * math.cos(t * 2 * math.pi), 50 + radius * math.sin(t * 2 * math.pi))
def fract(v: vec2): return vec2(math.modf(v.x)[0], math.modf(v.y)[0])
def interp(grid, pos): size = len(grid) pos = (size - 1) * pos / 100 topleft = vec2(math.floor(pos.x), math.floor(pos.y)) topright = topleft + vec2(1, 0) bottomright = topleft + vec2(1) bottomleft = topleft + vec2(0, 1) d = fract(pos) top = lerp(grid[topleft.y][topleft.x], grid[topright.y][topright.x], d.x) bottom = lerp(grid[bottomleft.y][bottomleft.x], grid[bottomright.y][bottomright.x], d.x) return lerp(top, bottom, d.y) SEED = vec2(random.uniform(-1000, 1000), random.uniform(-1000, 1000)) def get_noise(p: vec2): noise_scale = 0.02 return noise.snoise2(*(SEED + p * noise_scale)) def get_curl(p: vec2): delta = 0.1 dx = (get_noise(p + vec2(delta, 0)) - get_noise(p - vec2(delta, 0))) / (delta * 2) dy = (get_noise(p + vec2(0, delta)) - get_noise(p - vec2(0, delta))) / (delta * 2) return vec2(dy, -dx)
def simplex_to_cart(pos, origin, size): ret = (pos[0] * origin + pos[1] * vec2(origin.x + size, origin.y) + pos[2] * vec2(origin.x + size / 2, origin.y - SQRT_3 * size / 2)) return ret