Setting `n2=n3=1.5`

generates smoothly rounded shapes, rather than the spiky ones produced by `n2=n3=1.0`

, so I combined the two into a single demo routine:

A closer look shows all the curves meet at the points, of which there are 37:

The spikes suffer from limited resolution: each curve has 10 k points, but if the extreme end of a spike lies between two points, then it gets blunted on the page. Doubling the number of points would help, although I think this has already gone well beyond the, ah, point of diminishing returns.

I used the three remaining “disposable” liquid ink pens for the spiked curves; the black pen was beyond repair. They produce gorgeous lines, although the magenta ink seems a bit thinned out by the water I used to rinse the remains of the last refill out of the spiral vent channel.

I modified the Chiplotle `supershape()`

function to default to my choices for `point_count`

and `travel`

, then copied the `superformula()`

function and changed it to return polar coordinates, because I’ll eventually try scaling the linear value as a function of the total angle, which is *much* easier in polar coordinates.

The demo code produces the patterns in the picture by iterating over interesting values of `n1`

and `n2=n3`

, stepping through the pen carousel for each pattern. As before, `m`

should be `prime/10`

to produce a `prime`

number of spikes / bumps. You could add more iteration values, but six of ’em seem entirely sufficient.

A real demo should include a large collection of known-good parameter sets, from which it can pick six sets to make a plot. A legend documenting the parameters for each pattern, plus the date & time, would bolster the geek cred.

The Python source code with the modified Chiplotle routines:

from chiplotle import * from math import * def superformula_polar(a, b, m, n1, n2, n3, phi): ''' Computes the position of the point on a superformula curve. Superformula has first been proposed by Johan Gielis and is a generalization of superellipse. see: http://en.wikipedia.org/wiki/Superformula Tweaked to return polar coordinates ''' t1 = cos(m * phi / 4.0) / a t1 = abs(t1) t1 = pow(t1, n2) t2 = sin(m * phi / 4.0) / b t2 = abs(t2) t2 = pow(t2, n3) t3 = -1 / float(n1) r = pow(t1 + t2, t3) if abs(r) == 0: return (0,0) else: # return (r * cos(phi), r * sin(phi)) return (r,phi) def supershape(width, height, m, n1, n2, n3, point_count=10*1000, percentage=1.0, a=1.0, b=1.0, travel=None): '''Supershape, generated using the superformula first proposed by Johan Gielis. - `points_count` is the total number of points to compute. - `travel` is the length of the outline drawn in radians. 3.1416 * 2 is a complete cycle. ''' travel = travel or (10*2*pi) ## compute points... phis = [i * travel / point_count for i in range(1 + int(point_count * percentage))] points = [superformula_polar(a, b, m, n1, n2, n3, x) for x in phis] ## scale and transpose... path = [ ] for r, a in points: x = width * r * cos(a) y = height * r * sin(a) path.append(Coordinate(x, y)) return Path(path) ## RUN DEMO CODE if __name__ == '__main__': paperx = 8000 papery = 5000 if not False: plt=instantiate_plotters()[0] plt.set_origin_center() plt.write(hpgl.VS(10)) pen = 1 for m in [3.7]: for n1 in [0.20, 0.60, 0.8]: for n2 in [1.0, 1.5]: n3 = n2 e = supershape(paperx, papery, m, n1, n2, n3) plt.select_pen(pen) if pen < 6: pen += 1 else: pen = 1 plt.write(e) plt.select_pen(0) else: e = supershape(paperx, papery, 1.9, 0.8, 3, 3) io.view(e)

Can you dynamically change the number of points based on the rate of change of the vector?

That’s left as an exercise for the student… [evil grin]

It’d also be handy to discard successive points falling within epsilon of the previously plotted point, mostly to

increasethe pen speed near the middle of the figure where the angle increases continuously as the radius muddles along.As it stands, the program whacks the formula against a list of equally spaced points and plots whatever comes out. You could postprocess the whole list (maybe starting with 10x more points) or generate angles on the fly to satisfy a spacing parameter.

So many projects…

Alternatively, if you’re doing the calculations in polar coördinates, you can arrange for the angles to align with the points.