diff --git a/2019/sketch_190126a/cell.py b/2019/sketch_190126a/cell.py index 7d316848..8c1fdfce 100644 --- a/2019/sketch_190126a/cell.py +++ b/2019/sketch_190126a/cell.py @@ -142,19 +142,20 @@ class Cell(): for (ni, nj, nk) in Cell.ONL: nb = Cell.grid.get((i + ni, j + nj, k + nk), None) if nb and nb.state: - stroke(64, 255, 100) + stroke(200) bar(0, 0, 0, - ni * siz / 2, nj * siz / 2, nk * siz / 2) + ni * siz, nj * siz, nk * siz) # stroke(64, 200, 200) # with pushMatrix(): # translate(ni * siz / 3, nj * siz / 3, nk * siz / 3) # box(siz / 3) - stroke(128, 255, 100) for (ni, nj, nk) in Cell.DNL: nb = Cell.grid.get((i + ni, j + nj, k + nk), None) if nb and nb.state: + stroke(64 + (ni * 2 + nj * 3 + nk * 5) * 16, 255, 200) bar(0, 0, 0, - ni * siz / 2, nj * siz / 2, nk * siz / 2) + ni * siz, nj * siz, nk * siz, + ni * 2 + nj * 3 + nk * 5) def identify_module(self, nbs): i, j, k = self.index diff --git a/2019/sketch_190126a/sketch_190126a.pyde b/2019/sketch_190126a/sketch_190126a.pyde index a063cfa7..34e5b9f9 100644 --- a/2019/sketch_190126a/sketch_190126a.pyde +++ b/2019/sketch_190126a/sketch_190126a.pyde @@ -1,5 +1,5 @@ # Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day -SKETCH_NAME, OUTPUT = "sketch_190125a", ".gif" # find sketch name yourself! +SKETCH_NAME, OUTPUT = "sketch_190126a", ".gif" # find sketch name yourself! from cell import Cell from random import choice @@ -44,7 +44,7 @@ def init_grid(f=None): def draw(): global save_frame, frame_saved - background(200) + background(0) for c in Cell.grid.values(): c.update(mouseX, mouseY) for c in Cell.grid.values(): diff --git a/2019/sketch_190127a/bar.py b/2019/sketch_190127a/bar.py new file mode 100644 index 00000000..8140cee3 --- /dev/null +++ b/2019/sketch_190127a/bar.py @@ -0,0 +1,20 @@ +def bar(x1, y1, z1, x2, y2, z2, weight=10): + """ + from code by James Carruthers found on + https://forum.processing.org/two/discussion/21400/how-to-rotate-a-3d-line-like-a-2d-line + """ + p1 = PVector(x1, y1, z1) + p2 = PVector(x2, y2, z2) + v1 = PVector(x2 - x1, y2 - y1, z2 - z1) + rho = sqrt(v1.x ** 2 + v1.y ** 2 + v1.z ** 2) + phi = acos(v1.z / rho) + the = atan2(v1.y, v1.x) + v1.mult(0.5) + with pushMatrix(): + translate(x1, y1, z1) + translate(v1.x, v1.y, v1.z) + rotateZ(the) + rotateY(phi) + # box(weight,weight,p1.dist(p2)*1.2) + box(weight, weight, p1.dist(p2) * 1.0) + diff --git a/2019/sketch_190127a/cell.py b/2019/sketch_190127a/cell.py new file mode 100644 index 00000000..8c1fdfce --- /dev/null +++ b/2019/sketch_190127a/cell.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +from random import choice +from bar import bar + +class Cell(): + border = 0 + RES = 4. + grid = dict() + debug_mode = False + # constants + variations = "abcde" + N, A, I, T, L, C, E = type_names = "NAITLCE" + module_types = {"11111": A, # All neighbours on + "00100": N, # No neighbours on - isolated + "01111": T, # T-shaped (three neighbours) + "11110": T, + "11101": T, + "10111": T, + "10101": I, # I - Up & down or Left and Right + "01110": I, + "01100": C, # Cap - single neighbour + "00110": C, + "00101": C, + "10100": C, + "01101": L, # L-shaped (two neighbours) + "10110": L, + "00111": L, + "11100": L, + "00000": E, # Empty - not used at this point + # "10000": E, + # "01000": E, + # "00010": E + } + + # ortho neighbours + ONL = ((+0, -1, +0), + (-1, +0, +0), # (+0, +0, +0), + (+1, +0, +0), + (+0, +1, +0), + (+0, +0, -1), (+0, +0, +1), + ) + # diagonal neighbours + DNL = ((+1, +1, +0), + (-1, -1, +0), # (+0, +0, +0), + (+1, -1, +0), + (-1, +1, +0), + (+0, -1, +1), + (-1, +0, +1), + (+1, +0, +1), + (+0, +1, +1), + (+0, -1, -1), + (-1, +0, -1), + (+1, +0, -1), + (+0, +1, -1), + ) + + def __init__(self, index, cell_size, state=False): + self.index = index + self.state = state + self.size_ = cell_size + self.mouse_down = False + self.variation = "a" + self.ang = choice((0, 1, 2, 3)) + self.calculate_pos() + + def calculate_pos(self): + i, j, k = self.index + self.pos = PVector(Cell.border + self.size_ / 2 + i * self.size_ - width / 2, + Cell.border + self.size_ / 2 + + j * self.size_ - height / 2, + k * self.size_) + + def update(self, mx, my): + # mouse over & selection treatment + hs = self.size_ / 2 + px, py = self.pos.x + width / 2, self.pos.y + height / 2 + 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.identify_module(Cell.ONL) + self.type = Cell.module_types.get(self.module, "") + + def plot(self, mode): + rnd = choice(Cell.variations) + mode_variation = {1: "a", + 2: "b", + 3: "c", + 4: "d", + 5: "e", + 6: Cell.variation_dict.get(Cell.module_types.get(self.module)), + 7: rnd + } + if self.state: + strokeWeight(1) + self.variation = mode_variation.get(mode, self.variation) + self.draw_mode() + if mode == -1: + fill(100, 100, 100, 10) + noStroke() + rect(self.pos.x, self.pos.y, self.size_, self.size_) + noFill() + + def draw_mode(self): + """ draws node """ + siz = self.size_ + with pushMatrix(): + translate(self.pos.x, self.pos.y, self.pos.z) + if Cell.debug_mode: + fill(255, 0, 100) + text(self.module, 0, 0) + noFill() # stroke(0) + # rotation = {"11110": PI, + # "10110": PI, + # "00101": PI, + # "11101": HALF_PI, + # "01110": HALF_PI, + # "11100": HALF_PI, + # "00110": HALF_PI, + # "11111": HALF_PI * self.ang, + # "10111": PI + HALF_PI, + # "00111": PI + HALF_PI, + # "01100": PI + HALF_PI + # } + # rotation appropriate for each type + # rotate(rotation.get(self.module, 0)) + + # for i in range(Cell.step_start, + # Cell.step_end, + # Cell.step): # (-28, 29, 7): + # #translate(0, 0, (a + i)) + # stroke(16 + i * 8, 255, 255) + # #stroke(self.index[2] * 8, 255, 255) + # # fill(200,10) + # box(siz / 3 + i) + i, j, k = self.index + for (ni, nj, nk) in Cell.ONL: + nb = Cell.grid.get((i + ni, j + nj, k + nk), None) + if nb and nb.state: + stroke(200) + bar(0, 0, 0, + ni * siz, nj * siz, nk * siz) + # stroke(64, 200, 200) + # with pushMatrix(): + # translate(ni * siz / 3, nj * siz / 3, nk * siz / 3) + # box(siz / 3) + for (ni, nj, nk) in Cell.DNL: + nb = Cell.grid.get((i + ni, j + nj, k + nk), None) + if nb and nb.state: + stroke(64 + (ni * 2 + nj * 3 + nk * 5) * 16, 255, 200) + bar(0, 0, 0, + ni * siz, nj * siz, nk * siz, + ni * 2 + nj * 3 + nk * 5) + + def identify_module(self, nbs): + i, j, k = self.index + self.module = "" + for (ni, nj, nk) in nbs: + nb = Cell.grid.get((i + ni, j + nj, k + nk), None) + if nb and nb.state: + self.module += "1" + else: + self.module += "0" + + @staticmethod + def variation_choices(): + Cell.variation_dict = dict() + for t in Cell.type_names: + Cell.variation_dict[t] = choice(Cell.variations) diff --git a/2019/sketch_190127a/gif_exporter.py b/2019/sketch_190127a/gif_exporter.py new file mode 100644 index 00000000..bb246585 --- /dev/null +++ b/2019/sketch_190127a/gif_exporter.py @@ -0,0 +1,41 @@ +""" +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=900, # this is quick + # 0 will stop on keyPressed or frameCount >= 100000 + frames=0, + 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_190127a/sketch_190127a.gif b/2019/sketch_190127a/sketch_190127a.gif new file mode 100644 index 00000000..f0f5fa70 Binary files /dev/null and b/2019/sketch_190127a/sketch_190127a.gif differ diff --git a/2019/sketch_190127a/sketch_190127a.pyde b/2019/sketch_190127a/sketch_190127a.pyde new file mode 100644 index 00000000..34e5b9f9 --- /dev/null +++ b/2019/sketch_190127a/sketch_190127a.pyde @@ -0,0 +1,116 @@ +# Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day +SKETCH_NAME, OUTPUT = "sketch_190126a", ".gif" # find sketch name yourself! + +from cell import Cell +from random import choice +add_library('GifAnimation') +add_library('peasycam') +from gif_exporter import gif_export + +CELL_SIZE = 100 +Cell.step_start = -2 +Cell.step_end = 3 +Cell.step = 2 +modulus = 3 +mode = 0 +save_frame = False +frame_saved = 0 + +def setup(): + hint(ENABLE_DEPTH_SORT) + size(600, 600, P3D) + colorMode(HSB) + global grid_size + grid_size = width / CELL_SIZE + rectMode(CENTER) + strokeCap(SQUARE) + Cell.variation_choices() + cam = PeasyCam(this, 700) + + +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 + z = 3 + # print(w, h) + for i in range(w): + for j in range(h): + for k in range(z): + Cell.grid[(i, j, k)] = Cell((i, j, k), CELL_SIZE, f(i, j)) + +def draw(): + global save_frame, frame_saved + background(0) + 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 + frame_saved += 1 + gif_export(GifMaker, SKETCH_NAME) + println(frame_saved) + +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 == "R": + Cell.variation_choices() + 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): + for k in range(h): + c = Cell.grid.get((i, j, k), None) + if c: + c.index = ((i + x) % w, (j + y) % h, k) + c.calculate_pos() + new_grid[c.index] = c + 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/2019/{0}) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] +""".format(SKETCH_NAME, OUTPUT) + )