inconvergent has a great article about generative art, with many excellent examples of various techniques. While reading the section about Hyphae , I decided to give it a try and see what I could come up with along those lines.
Hyphae (the plural of hypha) are long tendrils that grow from fungi. They grow from their tips, and will often branch new tendrils. My goal was to come up with a system to simulate their growth by following these rules:
- There will be one or more root positions, randomly placed on the canvas. Each of those has a randomly assigned direction in which it will grow.
- A tendril grows in pretty much a straight line.
- As it grows, a tendril will periodically branch new tendrils which takes off at roughly right angles to their parents. New tendrils are slightly smaller than their parents. Also, they grow slightly slower, and have a bit more variation in what direction they go – they will likely not travel in quite as straight a line as their parents.
- When a tendril would hit the edge of the canvas, or would hit another tendril, it dies.
Conceptually, this is not particularly complicated, but I ran into a couple of sticking points, one specific to the Rust language, and one mathematical.
First, Rust has many memory safety guarantees that other languages do not. An effect of this is that it can be more difficult to do some things in Rust than in other languages, not because Rust is overly protective but because those things, even though allowed in many languages, really Should Not Be Done. My situation here was that I have a have in my Model
a list of hyphae (tendrils), starting with whatever ones I randomly placed on the screen. As more branch out, this list grows. Each of those hyphae has a list of lines it has drawn on the screen as part of its path. My difficulty was that, while modifying a hypha, I am creating a new line as the next step in that hypha’s path, but before I add it to the list, I need to check it against every other line in every other hypha to make sure I’m not going to hit any of them. However, Rust wisely won’t let me read a structure as it is being modified. So I couldn’t look at all those lines when I needed to do so. There are a few ways around this in Rust; one of them is
interior mutability
. It took the simpler approach of making a separate list which contained all lines on the screen, and checked against that.
The other problem I had some difficulty with was how to tell when I was going to hit another line. A tendril should not actually hit another tendril; it should die when it is about to. So tendrils should not touch each other. Just doing the math to see whether the lines would intersect was not good enough. If a line ended up stopping one pixel short of another line, they would not be intersecting, but as they were on adjacent pixels, they would visually be touching. Plus, lines on the screen have thickness, with the first ones on the screen starting at several pixels wide, so even lines several pixels apart could be touching on the screen. I approached this problem by first checking for intersection, and, if no intersection, defining a circle at the new line endpoint with a radius slightly larger than the current line thickness, then checking so see whether that circle intersected any lines. The techniques for doing this are explained nicely in this reference (see the discussions on line/line and line/circle collisions.) The result is not perfect, but works fairly well. However, there are a lot of hyphae in one image, and therefore a lot of lines. All those calculations make the drawing really slow!
Once I got around those two issues, the rest was fairly easy,
OK, so as Works of Art, these are not particularly thrilling, but I can certainly see making use of these techniques in a larger work!
The Nannou app for this project can be found on GitLab .