1 | (function() { |
---|
2 | var _symbol = d3.svg.symbol(), |
---|
3 | _line = d3.svg.line(); |
---|
4 | |
---|
5 | superformula = function() { |
---|
6 | var type = _symbol.type(), |
---|
7 | size = _symbol.size(), |
---|
8 | segments = size, |
---|
9 | params = {}; |
---|
10 | |
---|
11 | function superformula(d, i) { |
---|
12 | var n, p = _superformulaTypes[type.call(this, d, i)]; |
---|
13 | for (n in params) p[n] = params[n].call(this, d, i); |
---|
14 | return _superformulaPath(p, segments.call(this, d, i), Math.sqrt(size.call(this, d, i))); |
---|
15 | } |
---|
16 | |
---|
17 | superformula.type = function(x) { |
---|
18 | if (!arguments.length) return type; |
---|
19 | type = d3.functor(x); |
---|
20 | return superformula; |
---|
21 | }; |
---|
22 | |
---|
23 | superformula.param = function(name, value) { |
---|
24 | if (arguments.length < 2) return params[name]; |
---|
25 | params[name] = d3.functor(value); |
---|
26 | return superformula; |
---|
27 | }; |
---|
28 | |
---|
29 | // size of superformula in square pixels |
---|
30 | superformula.size = function(x) { |
---|
31 | if (!arguments.length) return size; |
---|
32 | size = d3.functor(x); |
---|
33 | return superformula; |
---|
34 | }; |
---|
35 | |
---|
36 | // number of discrete line segments |
---|
37 | superformula.segments = function(x) { |
---|
38 | if (!arguments.length) return segments; |
---|
39 | segments = d3.functor(x); |
---|
40 | return superformula; |
---|
41 | }; |
---|
42 | |
---|
43 | return superformula; |
---|
44 | }; |
---|
45 | |
---|
46 | function _superformulaPath(params, n, diameter) { |
---|
47 | var i = -1, |
---|
48 | dt = 2 * Math.PI / n, |
---|
49 | t, |
---|
50 | r = 0, |
---|
51 | x, |
---|
52 | y, |
---|
53 | points = []; |
---|
54 | |
---|
55 | while (++i < n) { |
---|
56 | t = params.m * (i * dt - Math.PI) / 4; |
---|
57 | t = Math.pow(Math.abs(Math.pow(Math.abs(Math.cos(t) / params.a), params.n2) |
---|
58 | + Math.pow(Math.abs(Math.sin(t) / params.b), params.n3)), -1 / params.n1); |
---|
59 | if (t > r) r = t; |
---|
60 | points.push(t); |
---|
61 | } |
---|
62 | |
---|
63 | r = diameter * Math.SQRT1_2 / r; |
---|
64 | i = -1; while (++i < n) { |
---|
65 | x = (t = points[i] * r) * Math.cos(i * dt); |
---|
66 | y = t * Math.sin(i * dt); |
---|
67 | points[i] = [Math.abs(x) < 1e-6 ? 0 : x, Math.abs(y) < 1e-6 ? 0 : y]; |
---|
68 | } |
---|
69 | |
---|
70 | return _line(points) + "Z"; |
---|
71 | } |
---|
72 | |
---|
73 | var _superformulaTypes = { |
---|
74 | asterisk: {m: 12, n1: .3, n2: 0, n3: 10, a: 1, b: 1}, |
---|
75 | bean: {m: 2, n1: 1, n2: 4, n3: 8, a: 1, b: 1}, |
---|
76 | butterfly: {m: 3, n1: 1, n2: 6, n3: 2, a: .6, b: 1}, |
---|
77 | circle: {m: 4, n1: 2, n2: 2, n3: 2, a: 1, b: 1}, |
---|
78 | clover: {m: 6, n1: .3, n2: 0, n3: 10, a: 1, b: 1}, |
---|
79 | cloverFour: {m: 8, n1: 10, n2: -1, n3: -8, a: 1, b: 1}, |
---|
80 | cross: {m: 8, n1: 1.3, n2: .01, n3: 8, a: 1, b: 1}, |
---|
81 | diamond: {m: 4, n1: 1, n2: 1, n3: 1, a: 1, b: 1}, |
---|
82 | drop: {m: 1, n1: .5, n2: .5, n3: .5, a: 1, b: 1}, |
---|
83 | ellipse: {m: 4, n1: 2, n2: 2, n3: 2, a: 9, b: 6}, |
---|
84 | gear: {m: 19, n1: 100, n2: 50, n3: 50, a: 1, b: 1}, |
---|
85 | heart: {m: 1, n1: .8, n2: 1, n3: -8, a: 1, b: .18}, |
---|
86 | heptagon: {m: 7, n1: 1000, n2: 400, n3: 400, a: 1, b: 1}, |
---|
87 | hexagon: {m: 6, n1: 1000, n2: 400, n3: 400, a: 1, b: 1}, |
---|
88 | malteseCross: {m: 8, n1: .9, n2: .1, n3: 100, a: 1, b: 1}, |
---|
89 | pentagon: {m: 5, n1: 1000, n2: 600, n3: 600, a: 1, b: 1}, |
---|
90 | rectangle: {m: 4, n1: 100, n2: 100, n3: 100, a: 2, b: 1}, |
---|
91 | roundedStar: {m: 5, n1: 2, n2: 7, n3: 7, a: 1, b: 1}, |
---|
92 | square: {m: 4, n1: 100, n2: 100, n3: 100, a: 1, b: 1}, |
---|
93 | star: {m: 5, n1: 30, n2: 100, n3: 100, a: 1, b: 1}, |
---|
94 | triangle: {m: 3, n1: 100, n2: 200, n3: 200, a: 1, b: 1} |
---|
95 | }; |
---|
96 | |
---|
97 | superformulaTypes = d3.keys(_superformulaTypes); |
---|
98 | })(); |
---|