diff --git a/2019/sketch_190829b/arcs.py b/2019/sketch_190829b/arcs.py new file mode 100644 index 00000000..f771db60 --- /dev/null +++ b/2019/sketch_190829b/arcs.py @@ -0,0 +1,142 @@ +# -*- 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 b_circle_arc(x, y, radius, start_ang, sweep_ang, mode=0): + b_arc(x, y, radius * 2, radius * 2, start_ang, start_ang + sweep_ang, + mode=mode) + +def b_arc(cx, cy, w, h, start_angle, end_angle, mode=0): + """ + A bezier approximation of an arc + using the same signature as the original Processing arc() + mode: 0 "normal" arc, using beginShape() and endShape() + 1 "middle" used in recursive call of smaller arcs + 2 "naked" like normal, but without beginShape() and endShape() + for use inside a larger PShape + """ + theta = end_angle - start_angle + # Compute raw Bezier coordinates. + if mode != 1 or theta < HALF_PI: + x0 = cos(theta / 2.0) + y0 = sin(theta / 2.0) + x3 = x0 + y3 = 0 - y0 + x1 = (4.0 - x0) / 3.0 + if y0 != 0: + y1 = ((1.0 - x0) * (3.0 - x0)) / (3.0 * y0) # y0 != 0... + else: + y1 = 0 + x2 = x1 + y2 = 0 - y1 + # Compute rotationally-offset Bezier coordinates, using: + # x' = cos(angle) * x - sin(angle) * y + # y' = sin(angle) * x + cos(angle) * y + bezAng = start_angle + theta / 2.0 + cBezAng = cos(bezAng) + sBezAng = sin(bezAng) + rx0 = cBezAng * x0 - sBezAng * y0 + ry0 = sBezAng * x0 + cBezAng * y0 + rx1 = cBezAng * x1 - sBezAng * y1 + ry1 = sBezAng * x1 + cBezAng * y1 + rx2 = cBezAng * x2 - sBezAng * y2 + ry2 = sBezAng * x2 + cBezAng * y2 + rx3 = cBezAng * x3 - sBezAng * y3 + ry3 = sBezAng * x3 + cBezAng * y3 + # Compute scaled and translated Bezier coordinates. + rx, ry = w / 2.0, h / 2.0 + px0 = cx + rx * rx0 + py0 = cy + ry * ry0 + px1 = cx + rx * rx1 + py1 = cy + ry * ry1 + px2 = cx + rx * rx2 + py2 = cy + ry * ry2 + px3 = cx + rx * rx3 + py3 = cy + ry * ry3 + # Debug points... comment this out! + # stroke(0) + # ellipse(px3, py3, 15, 15) + # ellipse(px0, py0, 5, 5) + # Drawing + if mode == 0: # 'normal' arc (not 'middle' nor 'naked') + beginShape() + if mode != 1: # if not 'middle' + vertex(px3, py3) + if theta < HALF_PI: + bezierVertex(px2, py2, px1, py1, px0, py0) + else: + # to avoid distortion, break into 2 smaller arcs + b_arc(cx, cy, w, h, start_angle, end_angle - theta / 2.0, mode=1) + b_arc(cx, cy, w, h, start_angle + theta / 2.0, end_angle, mode=1) + if mode == 0: # end of a 'normal' arc + endShape() + +def p_circle_arc(x, y, radius, start_ang, sweep_ang, mode=0, num_points=None): + p_arc(x, y, radius * 2, radius * 2, start_ang, start_ang + sweep_ang, + mode=mode, num_points=num_points) + +def p_arc(cx, cy, w, h, start_angle, end_angle, mode=0, num_points=None): + """ + A poly approximation of an arc + using the same signature as the original Processing arc() + mode: 0 "normal" arc, using beginShape() and endShape() + 2 "naked" like normal, but without beginShape() and endShape() + for use inside a larger PShape + """ + if not num_points: + num_points = 24 + # start_angle = start_angle if start_angle < end_angle else start_angle - TWO_PI + sweep_angle = end_angle - start_angle + if mode == 0: + beginShape() + if sweep_angle < 0: + start_angle, end_angle = end_angle, start_angle + sweep_angle = -sweep_angle + angle = sweep_angle / int(num_points) + a = end_angle + while a >= start_angle: + sx = cx + cos(a) * w / 2. + sy = cy + sin(a) * h / 2. + vertex(sx, sy) + a -= angle + elif sweep_angle > 0: + angle = sweep_angle / int(num_points) + a = start_angle + while a <= end_angle: + sx = cx + cos(a) * w / 2. + sy = cy + sin(a) * h / 2. + vertex(sx, sy) + a += angle + else: + sx = cx + cos(start_angle) * w / 2. + sy = cy + sin(start_angle) * h / 2. + vertex(sx, sy) + if mode == 0: + endShape() diff --git a/2019/sketch_190829b/sketch_190829b.gif b/2019/sketch_190829b/sketch_190829b.gif new file mode 100644 index 00000000..e746a3ff Binary files /dev/null and b/2019/sketch_190829b/sketch_190829b.gif differ diff --git a/2019/sketch_190829b/sketch_190829b.pyde b/2019/sketch_190829b/sketch_190829b.pyde new file mode 100644 index 00000000..976755d0 --- /dev/null +++ b/2019/sketch_190829b/sketch_190829b.pyde @@ -0,0 +1,100 @@ +# inspired by https://twitter.com/takawo/status/1164723663200870401 + +# add_library('peasycam') +from random import randint as ri +from random import seed +from arcs import * + +a = 516 +s = 1 + +def setup(): + size(a, a) + colorMode(HSB) + strokeWeight(1.5) + blendMode(MULTIPLY) + # cam = PeasyCam(this, 500) + +def draw(): + background(240) + # translate(-width/ 2, -height / 2) + randomSeed(s) + seed(s) + t(a // 10, a // 10, a - a // 10 * 2) + +def t(x, y, w): + s = w // ri(2, 3) + noStroke() + fill(s * 6, 255, 200) + for i in range(x, x + w - 1, s): + for j in range(y, y + w - 1, s): + if random(1) < .85 and w > 90: + # translate(0, 0, i / 32 - j / 32) + t(i, j, s) + elif random(1) < .5: + l(i, j, i + s, j + s, s // 2) + else: + l(i, j + s, i + s, j, s // 2) + +def l(x1, y1, x2, y2, s): + D = dist(x1, y1, x2, y2) + var_bar(x1, y1, x2, y2, s/D*20, s/D*20) + # rectMode(CENTER) + # circle(x1, y1, s) + # circle(x2, y2, s) + # rectMode(CORNER) + + +def keyPressed(): + global s + if key == ' ': + redraw() + s += 1 + if key == 's': saveFrame("#####.png") + + +def var_bar(p1x, p1y, p2x, p2y, r1, r2=None): + """ + Tangent/tangent shape on 2 circles of arbitrary radius + """ + if r2 is None: + r2 = r1 + #line(p1x, p1y, p2x, p2y) + d = dist(p1x, p1y, p2x, p2y) + ri = r1 - r2 + if d > abs(ri): + rid = (r1 - r2) / d + if rid > 1: + rid = 1 + if rid < -1: + rid = -1 + beta = asin(rid) + HALF_PI + with pushMatrix(): + translate(p1x, p1y) + angle = atan2(p1x - p2x, p2y - p1y) + rotate(angle + HALF_PI) + x1 = cos(beta) * r1 + y1 = sin(beta) * r1 + x2 = cos(beta) * r2 + y2 = sin(beta) * r2 + #print((d, beta, ri, x1, y1, x2, y2)) + beginShape() + b_arc(0, 0, r1 * 2, r1 * 2, + -beta - PI, beta - PI, mode=2) + b_arc(d, 0, r2 * 2, r2 * 2, + beta - PI, PI - beta, mode=2) + endShape(CLOSE) + +def settings(): + """ print markdown to add at the sketc-a-day page""" + from os import path + global SKETCH_NAME + SKETCH_NAME = path.basename(sketchPath()) + OUTPUT = ".png" + println( + """ +![{0}]({2}/{0}/{0}{1}) + +[{0}](https://github.com/villares/sketch-a-day/tree/master/{2}/{0}) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)] +""".format(SKETCH_NAME, OUTPUT, year()) + )