Skip to content

Instantly share code, notes, and snippets.

@monkstone
Created January 10, 2019 09:36
Show Gist options
  • Save monkstone/77b95a422a58974ea2af95cd0b7b0aab to your computer and use it in GitHub Desktop.
Save monkstone/77b95a422a58974ea2af95cd0b7b0aab to your computer and use it in GitHub Desktop.
Recursive Pentagons
attr_reader :strut_factor, :renderer
MAX_LEVEL = 5
def setup
sketch_title 'Recursive Fractals'
@strut_factor = 0.2
@renderer = AppRender.new self # so we can send Vec2D :to_vertex
background(255)
no_loop
end
def draw
translate(width / 2, height / 2)
angle = TWO_PI / 5
radius = width / 2
points = (0...5).map do |i|
x = radius * cos(angle * i)
y = radius * sin(angle * i)
Vec2D.new(x, y)
end
fractal = Fractal.new(Pentagon.new(1, points))
fractal.draw
end
def settings
size(800, 800)
end
class Pentagon
attr_reader :level, :points, :weight
def initialize(level, points)
@level = level
@points = points
@weight = [0.5, 1, 3, 5].sample
end
def draw
no_fill
begin_shape
stroke_weight weight
points.each do |point|
point.to_vertex(renderer)
end
end_shape CLOSE
end
end
# Here we include Processing::Proxy to mimic vanilla processing inner class
# access.
class Fractal
include Processing::Proxy
attr_reader :pentagon ,:branches, :midpoints, :innerpoints
def initialize(pentagon)
@pentagon = pentagon
points = pentagon.points
return if pentagon.level == MAX_LEVEL
# find the midpoints on each edge
@midpoints = (0...5).map do |i|
midpoint(points[i], points[(i + 1) % 5])
end
# find the inner points
@innerpoints = (0...5).map do |i|
opposite = points[(i + 3) % 5]
x = midpoints[i].x + (opposite.x - midpoints[i].x) * strut_factor
y = midpoints[i].y + (opposite.y - midpoints[i].y) * strut_factor
Vec2D.new(x, y)
end
# Create the Pentagon objects representing the six inner
# Pentagons
# the shape is very regular, so we can build the ring of five
@branches = (0...5).map do |i|
p = [
midpoints[i],
innerpoints[i],
innerpoints[(i + 1) % 5],
midpoints[(i + 1) % 5],
points[(i + 1) % 5]
]
Fractal.new(Pentagon.new(pentagon.level + 1, p))
end
# add the final innermost Fractal
branches << Fractal.new(Pentagon.new(pentagon.level + 1, innerpoints))
end
# This is a simple helper function that takes in two points (as Vec2D) and
# returns the midpoint between them as Vec2D.
def midpoint(point1, point2)
(point2 + point1) * 0.5
end
# This draws the fractal. If this is on level 0, we just draw the
# Fractal formed by the points. When not level 0, iterate through the
# six branches and tell them to draw themselves.
def draw
branches.each do |branch|
break if branch.pentagon.level == MAX_LEVEL
branch.pentagon.draw
branch.draw
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment