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
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
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() 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)