diff --git a/2019/sketch_190111a/arcs.py b/2019/sketch_190111a/arcs.py new file mode 100644 index 00000000..241ce9ac --- /dev/null +++ b/2019/sketch_190111a/arcs.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +ROTATION = {0 : 0, + BOTTOM : 0, + DOWN : 0, + 1 : HALF_PI, + LEFT : HALF_PI, + 2 : PI, + TOP : PI, + UP : PI, + 3 : PI + HALF_PI, + RIGHT: PI + HALF_PI, + BOTTOM + RIGHT : 0, + DOWN + RIGHT : 0, + DOWN + LEFT : HALF_PI, + BOTTOM + LEFT : HALF_PI, + TOP + LEFT : PI, + UP + LEFT : PI, + TOP + RIGHT: PI + HALF_PI, + UP + RIGHT: PI + HALF_PI, + } + +def quarter_circle(x, y, radius, quadrant): + circle_arc(x, y, radius, ROTATION[quadrant], HALF_PI) + +def half_circle(x, y, radius, quadrant): + circle_arc(x, y, radius, ROTATION[quadrant], PI) + +def circle_arc(x, y, radius, start_ang, sweep_ang): + arc(x, y, radius * 2, radius * 2, start_ang, start_ang + sweep_ang) + +def bar(x1, y1, x2, y2, thickness=None, shorter=0, ends=(1,1)): + """ + O código para fazer as barras, dois pares (x, y), + um parâmetro de encurtamento: shorter + """ + L = dist(x1, y1, x2, y2) + if not thickness: + thickness = 10 + with pushMatrix(): + translate(x1, y1) + angle = atan2(x1 - x2, y2 - y1) + rotate(angle) + offset = shorter / 2 + line(thickness/2, offset, thickness/2, L - offset) + line(-thickness/2, offset, -thickness/2, L - offset) + if ends[0]: + half_circle(0, offset, thickness/2, UP) + if ends[1]: + half_circle(0, L - offset, thickness/2, DOWN) diff --git a/2019/sketch_190111a/cell.py b/2019/sketch_190111a/cell.py new file mode 100644 index 00000000..c2ae23fd --- /dev/null +++ b/2019/sketch_190111a/cell.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +from random import choice +from arcs import quarter_circle, half_circle, circle_arc, bar + + +class Cell(): + grid = dict() + # neighbours list + NL = ((-1, -1), (+0, -1), (+1, -1), + (-1, +0), (+0, +0), (+1, +0), + (-1, +1), (+0, +1), (+1, +1)) + ONL = ((+0, -1), + (-1, +0), (+0, +0), (+1, +0), + (+0, +1)) + DNL = ((-1, -1), (+1, -1), + (+0, +0), + (-1, +1), (+1, +1)) + + def __init__(self, index, cell_size, state=False, border=None): + self.index = index + self.state = state + self.size_ = cell_size + self.mouse_down = False + self.variation = choice(("a", "b", "c")) + self.ang = choice((0, 1, 2, 3)) + self.border = border + self.calculate_pos() + + def calculate_pos(self): + i, j = self.index + if self.border == None: + self.border = self.size_ + self.pos = PVector(self.border + self.size_ / 2 + i * self.size_, + self.border + self.size_ / 2 + j * self.size_) + + def update(self, mx, my): + # mouse over & selection treatment + hs = self.size_ / 2 + px, py = self.pos.x, self.pos.y + self.mouse_on = (px - hs < mx < px + hs and + py - hs < my < py + hs) + if self.mouse_on and mousePressed: + self.mouse_down = True + + elif self.mouse_down: + self.state = not self.state + self.mouse_down = False + + self.find_type(Cell.ONL) + + def plot(self, mode): + if self.state: + strokeWeight(1) + if mode == 1: + self.variation = "a" + if mode == 2: + self.variation = "b" + if mode == 3: + self.variation = "c" + if mode == 4: + self.variation = "d" + if mode == 5: + self.variation = choice(("a", "b", "c", "d")) + if mode == -1: + fill(100, 100) + noStroke() + rect(self.pos.x, self.pos.y, self.size_, self.size_) + noFill() + siz = self.size_ + l = siz / 2. + a = l / 2. #- 1 + c = l / 2. #+ 1 + # diagonal mode + if mode == 6: + i, j = self.index + for (ni, nj) in Cell.DNL: + nb = Cell.grid.get((i + ni, j + nj), None) + if nb and nb.state and ni <> 0 and nj <> 0: + for ii in range(Cell.step_start, + Cell.step_end, + Cell.step): # (-28, 29, 7): + stroke(64 - ii * 8, 128, 64 + ii * 8) + bar(self.pos.x, + self.pos.y, + nb.pos.x, + nb.pos.y, + (a + ii) * 2, + ends=(0, 1)) + + """ draws node """ + with pushMatrix(): + translate(self.pos.x, self.pos.y) + noFill() # stroke(0) + if (self.type == "11110" or + self.type == "10110" or + self.type == "00101" + ): + rotate(PI) + if (self.type == "11101" or + self.type == "01110" or + self.type == "11100" or + self.type == "00110" or + (self.type == "11111" and self.ang % 2) + ): # t r & i + rotate(HALF_PI) + if (self.type == "10111" or + self.type == "00111" or + self.type == "01100" + ): # t l + rotate(PI + HALF_PI) + + for i in range(Cell.step_start, + Cell.step_end, + Cell.step): # (-28, 29, 7): + stroke(128, 64 + i * 8, 64 - i * 8) + if self.type == "11111" and self.variation in "bd": + quarter_circle(l, l, c + i, TOP + LEFT) + quarter_circle(-l, -l, c + i, BOTTOM + RIGHT) + quarter_circle(-l, l, c + i, TOP + RIGHT) + quarter_circle(l, -l, c + i, BOTTOM + LEFT) + if self.type == "11111" and self.variation == "d": + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + if self.type == "11111" and self.variation == "a": + # ellipse(0, 0, (a + i) * 2, (a + i) * 2) + half_circle(-l, 0, a - i, RIGHT) + half_circle(l, 0, a - i, LEFT) + half_circle(0, l, a - i, TOP) + half_circle(0, -l, a - i, BOTTOM) + if self.type == "11111" and self.variation == "c": + line(+a - i, -l, +a - i, l) + line(-a + i, -l, -a + i, l) + half_circle(-l, 0, a - i, RIGHT) + half_circle(l, 0, a - i, LEFT) + #if keyPressed: ellipse(0, 0, (a - i) * 2, (a - i) * 2) + elif (self.type == "01111" or # t + self.type == "11110" or + self.type == "11101" or + self.type == "10111"): # t + if self.variation in "bd": + line(-l, -a + i, l, -a + i) + quarter_circle(l, l, c + i, TOP + LEFT) + quarter_circle(-l, l, c + i, TOP + RIGHT) + elif self.variation == "c": + half_circle(-l, 0, a - i, RIGHT) + half_circle(l, 0, a - i, LEFT) + half_circle(0, l, a - i, TOP) + if self.variation in "cd": + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + if self.variation == "a": + line(-l, -a + i, l, -a + i) + half_circle(-l, 0, a - i, RIGHT) + half_circle(l, 0, a - i, LEFT) + half_circle(0, l, a - i, TOP) + + elif self.type == "10101" or self.type == "01110": + if self.variation == "d": + line(+a - i, -l, +a - i, l) + line(-a + i, -l, -a + i, l) + half_circle(0, l, a - i, TOP) + half_circle(0, -l, a - i, BOTTOM) + if self.variation in "abc": + line(+a - i, -l, +a - i, l) + line(-a + i, -l, -a + i, l) + if self.variation in "cd": + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + elif self.variation == "c": + half_circle(0, l, a - i, TOP) + half_circle(0, -l, a - i, BOTTOM) + #ellipse(0, 0, (a - i) * 2, (a - i) * 2) + elif (self.type == "01101" or + self.type == "10110" or + self.type == "00111" or + self.type == "11100"): # l + if self.variation == "c": + # stroke(255, 0, 0) + # text(self.type, 0, 0) + half_circle(-l, 0, a - i, RIGHT) + half_circle(0, l, a - i, TOP) + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + elif self.variation == "b": + # stroke(0, 255, 0) + # text(self.type, 0, 0) + quarter_circle(-l, l, siz - c - i, TOP + RIGHT) + i *= -1 + quarter_circle(-l, l, c - i, TOP + RIGHT) + else: + quarter_circle(-l, l, siz - c - i, TOP + RIGHT) + half_circle(-l, 0, a - i, RIGHT) + half_circle(0, l, a - i, TOP) + + elif (self.type == "01100" or + self.type == "00110" or + self.type == "00101" or + self.type == "10100"): + if self.variation in "bd": + half_circle(0, 0, a - i, BOTTOM) + if self.variation in "abd": + line(+a - i, -l, +a - i, 0) + line(-a + i, -l, -a + i, 0) + if self.variation in "ac": + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + half_circle(0, -l, a - i, BOTTOM) + + elif self.type == "00100": + ellipse(0, 0, (a - i) * 2, (a - i) * 2) + + def find_type(self, nbs): + i, j = self.index[0], self.index[1] + self.type = "" + for (ni, nj) in nbs: + nb = Cell.grid.get((i + ni, j + nj), None) + if nb and nb.state: + self.type += "1" + else: + self.type += "0" diff --git a/2019/sketch_190111a/gif_exporter.py b/2019/sketch_190111a/gif_exporter.py new file mode 100644 index 00000000..51c431df --- /dev/null +++ b/2019/sketch_190111a/gif_exporter.py @@ -0,0 +1,40 @@ +""" +Alexandre B A Villares http://abav.lugaralgum.com - GPL v3 + +A helper for the Processing gifAnimation library https://github.com/extrapixel/gif-animation/tree/3.0 +Download from https://github.com/villares/processing-play/blob/master/export_GIF/unzip_and_move_to_libraries_GifAnimation.zip +This helper was inspired by an example by Art Simon https://github.com/APCSPrinciples/AnimatedGIF/ + +# add at the start of your sketch: + add_library('gifAnimation') + from gif_exporter import gif_export +# add at the end of draw(): + gif_export(GifMaker) +""" + +def gif_export(GifMaker, # gets a reference to the library + filename="exported", # .gif will be added + repeat=0, # 0 makes it an "endless" animation + quality=255, # quality range 0 - 255 + delay=200, # this is quick + frames=0, # 0 will stop on keyPressed or frameCount >= 100000 + finish=False): # force stop + global gifExporter + try: + gifExporter + except NameError: + gifExporter = GifMaker(this, filename + ".gif") + gifExporter.setRepeat(repeat) + gifExporter.setQuality(quality) + gifExporter.setDelay(delay) + + gifExporter.addFrame() + + if frames == 0: + if keyPressed and key == "e": + finish = True + + if finish: + gifExporter.finish() + print("gif saved") + exit() diff --git a/2019/sketch_190111a/sketch_190111a.pyde b/2019/sketch_190111a/sketch_190111a.pyde new file mode 100644 index 00000000..81ad7fd7 --- /dev/null +++ b/2019/sketch_190111a/sketch_190111a.pyde @@ -0,0 +1,107 @@ +# Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day +SKETCH_NAME = "sketch_19011a" # find sketch name yourself! +OUTPUT = ".gif" +mode = 0 +save_frame = False + +from cell import Cell +from random import choice +add_library('GifAnimation') +from gif_exporter import gif_export + +CELL_SIZE = 25 +Cell.step_start = -3 +Cell.step_end = 4 +Cell.step = 3 +modulus = 3 + +def setup(): + size(500, 500) + global grid_size + grid_size = width / CELL_SIZE + rectMode(CENTER) + strokeCap(SQUARE) + +def init_grid(f=None): + # default grid is with random state for cells + if f == None: + f = lambda i, j: choice((True, False)) + # number of collums and rows -2 for default cell sized border + w = int(width // CELL_SIZE) #- 2 + h = int(height // CELL_SIZE) #- 2 + for i in range(w): + for j in range(h): + # default Cell constructor has border=CELL_SIZE + Cell.grid[(i, j)] = Cell((i, j), CELL_SIZE, f(i, j), border=0) + +def draw(): + global save_frame + background(200) + for c in Cell.grid.values(): + c.update(mouseX, mouseY) + for c in Cell.grid.values(): + c.plot(mode) + + if save_frame: + save_frame = False + gif_export(GifMaker, SKETCH_NAME) + +def keyPressed(): + global mode, modulus, save_frame + if key == "g" or key == "G": + save_frame = True + if key == "s" or key == "S": + saveFrame(SKETCH_NAME + "_#######.png") + if key != CODED and key in "01234567789": + mode = int(key) + if key == "-": + mode = -1 + if key == " ": + t = lambda i, j: True + f = lambda i, j: False + init_grid(choice((t, f))) + if key == "r": + init_grid() + if key == "x": + init_grid(lambda i, j: (i + j) % modulus) + if key == "<" and modulus > 2: + modulus -= 1 + if key == ">": + modulus += 1 + if key == "z": + move_grid() + if keyCode == RIGHT: + move_grid(x=1, y=0) + if keyCode == LEFT: + move_grid(x=-1, y=0) + if keyCode == UP: + move_grid(x=0, y=-1) + if keyCode == DOWN: + move_grid(x=0, y=1) + +def move_grid(x=1, y=1): + w, h = width // CELL_SIZE, height // CELL_SIZE + new_grid = dict() + for i in range(w): + for j in range(h): + c = Cell.grid.get((i, j), None) + if c: + c.index = ((i + x) % w, (j + y) % h) + c.calculate_pos() + new_grid[c.index] = c + # else: + # f = lambda i, j: choice((True, False)) + # new_grid[(i, j)] = Cell((i, j), CELL_SIZE, f(i, j)) + + Cell.grid = new_grid + + +# print text to add to the project's README.md +def settings(): + println( + """ +![{0}](2019/{0}/{0}{1}) + +[{0}](https://github.com/villares/sketch-a-day/tree/master/{0}) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] +""".format(SKETCH_NAME,OUTPUT) + ) diff --git a/2019/sketch_190111a/sketch_19011a.gif b/2019/sketch_190111a/sketch_19011a.gif new file mode 100644 index 00000000..cd8d5235 Binary files /dev/null and b/2019/sketch_190111a/sketch_19011a.gif differ