~ubuntu-branches/ubuntu/precise/whoopsie-daisy/precise-proposed

« back to all changes in this revision

Viewing changes to backend/stats/static/js/d3/src/svg/line.js

  • Committer: Package Import Robot
  • Author(s): Evan Dandrea
  • Date: 2012-04-10 14:28:58 UTC
  • Revision ID: package-import@ubuntu.com-20120410142858-nk453o1z7t7py3bs
Tags: 0.1.26
* Take ownership of the NetworkManager state variant on setup and
  unref it, plugging a memory leak.
* Log the reason the server rejected the submitted crash report.
* Send the Whoopsie version with each crash submission.
* Delete both .upload and .uploaded files after 14 days. Thanks
  Marc Deslauriers (LP: #973687).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
function d3_svg_line(projection) {
 
2
  var x = d3_svg_lineX,
 
3
      y = d3_svg_lineY,
 
4
      interpolate = d3_svg_lineInterpolatorDefault,
 
5
      interpolator = d3_svg_lineInterpolators.get(interpolate),
 
6
      tension = .7;
 
7
 
 
8
  function line(d) {
 
9
    return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension);
 
10
  }
 
11
 
 
12
  line.x = function(v) {
 
13
    if (!arguments.length) return x;
 
14
    x = v;
 
15
    return line;
 
16
  };
 
17
 
 
18
  line.y = function(v) {
 
19
    if (!arguments.length) return y;
 
20
    y = v;
 
21
    return line;
 
22
  };
 
23
 
 
24
  line.interpolate = function(v) {
 
25
    if (!arguments.length) return interpolate;
 
26
    if (!d3_svg_lineInterpolators.has(v += "")) v = d3_svg_lineInterpolatorDefault;
 
27
    interpolator = d3_svg_lineInterpolators.get(interpolate = v);
 
28
    return line;
 
29
  };
 
30
 
 
31
  line.tension = function(v) {
 
32
    if (!arguments.length) return tension;
 
33
    tension = v;
 
34
    return line;
 
35
  };
 
36
 
 
37
  return line;
 
38
}
 
39
 
 
40
d3.svg.line = function() {
 
41
  return d3_svg_line(Object);
 
42
};
 
43
 
 
44
// Converts the specified array of data into an array of points
 
45
// (x-y tuples), by evaluating the specified `x` and `y` functions on each
 
46
// data point. The `this` context of the evaluated functions is the specified
 
47
// "self" object; each function is passed the current datum and index.
 
48
function d3_svg_linePoints(self, d, x, y) {
 
49
  var points = [],
 
50
      i = -1,
 
51
      n = d.length,
 
52
      fx = typeof x === "function",
 
53
      fy = typeof y === "function",
 
54
      value;
 
55
  if (fx && fy) {
 
56
    while (++i < n) points.push([
 
57
      x.call(self, value = d[i], i),
 
58
      y.call(self, value, i)
 
59
    ]);
 
60
  } else if (fx) {
 
61
    while (++i < n) points.push([x.call(self, d[i], i), y]);
 
62
  } else if (fy) {
 
63
    while (++i < n) points.push([x, y.call(self, d[i], i)]);
 
64
  } else {
 
65
    while (++i < n) points.push([x, y]);
 
66
  }
 
67
  return points;
 
68
}
 
69
 
 
70
// The default `x` property, which references d[0].
 
71
function d3_svg_lineX(d) {
 
72
  return d[0];
 
73
}
 
74
 
 
75
// The default `y` property, which references d[1].
 
76
function d3_svg_lineY(d) {
 
77
  return d[1];
 
78
}
 
79
 
 
80
var d3_svg_lineInterpolatorDefault = "linear";
 
81
 
 
82
// The various interpolators supported by the `line` class.
 
83
var d3_svg_lineInterpolators = d3.map({
 
84
  "linear": d3_svg_lineLinear,
 
85
  "step-before": d3_svg_lineStepBefore,
 
86
  "step-after": d3_svg_lineStepAfter,
 
87
  "basis": d3_svg_lineBasis,
 
88
  "basis-open": d3_svg_lineBasisOpen,
 
89
  "basis-closed": d3_svg_lineBasisClosed,
 
90
  "bundle": d3_svg_lineBundle,
 
91
  "cardinal": d3_svg_lineCardinal,
 
92
  "cardinal-open": d3_svg_lineCardinalOpen,
 
93
  "cardinal-closed": d3_svg_lineCardinalClosed,
 
94
  "monotone": d3_svg_lineMonotone
 
95
});
 
96
 
 
97
// Linear interpolation; generates "L" commands.
 
98
function d3_svg_lineLinear(points) {
 
99
  var i = 0,
 
100
      n = points.length,
 
101
      p = points[0],
 
102
      path = [p[0], ",", p[1]];
 
103
  while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]);
 
104
  return path.join("");
 
105
}
 
106
 
 
107
// Step interpolation; generates "H" and "V" commands.
 
108
function d3_svg_lineStepBefore(points) {
 
109
  var i = 0,
 
110
      n = points.length,
 
111
      p = points[0],
 
112
      path = [p[0], ",", p[1]];
 
113
  while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
 
114
  return path.join("");
 
115
}
 
116
 
 
117
// Step interpolation; generates "H" and "V" commands.
 
118
function d3_svg_lineStepAfter(points) {
 
119
  var i = 0,
 
120
      n = points.length,
 
121
      p = points[0],
 
122
      path = [p[0], ",", p[1]];
 
123
  while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
 
124
  return path.join("");
 
125
}
 
126
 
 
127
// Open cardinal spline interpolation; generates "C" commands.
 
128
function d3_svg_lineCardinalOpen(points, tension) {
 
129
  return points.length < 4
 
130
      ? d3_svg_lineLinear(points)
 
131
      : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1),
 
132
        d3_svg_lineCardinalTangents(points, tension));
 
133
}
 
134
 
 
135
// Closed cardinal spline interpolation; generates "C" commands.
 
136
function d3_svg_lineCardinalClosed(points, tension) {
 
137
  return points.length < 3
 
138
      ? d3_svg_lineLinear(points)
 
139
      : points[0] + d3_svg_lineHermite((points.push(points[0]), points),
 
140
        d3_svg_lineCardinalTangents([points[points.length - 2]]
 
141
        .concat(points, [points[1]]), tension));
 
142
}
 
143
 
 
144
// Cardinal spline interpolation; generates "C" commands.
 
145
function d3_svg_lineCardinal(points, tension, closed) {
 
146
  return points.length < 3
 
147
      ? d3_svg_lineLinear(points)
 
148
      : points[0] + d3_svg_lineHermite(points,
 
149
        d3_svg_lineCardinalTangents(points, tension));
 
150
}
 
151
 
 
152
// Hermite spline construction; generates "C" commands.
 
153
function d3_svg_lineHermite(points, tangents) {
 
154
  if (tangents.length < 1
 
155
      || (points.length != tangents.length
 
156
      && points.length != tangents.length + 2)) {
 
157
    return d3_svg_lineLinear(points);
 
158
  }
 
159
 
 
160
  var quad = points.length != tangents.length,
 
161
      path = "",
 
162
      p0 = points[0],
 
163
      p = points[1],
 
164
      t0 = tangents[0],
 
165
      t = t0,
 
166
      pi = 1;
 
167
 
 
168
  if (quad) {
 
169
    path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3)
 
170
        + "," + p[0] + "," + p[1];
 
171
    p0 = points[1];
 
172
    pi = 2;
 
173
  }
 
174
 
 
175
  if (tangents.length > 1) {
 
176
    t = tangents[1];
 
177
    p = points[pi];
 
178
    pi++;
 
179
    path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1])
 
180
        + "," + (p[0] - t[0]) + "," + (p[1] - t[1])
 
181
        + "," + p[0] + "," + p[1];
 
182
    for (var i = 2; i < tangents.length; i++, pi++) {
 
183
      p = points[pi];
 
184
      t = tangents[i];
 
185
      path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1])
 
186
          + "," + p[0] + "," + p[1];
 
187
    }
 
188
  }
 
189
 
 
190
  if (quad) {
 
191
    var lp = points[pi];
 
192
    path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3)
 
193
        + "," + lp[0] + "," + lp[1];
 
194
  }
 
195
 
 
196
  return path;
 
197
}
 
198
 
 
199
// Generates tangents for a cardinal spline.
 
200
function d3_svg_lineCardinalTangents(points, tension) {
 
201
  var tangents = [],
 
202
      a = (1 - tension) / 2,
 
203
      p0,
 
204
      p1 = points[0],
 
205
      p2 = points[1],
 
206
      i = 1,
 
207
      n = points.length;
 
208
  while (++i < n) {
 
209
    p0 = p1;
 
210
    p1 = p2;
 
211
    p2 = points[i];
 
212
    tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
 
213
  }
 
214
  return tangents;
 
215
}
 
216
 
 
217
// B-spline interpolation; generates "C" commands.
 
218
function d3_svg_lineBasis(points) {
 
219
  if (points.length < 3) return d3_svg_lineLinear(points);
 
220
  var i = 1,
 
221
      n = points.length,
 
222
      pi = points[0],
 
223
      x0 = pi[0],
 
224
      y0 = pi[1],
 
225
      px = [x0, x0, x0, (pi = points[1])[0]],
 
226
      py = [y0, y0, y0, pi[1]],
 
227
      path = [x0, ",", y0];
 
228
  d3_svg_lineBasisBezier(path, px, py);
 
229
  while (++i < n) {
 
230
    pi = points[i];
 
231
    px.shift(); px.push(pi[0]);
 
232
    py.shift(); py.push(pi[1]);
 
233
    d3_svg_lineBasisBezier(path, px, py);
 
234
  }
 
235
  i = -1;
 
236
  while (++i < 2) {
 
237
    px.shift(); px.push(pi[0]);
 
238
    py.shift(); py.push(pi[1]);
 
239
    d3_svg_lineBasisBezier(path, px, py);
 
240
  }
 
241
  return path.join("");
 
242
}
 
243
 
 
244
// Open B-spline interpolation; generates "C" commands.
 
245
function d3_svg_lineBasisOpen(points) {
 
246
  if (points.length < 4) return d3_svg_lineLinear(points);
 
247
  var path = [],
 
248
      i = -1,
 
249
      n = points.length,
 
250
      pi,
 
251
      px = [0],
 
252
      py = [0];
 
253
  while (++i < 3) {
 
254
    pi = points[i];
 
255
    px.push(pi[0]);
 
256
    py.push(pi[1]);
 
257
  }
 
258
  path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px)
 
259
    + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
 
260
  --i; while (++i < n) {
 
261
    pi = points[i];
 
262
    px.shift(); px.push(pi[0]);
 
263
    py.shift(); py.push(pi[1]);
 
264
    d3_svg_lineBasisBezier(path, px, py);
 
265
  }
 
266
  return path.join("");
 
267
}
 
268
 
 
269
// Closed B-spline interpolation; generates "C" commands.
 
270
function d3_svg_lineBasisClosed(points) {
 
271
  var path,
 
272
      i = -1,
 
273
      n = points.length,
 
274
      m = n + 4,
 
275
      pi,
 
276
      px = [],
 
277
      py = [];
 
278
  while (++i < 4) {
 
279
    pi = points[i % n];
 
280
    px.push(pi[0]);
 
281
    py.push(pi[1]);
 
282
  }
 
283
  path = [
 
284
    d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",",
 
285
    d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)
 
286
  ];
 
287
  --i; while (++i < m) {
 
288
    pi = points[i % n];
 
289
    px.shift(); px.push(pi[0]);
 
290
    py.shift(); py.push(pi[1]);
 
291
    d3_svg_lineBasisBezier(path, px, py);
 
292
  }
 
293
  return path.join("");
 
294
}
 
295
 
 
296
function d3_svg_lineBundle(points, tension) {
 
297
  var n = points.length - 1,
 
298
      x0 = points[0][0],
 
299
      y0 = points[0][1],
 
300
      dx = points[n][0] - x0,
 
301
      dy = points[n][1] - y0,
 
302
      i = -1,
 
303
      p,
 
304
      t;
 
305
  while (++i <= n) {
 
306
    p = points[i];
 
307
    t = i / n;
 
308
    p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
 
309
    p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
 
310
  }
 
311
  return d3_svg_lineBasis(points);
 
312
}
 
313
 
 
314
// Returns the dot product of the given four-element vectors.
 
315
function d3_svg_lineDot4(a, b) {
 
316
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
 
317
}
 
318
 
 
319
// Matrix to transform basis (b-spline) control points to bezier
 
320
// control points. Derived from FvD 11.2.8.
 
321
var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0],
 
322
    d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0],
 
323
    d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6];
 
324
 
 
325
// Pushes a "C" Bézier curve onto the specified path array, given the
 
326
// two specified four-element arrays which define the control points.
 
327
function d3_svg_lineBasisBezier(path, x, y) {
 
328
  path.push(
 
329
      "C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x),
 
330
      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y),
 
331
      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x),
 
332
      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y),
 
333
      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x),
 
334
      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
 
335
}
 
336
 
 
337
// Computes the slope from points p0 to p1.
 
338
function d3_svg_lineSlope(p0, p1) {
 
339
  return (p1[1] - p0[1]) / (p1[0] - p0[0]);
 
340
}
 
341
 
 
342
// Compute three-point differences for the given points.
 
343
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Finite_difference
 
344
function d3_svg_lineFiniteDifferences(points) {
 
345
  var i = 0,
 
346
      j = points.length - 1,
 
347
      m = [],
 
348
      p0 = points[0],
 
349
      p1 = points[1],
 
350
      d = m[0] = d3_svg_lineSlope(p0, p1);
 
351
  while (++i < j) {
 
352
    m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]));
 
353
  }
 
354
  m[i] = d;
 
355
  return m;
 
356
}
 
357
 
 
358
// Interpolates the given points using Fritsch-Carlson Monotone cubic Hermite
 
359
// interpolation. Returns an array of tangent vectors. For details, see
 
360
// http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
 
361
function d3_svg_lineMonotoneTangents(points) {
 
362
  var tangents = [],
 
363
      d,
 
364
      a,
 
365
      b,
 
366
      s,
 
367
      m = d3_svg_lineFiniteDifferences(points),
 
368
      i = -1,
 
369
      j = points.length - 1;
 
370
 
 
371
  // The first two steps are done by computing finite-differences:
 
372
  // 1. Compute the slopes of the secant lines between successive points.
 
373
  // 2. Initialize the tangents at every point as the average of the secants.
 
374
 
 
375
  // Then, for each segment…
 
376
  while (++i < j) {
 
377
    d = d3_svg_lineSlope(points[i], points[i + 1]);
 
378
 
 
379
    // 3. If two successive yk = y{k + 1} are equal (i.e., d is zero), then set
 
380
    // mk = m{k + 1} = 0 as the spline connecting these points must be flat to
 
381
    // preserve monotonicity. Ignore step 4 and 5 for those k.
 
382
 
 
383
    if (Math.abs(d) < 1e-6) {
 
384
      m[i] = m[i + 1] = 0;
 
385
    } else {
 
386
      // 4. Let ak = mk / dk and bk = m{k + 1} / dk.
 
387
      a = m[i] / d;
 
388
      b = m[i + 1] / d;
 
389
 
 
390
      // 5. Prevent overshoot and ensure monotonicity by restricting the
 
391
      // magnitude of vector <ak, bk> to a circle of radius 3.
 
392
      s = a * a + b * b;
 
393
      if (s > 9) {
 
394
        s = d * 3 / Math.sqrt(s);
 
395
        m[i] = s * a;
 
396
        m[i + 1] = s * b;
 
397
      }
 
398
    }
 
399
  }
 
400
 
 
401
  // Compute the normalized tangent vector from the slopes. Note that if x is
 
402
  // not monotonic, it's possible that the slope will be infinite, so we protect
 
403
  // against NaN by setting the coordinate to zero.
 
404
  i = -1; while (++i <= j) {
 
405
    s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0])
 
406
      / (6 * (1 + m[i] * m[i]));
 
407
    tangents.push([s || 0, m[i] * s || 0]);
 
408
  }
 
409
 
 
410
  return tangents;
 
411
}
 
412
 
 
413
function d3_svg_lineMonotone(points) {
 
414
  return points.length < 3
 
415
      ? d3_svg_lineLinear(points)
 
416
      : points[0] +
 
417
        d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
 
418
}