Morph#
Adapted from https://p5js.org/examples/motion-morph.html
Changing one shape into another by interpolating vertices from one to another.
from proceso import Sketch
p5 = Sketch()
p5.describe("A white shape on a dark gray background repeatedly morphs between a square and a circle.")
# Two lists to store the vertices for two shapes
# This example assumes that each shape will have the same
# number of vertices, i.e. the size of each list will be the same
circle = []
square = []
# A list for a third set of vertices, the ones we will be drawing
# in the window
morph = []
# This boolean variable will control if we are morphing to a circle or square
state = False
def setup():
p5.create_canvas(720, 400)
# Create a circle using vectors pointing from center
for angle in range(0, 360, 9):
# Note we are not starting from 0 in order to match the
# path of a circle.
v = p5.Vector.from_heading(p5.radians(angle - 135))
v *= 100
circle.append(v)
# Let's fill out morph list with blank Vectors while we are at it
morph.append(p5.Vector(0, 0))
# A square is a bunch of vertices along straight lines
# Top of square
for x in range(-50, 50, 10):
square.append(p5.Vector(x, -50))
# Right side
for y in range(-50, 50, 10):
square.append(p5.Vector(50, y))
# Bottom
for x in range(50, -50, -10):
square.append(p5.Vector(x, 50))
# Left side
for y in range(50, -50, -10):
square.append(p5.Vector(-50, y))
def draw():
global state
p5.background(51)
# We will keep how far the vertices are from their target
total_distance = 0
# Look at each vertex
for i in range(len(circle)):
v1: p5.Vector
# Are we lerping to the circle or square?
if state:
v1 = circle[i]
else:
v1 = square[i]
# Get the vertex we will draw
v2 = morph[i]
# Lerp to the target
v2 = v2.lerp(v1, 0.1)
# Check how far we are from target
total_distance += p5.Vector.dist(v1, v2)
# Update vertex in morph list
morph[i] = v2
# If all the vertices are close, switch shape
if total_distance < 0.1:
state = not state
# Draw relative to center
p5.translate(p5.width / 2, p5.height / 2)
p5.stroke_weight(4)
# Draw a polygon that makes up all the vertices
p5.begin_shape()
p5.no_fill()
p5.stroke(255)
for v in morph:
p5.vertex(v.x, v.y)
p5.end_shape(p5.CLOSE)
p5.run_sketch(setup=setup, draw=draw)