Friday, February 5, 2021

Racetrack Update

 

You may not recall, but a while ago, I drew some paths using Voronoi Regions (look back to Genuary Day 26). 



I was pleased with the output, but a little perplexed that the hairpin turn on the NE corner of the westernmost track seemed to be too sharp a turn. More specifically, if the notional "cars" were going from the fairly vanilla hexagon at the far N of the track, into the "diamond" shaped pentagon, with the pointy bit to the south, on to the flat hexagon, back to the diamond pentagon. 

My code should not generate tracks based on previous regions - what's going on?

I've got all the code from the various works, and each of those used a seed string, so I could reproduce the calculations that I considered suspect. So, I dug back into the code, made a copy, and (re)enabled some debugging information, along with drawing a lot of dots.


One thing I discovered in my spline code was that I was asking for 10 points on my curve, but my generators were evaluating from 0 to 10, inclusive. This caused some of my curve data to overshoot the intended data.

Another thing I discovered was that my tracks (the blue curve, here) were based on the generating points for the voronoi regions. I'm not doing anything fancy like using the centerpoint of the edge between regions, to ensure that the curve would be centered on that edge. I'm basically just drawing a polyline from generating point to generating point, but then I round off the corners.

What's important(?) to recognize here is that that generated polyline may cross between regions along the voronoi edge between those regions, or it might not.

If you look super carefully at the "flat hexagon" and the "apparent pentagon" to its west, there's a tiny little edge connecting them, which is what my track layout algorithm used. But the line connecting the generating points crosses back into the diamond pentago on its way from the flat hexagon to the "apparent pentagon" (which is actually a hexagon, because the 6th side is tiny, and the flat hexagon is a heptagon).

I'm sure you were as curious as I was about why the tracks weren't working. Now they are. Although I suspect the drawings are just about indistinguishable. But now they're right, and we understand why.

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.