diff --git a/2019/sketch_190424a/sketch_190424a.png b/2019/sketch_190424a/sketch_190424a.png new file mode 100644 index 00000000..cf87d37a Binary files /dev/null and b/2019/sketch_190424a/sketch_190424a.png differ diff --git a/2019/sketch_190424a/sketch_190424a.pyde b/2019/sketch_190424a/sketch_190424a.pyde index 95891898..120de907 100644 --- a/2019/sketch_190424a/sketch_190424a.pyde +++ b/2019/sketch_190424a/sketch_190424a.pyde @@ -84,7 +84,7 @@ def keyPressed(): # if key == "g": # gif_export(GifMaker, filename=SKETCH_NAME) if key == "s": - saveFrame(SKETCH_NAME + "#.png") + saveFrame(SKETCH_NAME + ".png") if key == "t": Poly.text_on = not Poly.text_on diff --git a/2019/sketch_190424b/172.png b/2019/sketch_190424b/172.png new file mode 100644 index 00000000..1e3adf91 Binary files /dev/null and b/2019/sketch_190424b/172.png differ diff --git a/2019/sketch_190424b/sketch_190424b.pyde b/2019/sketch_190424b/sketch_190424b.pyde index beb5a211..33110eca 100644 --- a/2019/sketch_190424b/sketch_190424b.pyde +++ b/2019/sketch_190424b/sketch_190424b.pyde @@ -1,4 +1,5 @@ from __future__ import division + order = 9 def setup(): @@ -22,10 +23,9 @@ def draw(): def draw_trit(trit): r = 8 for t in trit: - tn = int(t) - if tn == 0: + if t == '0': rect(0, 0, r, r) - elif tn == 1: + elif t == '1': rect(0, 0, r/2, r*2) else: rect(0, 0, r*2, r/2) @@ -49,3 +49,16 @@ def trit(n, pad): def keyPressed(): saveFrame("###.png") + +def settings(): + from os import path + global SKETCH_NAME + SKETCH_NAME = path.basename(sketchPath()) + OUTPUT = ".png" + 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) + ) diff --git a/2019/sketch_190425a/gif_exporter.py b/2019/sketch_190425a/gif_exporter.py new file mode 100644 index 00000000..51c431df --- /dev/null +++ b/2019/sketch_190425a/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_190425a/poly.py b/2019/sketch_190425a/poly.py new file mode 100644 index 00000000..5fb2ae00 --- /dev/null +++ b/2019/sketch_190425a/poly.py @@ -0,0 +1,118 @@ + +class Poly(): + + text_on = False + drag = -1 + drag_hole = -1 + drag_drag_pt = -1 + + def __init__(self, outer_pts, holes=[[(0, 0)]]): + self.outer_pts = outer_pts + self.holes = holes + + @classmethod + def setup_grid(cls, cell_size, order, x_offset, y_offset): + cls.cell_size = cell_size + cls.order = order + cls.x_offset, cls.y_offset = x_offset, y_offset + + def plot(self): + pushStyle() + if len(self.outer_pts) >= 3: + fill(255) + beginShape() + for x, y in self.outer_pts: + stroke(0) + sx = (x + Poly.x_offset) * Poly.cell_size + sy = (y + Poly.y_offset) * Poly.cell_size + vertex(sx, sy) + for h in self.holes: + beginContour() + for x, y in h: + sx = (x + Poly.x_offset) * Poly.cell_size + sy = (y + Poly.y_offset) * Poly.cell_size + vertex(sx, sy) + endContour() + endShape(CLOSE) + Poly.annotate_pts(self.outer_pts, color(200, 0, 0), 5) + Poly.annotate_pts(self.holes[0], color(0, 0, 200), 5) + popStyle() + + def remove_pt(self): + snap = Poly.mouse_snap() + if snap: + for pt in self.outer_pts: + if pt == snap: + self.outer_pts.remove(pt) + return True + for h in self.holes: + for pt in h: + if pt == snap: + h.remove(pt) + return True + + def set_drag(self): #, io, jo): + snap = Poly.mouse_snap() + if snap: + for ipt, pt in enumerate(self.outer_pts): + if pt == snap: #(io, jo): + Poly.drag_pt = ipt + return True + for ih, h in enumerate(self.holes): + for ipt, pt in enumerate(h): + if pt == snap: #(io, jo): + Poly.drag_hole = ih + Poly.drag_pt = ipt + return True + return False + + @classmethod + def annotate_pts(cls, pts, c, scale_m=1): + if Poly.text_on: + strokeWeight(5) + textSize(12) + fill(c) + stroke(c) + for i, j in pts: + x = (i + cls.x_offset) * cls.cell_size + y = (j + cls.y_offset) * cls.cell_size + point(x, y) + text(str((i * scale_m, j * scale_m)), x, y) + + @classmethod + def draw_grid(cls): + stroke(128) + noFill() + for x in range(cls.order): + for y in range(cls.order): + rect(x * cls.cell_size, y * cls.cell_size, + cls.cell_size, cls.cell_size) + + @staticmethod + def clockwise_sort(xy_pairs): + # https://stackoverflow.com/questions/51074984/sorting-according-to-clockwise-point-coordinates + data_len = len(xy_pairs) + if data_len > 2: + x, y = zip(*xy_pairs) + else: + return xy_pairs + centroid_x, centroid_y = sum(x) / data_len, sum(y) / data_len + xy_sorted = sorted(xy_pairs, + key=lambda p: atan2((p[1] - centroid_y), (p[0] - centroid_x))) + xy_sorted_xy = [ + coord for pair in list(zip(*xy_sorted)) for coord in pair] + half_len = int(len(xy_sorted_xy) / 2) + return list(zip(xy_sorted_xy[:half_len], xy_sorted_xy[half_len:])) + + @classmethod + def mouse_snap(cls): + for i in range(Poly.order): + x = i * Poly.cell_size + for j in range(Poly.order): + y = j * Poly.cell_size + io, jo = i - Poly.x_offset, j - Poly.y_offset # grid origin correction + if dist(mouseX, mouseY, x, y) < Poly.cell_size / 2: + return (io, jo) + return None + + diff --git a/2019/sketch_190425a/sketch_190425a.pyde b/2019/sketch_190425a/sketch_190425a.pyde new file mode 100644 index 00000000..95891898 --- /dev/null +++ b/2019/sketch_190425a/sketch_190425a.pyde @@ -0,0 +1,102 @@ +# Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day +""" +A minimal poly editor +- Add points +""" + +from poly import Poly +# add_library('GifAnimation') +# from gif_exporter import gif_export + +# f_pts = [map(lambda x: x / 5 - 12, pair) for pair in f_pts] +polys = [Poly([(2, 2), (2, 4), (4, 4), (4, 2)]), + Poly([(5, 5), (5, 7), (3, 3)]), + Poly([(-8, -7), (-1, 0), (1, -9)], + holes=[[(-4, -4), (-6, -6), (-1, -7)], ]), + ] + +def setup(): + size(500, 500, P2D) + CELL_SIZE = 25 + order = width / CELL_SIZE + x_offset = y_offset = int(order / 2) + Poly.setup_grid(CELL_SIZE, order, x_offset, y_offset) + Poly.text_on = False + strokeJoin(ROUND) + f = createFont("Fira Mono Bold", 16) + textFont(f) + +def draw(): + background(230) + # grade + Poly.draw_grid() + # polĂ­gonos + for p in polys: + p.plot() + +def mousePressed(): + if keyPressed and keyCode == CONTROL: + for p in polys: + if p.remove_pt(): # io, jo): + return + else: + for ip, p in enumerate(polys): + if p.set_drag(): # io, jo): + Poly.drag = ip + return + +def mouseDragged(): + if Poly.drag >= 0 and not keyPressed: + # a Poly point has been selected to be dragged + # and no modifier key is pressed... + if Poly.drag_hole == -1: # if no hole wase selected + polys[Poly.drag].outer_pts[Poly.drag_pt] = ( + int(mouseX / Poly.cell_size) - Poly.x_offset, + int(mouseY / Poly.cell_size) - Poly.y_offset) + else: + polys[Poly.drag].holes[Poly.drag_hole][Poly.drag_pt] = ( + int(mouseX / Poly.cell_size) - Poly.x_offset, + int(mouseY / Poly.cell_size) - Poly.y_offset) + +def mouseReleased(): + if Poly.drag >= 0 and keyPressed and keyCode == SHIFT: + # a Poly point has been selected to be dragged + # and SHIFT key is pressed... + if Poly.drag_hole == -1: # if no hole wase selected + polys[Poly.drag].outer_pts.insert( + Poly.drag_pt, (int(mouseX / Poly.cell_size) - Poly.x_offset, + int(mouseY / Poly.cell_size) - Poly.y_offset)) + else: + polys[Poly.drag].holes[Poly.drag_hole].insert( + Poly.drag_pt, (int(mouseX / Poly.cell_size) - Poly.x_offset, + int(mouseY / Poly.cell_size) - Poly.y_offset)) + + Poly.drag = -1 # No poly selected + Poly.drag_hole = -1 # No hole selected + Poly.drag_pt = -1 # No point selected + +def keyPressed(): + if key == " ": + for p in polys: + p.outer_pts[:] = Poly.clockwise_sort(p.outer_pts) + for h in p.holes: + h[:] = Poly.clockwise_sort(h)[::-1] + # if key == "g": + # gif_export(GifMaker, filename=SKETCH_NAME) + if key == "s": + saveFrame(SKETCH_NAME + "#.png") + if key == "t": + Poly.text_on = not Poly.text_on + +def settings(): + from os import path + global SKETCH_NAME + SKETCH_NAME = path.basename(sketchPath()) + OUTPUT = ".png" + 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) + ) diff --git a/2019/sketch_190425b/278.png b/2019/sketch_190425b/278.png new file mode 100644 index 00000000..c627d09b Binary files /dev/null and b/2019/sketch_190425b/278.png differ diff --git a/2019/sketch_190425b/458.png b/2019/sketch_190425b/458.png new file mode 100644 index 00000000..b8846f0b Binary files /dev/null and b/2019/sketch_190425b/458.png differ diff --git a/2019/sketch_190425b/598.png b/2019/sketch_190425b/598.png new file mode 100644 index 00000000..572d04fc Binary files /dev/null and b/2019/sketch_190425b/598.png differ diff --git a/2019/sketch_190425b/773.png b/2019/sketch_190425b/773.png new file mode 100644 index 00000000..4d7afc1a Binary files /dev/null and b/2019/sketch_190425b/773.png differ diff --git a/2019/sketch_190425b/sketch_190425b.pyde b/2019/sketch_190425b/sketch_190425b.pyde new file mode 100644 index 00000000..9c5d4e7e --- /dev/null +++ b/2019/sketch_190425b/sketch_190425b.pyde @@ -0,0 +1,101 @@ +from __future__ import division + +order = 9 +p = 4 +alt = False + + +def setup(): + size(700, 700) + noFill() # fill(0) + textAlign(CENTER, CENTER) + rectMode(CENTER) + strokeWeight(2) + colorMode(HSB) + +def draw(): + background(240) + siz = width / order + if alt: + grid(siz, draw_tritB) + else: + grid(siz, draw_tritA) + +def grid(siz, func): + i = 0 + for x in range(order): + for y in range(order): + with pushMatrix(): + translate(siz / 2 + x * siz, + siz / 2 + y * siz) + #text(trit(i, pad=4), 0, 0) + func(trit(i, pad=p)) + i += 1 + +def draw_tritA(trit): + r = 32 + for t in trit: + if t == '0': + stroke(0, 255, 128) + rect(0, 0, r, r) + elif t == '1': + stroke(256 / 3 * 2, 255, 128) + rect(0, 0, r / 2, r * 2) + else: + stroke(256 / 3, 255, 128) + rect(0, 0, r * 2, r / 2) + r -= 8 + +def draw_tritB(trit): + r = 32 + for t in trit: + stroke(8 + r * 7, 255, 128) + if t == '0': + rect(0, 0, r, r) + elif t == '1': + rect(0, 0, r / 2, r * 2) + else: + rect(0, 0, r * 2, r / 2) + r -= 8 + +def to_base(num, base): + # inverse of int(str, base) + BS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + result = "" + while num: + result += BS[num % base] + num //= base + return result[::-1] or "0" + +def trit(n, pad): + s = to_base(n, 3) + while len(s) < pad: + s = "0" + s + return s[::-1] + + +def keyPressed(): + global alt, p + + if key == "s": + saveFrame("###.png") + + if key == "a": + alt = not alt + + if key == "p": + p = (p - 1) % 5 + + +def settings(): + from os import path + global SKETCH_NAME + SKETCH_NAME = path.basename(sketchPath()) + OUTPUT = ".png" + 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) + ) diff --git a/README.md b/README.md index 215010af..e4aa499e 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,26 @@ Get updates from my sort-of-weekly newsletter: [[sketch-mail](https://villares.o --- ## 2019 + +--- + + +![sketch_190425b](2019/sketch_190425b/sketch_190425b.png) + +[sketch_190425b](https://github.com/villares/sketch-a-day/tree/master/2019/sketch_190425b) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] + +--- + +![sketch_190424b](2019/sketch_190424b/sketch_190424b.png) + +[sketch_190424b](https://github.com/villares/sketch-a-day/tree/master/2019/sketch_190424b) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] + +--- + +![sketch_190424a](2019/sketch_190424a/sketch_190424a.png) + +[sketch_190424a](https://github.com/villares/sketch-a-day/tree/master/2019/sketch_190424a) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] + --- ![sketch_190423a](2019/sketch_190423a/sketch_190423a.png) diff --git a/sketch_190425b.gif b/sketch_190425b.gif new file mode 100644 index 00000000..d9855059 Binary files /dev/null and b/sketch_190425b.gif differ