|
The red parts of this image are a hypocycloid.
The blue parts of this image are an epicycloid.
The gap on the right side is an unsolved problem. |
Perl blogger Gabor Szabo of
Perl Maven asked me to show off my SVG Spirograph code, and so, here it, released
as a Github Gist. I'm not quite to the point where I'm happy with it.
Years ago, as a child, I knew people with
Spirographs, and I loved playing with them, making these crazy patterns with just pen, paper and geared plastic circles.
Years later, when I heard that Canvas support was being added to browsers, I developed tools in Javascript to draw these things. Nobody I knew had really any practical use for that skill, and so I kinda left it.
Until I started looking into laser cutters. Essentially, they're high-contrast printers, and they love vector graphics, using a thin red vector as an indication to cut rather than etch. So, when I saw
Gabor write about the SVG module on Perl Maven, I knew what I must do.
Right now, I have three functions that generate these images, corresponding to
epicycloid,
hypocycloid and
hypotrochoid curves, with two functions each providing the X and Y coordinates. In each, take a circle, rotate another circle around it (outside for epicycloids, inside for the others). If the point you're using is along the circumference, it's a cycloid, and if it's beyond that, it's an hypotrochoid, which, strictly speaking, could not be done with a Spirograph because the rings would get in the way. With math, Perl and
SVG, this is not a problem.
SVG has the capability of drawing curves, but I assure you that the number of curves in the SVGs that created the images here are zero. If you draw lines between points, and those points are close enough, the lines look like curves, and the file sizes explode. On the other end, if you have the distance between points long enough, they are clearly lines, and it takes a large number of loops over to disguise the straight lines and get a thick curve. My code currently cycles through at 1/400ths of a degree at a time, which is fine for epicycloids and hypocycloids, but overkill for hypotrochoids.
Getting this code to handle
Bézier curves and the like requires more math than I currently know, and might not actually be possible, but would certainly be good for reducing file sizes.
|
This is a number of hypotrochoids stacked on top of each other,
cut into balsa wood. I love the 21st century. |
The other problem my code has goes back to ensuring an end. Circles and ellipses are special cases of these things, and it is also the case that, with irrational numbers, that the thing will never complete, but instead look like a big black (or red, or blue) circle. So, we need to ensure that, eventually, it'll halt. If it goes over the same part twice, it makes the line thicker, which I don't want, but the problem is we're dealing with floating point, and 0.0000000000000000014 isn't mathematically equal to 0.0000000000000000015, but if we have several x and y coordinates in a row that are within 0.0000000000000000001 of previous pairs, we're probably looping over again. Eventually, I'll poke at that idea. As is, it loops 50,000 times, which is why the "both" image above isn't complete.
And, having an offset, to rotate these things as desired, would also be good. Code below, and also on Github.