kopia lustrzana https://github.com/villares/sketch-a-day
main
rodzic
13465c2ac9
commit
15937ef6af
|
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
Alexandre B A Villares http://abav.lugaralgum.com - GPL v3
|
||||
|
||||
A helper for the Processing gifAnimation library (https://github.com/jordanorelli)
|
||||
ported to Processing 3 by 01010101 (https://github.com/01010101)
|
||||
Download the library from https://github.com/01010101/GifAnimation/archive/master.zip
|
||||
This helper was inspired by an example by Art Simon https://github.com/APCSPrinciples/AnimatedGIF/
|
||||
|
||||
Put at the start of your sketch:
|
||||
add_library('gifAnimation')
|
||||
from gif_exporter import gif_export
|
||||
and 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=182, # quality range 0 - 255
|
||||
delay=170, # this is quick
|
||||
frames=0): # 0 will stop on keyPressed or frameCount >= 100000
|
||||
global gifExporter
|
||||
try:
|
||||
gifExporter
|
||||
except NameError:
|
||||
gifExporter = GifMaker(this, filename + ".gif")
|
||||
gifExporter.setRepeat(repeat)
|
||||
gifExporter.setQuality(quality)
|
||||
gifExporter.setDelay(delay)
|
||||
gif_export._frame = frameCount
|
||||
print("gif start")
|
||||
|
||||
gifExporter.addFrame()
|
||||
|
||||
if (frames == 0 and keyPressed or frameCount - gif_export._frame >= 100000) \
|
||||
or (frames != 0 and frameCount - gif_export._frame >= frames):
|
||||
gifExporter.finish()
|
||||
background(255)
|
||||
print("gif saved")
|
||||
del(gifExporter)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
Plik binarny nie jest wyświetlany.
|
Po Szerokość: | Wysokość: | Rozmiar: 381 KiB |
|
|
@ -0,0 +1,195 @@
|
|||
"""
|
||||
Alexandre B A Villares - https://abav.lugaralgum.com/sketch-a-day
|
||||
|
||||
- Unfolding solid....
|
||||
"""
|
||||
|
||||
add_library('GifAnimation')
|
||||
from gif_exporter import gif_export
|
||||
from unfold_face import *
|
||||
|
||||
CUT_STROKE = color(255, 0, 0)
|
||||
FOLD_STROKE = color(0, 0, 255)
|
||||
|
||||
p_height, base_radius, top_radius = 100, 50, 50
|
||||
sides = 5
|
||||
|
||||
def setup():
|
||||
size(600, 600, P3D)
|
||||
hint(ENABLE_DEPTH_TEST)
|
||||
hint(ENABLE_DEPTH_SORT)
|
||||
|
||||
def draw():
|
||||
background(240)
|
||||
pushMatrix()
|
||||
translate(width / 2, height / 4 + 50)
|
||||
rotateX(radians(45))
|
||||
rotateZ(radians(frameCount / 3.))
|
||||
fill(255, 200)
|
||||
stroke(0)
|
||||
strokeWeight(2)
|
||||
# draw 3D piramid and get points
|
||||
points, face = prism_3D(sides, p_height, base_radius, top_radius)
|
||||
popMatrix()
|
||||
# draw unfolded 2D
|
||||
translate(width / 2, height * 3 / 4 - 50)
|
||||
prism_2D(points, face)
|
||||
# triangulated_face(*face)
|
||||
|
||||
def prism_3D(np, h, base_r, top_r):
|
||||
# calculando os points
|
||||
base_points = []
|
||||
for i in range(np):
|
||||
ang = radians(i * 360. / np)
|
||||
x = sin(ang) * base_r
|
||||
y = cos(ang) * base_r
|
||||
base_points.append((x, y))
|
||||
# edges da base
|
||||
o_base_points = base_points[1:] + [base_points[0]]
|
||||
base_edges = zip(base_points, o_base_points)
|
||||
top_points = []
|
||||
for i in range(np):
|
||||
ang = radians(i * 360. / np)
|
||||
x = sin(ang) * top_r
|
||||
y = cos(ang) * top_r
|
||||
top_points.append((x, y))
|
||||
# edges da base
|
||||
o_top_points = top_points[1:] + [top_points[0]]
|
||||
top_edges = zip(top_points, o_top_points)
|
||||
# edges
|
||||
for base_edge, top_edge in zip(base_edges, top_edges):
|
||||
(p1x, p1y), (p2x, p2y) = base_edge
|
||||
(p1tx, p1ty), (p2tx, p2ty) = top_edge
|
||||
beginShape()
|
||||
vertex(p1x, p1y, 0)
|
||||
vertex(p1tx, p1ty, h)
|
||||
vertex(p2tx, p2ty, h)
|
||||
vertex(p2x, p2y, 0)
|
||||
endShape(CLOSE)
|
||||
#line(p1x, p1y, 0, p2tx, p2ty, h)
|
||||
# one face
|
||||
(p1x, p1y), (p2x, p2y) = base_edges[0]
|
||||
(p1tx, p1ty), (p2tx, p2ty) = top_edges[0]
|
||||
face = [(p2x, p2y, 0),
|
||||
(p1x, p1y, 0),
|
||||
(p1tx, p1ty, h),
|
||||
(p2tx, p2ty, h),
|
||||
]
|
||||
# always draws base
|
||||
beginShape()
|
||||
for bpt in base_points:
|
||||
vertex(bpt[0], bpt[1], 0)
|
||||
endShape(CLOSE)
|
||||
beginShape()
|
||||
for tpt in top_points:
|
||||
vertex(tpt[0], tpt[1], h)
|
||||
endShape(CLOSE)
|
||||
# return points for 2D!
|
||||
return (base_points, top_points), face
|
||||
|
||||
def prism_2D(top_bot, face):
|
||||
with pushMatrix():
|
||||
translate(150, -300)
|
||||
poly_draw(top_bot[1])
|
||||
with pushMatrix():
|
||||
translate(-150, -300)
|
||||
poly_draw(top_bot[0])
|
||||
x0, y0, z0 = face[1]
|
||||
x2, y2, z2 = face[2]
|
||||
d = dist(x0, y0, z0, x2, y2, z2)
|
||||
side = ((150, d - 150), (150, -150))
|
||||
for i in range(sides):
|
||||
side = unfold_tri_face(side, face[::-1])
|
||||
stroke(CUT_STROKE)
|
||||
glue_tab((150, -150), (150, d - 150), 10)
|
||||
|
||||
# for points in all_points:
|
||||
# ang = radians(360. / len(points))
|
||||
# with pushMatrix():
|
||||
# translate(-width / 4, 0)
|
||||
# rotate(ang / 2)
|
||||
# noFill()
|
||||
# base fold lines
|
||||
# stroke(FOLD_STROKE)
|
||||
# beginShape()
|
||||
# for pt in points:
|
||||
# vertex(*pt)
|
||||
# endShape(CLOSE)
|
||||
# lateral edges
|
||||
# o_points = points[1:] + [points[0]]
|
||||
# edges = zip(points, o_points)
|
||||
# for i, edge in enumerate(edges): # edges[1:] to skip one
|
||||
# p1, p2 = edge
|
||||
# stroke(CUT_STROKE)
|
||||
# abas de cola
|
||||
# glue_tab(p2, p1, 10, )
|
||||
# FOLD_STROKE
|
||||
# stroke(FOLD_STROKE)
|
||||
# line(p2[0], p2[1], p1[0], p1[1])
|
||||
# translate(width / 2, 0)
|
||||
|
||||
def glue_tab(p1, p2, tab_w, cut_ang=QUARTER_PI / 3):
|
||||
"""
|
||||
draws a trapezoidal or triangular glue tab along edge defined by p1 and p2,
|
||||
with width tab_w and cut angle a
|
||||
"""
|
||||
al = atan2(p1[0] - p2[0], p1[1] - p2[1])
|
||||
a1 = al + cut_ang + PI
|
||||
a2 = al - cut_ang
|
||||
# calculate cut_len to get the base_rght tab width
|
||||
cut_len = tab_w / sin(cut_ang)
|
||||
f1 = (p1[0] + cut_len * sin(a1),
|
||||
p1[1] + cut_len * cos(a1))
|
||||
f2 = (p2[0] + cut_len * sin(a2),
|
||||
p2[1] + cut_len * cos(a2))
|
||||
edge_len = dist(p1[0], p1[1], p2[0], p2[1])
|
||||
|
||||
if edge_len > 2 * cut_len * cos(cut_ang): # 'normal' trapezoidal tab
|
||||
beginShape()
|
||||
vertex(*p1) # vertex(p1[0], p1[1])
|
||||
vertex(*f1)
|
||||
vertex(*f2)
|
||||
vertex(*p2)
|
||||
endShape()
|
||||
else: # short triangular tab
|
||||
fm = ((f1[0] + f2[0]) / 2, (f1[1] + f2[1]) / 2)
|
||||
beginShape()
|
||||
vertex(*p1)
|
||||
vertex(*fm) # middle way of f1 and f2
|
||||
vertex(*p2)
|
||||
endShape()
|
||||
|
||||
def keyPressed():
|
||||
global base_radius, top_radius, p_height, sides
|
||||
if keyCode == UP:
|
||||
p_height += 5
|
||||
if keyCode == DOWN:
|
||||
p_height -= 5
|
||||
if keyCode == LEFT:
|
||||
base_radius += 5
|
||||
if keyCode == RIGHT:
|
||||
base_radius -= 5
|
||||
if key == "w":
|
||||
sides += 1
|
||||
if key == "s" and sides > 3:
|
||||
sides -= 1
|
||||
if key == "a" and top_radius > 0:
|
||||
top_radius -= 5
|
||||
if key == "d":
|
||||
top_radius += 5
|
||||
if key == "g":
|
||||
# saveFrame(SKETCH_NAME + ".gif")
|
||||
gif_export(GifMaker, filename=SKETCH_NAME)
|
||||
|
||||
def settings():
|
||||
from os import path
|
||||
global SKETCH_NAME
|
||||
SKETCH_NAME = path.basename(sketchPath())
|
||||
OUTPUT = ".gif"
|
||||
println(
|
||||
"""
|
||||

|
||||
|
||||
[{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())
|
||||
)
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
CUT_STROKE = color(255, 0, 0)
|
||||
|
||||
def test():
|
||||
#size(600, 400, P3D)
|
||||
p3D = [(50, 100, 0), (200, 100, 0), (200, 200, 0), (100, 300, -100)]
|
||||
debug_text("ABCD", p3D)
|
||||
beginShape()
|
||||
for p in p3D:
|
||||
vertex(*p)
|
||||
endShape(CLOSE)
|
||||
x0, y0, z0 = p3D[1]
|
||||
x2, y2, z2 = p3D[3]
|
||||
line(x0, y0, z0, x2, y2, z2)
|
||||
println(dist(x0, y0, z0, x2, y2, z2))
|
||||
|
||||
p2D = [(250, 100), (250, 200)]
|
||||
bx, by = p2D[0]
|
||||
debug_text("BC", p2D)
|
||||
for i in range(1):
|
||||
p2D = unfold_tri_face(p2D, p3D)
|
||||
println(p2D)
|
||||
debug_text("AD", p2D)
|
||||
dx, dy, _ = p2D[1]
|
||||
println(dist(bx, by, dx, dy))
|
||||
|
||||
|
||||
def unfold_tri_face(pts_2D, pts_3D):
|
||||
"""
|
||||
gets a collection of 2 (B, C) starting 2D points (PVectors or tuples)
|
||||
Gets a collection of 4 (A, B, C, D) 3D points (PVectors or tuples)
|
||||
Draws the unfolded face and returns (A, D) 2D positions.
|
||||
"""
|
||||
b2D, c2D = pts_2D
|
||||
a3D, b3D, c3D, d3D = pts_3D
|
||||
bd_len = dist(b3D[0], b3D[1], b3D[2], d3D[0], d3D[1], d3D[2])
|
||||
cd_len = dist(c3D[0], c3D[1], c3D[2], d3D[0], d3D[1], d3D[2])
|
||||
# lower triangle
|
||||
d2D = third_point(b2D, c2D, bd_len, cd_len)[0] # gets the first solution
|
||||
line_draw(b2D, c2D)
|
||||
#line_draw(b2D, d2D)
|
||||
line_draw(d2D, c2D, tab=True)
|
||||
# upper triangle (fixed from 190408a)
|
||||
ab_len = dist(b3D[0], b3D[1], b3D[2], a3D[0], a3D[1], a3D[2])
|
||||
ad_len = dist(a3D[0], a3D[1], a3D[2], d3D[0], d3D[1], d3D[2])
|
||||
# gets the 1st solution too!
|
||||
a2D = third_point(b2D, d2D, ab_len, ad_len)[0]
|
||||
line_draw(b2D, a2D, tab=True)
|
||||
line_draw(d2D, a2D)
|
||||
return (a2D, d2D)
|
||||
|
||||
def third_point(a, b, ac_len, bc_len):
|
||||
"""
|
||||
Adapted from code by Monkut https://stackoverflow.com/users/24718/monkut
|
||||
at https://stackoverflow.com/questions/4001948/drawing-a-triangle-in-a-coordinate-plane-given-its-three-sides
|
||||
for use with Processing Python Mode - using PVectors
|
||||
|
||||
Returns two point c options given:
|
||||
point a, point b, ac length, bc length
|
||||
"""
|
||||
class NoTrianglePossible(BaseException):
|
||||
pass
|
||||
|
||||
# To allow use of tuples, creates or recreates PVectors
|
||||
a, b = PVector(*a), PVector(*b)
|
||||
# check if a triangle is possible
|
||||
ab_len = a.dist(b)
|
||||
if ab_len > (ac_len + bc_len) or ab_len < abs(ac_len - bc_len):
|
||||
raise NoTrianglePossible("The sides do not form a triangle")
|
||||
|
||||
# get the length to the vertex of the right triangle formed,
|
||||
# by the intersection formed by circles a and b
|
||||
ad_len = (ab_len ** 2 + ac_len ** 2 - bc_len ** 2) / (2.0 * ab_len)
|
||||
# get the height of the line at a right angle from a_len
|
||||
h = sqrt(abs(ac_len ** 2 - ad_len ** 2))
|
||||
|
||||
# Calculate the mid point d, needed to calculate point c(1|2)
|
||||
d = PVector(a.x + ad_len * (b.x - a.x) / ab_len,
|
||||
a.y + ad_len * (b.y - a.y) / ab_len)
|
||||
# get point c locations
|
||||
c1 = PVector(d.x + h * (b.y - a.y) / ab_len,
|
||||
d.y - h * (b.x - a.x) / ab_len)
|
||||
c2 = PVector(d.y + h * (b.x - a.x) / ab_len,
|
||||
d.x - h * (b.y - a.y) / ab_len)
|
||||
return c1, c2
|
||||
|
||||
def line_draw(p1, p2, tab=False):
|
||||
"""
|
||||
sugar for drawing lines from 2 "points" (tuples or PVectors)
|
||||
may also draw a glue tab suitably marked for cutting.
|
||||
"""
|
||||
line(p1[0], p1[1], p2[0], p2[1])
|
||||
if tab:
|
||||
with pushStyle():
|
||||
stroke(CUT_STROKE)
|
||||
glue_tab(p1, p2)
|
||||
|
||||
def glue_tab(p1, p2, tab_w=10, cut_ang=QUARTER_PI):
|
||||
"""
|
||||
draws a trapezoidal or triangular glue tab
|
||||
along edge defined by p1 and p2, with provided
|
||||
width (tab_w) and cut angle (cut_ang)
|
||||
"""
|
||||
a1 = atan2(p1[0] - p2[0], p1[1] - p2[1]) + cut_ang + PI
|
||||
a2 = atan2(p1[0] - p2[0], p1[1] - p2[1]) - cut_ang
|
||||
# calculate cut_len to get the right tab width
|
||||
cut_len = tab_w / sin(cut_ang)
|
||||
f1 = (p1[0] + cut_len * sin(a1),
|
||||
p1[1] + cut_len * cos(a1))
|
||||
f2 = (p2[0] + cut_len * sin(a2),
|
||||
p2[1] + cut_len * cos(a2))
|
||||
edge_len = dist(p1[0], p1[1], p2[0], p2[1])
|
||||
|
||||
if edge_len > 2 * cut_len * cos(cut_ang): # 'normal' trapezoidal tab
|
||||
line_draw(p1, f1)
|
||||
line_draw(f1, f2)
|
||||
line_draw(f2, p2)
|
||||
else: # short triangular tab
|
||||
fm = ((f1[0] + f2[0]) / 2, (f1[1] + f2[1]) / 2)
|
||||
line_draw(p1, fm)
|
||||
line_draw(fm, p2)
|
||||
|
||||
|
||||
DEBUG = True
|
||||
|
||||
def debug_text(name, points, enum=False):
|
||||
if DEBUG:
|
||||
for i, p in enumerate(points):
|
||||
with push():
|
||||
|
||||
fill(255, 0, 0)
|
||||
if enum:
|
||||
translate(0, -5, 10)
|
||||
text(name + "-" + str(i), *p)
|
||||
else:
|
||||
translate(10, 10, 10)
|
||||
text(name[i], *p)
|
||||
|
||||
def poly_draw(points, closed=True):
|
||||
""" sugar for face drawing """
|
||||
beginShape()
|
||||
for p in points:
|
||||
vertex(*p)
|
||||
if closed:
|
||||
endShape(CLOSE)
|
||||
else:
|
||||
endShape()
|
||||
|
||||
def triangulated_face(*args):
|
||||
if len(args) == 4:
|
||||
a, b, c, d = args
|
||||
println("face")
|
||||
else:
|
||||
a, b, c, d = args[0]
|
||||
# two triangles - could be with a diferent diagonal!
|
||||
# TODO: let one choose diagonal orientation
|
||||
stroke(0)
|
||||
poly_draw((a, b, d))
|
||||
poly_draw((b, d, c))
|
||||
Ładowanie…
Reference in New Issue