Plot #1: Learning Hexagons
As a software engineer that builds web applications, it took me some time to wrap my head around how generative art is rendered. Web browsers use a box model for positioning, which means everything is encapsulated in a box and you manipulate the contents within it.
This is very different from the standard x, y-coordinate system.
Since I'm familiar with Python, I decided to use vsketch as my primary tool. This is a really incredible piece of open source software developed specifically for creating pen plotter art. The framework is built to mimic Processing, a popular open source software tool for creating generative art that has a wider set of capabilities.
The real benefit to this approach is that I can learn how to create generative art with Processing and apply those principals to vsketch. I'm currently reading Generative Art: A Practical Guide Using Processing (free PDF).
Naïvety can be useful
When you have an infinite set of possibilities, where do you even start? Drawing a line, sure, easy enough. But where's the sweet spot between bewildering complexity and an accomplishable challenge?
I decided to start with a "simple" hexagon. I figured there must be some hexagon
or polygon
method that could create this basic shape. And there is, in fact, a polygon
method, but I wanted to know how to make one from "scratch," er, math.
What I didn't realize was that a hexagon, or any regular polygon for that matter, is calculated using a circle. After doing some googling, I came across this excellent guide that details exactly what a hexagon is and how to create a grid of hexagons.
After dabbling for hours, things started to take shape. There are some serious hacks in this code snippet, but it does the job:
spacing = vsketch.Param(0.0, step=0.01, decimals=2)
nested_count = vsketch.Param(11, step=1)
rows = vsketch.Param(11, step=1)
cols = vsketch.Param(11, step=1)
def draw(self, vsk: vsketch.Vsketch) -> None:
vsk.size("a4", landscape=False)
vsk.scale("cm")
radius = 1
points = 6
class RegularPolygon:
def __init__(self, points=6, radius=1):
self.points = points
self.radius = radius
self.coordinates = []
def generate_coordinates(self, vsk):
self.coordinates = []
for i in range(self.points):
with vsk.pushMatrix():
angle = 2 * math.pi * i / self.points
x = self.radius * math.cos(angle)
y = self.radius * math.sin(angle)
self.coordinates.append((x, y))
return self.coordinates
mid_column = self.cols // 2
for row in range(self.rows):
with vsk.pushMatrix():
offset = vsk.random(.25, .5)
is_odd_row = row % 2 == 1
absolute_offset = abs(offset)
offset = absolute_offset if is_odd_row else -absolute_offset
for col in range(self.cols):
with vsk.pushMatrix():
rows_remaining = self.rows - row
begin_trimming = (mid_column + 1) - rows_remaining
if begin_trimming > col:
continue
for i in range(self.nested_count-1, -1, -1):
size = (i + 1) / self.nested_count
polygon = RegularPolygon(points, size)
coordinates = polygon.generate_coordinates(vsk)
if mid_column - row <= col:
vsk.polygon(
coordinates,
close=True,
)
vsk.translate((size / self.nested_count) * offset,
(size / self.nested_count) * offset)
vsk.translate((3 / 2 * radius) + self.spacing,
(math.sqrt(3) / 2 * radius) + self.spacing)
vsk.translate(0, (math.sqrt(3) * radius) + self.spacing)
I'm not going to break this code down, but, in essence, it creates nested hexagons in a "diagonal" grid and trims the edges to create a unified shape. It needs more work to make it truly dynamic, but it's a good start.
Next Steps
Is this generative art? Sort of. Purists would contend that there needs to be more randomness involved. And while that's true, I don't think you should inject too much randomness while you're learning the basics. Randomness is easy to add once you understand the basic concepts and mental models.
These pieces turned out much better than I expected for my first plots. The next step will be experimenting with some different mediums: black cardstock and various pens.
Of course, I'll also be dabbling with new algorithms, increased randomness and reporting on everything I learn.
You can follow me on Instagram for snapshots of the work. (And, yes, the photography needs some improvement 🙃)