Sunday, January 31, 2021

Genuary 2021 Day 31: "Oblique Strategies"

 


I like the idea of Brian Eno's cards for jarring your brain to be more creative, to get out of its rut. I found an online Eno Oblique Strategy oracle, and it told me:

"Don't be afraid of things because they're easy to do."

Which I played around with for a while. I remembered the old vector arcade Star Wars game that allowed you to select your level and get a bonus if you selected anything but the easiest difficulty. But no shame in playing on "easy". Some people prefer to experience the story.



So, I rendered my own version of the level selection screen, using my ray marcher. I added in some "reflection" operators, so the four X-Wing cannons are actually a single piece of geometry. The 3 Death Stars are, in fact, 3 separate items in the scene hierarchy.

I then rendered a starfield as 4 separate Bridson blue noise pointsets. I drew the different pointsets with different colors - I think this gives some satisfying clustering, and looks like a SF vision of how stars look, even if it's not realistic.

I then used my Hershey Font renderer to draw some text. I put in the Eno prompt to give the player some reassurance.

I composited the starfield, the rendered scene, and the text together in GIMP.

Tools Used: drawSVG, my ray marcher, GIMP, Hershey Futura L font

Languages Used: Python

Development Time: ~3 hours

Drawing Time: ~1.5 hours (for the rendered bits, negligible for the rest)

What's Generative Here: only the starfield. Everything else was done by hand.

Saturday, January 30, 2021

Genuary 2021 Revisiting the Penrose Tiles (Day 29)

 



I wasn't super satisfied with my Penrose Tile drawing from Day 29, so I modified it (perhaps imperceptibly), and had another go at it. It's better, but I think there's even more to be done.

Also, I wanted to describe my approach, which comes, in part from the discussion here: http://www.math.ubc.ca/~cass/courses/m308-02b/projects/schweber/penrose.html talking about beginning with a known good tiling and then subdividing from there.


I won't explain them here, (read the above linked page for more detail) but I'm using two different shapes of rhombuses, "tall" and "short". In the earlier version, my seed pattern was a "wheel" or flower shape made up of 10 "tall" rhombuses arrayed around a point at the center of the page.

I was dissatisfied with this for a couple of reasons:

  1. It's not "generative" enough - it's some natural origin of some pattern, lining up with the center of the page. Bleh.
  2. There's too much symmetry. Penrose tiles are supposed to be this magnificent non-periodic pattern, but sitting right at the center of the screen is a 5-fold rotational axis of symmetry. Bleh. Not just a rotational axis, but 5 different planes of mirror symmetry.
So, I went in to modify the generator in two ways to fight this to some degree:
  1. My new generator wouldn't use a symmetric "wheel", it would generate all possible patterns of rhombuses coming together at a vertex, and choose one. Also, rotate it, which is easy.
  2. The new generator should also offset the center of the page, relative to the center of the "wheel". This is also easy. Indeed, my earlier Genuary code was repurposed from some earlier code where I was making laser cut jigsaw puzzles, and that code had an offset. I deleted the offset to make porting my old code to my Genuary codebase easier. Putting it back is not a big deal.

This is what a wheel looks like. The blue triangles are from "Tall" rhombuses, and red are from "Short". I didn't make up the names. Note that there are edge labelings that force the triangles to alternate, to keep from falling into a degenerate, boring, tiling.

I am already happy at this point that my wheel is asymmetric, look at all that asymmetry. Mission accomplished.



Subdividing all of those triangles once.

I won't describe the subdivision here (read the linked page), but you can see that the tall triangles turn into a tall and a short triangle and the short triangles turn into a tall and two short triangles. And, whaaaat? We now have a symmetric red star inside a symmetric blue ring. There's asymmetry outside the blue ring, but we have to move a ways to get there.


Subdividing a second time, the symmetry hasn't gone away, nor will it. 


It's harder to be certain about the symmetry as the subdivisions increase, but you can feel its presence.


Ok, but if I shift it off the side of the page, it's not so bad, right?


Zooming in (and subdividing to maintain approximately the same level of detail). The point of symmetry is still staring at me from the top-middle of the page, like the eye of Sauron, in the middle of the red spot on Jupiter. Checkmate.

Let's see how I did, relative to my objectives:
  1. More "generative"? Check, I guess? I like the fact that my seed "wheel" has more variety to it. And I'm rotating and centering in ways that mean that the next one I generate will be somewhat different from this drawing.
  2. Less symmetry? Meh, let's give that a C. The rotational center is not at the center of the page, so that's good. I could actually modify the code to ensure that my recenter-and-zoom code moved the rotational center off the page, that wouldn't be too hard.
Another way to carry this forward would be to throw out the "wheel" seed altogether and just start with a rhombus and zoom in to that. Or even a triangle.

I really should give it another go - the zooming wouldn't be too hard, and I'm happy with the output in other respects.

One other thing that I should revisit for the next pass is my "edgepool" system - it's doing a pretty good job of accumulating paths and giving them back to me in a left-to-right draw order, which makes the page fill up in a sane order, mostly. This also does a good job of lessening (perhaps not optimizing) the pen up movements, which makes the drawing more efficient. So that's all good. But a few things I could do:
  1. Right now, the paths are sorted based on the x-coordinate (or "abscissa") of vertex 0 on the path. I had considered checking to see if the last vertex is lower in x, and if so, flipping, which for this drawing wouldn't do anything, as all the drawn shapes are closed (unless you're clipping off the edge of the page, but that's not important right now). What I could do, instead, is to find the minimum x for all the points on the path, and use that to sort. This would avoid a little bit of "swiss cheese" effect where I'm filling the page with things and some things almost entirely to the right of some other things draw first. This would fill more evenly
  2. Don't just sort on x, also sort on y. I don't think this would have a lot of effect, as floating point, it'll getcha 99.99% of the time. But if there were three paths with "the same" x value, maybe draw them top to bottom, rather than middle, top, bottom, or some other weird order.
  3. A variant on the above would be to bucket the paths in x, and then within a bucket, sort in y. This would work around the floating point issue where things aren't ever going to match their x coordinates exactly. I could even just round the (x, y) pairs to integers, and it'd be pretty close to this.
I'm stepping away from this for a little bit to work on revisiting a different piece. Maybe I'll post about that. Maybe I'll post about coming back to this. Stay tuned.






Genuary 2021 Day 30: Replicate a Natural Concept

 


I drew a double pendulum today, using some math pointed out by the Coding Train "Coding Challenge #93: Double Pendulum" video: https://www.youtube.com/watch?v=uWzPe_S-RVE

I recall at some point when I was in high school, knowing a little bit about the Mandelbrot Set and a little bit about chaos, thinking that a double pendulum graph would be cool to explore. 

It's kind of cool to see how the red bob ("bob 1") is jerked around by the blue bob ("bob 2"), yielding non periodic motion, but it's surprising to me to see how smooth bob 2's motion looks; the path looks like a sine wave to my eye. It's probably a little sharper, but hard to tell.

Interesting direction to go with this: instead of just a single plot of x versus time, what if we had multiple configurations in parallel, and compress the pendulum x value into a color? So, maybe time would extend to the right in the image, and the image x would represent some continuously varying set of initial conditions.


Tools Used: drawSVG Python Library

Languages Used: Python

Development Time: ~1 hours

Drawing Time: ~2 minutes

What's Generative Here: the mass and length m1 and L1 are chosen to be 1.0 each, but the mass and length m2 and L2 are chosen randomly. Similarly the initial pose of the double pendulum is randomly generated.


Friday, January 29, 2021

Genuary 2021 Day 29: "Any shape, none can touch"

 "Penrose Tiling"


For this one, I dug around in my hard drive, and found an old bit of code that generated Penrose tilings. The code starts with a configuration of triangles, a "wheel" of isosceles triangles, and then subdivides them based on the subdivision rules here: http://www.math.ubc.ca/~cass/courses/m308-02b/projects/schweber/penrose.html This guarantees a valid Penrose tiling without having to do the hard job of extending the tiling from a seed rhombus.

I subdivided a few times to get the density I liked, and then inset each rhombus by 10% so that things wouldn't touch.





Tools Used: AxiDraw, Pentel .5mm pen, old Penrose Tiling code I had written previously

Languages Used: Python

Development Time: ~1.5 hours

Drawing Time: ~10 minutes

What's Generative Here: Not a lot, really - the initial configuration was selected by hand. Maybe the subdivision rules can be considered generative. I want to revisit this with a random zoom into the initial configuration (which is what the original code did, but I didn't port the random bits).








Thursday, January 28, 2021

Genuary 2021 Day 28: "Use Sound"


"Clash of the Piano Rolls"

For this one, I took 4 MIDI files and extracted the note_on data using the "mido" Python library. I cut out a random 60 second portion from each, and plotted the notes. I also drew a line for Middle C, to help orient you.

The four songs, in case you can't read piano rolls, are:

  1. "Popcorn" by Hot Butter
  2. "Never Gonna Give You Up" by Rick Astley
  3. "Tarzan Boy" by Baltimora
  4. "Take on Me" by A-ha

I think my parsing of the Rick Astley song must be wrong; it looks like I'm never finding "note off" messages. Damn you, Rick Astley!

I'm curious to play around with making a markov chain out of the percussion tracks. There's a lot of little notes going on down there.





Tools Used: AxiDraw, Pentel .5mm pen, mido Python library

Languages Used: Python

Development Time: ~1 hours

Drawing Time: ~40 minutes

What's Generative Here: I picked a random ordering of 4 songs, and picked a random portion from each, and then drew the song data (in random colors).

 




Wednesday, January 27, 2021

Genuary 2021 Day 27: "Monochrome Gradients without Lines"

"Rubber Duck-lish?"




Monochrome, yes. Gradients, um, ok. Without lines, well...

I interpreted the "without lines" to mean that I shouldn't be drawing straight lines or line segments. So, the only primitives I used was the Circle, which I used to halftone an image. 

I first used my ray marcher to render an image of a donut plus two spheres. I used a Smooth Union operator ("Smooth Union Operator" is the name of my easy listening jazz trio). You can see a falloff - or "gradient" in the shading of the donut and the top sphere, so that's something to work with. The second sphere is below and to the right, mostly hidden. The camera angle and positions of the spheres, as well as rotation of the overall thing is largely procedural, so I didn't have a lot of control over it. There was an initial configuration that looked uncomfortably anatomical, so I adjusted some values to get this configuration.



I then switched over to plotterworld, generated a blue noise point grid (of course), then for each of the points, I sampled the raster image, giving me a gray value from 0 to 1, 0 = black, 1 = white. I wrote a small function that turned a gray value into a list of circle radii that would give me darkness options. I had a list of candidate radii, and I greedily output radii that would approximate the gray fraction. Black = all radii, white = no radii, 40% might be the biggest circle alone, 50% might be the biggest circle and the second smallest circle.

I was somewhat clever this time, and I sorted my points by X, so that I drew from left to right:













Tools Used: My ray marcher, AxiDraw, Pentel .5mm pen

Languages Used: Python

Development Time: ~1 hour

Drawing Time: ~100 minutes

What's Generative Here: The camera position, the orientation, and the basic geometry of the donut + spheres are all randomly generated. I then use a random blue noise pointset to sample that image for halftoning.


Tuesday, January 26, 2021

Genuary 2021 Day 26: 2D Perspective

"Random Regional Racetracks"


 
I wanted to do something quick today, and it didn't turn out quite as quick as I intended. I had wanted to do something based on the loop of a racetrack, and I had some algorithmic ideas in the back of my head that I wanted to try out.

So, first, I generated a Bridson blue noise grid, of course. I used scipy's Voronoi package to generate Voronoi regions for each of the points. I then did some data structure munging to build a way of knowing what regions neighbor each other. 

Then, I used this neighbor table to generate paths of connected regions that looped back to their beginning within a given window of path lengths. Each time I found a loop, I stored that, and made subsequent length windows smaller, until I got an empty path for my query. (Not that I couldn't make more paths, clearly I could, just that particular query started from a point that led to a dead end.)

For each list of regions, I drew a path, using a cubic bezier curve to round out the edges, and letting drawSVG close the curves for me.

Looking at the raster(color) version, they look more like lakes than they look like racetracks - I would like to fatten up the paths, which wouldn't be too hard to do, just offset left and right perpendicular to the track path segments.

Another thing I got around to doing was to add a sorted draw path function to my edgepool class, so the Voronoi grid drew mostly left to right.





Tools Used: AxiDraw, Pentel .5mm pen
Languages Used: Python
Development Time: ~2 hours
Drawing Time: ~5 minutes
What's Generative Here: I start with a random blue noise point set, generate the voronoi graph for those points, and then trace closed paths on those voronoi cells.





Monday, January 25, 2021

Genuary 2021 Day 25 "Make a grid of permutations of something"

"Random Duets of Something"


The prompt says to make a grid of permutations of something. My first thought was to take the word "Something", break it into chunks and shuffle those chunks, like THSOINMEG. Totally would have technically, literally been permutations of something.

Instead, I took the things mentioned in "Something" by the Beatles, and selected random 2-permutations of those, and assigned them to random 2-permutations of the Beatles themselves, and envisioned that as a little duet. 

Also, I drew a couple random flowers (epicycloids + circles for easy botany) to make it more suitable for a Summer Of Love art mood.

I drew the text using the "Futura L" Hershey Font, and my own hershey font renderer. I think the text came out OK - it's totally legible at this size, but I wouldn't want to go much smaller with a 0.5mm pen.




Tools Used: AxiDraw, Pentel .5mm pen
Languages Used: Python
Development Time: ~1 hour
Drawing Time: ~10 minutes
What's Generative Here: The flower positions, rotations, and color were selected randomly. Each duet is a random selection of 2-permutations of phrases from "Something" combined with random 2-permutations of Beatles.








Sunday, January 24, 2021

Genuary 2021 Day 24 "500 Lines"



This one started out as being a simple variant of my "no loops" piece, starting with a Bridson blue noise point set, doing a Delaunay triangulation on that to get a tri mesh, then taking the edges of that mesh to generate 500 polylines.

I then added quadratic Bezier curves to round off the pointy parts of those polylines, and the result is surprisingly pleasing. The raster version has a little bit of a Keith Haring style.

I still ought to make a tool to sort my polylines by x to decrease the amount of time the AxiDraw pen spends moving around when drawing a piece like this.



Tools Used: AxiDraw, Pentel 5mm pen
Languages Used: Python
Development Time: ~2 hours
Drawing Time: ~5 minutes
What's Generative Here: The squiggly lines are generated from edges of a triangular mesh that's generated from a random blue noise point cloud.
 


Saturday, January 23, 2021

Genuary 2021 Day 23: ", no gradient" (variant)


"More Colorful Ripples. Chance of Gradient"




I decided to revisit this one, to try a few things. I kept the basic ideas, but altered the implementation. First up, instead of randomly positioning the color strings, I placed the color strings in an RGB cube, and randomly oriented that cube (generativity!) within the canvas.

I then replaced my square sampling of the SDF field with a triangular mesh, based on a Delaunay triangulation of a Bridson blue noise point set.

This allowed me / required me to rewrite my "Marching Cubes" implementation to be a "Marching Triangles" implementation, except that I guess "Marching Triangles" is the name of a different algorithm. Rewriting my marching squares actually simplified things.

I then did my ripples rendering - first with a version that just colored the segment of the ripple based on the closest color string, which was kind of interesting.

But then I rewrote it to do a weighted sum based on the inverse distance to each of the color strings. Which I think violates the "no gradient" part of the prompt. Bah! I'm not beholden to prompts! They serve me, not the other way around! Also, this is a variant, I feel like I have even more flexibility than the prime work.

I added an "edge pool" class, which collects line segments and accumulates them into long polylines. This made the ripple drawing a lot faster. And it invited me to draw the underlying triangle mesh, which is kind of interesting in the raster picture, but overwhelming when drawn on the AxiDraw.

 







Genuary 2021 Day 23: ", no gradients"

 The prompt says:

#264653 #2a9d8f #e9c46a #f4a261 #e76f51, no gradients.

Optionally, you can use a black or white background.

Which isn't super attractive to me, since I want to draw a single-color work on my AxiDraw. So, I didn't interpret the color hexcodes as colors, I interpreted them as unparsed strings. And gradients aren't really a viable thing with a pen drawing - I could do some sort of hatching, which would be interesting, which would approximate a gradient, but I wasn't really up for that. So I did iso-lines of distance functions from the actual letterforms, using marching squares to sample the space.


I first wrote a font for the hex digits (plus octothorpe), which took up a bunch of my time. I designed this font around the shapes that I knew that drawSVG had, including (poly)lines, circular arcs, and circles. And then I cheesed it and just entered the font data using lines and circular arcs - polylines were just a bunch of individual lines, circles were pairs of circular arcs.

I positioned the strings at random places (generativity!) on the canvas, and then traced the signed distance function to the lines and arcs. Actually, I hacked it, and allowed the arcs to pretend to be circles, which made the SDF much simpler. Originally, I had the slanty upright part of my "7" be an arc of a circle, but the center of the circle was way off to the right, and I wasn't going to go through the effort to make it correct, so I re-coded the upright to just be a straight line, which worked fine, and is almost as good.

I sampled the overall SDF for the composition of all the positioned strings on a square lattice, which gave me a nice smooth(ish) function to run marching squares on. My marching squares code is pretty simple and stupid, and just outputs tiny little line segments for each square. I want to revisit it to string together the line segments into paths, which will improve print speed.

One thing that I'm (slowly) learning is to try to feed the AxiDraw stuff in order, so that the pen doesn't have to lift up and move across the paper, and drop down again very often, or the move is short, if it does. So, this does a left-to-right drawing of the little line segments, per iso-line. When I do the path consolidation, this would be substantially faster.


Tools Used: AxiDraw, Pentel 5mm pen, Inigo Quilezles's 2d SDF reference: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm, Wikipedia's page on Marching Squares https://en.wikipedia.org/wiki/Marching_squares
Languages Used: Python
Development Time: ~3 hours
Drawing Time: ~45 minutes
What's Generative Here: The 5 strings from the prompt are randomly positioned on the canvas, and serve as "seeds" that the curves loop around, like ripples on a pond.




Friday, January 22, 2021

Genuary 2021 Day 22: "Draw a line. Wrong Answers Only"



So, a bunch of stick figures showed up on my page, and they more or less lined up, but not perfectly.

This was basically an exercise in refactoring my people code from Day 3 (Draw something Human). Each person is assigned a random y position, and then x is moved as far right as possible such that the bounding boxes don't overlap.


 


Tools Used: AxiDraw, Pentel 5mm pen
Languages Used: Python
Development Time: ~45 minutes
Drawing Time: ~2 minutes
What's Generative Here: each person is assigned a random y position, and their x position is determined based on a deterministic process. Also, in the raster version (below), skin tone is selected randomly.