Recently suzy on the processing forum was asking how to create a Sutcliffe pentagon, this got me thinking is there such a thing. So far the only reference I have found to it, was in an extract of Matt Pearsons Book Generative Art book. Anyway it looked interesting so I had go at coding it in JRubyArt (using some logic from a recursive pentagon sketch by C. Andrews on openprocessing). The sketch features a couple of nifty JRubyArt features including Vec2D (whose methods can be chained, and just look like math) DegLUT tables, and a handy way of creating an enumerable colour palette from an array of web strings. The other quite useful feature (missing in vanilla processing) is the ability to create a vertex directly from the vector.

sutcliffe.rb

# Sutcliffe Pentagons (a JRubyArt Sketch by Martin Prout)

load_library :color_group
attr_reader :strut_factor, :renderer, :cols
PALETTE = %w[#fff0a5 #ffd500 #594a00 #9999ff #000059].freeze

def setup
  sketch_title 'Recursive Pentagons'
  @strut_factor = 0.2
  @renderer = AppRender.new self # so we can send Vec2D :to_vertex
  group = ColorGroup.from_web_array(PALETTE.to_java(:string))
  @cols = group.colors
  background(cols.last)
  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 = Pentagon.new(points, 4)
  fractal.draw
  save_frame(data_path('sutcliffe.png'))
end

def settings
  size(800, 800)
end

# Here we include Processing::Proxy to mimic vanilla processing inner class
# access.
class Pentagon
  include Processing::Proxy
  attr_reader :points ,:branches, :level, :midpoints, :innerpoints

  def initialize(points, levels)
    @points = points
    @level = levels
    return if level.zero? # so called guard clause in ruby simplifies code
    # 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 (`logic stolen from C. Andrews`)
    # 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]
      ]
      Pentagon.new(p, level - 1)
    end
    # add the final innermost pentagon
    branches << Pentagon.new(innerpoints, level - 1)
  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
  # pentagon formed by the points. When not level 0, iterate through the
  # six branches and tell them to draw themselves.
  def draw
    no_fill
    begin_shape
    stroke_weight level
    stroke cols[level]
    points.each do |point|
      point.to_vertex(renderer)
    end
    end_shape CLOSE
    return if level.zero?

    branches.each(&:draw)
  end
end

sutcliffe.png