source: Dev/trunk/d3/d3.js @ 198

Last change on this file since 198 was 76, checked in by fpvanagthoven, 14 years ago

d3

File size: 91.4 KB
Line 
1(function(){d3 = {version: "1.29.1"}; // semver
2if (!Date.now) Date.now = function() {
3  return +new Date;
4};
5if (!Object.create) Object.create = function(o) {
6  /** @constructor */ function f() {}
7  f.prototype = o;
8  return new f;
9};
10var d3_array = d3_arraySlice; // conversion for NodeLists
11
12function d3_arrayCopy(psuedoarray) {
13  var i = -1, n = psuedoarray.length, array = [];
14  while (++i < n) array.push(psuedoarray[i]);
15  return array;
16}
17
18function d3_arraySlice(psuedoarray) {
19  return Array.prototype.slice.call(psuedoarray);
20}
21
22try {
23  d3_array(document.documentElement.childNodes)[0].nodeType;
24} catch(e) {
25  d3_array = d3_arrayCopy;
26}
27d3.functor = function(v) {
28  return typeof v === "function" ? v : function() { return v; };
29};
30// A getter-setter method that preserves the appropriate `this` context.
31d3.rebind = function(object, method) {
32  return function() {
33    var x = method.apply(object, arguments);
34    return arguments.length ? object : x;
35  };
36};
37d3.ascending = function(a, b) {
38  return a < b ? -1 : a > b ? 1 : 0;
39};
40d3.descending = function(a, b) {
41  return b < a ? -1 : b > a ? 1 : 0;
42};
43d3.min = function(array, f) {
44  var i = -1,
45      n = array.length,
46      a,
47      b;
48  if (arguments.length === 1) {
49    while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
50    while (++i < n) if ((b = array[i]) != null && a > b) a = b;
51  } else {
52    while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
53    while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
54  }
55  return a;
56};
57d3.max = function(array, f) {
58  var i = -1,
59      n = array.length,
60      a,
61      b;
62  if (arguments.length === 1) {
63    while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
64    while (++i < n) if ((b = array[i]) != null && b > a) a = b;
65  } else {
66    while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
67    while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
68  }
69  return a;
70};
71d3.sum = function(array, f) {
72  var s = 0,
73      n = array.length,
74      a,
75      i = -1;
76
77  if (arguments.length === 1) {
78    while (++i < n) if (!isNaN(a = +array[i])) s += a;
79  } else {
80    while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
81  }
82
83  return s;
84};
85// R-7 per <http://en.wikipedia.org/wiki/Quantile>
86d3.quantile = function(values, p) {
87  var H = (values.length - 1) * p + 1,
88      h = Math.floor(H),
89      v = values[h - 1],
90      e = H - h;
91  return e ? v + e * (values[h] - v) : v;
92};
93d3.zip = function() {
94  if (!(n = arguments.length)) return [];
95  for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) {
96    for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) {
97      zip[j] = arguments[j][i];
98    }
99  }
100  return zips;
101};
102
103function d3_zipLength(d) {
104  return d.length;
105}
106// Locate the insertion point for x in a to maintain sorted order. The
107// arguments lo and hi may be used to specify a subset of the array which should
108// be considered; by default the entire array is used. If x is already present
109// in a, the insertion point will be before (to the left of) any existing
110// entries. The return value is suitable for use as the first argument to
111// `array.splice` assuming that a is already sorted.
112//
113// The returned insertion point i partitions the array a into two halves so that
114// all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi]
115// for the right side.
116d3.bisectLeft = function(a, x, lo, hi) {
117  if (arguments.length < 3) lo = 0;
118  if (arguments.length < 4) hi = a.length;
119  while (lo < hi) {
120    var mid = (lo + hi) >> 1;
121    if (a[mid] < x) lo = mid + 1;
122    else hi = mid;
123  }
124  return lo;
125};
126
127// Similar to bisectLeft, but returns an insertion point which comes after (to
128// the right of) any existing entries of x in a.
129//
130// The returned insertion point i partitions the array into two halves so that
131// all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi]
132// for the right side.
133d3.bisect =
134d3.bisectRight = function(a, x, lo, hi) {
135  if (arguments.length < 3) lo = 0;
136  if (arguments.length < 4) hi = a.length;
137  while (lo < hi) {
138    var mid = (lo + hi) >> 1;
139    if (x < a[mid]) hi = mid;
140    else lo = mid + 1;
141  }
142  return lo;
143};
144d3.first = function(array, f) {
145  var i = 0,
146      n = array.length,
147      a = array[0],
148      b;
149  if (arguments.length === 1) f = d3.ascending;
150  while (++i < n) {
151    if (f.call(array, a, b = array[i]) > 0) {
152      a = b;
153    }
154  }
155  return a;
156};
157d3.last = function(array, f) {
158  var i = 0,
159      n = array.length,
160      a = array[0],
161      b;
162  if (arguments.length === 1) f = d3.ascending;
163  while (++i < n) {
164    if (f.call(array, a, b = array[i]) <= 0) {
165      a = b;
166    }
167  }
168  return a;
169};
170d3.nest = function() {
171  var nest = {},
172      keys = [],
173      sortKeys = [],
174      sortValues,
175      rollup;
176
177  function map(array, depth) {
178    if (depth >= keys.length) return rollup
179        ? rollup.call(nest, array) : (sortValues
180        ? array.sort(sortValues)
181        : array);
182
183    var i = -1,
184        n = array.length,
185        key = keys[depth++],
186        keyValue,
187        object,
188        o = {};
189
190    while (++i < n) {
191      if ((keyValue = key(object = array[i])) in o) {
192        o[keyValue].push(object);
193      } else {
194        o[keyValue] = [object];
195      }
196    }
197
198    for (keyValue in o) {
199      o[keyValue] = map(o[keyValue], depth);
200    }
201
202    return o;
203  }
204
205  function entries(map, depth) {
206    if (depth >= keys.length) return map;
207
208    var a = [],
209        sortKey = sortKeys[depth++],
210        key;
211
212    for (key in map) {
213      a.push({key: key, values: entries(map[key], depth)});
214    }
215
216    if (sortKey) a.sort(function(a, b) {
217      return sortKey(a.key, b.key);
218    });
219
220    return a;
221  }
222
223  nest.map = function(array) {
224    return map(array, 0);
225  };
226
227  nest.entries = function(array) {
228    return entries(map(array, 0), 0);
229  };
230
231  nest.key = function(d) {
232    keys.push(d);
233    return nest;
234  };
235
236  // Specifies the order for the most-recently specified key.
237  // Note: only applies to entries. Map keys are unordered!
238  nest.sortKeys = function(order) {
239    sortKeys[keys.length - 1] = order;
240    return nest;
241  };
242
243  // Specifies the order for leaf values.
244  // Applies to both maps and entries array.
245  nest.sortValues = function(order) {
246    sortValues = order;
247    return nest;
248  };
249
250  nest.rollup = function(f) {
251    rollup = f;
252    return nest;
253  };
254
255  return nest;
256};
257d3.keys = function(map) {
258  var keys = [];
259  for (var key in map) keys.push(key);
260  return keys;
261};
262d3.values = function(map) {
263  var values = [];
264  for (var key in map) values.push(map[key]);
265  return values;
266};
267d3.entries = function(map) {
268  var entries = [];
269  for (var key in map) entries.push({key: key, value: map[key]});
270  return entries;
271};
272d3.permute = function(array, indexes) {
273  var permutes = [],
274      i = -1,
275      n = indexes.length;
276  while (++i < n) permutes[i] = array[indexes[i]];
277  return permutes;
278};
279d3.merge = function(arrays) {
280  return Array.prototype.concat.apply([], arrays);
281};
282d3.split = function(array, f) {
283  var arrays = [],
284      values = [],
285      value,
286      i = -1,
287      n = array.length;
288  if (arguments.length < 2) f = d3_splitter;
289  while (++i < n) {
290    if (f.call(values, value = array[i], i)) {
291      values = [];
292    } else {
293      if (!values.length) arrays.push(values);
294      values.push(value);
295    }
296  }
297  return arrays;
298};
299
300function d3_splitter(d) {
301  return d == null;
302}
303function d3_collapse(s) {
304  return s.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " ");
305}
306//
307// Note: assigning to the arguments array simultaneously changes the value of
308// the corresponding argument!
309//
310// TODO The `this` argument probably shouldn't be the first argument to the
311// callback, anyway, since it's redundant. However, that will require a major
312// version bump due to backwards compatibility, so I'm not changing it right
313// away.
314//
315function d3_call(callback) {
316  callback.apply(this, (arguments[0] = this, arguments));
317  return this;
318}
319/**
320 * @param {number} start
321 * @param {number=} stop
322 * @param {number=} step
323 */
324d3.range = function(start, stop, step) {
325  if (arguments.length === 1) { stop = start; start = 0; }
326  if (step == null) step = 1;
327  if ((stop - start) / step == Infinity) throw new Error("infinite range");
328  var range = [],
329       i = -1,
330       j;
331  if (step < 0) while ((j = start + step * ++i) > stop) range.push(j);
332  else while ((j = start + step * ++i) < stop) range.push(j);
333  return range;
334};
335d3.requote = function(s) {
336  return s.replace(d3_requote_re, "\\$&");
337};
338
339var d3_requote_re = /[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g;
340d3.round = function(x, n) {
341  return n
342      ? Math.round(x * Math.pow(10, n)) * Math.pow(10, -n)
343      : Math.round(x);
344};
345d3.xhr = function(url, mime, callback) {
346  var req = new XMLHttpRequest;
347  if (arguments.length < 3) callback = mime;
348  else if (mime && req.overrideMimeType) req.overrideMimeType(mime);
349  req.open("GET", url, true);
350  req.onreadystatechange = function() {
351    if (req.readyState === 4) callback(req.status < 300 ? req : null);
352  };
353  req.send(null);
354};
355d3.text = function(url, mime, callback) {
356  function ready(req) {
357    callback(req && req.responseText);
358  }
359  if (arguments.length < 3) {
360    callback = mime;
361    mime = null;
362  }
363  d3.xhr(url, mime, ready);
364};
365d3.json = function(url, callback) {
366  d3.text(url, "application/json", function(text) {
367    callback(text ? JSON.parse(text) : null);
368  });
369};
370d3.html = function(url, callback) {
371  d3.text(url, "text/html", function(text) {
372    if (text != null) { // Treat empty string as valid HTML.
373      var range = document.createRange();
374      range.selectNode(document.body);
375      text = range.createContextualFragment(text);
376    }
377    callback(text);
378  });
379};
380d3.xml = function(url, mime, callback) {
381  function ready(req) {
382    callback(req && req.responseXML);
383  }
384  if (arguments.length < 3) {
385    callback = mime;
386    mime = null;
387  }
388  d3.xhr(url, mime, ready);
389};
390d3.ns = {
391
392  prefix: {
393    svg: "http://www.w3.org/2000/svg",
394    xhtml: "http://www.w3.org/1999/xhtml",
395    xlink: "http://www.w3.org/1999/xlink",
396    xml: "http://www.w3.org/XML/1998/namespace",
397    xmlns: "http://www.w3.org/2000/xmlns/"
398  },
399
400  qualify: function(name) {
401    var i = name.indexOf(":");
402    return i < 0 ? name : {
403      space: d3.ns.prefix[name.substring(0, i)],
404      local: name.substring(i + 1)
405    };
406  }
407
408};
409/** @param {...string} types */
410d3.dispatch = function(types) {
411  var dispatch = {},
412      type;
413  for (var i = 0, n = arguments.length; i < n; i++) {
414    type = arguments[i];
415    dispatch[type] = d3_dispatch(type);
416  }
417  return dispatch;
418};
419
420function d3_dispatch(type) {
421  var dispatch = {},
422      listeners = [];
423
424  dispatch.add = function(listener) {
425    for (var i = 0; i < listeners.length; i++) {
426      if (listeners[i].listener == listener) return dispatch; // already registered
427    }
428    listeners.push({listener: listener, on: true});
429    return dispatch;
430  };
431
432  dispatch.remove = function(listener) {
433    for (var i = 0; i < listeners.length; i++) {
434      var l = listeners[i];
435      if (l.listener == listener) {
436        l.on = false;
437        listeners = listeners.slice(0, i).concat(listeners.slice(i + 1));
438        break;
439      }
440    }
441    return dispatch;
442  };
443
444  dispatch.dispatch = function() {
445    var ls = listeners; // defensive reference
446    for (var i = 0, n = ls.length; i < n; i++) {
447      var l = ls[i];
448      if (l.on) l.listener.apply(this, arguments);
449    }
450  };
451
452  return dispatch;
453};
454// TODO align
455d3.format = function(specifier) {
456  var match = d3_format_re.exec(specifier),
457      fill = match[1] || " ",
458      sign = match[3] || "",
459      zfill = match[5],
460      width = +match[6],
461      comma = match[7],
462      precision = match[8],
463      type = match[9],
464      percentage = false,
465      integer = false;
466
467  if (precision) precision = precision.substring(1);
468
469  if (zfill) {
470    fill = "0"; // TODO align = "=";
471    if (comma) width -= Math.floor((width - 1) / 4);
472  }
473
474  switch (type) {
475    case "n": comma = true; type = "g"; break;
476    case "%": percentage = true; type = "f"; break;
477    case "p": percentage = true; type = "r"; break;
478    case "d": integer = true; precision = "0"; break;
479  }
480
481  type = d3_format_types[type] || d3_format_typeDefault;
482
483  return function(value) {
484    var number = percentage ? value * 100 : +value,
485        negative = (number < 0) && (number = -number) ? "\u2212" : sign;
486
487    // Return the empty string for floats formatted as ints.
488    if (integer && (number % 1)) return "";
489
490    // Convert the input value to the desired precision.
491    value = type(number, precision);
492
493    // If the fill character is 0, the sign and group is applied after the fill.
494    if (zfill) {
495      var length = value.length + negative.length;
496      if (length < width) value = new Array(width - length + 1).join(fill) + value;
497      if (comma) value = d3_format_group(value);
498      value = negative + value;
499    }
500
501    // Otherwise (e.g., space-filling), the sign and group is applied before.
502    else {
503      if (comma) value = d3_format_group(value);
504      value = negative + value;
505      var length = value.length;
506      if (length < width) value = new Array(width - length + 1).join(fill) + value;
507    }
508    if (percentage) value += "%";
509
510    return value;
511  };
512};
513
514// [[fill]align][sign][#][0][width][,][.precision][type]
515var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
516
517var d3_format_types = {
518  g: function(x, p) { return x.toPrecision(p); },
519  e: function(x, p) { return x.toExponential(p); },
520  f: function(x, p) { return x.toFixed(p); },
521  r: function(x, p) {
522    var n = 1 + Math.floor(1e-15 + Math.log(x) / Math.LN10);
523    return d3.round(x, p - n).toFixed(Math.max(0, p - n));
524  }
525};
526
527function d3_format_typeDefault(x) {
528  return x + "";
529}
530
531// Apply comma grouping for thousands.
532function d3_format_group(value) {
533  var i = value.lastIndexOf("."),
534      f = i >= 0 ? value.substring(i) : (i = value.length, ""),
535      t = [];
536  while (i > 0) t.push(value.substring(i -= 3, i + 3));
537  return t.reverse().join(",") + f;
538}
539/*
540 * TERMS OF USE - EASING EQUATIONS
541 *
542 * Open source under the BSD License.
543 *
544 * Copyright 2001 Robert Penner
545 * All rights reserved.
546 *
547 * Redistribution and use in source and binary forms, with or without
548 * modification, are permitted provided that the following conditions are met:
549 *
550 * - Redistributions of source code must retain the above copyright notice, this
551 *   list of conditions and the following disclaimer.
552 *
553 * - Redistributions in binary form must reproduce the above copyright notice,
554 *   this list of conditions and the following disclaimer in the documentation
555 *   and/or other materials provided with the distribution.
556 *
557 * - Neither the name of the author nor the names of contributors may be used to
558 *   endorse or promote products derived from this software without specific
559 *   prior written permission.
560 *
561 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
562 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
563 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
564 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
565 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
566 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
567 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
568 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
569 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
570 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
571 * POSSIBILITY OF SUCH DAMAGE.
572 */
573
574var d3_ease_quad = d3_ease_poly(2),
575    d3_ease_cubic = d3_ease_poly(3);
576
577var d3_ease = {
578  linear: function() { return d3_ease_linear; },
579  poly: d3_ease_poly,
580  quad: function() { return d3_ease_quad; },
581  cubic: function() { return d3_ease_cubic; },
582  sin: function() { return d3_ease_sin; },
583  exp: function() { return d3_ease_exp; },
584  circle: function() { return d3_ease_circle; },
585  elastic: d3_ease_elastic,
586  back: d3_ease_back,
587  bounce: function() { return d3_ease_bounce; }
588};
589
590var d3_ease_mode = {
591  "in": function(f) { return f; },
592  "out": d3_ease_reverse,
593  "in-out": d3_ease_reflect,
594  "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); }
595};
596
597d3.ease = function(name) {
598  var i = name.indexOf("-"),
599      t = i >= 0 ? name.substring(0, i) : name,
600      m = i >= 0 ? name.substring(i + 1) : "in";
601  return d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1)));
602};
603
604function d3_ease_reverse(f) {
605  return function(t) {
606    return 1 - f(1 - t);
607  };
608}
609
610function d3_ease_reflect(f) {
611  return function(t) {
612    return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
613  };
614}
615
616function d3_ease_linear(t) {
617  return t;
618}
619
620function d3_ease_poly(e) {
621  return function(t) {
622    return Math.pow(t, e);
623  }
624}
625
626function d3_ease_sin(t) {
627  return 1 - Math.cos(t * Math.PI / 2);
628}
629
630function d3_ease_exp(t) {
631  return t ? Math.pow(2, 10 * (t - 1)) - 1e-3 : 0;
632}
633
634function d3_ease_circle(t) {
635  return 1 - Math.sqrt(1 - t * t);
636}
637
638function d3_ease_elastic(a, p) {
639  var s;
640  if (arguments.length < 2) p = 0.45;
641  if (arguments.length < 1) { a = 1; s = p / 4; }
642  else s = p / (2 * Math.PI) * Math.asin(1 / a);
643  return function(t) {
644    return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p);
645  };
646}
647
648function d3_ease_back(s) {
649  if (!s) s = 1.70158;
650  return function(t) {
651    return t * t * ((s + 1) * t - s);
652  };
653}
654
655function d3_ease_bounce(t) {
656  return t < 1 / 2.75 ? 7.5625 * t * t
657      : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
658      : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
659      : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
660}
661d3.event = null;
662d3.interpolate = function(a, b) {
663  var i = d3.interpolators.length, f;
664  while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
665  return f;
666};
667
668d3.interpolateNumber = function(a, b) {
669  b -= a;
670  return function(t) { return a + b * t; };
671};
672
673d3.interpolateRound = function(a, b) {
674  b -= a;
675  return function(t) { return Math.round(a + b * t); };
676};
677
678d3.interpolateString = function(a, b) {
679  var m, // current match
680      i, // current index
681      j, // current index (for coallescing)
682      s0 = 0, // start index of current string prefix
683      s1 = 0, // end index of current string prefix
684      s = [], // string constants and placeholders
685      q = [], // number interpolators
686      n, // q.length
687      o;
688
689  // Reset our regular expression!
690  d3_interpolate_number.lastIndex = 0;
691
692  // Find all numbers in b.
693  for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
694    if (m.index) s.push(b.substring(s0, s1 = m.index));
695    q.push({i: s.length, x: m[0]});
696    s.push(null);
697    s0 = d3_interpolate_number.lastIndex;
698  }
699  if (s0 < b.length) s.push(b.substring(s0));
700
701  // Find all numbers in a.
702  for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
703    o = q[i];
704    if (o.x == m[0]) { // The numbers match, so coallesce.
705      if (o.i) {
706        if (s[o.i + 1] == null) { // This match is followed by another number.
707          s[o.i - 1] += o.x;
708          s.splice(o.i, 1);
709          for (j = i + 1; j < n; ++j) q[j].i--;
710        } else { // This match is followed by a string, so coallesce twice.
711          s[o.i - 1] += o.x + s[o.i + 1];
712          s.splice(o.i, 2);
713          for (j = i + 1; j < n; ++j) q[j].i -= 2;
714        }
715      } else {
716          if (s[o.i + 1] == null) { // This match is followed by another number.
717          s[o.i] = o.x;
718        } else { // This match is followed by a string, so coallesce twice.
719          s[o.i] = o.x + s[o.i + 1];
720          s.splice(o.i + 1, 1);
721          for (j = i + 1; j < n; ++j) q[j].i--;
722        }
723      }
724      q.splice(i, 1);
725      n--;
726      i--;
727    } else {
728      o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
729    }
730  }
731
732  // Remove any numbers in b not found in a.
733  while (i < n) {
734    o = q.pop();
735    if (s[o.i + 1] == null) { // This match is followed by another number.
736      s[o.i] = o.x;
737    } else { // This match is followed by a string, so coallesce twice.
738      s[o.i] = o.x + s[o.i + 1];
739      s.splice(o.i + 1, 1);
740    }
741    n--;
742  }
743
744  // Special optimization for only a single match.
745  if (s.length === 1) {
746    return s[0] == null ? q[0].x : function() { return b; };
747  }
748
749  // Otherwise, interpolate each of the numbers and rejoin the string.
750  return function(t) {
751    for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
752    return s.join("");
753  };
754};
755
756d3.interpolateRgb = function(a, b) {
757  a = d3.rgb(a);
758  b = d3.rgb(b);
759  var ar = a.r,
760      ag = a.g,
761      ab = a.b,
762      br = b.r - ar,
763      bg = b.g - ag,
764      bb = b.b - ab;
765  return function(t) {
766    return "rgb(" + Math.round(ar + br * t)
767        + "," + Math.round(ag + bg * t)
768        + "," + Math.round(ab + bb * t)
769        + ")";
770  };
771};
772
773// interpolates HSL space, but outputs RGB string (for compatibility)
774d3.interpolateHsl = function(a, b) {
775  a = d3.hsl(a);
776  b = d3.hsl(b);
777  var h0 = a.h,
778      s0 = a.s,
779      l0 = a.l,
780      h1 = b.h - h0,
781      s1 = b.s - s0,
782      l1 = b.l - l0;
783  return function(t) {
784    return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t).toString();
785  };
786};
787
788d3.interpolateArray = function(a, b) {
789  var x = [],
790      c = [],
791      na = a.length,
792      nb = b.length,
793      n0 = Math.min(a.length, b.length),
794      i;
795  for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));
796  for (; i < na; ++i) c[i] = a[i];
797  for (; i < nb; ++i) c[i] = b[i];
798  return function(t) {
799    for (i = 0; i < n0; ++i) c[i] = x[i](t);
800    return c;
801  };
802};
803
804d3.interpolateObject = function(a, b) {
805  var i = {},
806      c = {},
807      k;
808  for (k in a) {
809    if (k in b) {
810      i[k] = d3_interpolateByName(k)(a[k], b[k]);
811    } else {
812      c[k] = a[k];
813    }
814  }
815  for (k in b) {
816    if (!(k in a)) {
817      c[k] = b[k];
818    }
819  }
820  return function(t) {
821    for (k in i) c[k] = i[k](t);
822    return c;
823  };
824}
825
826var d3_interpolate_number = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g,
827    d3_interpolate_rgb = {background: 1, fill: 1, stroke: 1};
828
829function d3_interpolateByName(n) {
830  return n in d3_interpolate_rgb || /\bcolor\b/.test(n)
831      ? d3.interpolateRgb
832      : d3.interpolate;
833}
834
835d3.interpolators = [
836  d3.interpolateObject,
837  function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); },
838  function(a, b) { return (typeof b === "string") && d3.interpolateString(String(a), b); },
839  function(a, b) { return (b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b)) && d3.interpolateRgb(String(a), b); },
840  function(a, b) { return (typeof b === "number") && d3.interpolateNumber(+a, b); }
841];
842function d3_uninterpolateNumber(a, b) {
843  b = 1 / (b - (a = +a));
844  return function(x) { return (x - a) * b; };
845}
846
847function d3_uninterpolateClamp(a, b) {
848  b = 1 / (b - (a = +a));
849  return function(x) { return Math.max(0, Math.min(1, (x - a) * b)); };
850}
851d3.rgb = function(r, g, b) {
852  return arguments.length === 1
853      ? d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb)
854      : d3_rgb(~~r, ~~g, ~~b);
855};
856
857function d3_rgb(r, g, b) {
858  return new d3_Rgb(r, g, b);
859}
860
861function d3_Rgb(r, g, b) {
862  this.r = r;
863  this.g = g;
864  this.b = b;
865}
866
867d3_Rgb.prototype.brighter = function(k) {
868  k = Math.pow(0.7, arguments.length ? k : 1);
869  var r = this.r,
870      g = this.g,
871      b = this.b,
872      i = 30;
873  if (!r && !g && !b) return d3_rgb(i, i, i);
874  if (r && r < i) r = i;
875  if (g && g < i) g = i;
876  if (b && b < i) b = i;
877  return d3_rgb(
878    Math.min(255, Math.floor(r / k)),
879    Math.min(255, Math.floor(g / k)),
880    Math.min(255, Math.floor(b / k)));
881};
882
883d3_Rgb.prototype.darker = function(k) {
884  k = Math.pow(0.7, arguments.length ? k : 1);
885  return d3_rgb(
886    Math.max(0, Math.floor(k * this.r)),
887    Math.max(0, Math.floor(k * this.g)),
888    Math.max(0, Math.floor(k * this.b)));
889};
890
891d3_Rgb.prototype.hsl = function() {
892  return d3_rgb_hsl(this.r, this.g, this.b);
893};
894
895d3_Rgb.prototype.toString = function() {
896  return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
897};
898
899function d3_rgb_hex(v) {
900  return v < 0x10 ? "0" + v.toString(16) : v.toString(16);
901}
902
903function d3_rgb_parse(format, rgb, hsl) {
904  var r = 0, // red channel; int in [0, 255]
905      g = 0, // green channel; int in [0, 255]
906      b = 0, // blue channel; int in [0, 255]
907      m1, // CSS color specification match
908      m2, // CSS color specification type (e.g., rgb)
909      name;
910
911  /* Handle hsl, rgb. */
912  m1 = /([a-z]+)\((.*)\)/i.exec(format);
913  if (m1) {
914    m2 = m1[2].split(",");
915    switch (m1[1]) {
916      case "hsl": {
917        return hsl(
918          parseFloat(m2[0]), // degrees
919          parseFloat(m2[1]) / 100, // percentage
920          parseFloat(m2[2]) / 100 // percentage
921        );
922      }
923      case "rgb": {
924        return rgb(
925          d3_rgb_parseNumber(m2[0]),
926          d3_rgb_parseNumber(m2[1]),
927          d3_rgb_parseNumber(m2[2])
928        );
929      }
930    }
931  }
932
933  /* Named colors. */
934  if (name = d3_rgb_names[format]) return rgb(name.r, name.g, name.b);
935
936  /* Hexadecimal colors: #rgb and #rrggbb. */
937  if (format != null && format.charAt(0) === "#") {
938    if (format.length === 4) {
939      r = format.charAt(1); r += r;
940      g = format.charAt(2); g += g;
941      b = format.charAt(3); b += b;
942    } else if (format.length === 7) {
943      r = format.substring(1, 3);
944      g = format.substring(3, 5);
945      b = format.substring(5, 7);
946    }
947    r = parseInt(r, 16);
948    g = parseInt(g, 16);
949    b = parseInt(b, 16);
950  }
951
952  return rgb(r, g, b);
953}
954
955function d3_rgb_hsl(r, g, b) {
956  var min = Math.min(r /= 255, g /= 255, b /= 255),
957      max = Math.max(r, g, b),
958      d = max - min,
959      h,
960      s,
961      l = (max + min) / 2;
962  if (d) {
963    s = l < .5 ? d / (max + min) : d / (2 - max - min);
964    if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
965    else if (g == max) h = (b - r) / d + 2;
966    else h = (r - g) / d + 4;
967    h *= 60;
968  } else {
969    s = h = 0;
970  }
971  return d3_hsl(h, s, l);
972}
973
974function d3_rgb_parseNumber(c) { // either integer or percentage
975  var f = parseFloat(c);
976  return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
977}
978
979var d3_rgb_names = {
980  aliceblue: "#f0f8ff",
981  antiquewhite: "#faebd7",
982  aqua: "#00ffff",
983  aquamarine: "#7fffd4",
984  azure: "#f0ffff",
985  beige: "#f5f5dc",
986  bisque: "#ffe4c4",
987  black: "#000000",
988  blanchedalmond: "#ffebcd",
989  blue: "#0000ff",
990  blueviolet: "#8a2be2",
991  brown: "#a52a2a",
992  burlywood: "#deb887",
993  cadetblue: "#5f9ea0",
994  chartreuse: "#7fff00",
995  chocolate: "#d2691e",
996  coral: "#ff7f50",
997  cornflowerblue: "#6495ed",
998  cornsilk: "#fff8dc",
999  crimson: "#dc143c",
1000  cyan: "#00ffff",
1001  darkblue: "#00008b",
1002  darkcyan: "#008b8b",
1003  darkgoldenrod: "#b8860b",
1004  darkgray: "#a9a9a9",
1005  darkgreen: "#006400",
1006  darkgrey: "#a9a9a9",
1007  darkkhaki: "#bdb76b",
1008  darkmagenta: "#8b008b",
1009  darkolivegreen: "#556b2f",
1010  darkorange: "#ff8c00",
1011  darkorchid: "#9932cc",
1012  darkred: "#8b0000",
1013  darksalmon: "#e9967a",
1014  darkseagreen: "#8fbc8f",
1015  darkslateblue: "#483d8b",
1016  darkslategray: "#2f4f4f",
1017  darkslategrey: "#2f4f4f",
1018  darkturquoise: "#00ced1",
1019  darkviolet: "#9400d3",
1020  deeppink: "#ff1493",
1021  deepskyblue: "#00bfff",
1022  dimgray: "#696969",
1023  dimgrey: "#696969",
1024  dodgerblue: "#1e90ff",
1025  firebrick: "#b22222",
1026  floralwhite: "#fffaf0",
1027  forestgreen: "#228b22",
1028  fuchsia: "#ff00ff",
1029  gainsboro: "#dcdcdc",
1030  ghostwhite: "#f8f8ff",
1031  gold: "#ffd700",
1032  goldenrod: "#daa520",
1033  gray: "#808080",
1034  green: "#008000",
1035  greenyellow: "#adff2f",
1036  grey: "#808080",
1037  honeydew: "#f0fff0",
1038  hotpink: "#ff69b4",
1039  indianred: "#cd5c5c",
1040  indigo: "#4b0082",
1041  ivory: "#fffff0",
1042  khaki: "#f0e68c",
1043  lavender: "#e6e6fa",
1044  lavenderblush: "#fff0f5",
1045  lawngreen: "#7cfc00",
1046  lemonchiffon: "#fffacd",
1047  lightblue: "#add8e6",
1048  lightcoral: "#f08080",
1049  lightcyan: "#e0ffff",
1050  lightgoldenrodyellow: "#fafad2",
1051  lightgray: "#d3d3d3",
1052  lightgreen: "#90ee90",
1053  lightgrey: "#d3d3d3",
1054  lightpink: "#ffb6c1",
1055  lightsalmon: "#ffa07a",
1056  lightseagreen: "#20b2aa",
1057  lightskyblue: "#87cefa",
1058  lightslategray: "#778899",
1059  lightslategrey: "#778899",
1060  lightsteelblue: "#b0c4de",
1061  lightyellow: "#ffffe0",
1062  lime: "#00ff00",
1063  limegreen: "#32cd32",
1064  linen: "#faf0e6",
1065  magenta: "#ff00ff",
1066  maroon: "#800000",
1067  mediumaquamarine: "#66cdaa",
1068  mediumblue: "#0000cd",
1069  mediumorchid: "#ba55d3",
1070  mediumpurple: "#9370db",
1071  mediumseagreen: "#3cb371",
1072  mediumslateblue: "#7b68ee",
1073  mediumspringgreen: "#00fa9a",
1074  mediumturquoise: "#48d1cc",
1075  mediumvioletred: "#c71585",
1076  midnightblue: "#191970",
1077  mintcream: "#f5fffa",
1078  mistyrose: "#ffe4e1",
1079  moccasin: "#ffe4b5",
1080  navajowhite: "#ffdead",
1081  navy: "#000080",
1082  oldlace: "#fdf5e6",
1083  olive: "#808000",
1084  olivedrab: "#6b8e23",
1085  orange: "#ffa500",
1086  orangered: "#ff4500",
1087  orchid: "#da70d6",
1088  palegoldenrod: "#eee8aa",
1089  palegreen: "#98fb98",
1090  paleturquoise: "#afeeee",
1091  palevioletred: "#db7093",
1092  papayawhip: "#ffefd5",
1093  peachpuff: "#ffdab9",
1094  peru: "#cd853f",
1095  pink: "#ffc0cb",
1096  plum: "#dda0dd",
1097  powderblue: "#b0e0e6",
1098  purple: "#800080",
1099  red: "#ff0000",
1100  rosybrown: "#bc8f8f",
1101  royalblue: "#4169e1",
1102  saddlebrown: "#8b4513",
1103  salmon: "#fa8072",
1104  sandybrown: "#f4a460",
1105  seagreen: "#2e8b57",
1106  seashell: "#fff5ee",
1107  sienna: "#a0522d",
1108  silver: "#c0c0c0",
1109  skyblue: "#87ceeb",
1110  slateblue: "#6a5acd",
1111  slategray: "#708090",
1112  slategrey: "#708090",
1113  snow: "#fffafa",
1114  springgreen: "#00ff7f",
1115  steelblue: "#4682b4",
1116  tan: "#d2b48c",
1117  teal: "#008080",
1118  thistle: "#d8bfd8",
1119  tomato: "#ff6347",
1120  turquoise: "#40e0d0",
1121  violet: "#ee82ee",
1122  wheat: "#f5deb3",
1123  white: "#ffffff",
1124  whitesmoke: "#f5f5f5",
1125  yellow: "#ffff00",
1126  yellowgreen: "#9acd32"
1127};
1128
1129for (var d3_rgb_name in d3_rgb_names) {
1130  d3_rgb_names[d3_rgb_name] = d3_rgb_parse(
1131      d3_rgb_names[d3_rgb_name],
1132      d3_rgb,
1133      d3_hsl_rgb);
1134}
1135d3.hsl = function(h, s, l) {
1136  return arguments.length === 1
1137      ? d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl)
1138      : d3_hsl(+h, +s, +l);
1139};
1140
1141function d3_hsl(h, s, l) {
1142  return new d3_Hsl(h, s, l);
1143}
1144
1145function d3_Hsl(h, s, l) {
1146  this.h = h;
1147  this.s = s;
1148  this.l = l;
1149}
1150
1151d3_Hsl.prototype.brighter = function(k) {
1152  k = Math.pow(0.7, arguments.length ? k : 1);
1153  return d3_hsl(this.h, this.s, this.l / k);
1154};
1155
1156d3_Hsl.prototype.darker = function(k) {
1157  k = Math.pow(0.7, arguments.length ? k : 1);
1158  return d3_hsl(this.h, this.s, k * this.l);
1159};
1160
1161d3_Hsl.prototype.rgb = function() {
1162  return d3_hsl_rgb(this.h, this.s, this.l);
1163};
1164
1165d3_Hsl.prototype.toString = function() {
1166  return "hsl(" + this.h + "," + this.s * 100 + "%," + this.l * 100 + "%)";
1167};
1168
1169function d3_hsl_rgb(h, s, l) {
1170  var m1,
1171      m2;
1172
1173  /* Some simple corrections for h, s and l. */
1174  h = h % 360; if (h < 0) h += 360;
1175  s = s < 0 ? 0 : s > 1 ? 1 : s;
1176  l = l < 0 ? 0 : l > 1 ? 1 : l;
1177
1178  /* From FvD 13.37, CSS Color Module Level 3 */
1179  m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
1180  m1 = 2 * l - m2;
1181
1182  function v(h) {
1183    if (h > 360) h -= 360;
1184    else if (h < 0) h += 360;
1185    if (h < 60) return m1 + (m2 - m1) * h / 60;
1186    if (h < 180) return m2;
1187    if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
1188    return m1;
1189  }
1190
1191  function vv(h) {
1192    return Math.round(v(h) * 255);
1193  }
1194
1195  return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
1196}
1197var d3_select = function(s, n) { return n.querySelector(s); },
1198    d3_selectAll = function(s, n) { return d3_array(n.querySelectorAll(s)); };
1199
1200// Use Sizzle, if available.
1201if (typeof Sizzle === "function") {
1202  d3_select = function(s, n) { return Sizzle(s, n)[0]; };
1203  d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); };
1204}
1205
1206var d3_root = d3_selection([[document]]);
1207d3_root[0].parentNode = document.documentElement;
1208
1209// TODO fast singleton implementation!
1210d3.select = function(selector) {
1211  return typeof selector === "string"
1212      ? d3_root.select(selector)
1213      : d3_selection([[selector]]); // assume node
1214};
1215
1216d3.selectAll = function(selector) {
1217  return typeof selector === "string"
1218      ? d3_root.selectAll(selector)
1219      : d3_selection([d3_array(selector)]); // assume node[]
1220};
1221
1222function d3_selection(groups) {
1223
1224  function select(select) {
1225    var subgroups = [],
1226        subgroup,
1227        subnode,
1228        group,
1229        node;
1230    for (var j = 0, m = groups.length; j < m; j++) {
1231      group = groups[j];
1232      subgroups.push(subgroup = []);
1233      subgroup.parentNode = group.parentNode;
1234      for (var i = 0, n = group.length; i < n; i++) {
1235        if (node = group[i]) {
1236          subgroup.push(subnode = select(node));
1237          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
1238        } else {
1239          subgroup.push(null);
1240        }
1241      }
1242    }
1243    return d3_selection(subgroups);
1244  }
1245
1246  function selectAll(selectAll) {
1247    var subgroups = [],
1248        subgroup,
1249        group,
1250        node;
1251    for (var j = 0, m = groups.length; j < m; j++) {
1252      group = groups[j];
1253      for (var i = 0, n = group.length; i < n; i++) {
1254        if (node = group[i]) {
1255          subgroups.push(subgroup = selectAll(node));
1256          subgroup.parentNode = node;
1257        }
1258      }
1259    }
1260    return d3_selection(subgroups);
1261  }
1262
1263  // TODO select(function)?
1264  groups.select = function(selector) {
1265    return select(function(node) {
1266      return d3_select(selector, node);
1267    });
1268  };
1269
1270  // TODO selectAll(function)?
1271  groups.selectAll = function(selector) {
1272    return selectAll(function(node) {
1273      return d3_selectAll(selector, node);
1274    });
1275  };
1276
1277  // TODO preserve null elements to maintain index?
1278  groups.filter = function(filter) {
1279    var subgroups = [],
1280        subgroup,
1281        group,
1282        node;
1283    for (var j = 0, m = groups.length; j < m; j++) {
1284      group = groups[j];
1285      subgroups.push(subgroup = []);
1286      subgroup.parentNode = group.parentNode;
1287      for (var i = 0, n = group.length; i < n; i++) {
1288        if ((node = group[i]) && filter.call(node, node.__data__, i)) {
1289          subgroup.push(node);
1290        }
1291      }
1292    }
1293    return d3_selection(subgroups);
1294  };
1295
1296  groups.map = function(map) {
1297    var group,
1298        node;
1299    for (var j = 0, m = groups.length; j < m; j++) {
1300      group = groups[j];
1301      for (var i = 0, n = group.length; i < n; i++) {
1302        if (node = group[i]) node.__data__ = map.call(node, node.__data__, i);
1303      }
1304    }
1305    return groups;
1306  };
1307
1308  // TODO data(null) for clearing data?
1309  groups.data = function(data, join) {
1310    var enter = [],
1311        update = [],
1312        exit = [];
1313
1314    function bind(group, groupData) {
1315      var i = 0,
1316          n = group.length,
1317          m = groupData.length,
1318          n0 = Math.min(n, m),
1319          n1 = Math.max(n, m),
1320          updateNodes = [],
1321          enterNodes = [],
1322          exitNodes = [],
1323          node,
1324          nodeData;
1325
1326      if (join) {
1327        var nodeByKey = {},
1328            keys = [],
1329            key,
1330            j = groupData.length;
1331
1332        for (i = 0; i < n; i++) {
1333          key = join.call(node = group[i], node.__data__, i);
1334          if (key in nodeByKey) {
1335            exitNodes[j++] = node; // duplicate key
1336          } else {
1337            nodeByKey[key] = node;
1338          }
1339          keys.push(key);
1340        }
1341
1342        for (i = 0; i < m; i++) {
1343          node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)];
1344          if (node) {
1345            node.__data__ = nodeData;
1346            updateNodes[i] = node;
1347            enterNodes[i] = exitNodes[i] = null;
1348          } else {
1349            enterNodes[i] = d3_selection_enterNode(nodeData);
1350            updateNodes[i] = exitNodes[i] = null;
1351          }
1352          delete nodeByKey[key];
1353        }
1354
1355        for (i = 0; i < n; i++) {
1356          if (keys[i] in nodeByKey) {
1357            exitNodes[i] = group[i];
1358          }
1359        }
1360      } else {
1361        for (; i < n0; i++) {
1362          node = group[i];
1363          nodeData = groupData[i];
1364          if (node) {
1365            node.__data__ = nodeData;
1366            updateNodes[i] = node;
1367            enterNodes[i] = exitNodes[i] = null;
1368          } else {
1369            enterNodes[i] = d3_selection_enterNode(nodeData);
1370            updateNodes[i] = exitNodes[i] = null;
1371          }
1372        }
1373        for (; i < m; i++) {
1374          enterNodes[i] = d3_selection_enterNode(groupData[i]);
1375          updateNodes[i] = exitNodes[i] = null;
1376        }
1377        for (; i < n1; i++) {
1378          exitNodes[i] = group[i];
1379          enterNodes[i] = updateNodes[i] = null;
1380        }
1381      }
1382
1383      enterNodes.parentNode
1384          = updateNodes.parentNode
1385          = exitNodes.parentNode
1386          = group.parentNode;
1387
1388      enter.push(enterNodes);
1389      update.push(updateNodes);
1390      exit.push(exitNodes);
1391    }
1392
1393    var i = -1,
1394        n = groups.length,
1395        group;
1396    if (typeof data === "function") {
1397      while (++i < n) {
1398        bind(group = groups[i], data.call(group, group.parentNode.__data__, i));
1399      }
1400    } else {
1401      while (++i < n) {
1402        bind(group = groups[i], data);
1403      }
1404    }
1405
1406    var selection = d3_selection(update);
1407    selection.enter = function() {
1408      return d3_selectionEnter(enter);
1409    };
1410    selection.exit = function() {
1411      return d3_selection(exit);
1412    };
1413    return selection;
1414  };
1415
1416  // TODO mask forEach? or rename for eachData?
1417  // TODO offer the same semantics for map, reduce, etc.?
1418  groups.each = function(callback) {
1419    for (var j = 0, m = groups.length; j < m; j++) {
1420      var group = groups[j];
1421      for (var i = 0, n = group.length; i < n; i++) {
1422        var node = group[i];
1423        if (node) callback.call(node, node.__data__, i);
1424      }
1425    }
1426    return groups;
1427  };
1428
1429  function first(callback) {
1430    for (var j = 0, m = groups.length; j < m; j++) {
1431      var group = groups[j];
1432      for (var i = 0, n = group.length; i < n; i++) {
1433        var node = group[i];
1434        if (node) return callback.call(node, node.__data__, i);
1435      }
1436    }
1437    return null;
1438  }
1439
1440  groups.empty = function() {
1441    return !first(function() { return true; });
1442  };
1443
1444  groups.node = function() {
1445    return first(function() { return this; });
1446  };
1447
1448  groups.attr = function(name, value) {
1449    name = d3.ns.qualify(name);
1450
1451    // If no value is specified, return the first value.
1452    if (arguments.length < 2) {
1453      return first(name.local
1454          ? function() { return this.getAttributeNS(name.space, name.local); }
1455          : function() { return this.getAttribute(name); });
1456    }
1457
1458    /** @this {Element} */
1459    function attrNull() {
1460      this.removeAttribute(name);
1461    }
1462
1463    /** @this {Element} */
1464    function attrNullNS() {
1465      this.removeAttributeNS(name.space, name.local);
1466    }
1467
1468    /** @this {Element} */
1469    function attrConstant() {
1470      this.setAttribute(name, value);
1471    }
1472
1473    /** @this {Element} */
1474    function attrConstantNS() {
1475      this.setAttributeNS(name.space, name.local, value);
1476    }
1477
1478    /** @this {Element} */
1479    function attrFunction() {
1480      var x = value.apply(this, arguments);
1481      if (x == null) this.removeAttribute(name);
1482      else this.setAttribute(name, x);
1483    }
1484
1485    /** @this {Element} */
1486    function attrFunctionNS() {
1487      var x = value.apply(this, arguments);
1488      if (x == null) this.removeAttributeNS(name.space, name.local);
1489      else this.setAttributeNS(name.space, name.local, x);
1490    }
1491
1492    return groups.each(value == null
1493        ? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
1494        ? (name.local ? attrFunctionNS : attrFunction)
1495        : (name.local ? attrConstantNS : attrConstant)));
1496  };
1497
1498  groups.classed = function(name, value) {
1499    var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
1500
1501    // If no value is specified, return the first value.
1502    if (arguments.length < 2) {
1503      return first(function() {
1504        if (c = this.classList) return c.contains(name);
1505        var c = this.className;
1506        re.lastIndex = 0;
1507        return re.test(c.baseVal != null ? c.baseVal : c);
1508      });
1509    }
1510
1511    /** @this {Element} */
1512    function classedAdd() {
1513      if (c = this.classList) return c.add(name);
1514      var c = this.className,
1515          cb = c.baseVal != null,
1516          cv = cb ? c.baseVal : c;
1517      re.lastIndex = 0;
1518      if (!re.test(cv)) {
1519        cv = d3_collapse(cv + " " + name);
1520        if (cb) c.baseVal = cv;
1521        else this.className = cv;
1522      }
1523    }
1524
1525    /** @this {Element} */
1526    function classedRemove() {
1527      if (c = this.classList) return c.remove(name);
1528      var c = this.className,
1529          cb = c.baseVal != null,
1530          cv = cb ? c.baseVal : c;
1531      cv = d3_collapse(cv.replace(re, " "));
1532      if (cb) c.baseVal = cv;
1533      else this.className = cv;
1534    }
1535
1536    /** @this {Element} */
1537    function classedFunction() {
1538      (value.apply(this, arguments)
1539          ? classedAdd
1540          : classedRemove).call(this);
1541    }
1542
1543    return groups.each(typeof value === "function"
1544        ? classedFunction : value
1545        ? classedAdd
1546        : classedRemove);
1547  };
1548
1549  groups.style = function(name, value, priority) {
1550    if (arguments.length < 3) priority = "";
1551
1552    // If no value is specified, return the first value.
1553    if (arguments.length < 2) {
1554      return first(function() {
1555        return window.getComputedStyle(this, null).getPropertyValue(name);
1556      });
1557    }
1558
1559    /** @this {Element} */
1560    function styleNull() {
1561      this.style.removeProperty(name);
1562    }
1563
1564    /** @this {Element} */
1565    function styleConstant() {
1566      this.style.setProperty(name, value, priority);
1567    }
1568
1569    /** @this {Element} */
1570    function styleFunction() {
1571      var x = value.apply(this, arguments);
1572      if (x == null) this.style.removeProperty(name);
1573      else this.style.setProperty(name, x, priority);
1574    }
1575
1576    return groups.each(value == null
1577        ? styleNull : (typeof value === "function"
1578        ? styleFunction : styleConstant));
1579  };
1580
1581  groups.property = function(name, value) {
1582    name = d3.ns.qualify(name);
1583
1584    // If no value is specified, return the first value.
1585    if (arguments.length < 2) {
1586      return first(function() {
1587        return this[name];
1588      });
1589    }
1590
1591    /** @this {Element} */
1592    function propertyNull() {
1593      delete this[name];
1594    }
1595
1596    /** @this {Element} */
1597    function propertyConstant() {
1598      this[name] = value;
1599    }
1600
1601    /** @this {Element} */
1602    function propertyFunction() {
1603      var x = value.apply(this, arguments);
1604      if (x == null) delete this[name];
1605      else this[name] = x;
1606    }
1607
1608    return groups.each(value == null
1609        ? propertyNull : (typeof value === "function"
1610        ? propertyFunction : propertyConstant));
1611  };
1612
1613  groups.text = function(value) {
1614
1615    // If no value is specified, return the first value.
1616    if (arguments.length < 1) {
1617      return first(function() {
1618        return this.textContent;
1619      });
1620    }
1621
1622    /** @this {Element} */
1623    function textConstant() {
1624      this.textContent = value;
1625    }
1626
1627    /** @this {Element} */
1628    function textFunction() {
1629      this.textContent = value.apply(this, arguments);
1630    }
1631
1632    return groups.each(typeof value === "function"
1633        ? textFunction : textConstant);
1634  };
1635
1636  groups.html = function(value) {
1637
1638    // If no value is specified, return the first value.
1639    if (arguments.length < 1) {
1640      return first(function() {
1641        return this.innerHTML;
1642      });
1643    }
1644
1645    /** @this {Element} */
1646    function htmlConstant() {
1647      this.innerHTML = value;
1648    }
1649
1650    /** @this {Element} */
1651    function htmlFunction() {
1652      this.innerHTML = value.apply(this, arguments);
1653    }
1654
1655    return groups.each(typeof value === "function"
1656        ? htmlFunction : htmlConstant);
1657  };
1658
1659  // TODO append(node)?
1660  // TODO append(function)?
1661  groups.append = function(name) {
1662    name = d3.ns.qualify(name);
1663
1664    function append(node) {
1665      return node.appendChild(document.createElement(name));
1666    }
1667
1668    function appendNS(node) {
1669      return node.appendChild(document.createElementNS(name.space, name.local));
1670    }
1671
1672    return select(name.local ? appendNS : append);
1673  };
1674
1675  // TODO insert(node, function)?
1676  // TODO insert(function, string)?
1677  // TODO insert(function, function)?
1678  groups.insert = function(name, before) {
1679    name = d3.ns.qualify(name);
1680
1681    function insert(node) {
1682      return node.insertBefore(
1683          document.createElement(name),
1684          d3_select(before, node));
1685    }
1686
1687    function insertNS(node) {
1688      return node.insertBefore(
1689          document.createElementNS(name.space, name.local),
1690          d3_select(before, node));
1691    }
1692
1693    return select(name.local ? insertNS : insert);
1694  };
1695
1696  // TODO remove(selector)?
1697  // TODO remove(node)?
1698  // TODO remove(function)?
1699  groups.remove = function() {
1700    return groups.each(function() {
1701      var parent = this.parentNode;
1702      if (parent) parent.removeChild(this);
1703    });
1704  };
1705
1706  groups.sort = function(comparator) {
1707    comparator = d3_selection_comparator.apply(this, arguments);
1708    for (var j = 0, m = groups.length; j < m; j++) {
1709      var group = groups[j];
1710      group.sort(comparator);
1711      for (var i = 1, n = group.length, prev = group[0]; i < n; i++) {
1712        var node = group[i];
1713        if (node) {
1714          if (prev) prev.parentNode.insertBefore(node, prev.nextSibling);
1715          prev = node;
1716        }
1717      }
1718    }
1719    return groups;
1720  };
1721
1722  // type can be namespaced, e.g., "click.foo"
1723  // listener can be null for removal
1724  groups.on = function(type, listener, capture) {
1725    if (arguments.length < 3) capture = false;
1726
1727    // parse the type specifier
1728    var i = type.indexOf("."),
1729        typo = i === -1 ? type : type.substring(0, i),
1730        name = "__on" + type;
1731
1732    // remove the old event listener, and add the new event listener
1733    return groups.each(function(d, i) {
1734      if (this[name]) this.removeEventListener(typo, this[name], capture);
1735      if (listener) this.addEventListener(typo, this[name] = l, capture);
1736
1737      // wrapped event listener that preserves i
1738      var node = this;
1739      function l(e) {
1740        var o = d3.event; // Events can be reentrant (e.g., focus).
1741        d3.event = e;
1742        try {
1743          listener.call(this, node.__data__, i);
1744        } finally {
1745          d3.event = o;
1746        }
1747      }
1748    });
1749  };
1750
1751  // TODO slice?
1752
1753  groups.transition = function() {
1754    return d3_transition(groups);
1755  };
1756
1757  groups.call = d3_call;
1758
1759  return groups;
1760}
1761
1762function d3_selectionEnter(groups) {
1763
1764  function select(select) {
1765    var subgroups = [],
1766        subgroup,
1767        subnode,
1768        group,
1769        node;
1770    for (var j = 0, m = groups.length; j < m; j++) {
1771      group = groups[j];
1772      subgroups.push(subgroup = []);
1773      subgroup.parentNode = group.parentNode;
1774      for (var i = 0, n = group.length; i < n; i++) {
1775        if (node = group[i]) {
1776          subgroup.push(subnode = select(group.parentNode));
1777          subnode.__data__ = node.__data__;
1778        } else {
1779          subgroup.push(null);
1780        }
1781      }
1782    }
1783    return d3_selection(subgroups);
1784  }
1785
1786  // TODO append(node)?
1787  // TODO append(function)?
1788  groups.append = function(name) {
1789    name = d3.ns.qualify(name);
1790
1791    function append(node) {
1792      return node.appendChild(document.createElement(name));
1793    }
1794
1795    function appendNS(node) {
1796      return node.appendChild(document.createElementNS(name.space, name.local));
1797    }
1798
1799    return select(name.local ? appendNS : append);
1800  };
1801
1802  // TODO insert(node, function)?
1803  // TODO insert(function, string)?
1804  // TODO insert(function, function)?
1805  groups.insert = function(name, before) {
1806    name = d3.ns.qualify(name);
1807
1808    function insert(node) {
1809      return node.insertBefore(
1810          document.createElement(name),
1811          d3_select(before, node));
1812    }
1813
1814    function insertNS(node) {
1815      return node.insertBefore(
1816          document.createElementNS(name.space, name.local),
1817          d3_select(before, node));
1818    }
1819
1820    return select(name.local ? insertNS : insert);
1821  };
1822
1823  return groups;
1824}
1825
1826function d3_selection_comparator(comparator) {
1827  if (!arguments.length) comparator = d3.ascending;
1828  return function(a, b) {
1829    return comparator(a && a.__data__, b && b.__data__);
1830  };
1831}
1832
1833function d3_selection_enterNode(data) {
1834  return {__data__: data};
1835}
1836d3.transition = d3_root.transition;
1837
1838var d3_transitionId = 0,
1839    d3_transitionInheritId = 0;
1840
1841function d3_transition(groups) {
1842  var transition = {},
1843      transitionId = d3_transitionInheritId || ++d3_transitionId,
1844      tweens = {},
1845      interpolators = [],
1846      remove = false,
1847      event = d3.dispatch("start", "end"),
1848      stage = [],
1849      delay = [],
1850      duration = [],
1851      durationMax,
1852      ease = d3.ease("cubic-in-out");
1853
1854  //
1855  // Be careful with concurrent transitions!
1856  //
1857  // Say transition A causes an exit. Before A finishes, a transition B is
1858  // created, and believes it only needs to do an update, because the elements
1859  // haven't been removed yet (which happens at the very end of the exit
1860  // transition).
1861  //
1862  // Even worse, what if either transition A or B has a staggered delay? Then,
1863  // some elements may be removed, while others remain. Transition B does not
1864  // know to enter the elements because they were still present at the time
1865  // the transition B was created (but not yet started).
1866  //
1867  // To prevent such confusion, we only trigger end events for transitions if
1868  // the transition ending is the only one scheduled for the given element.
1869  // Similarly, we only allow one transition to be active for any given
1870  // element, so that concurrent transitions do not overwrite each other's
1871  // properties.
1872  //
1873  // TODO Support transition namespaces, so that transitions can proceed
1874  // concurrently on the same element if needed. Hopefully, this is rare!
1875  //
1876
1877  groups.each(function() {
1878    (this.__transition__ || (this.__transition__ = {})).owner = transitionId;
1879  });
1880
1881  function step(elapsed) {
1882    var clear = true,
1883        k = -1;
1884    groups.each(function() {
1885      if (stage[++k] === 2) return; // ended
1886      var t = (elapsed - delay[k]) / duration[k],
1887          tx = this.__transition__,
1888          te, // ease(t)
1889          tk, // tween key
1890          ik = interpolators[k];
1891
1892      // Check if the (un-eased) time is outside the range [0,1].
1893      if (t < 1) {
1894        clear = false;
1895        if (t < 0) return;
1896      } else {
1897        t = 1;
1898      }
1899
1900      // Determine the stage of this transition.
1901      // 0 - Not yet started.
1902      // 1 - In progress.
1903      // 2 - Ended.
1904      if (stage[k]) {
1905        if (!tx || tx.active !== transitionId) {
1906          stage[k] = 2;
1907          return;
1908        }
1909      } else if (!tx || tx.active > transitionId) {
1910        stage[k] = 2;
1911        return;
1912      } else {
1913        stage[k] = 1;
1914        event.start.dispatch.apply(this, arguments);
1915        ik = interpolators[k] = {};
1916        tx.active = transitionId;
1917        for (tk in tweens) {
1918          if (te = tweens[tk].apply(this, arguments)) {
1919            ik[tk] = te;
1920          }
1921        }
1922      }
1923
1924      // Apply the interpolators!
1925      te = ease(t);
1926      for (tk in ik) ik[tk].call(this, te);
1927
1928      // Handle ending transitions.
1929      if (t === 1) {
1930        stage[k] = 2;
1931        if (tx.active === transitionId) {
1932          var owner = tx.owner;
1933          if (owner === transitionId) {
1934            delete this.__transition__;
1935            if (remove && this.parentNode) this.parentNode.removeChild(this);
1936          }
1937          d3_transitionInheritId = transitionId;
1938          event.end.dispatch.apply(this, arguments);
1939          d3_transitionInheritId = 0;
1940          tx.owner = owner;
1941        }
1942      }
1943    });
1944    return clear;
1945  }
1946
1947  transition.delay = function(value) {
1948    var delayMin = Infinity,
1949        k = -1;
1950    if (typeof value === "function") {
1951      groups.each(function(d, i) {
1952        var x = delay[++k] = +value.apply(this, arguments);
1953        if (x < delayMin) delayMin = x;
1954      });
1955    } else {
1956      delayMin = +value;
1957      groups.each(function(d, i) {
1958        delay[++k] = delayMin;
1959      });
1960    }
1961    d3_timer(step, delayMin);
1962    return transition;
1963  };
1964
1965  transition.duration = function(value) {
1966    var k = -1;
1967    if (typeof value === "function") {
1968      durationMax = 0;
1969      groups.each(function(d, i) {
1970        var x = duration[++k] = +value.apply(this, arguments);
1971        if (x > durationMax) durationMax = x;
1972      });
1973    } else {
1974      durationMax = +value;
1975      groups.each(function(d, i) {
1976        duration[++k] = durationMax;
1977      });
1978    }
1979    return transition;
1980  };
1981
1982  transition.ease = function(value) {
1983    ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments);
1984    return transition;
1985  };
1986
1987  transition.attrTween = function(name, tween) {
1988
1989    /** @this {Element} */
1990    function attrTween(d, i) {
1991      var f = tween.call(this, d, i, this.getAttribute(name));
1992      return f && function(t) {
1993        this.setAttribute(name, f(t));
1994      };
1995    }
1996
1997    /** @this {Element} */
1998    function attrTweenNS(d, i) {
1999      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
2000      return f && function(t) {
2001        this.setAttributeNS(name.space, name.local, f(t));
2002      };
2003    }
2004
2005    tweens["attr." + name] = name.local ? attrTweenNS : attrTween;
2006    return transition;
2007  };
2008
2009  transition.attr = function(name, value) {
2010    return transition.attrTween(name, d3_transitionTween(value));
2011  };
2012
2013  transition.styleTween = function(name, tween, priority) {
2014    if (arguments.length < 3) priority = null;
2015
2016    /** @this {Element} */
2017    function styleTween(d, i) {
2018      var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
2019      return f && function(t) {
2020        this.style.setProperty(name, f(t), priority);
2021      };
2022    }
2023
2024    tweens["style." + name] = styleTween;
2025    return transition;
2026  };
2027
2028  transition.style = function(name, value, priority) {
2029    if (arguments.length < 3) priority = null;
2030    return transition.styleTween(name, d3_transitionTween(value), priority);
2031  };
2032
2033  transition.text = function(value) {
2034    tweens.text = function(d, i) {
2035      this.textContent = typeof value === "function"
2036          ? value.call(this, d, i)
2037          : value;
2038    };
2039    return transition;
2040  };
2041
2042  transition.select = function(query) {
2043    var k, t = d3_transition(groups.select(query)).ease(ease);
2044    k = -1; t.delay(function(d, i) { return delay[++k]; });
2045    k = -1; t.duration(function(d, i) { return duration[++k]; });
2046    return t;
2047  };
2048
2049  transition.selectAll = function(query) {
2050    var k, t = d3_transition(groups.selectAll(query)).ease(ease);
2051    k = -1; t.delay(function(d, i) { return delay[i ? k : ++k]; })
2052    k = -1; t.duration(function(d, i) { return duration[i ? k : ++k]; });
2053    return t;
2054  };
2055
2056  transition.remove = function() {
2057    remove = true;
2058    return transition;
2059  };
2060
2061  transition.each = function(type, listener) {
2062    event[type].add(listener);
2063    return transition;
2064  };
2065
2066  transition.call = d3_call;
2067
2068  return transition.delay(0).duration(250);
2069}
2070
2071function d3_transitionTween(b) {
2072  return typeof b === "function"
2073      ? function(d, i, a) { var v = b.call(this, d, i) + ""; return a != v && d3.interpolate(a, v); }
2074      : (b = b + "", function(d, i, a) { return a != b && d3.interpolate(a, b); });
2075}
2076var d3_timer_queue = null,
2077    d3_timer_interval, // is an interval (or frame) active?
2078    d3_timer_timeout; // is a timeout active?
2079
2080// The timer will continue to fire until callback returns true.
2081d3.timer = function(callback) {
2082  d3_timer(callback, 0);
2083};
2084
2085function d3_timer(callback, delay) {
2086  var now = Date.now(),
2087      found = false,
2088      t0,
2089      t1 = d3_timer_queue;
2090
2091  if (!isFinite(delay)) return;
2092
2093  // See if the callback's already in the queue.
2094  while (t1) {
2095    if (t1.callback === callback) {
2096      t1.then = now;
2097      t1.delay = delay;
2098      found = true;
2099      break;
2100    }
2101    t0 = t1;
2102    t1 = t1.next;
2103  }
2104
2105  // Otherwise, add the callback to the queue.
2106  if (!found) d3_timer_queue = {
2107    callback: callback,
2108    then: now,
2109    delay: delay,
2110    next: d3_timer_queue
2111  };
2112
2113  // Start animatin'!
2114  if (!d3_timer_interval) {
2115    d3_timer_timeout = clearTimeout(d3_timer_timeout);
2116    d3_timer_interval = 1;
2117    d3_timer_frame(d3_timer_step);
2118  }
2119}
2120
2121function d3_timer_step() {
2122  var elapsed,
2123      now = Date.now(),
2124      t1 = d3_timer_queue;
2125
2126  while (t1) {
2127    elapsed = now - t1.then;
2128    if (elapsed > t1.delay) t1.flush = t1.callback(elapsed);
2129    t1 = t1.next;
2130  }
2131
2132  var delay = d3_timer_flush() - now;
2133  if (delay > 24) {
2134    if (isFinite(delay)) {
2135      clearTimeout(d3_timer_timeout);
2136      d3_timer_timeout = setTimeout(d3_timer_step, delay);
2137    }
2138    d3_timer_interval = 0;
2139  } else {
2140    d3_timer_interval = 1;
2141    d3_timer_frame(d3_timer_step);
2142  }
2143}
2144
2145d3.timer.flush = function() {
2146  var elapsed,
2147      now = Date.now(),
2148      t1 = d3_timer_queue;
2149
2150  while (t1) {
2151    elapsed = now - t1.then;
2152    if (!t1.delay) t1.flush = t1.callback(elapsed);
2153    t1 = t1.next;
2154  }
2155
2156  d3_timer_flush();
2157};
2158
2159// Flush after callbacks, to avoid concurrent queue modification.
2160function d3_timer_flush() {
2161  var t0 = null,
2162      t1 = d3_timer_queue,
2163      then = Infinity;
2164  while (t1) {
2165    if (t1.flush) {
2166      t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
2167    } else {
2168      then = Math.min(then, t1.then + t1.delay);
2169      t1 = (t0 = t1).next;
2170    }
2171  }
2172  return then;
2173}
2174
2175var d3_timer_frame = window.requestAnimationFrame
2176    || window.webkitRequestAnimationFrame
2177    || window.mozRequestAnimationFrame
2178    || window.oRequestAnimationFrame
2179    || window.msRequestAnimationFrame
2180    || function(callback) { setTimeout(callback, 17); };
2181function d3_noop() {}
2182d3.scale = {};
2183
2184function d3_scaleExtent(domain) {
2185  var start = domain[0], stop = domain[domain.length - 1];
2186  return start < stop ? [start, stop] : [stop, start];
2187}
2188function d3_scale_nice(domain, nice) {
2189  var i0 = 0,
2190      i1 = domain.length - 1,
2191      x0 = domain[i0],
2192      x1 = domain[i1],
2193      dx;
2194
2195  if (x1 < x0) {
2196    dx = i0; i0 = i1; i1 = dx;
2197    dx = x0; x0 = x1; x1 = dx;
2198  }
2199
2200  nice = nice(x1 - x0);
2201  domain[i0] = nice.floor(x0);
2202  domain[i1] = nice.ceil(x1);
2203  return domain;
2204}
2205
2206function d3_scale_niceDefault() {
2207  return Math;
2208}
2209d3.scale.linear = function() {
2210  var domain = [0, 1],
2211      range = [0, 1],
2212      interpolate = d3.interpolate,
2213      clamp = false,
2214      output,
2215      input;
2216
2217  function rescale() {
2218    var linear = domain.length == 2 ? d3_scale_bilinear : d3_scale_polylinear,
2219        uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
2220    output = linear(domain, range, uninterpolate, interpolate);
2221    input = linear(range, domain, uninterpolate, d3.interpolate);
2222    return scale;
2223  }
2224
2225  function scale(x) {
2226    return output(x);
2227  }
2228
2229  // Note: requires range is coercible to number!
2230  scale.invert = function(y) {
2231    return input(y);
2232  };
2233
2234  scale.domain = function(x) {
2235    if (!arguments.length) return domain;
2236    domain = x.map(Number);
2237    return rescale();
2238  };
2239
2240  scale.range = function(x) {
2241    if (!arguments.length) return range;
2242    range = x;
2243    return rescale();
2244  };
2245
2246  scale.rangeRound = function(x) {
2247    return scale.range(x).interpolate(d3.interpolateRound);
2248  };
2249
2250  scale.clamp = function(x) {
2251    if (!arguments.length) return clamp;
2252    clamp = x;
2253    return rescale();
2254  };
2255
2256  scale.interpolate = function(x) {
2257    if (!arguments.length) return interpolate;
2258    interpolate = x;
2259    return rescale();
2260  };
2261
2262  scale.ticks = function(m) {
2263    return d3_scale_linearTicks(domain, m);
2264  };
2265
2266  scale.tickFormat = function(m) {
2267    return d3_scale_linearTickFormat(domain, m);
2268  };
2269
2270  scale.nice = function() {
2271    d3_scale_nice(domain, d3_scale_linearNice);
2272    return rescale();
2273  };
2274
2275  return rescale();
2276};
2277
2278function d3_scale_linearRebind(scale, linear) {
2279  scale.range = d3.rebind(scale, linear.range);
2280  scale.rangeRound = d3.rebind(scale, linear.rangeRound);
2281  scale.interpolate = d3.rebind(scale, linear.interpolate);
2282  scale.clamp = d3.rebind(scale, linear.clamp);
2283  return scale;
2284}
2285
2286function d3_scale_linearNice(dx) {
2287  dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
2288  return {
2289    floor: function(x) { return Math.floor(x / dx) * dx; },
2290    ceil: function(x) { return Math.ceil(x / dx) * dx; }
2291  };
2292}
2293
2294// TODO Dates? Ugh.
2295function d3_scale_linearTickRange(domain, m) {
2296  var extent = d3_scaleExtent(domain),
2297      span = extent[1] - extent[0],
2298      step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)),
2299      err = m / span * step;
2300
2301  // Filter ticks to get closer to the desired count.
2302  if (err <= .15) step *= 10;
2303  else if (err <= .35) step *= 5;
2304  else if (err <= .75) step *= 2;
2305
2306  // Round start and stop values to step interval.
2307  extent[0] = Math.ceil(extent[0] / step) * step;
2308  extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive
2309  extent[2] = step;
2310  return extent;
2311}
2312
2313function d3_scale_linearTicks(domain, m) {
2314  return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
2315}
2316
2317function d3_scale_linearTickFormat(domain, m) {
2318  return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f");
2319}
2320function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
2321  var u = uninterpolate(domain[0], domain[1]),
2322      i = interpolate(range[0], range[1]);
2323  return function(x) {
2324    return i(u(x));
2325  };
2326}
2327function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
2328  var u = [],
2329      i = [],
2330      j = 0,
2331      n = domain.length;
2332
2333  while (++j < n) {
2334    u.push(uninterpolate(domain[j - 1], domain[j]));
2335    i.push(interpolate(range[j - 1], range[j]));
2336  }
2337
2338  return function(x) {
2339    var j = d3.bisect(domain, x, 1, domain.length - 1) - 1;
2340    return i[j](u[j](x));
2341  };
2342}
2343d3.scale.log = function() {
2344  var linear = d3.scale.linear(),
2345      log = d3_scale_log,
2346      pow = log.pow;
2347
2348  function scale(x) {
2349    return linear(log(x));
2350  }
2351
2352  scale.invert = function(x) {
2353    return pow(linear.invert(x));
2354  };
2355
2356  scale.domain = function(x) {
2357    if (!arguments.length) return linear.domain().map(pow);
2358    log = x[0] < 0 ? d3_scale_logn : d3_scale_log;
2359    pow = log.pow;
2360    linear.domain(x.map(log));
2361    return scale;
2362  };
2363
2364  scale.nice = function() {
2365    linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
2366    return scale;
2367  };
2368
2369  scale.ticks = function() {
2370    var extent = d3_scaleExtent(linear.domain()),
2371        ticks = [];
2372    if (extent.every(isFinite)) {
2373      var i = Math.floor(extent[0]),
2374          j = Math.ceil(extent[1]),
2375          u = pow(extent[0]),
2376          v = pow(extent[1]);
2377      if (log === d3_scale_logn) {
2378        ticks.push(pow(i));
2379        for (; i++ < j;) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
2380      } else {
2381        for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);
2382        ticks.push(pow(i));
2383      }
2384      for (i = 0; ticks[i] < u; i++) {} // strip small values
2385      for (j = ticks.length; ticks[j - 1] > v; j--) {} // strip big values
2386      ticks = ticks.slice(i, j);
2387    }
2388    return ticks;
2389  };
2390
2391  scale.tickFormat = function() {
2392    return d3_scale_logTickFormat;
2393  };
2394
2395  return d3_scale_linearRebind(scale, linear);
2396};
2397
2398function d3_scale_log(x) {
2399  return Math.log(x) / Math.LN10;
2400}
2401
2402function d3_scale_logn(x) {
2403  return -Math.log(-x) / Math.LN10;
2404}
2405
2406d3_scale_log.pow = function(x) {
2407  return Math.pow(10, x);
2408};
2409
2410d3_scale_logn.pow = function(x) {
2411  return -Math.pow(10, -x);
2412};
2413
2414function d3_scale_logTickFormat(d) {
2415  return d.toPrecision(1);
2416}
2417d3.scale.pow = function() {
2418  var linear = d3.scale.linear(),
2419      exponent = 1,
2420      powp = Number,
2421      powb = powp;
2422
2423  function scale(x) {
2424    return linear(powp(x));
2425  }
2426
2427  scale.invert = function(x) {
2428    return powb(linear.invert(x));
2429  };
2430
2431  scale.domain = function(x) {
2432    if (!arguments.length) return linear.domain().map(powb);
2433    powp = d3_scale_powPow(exponent);
2434    powb = d3_scale_powPow(1 / exponent);
2435    linear.domain(x.map(powp));
2436    return scale;
2437  };
2438
2439  scale.ticks = function(m) {
2440    return d3_scale_linearTicks(scale.domain(), m);
2441  };
2442
2443  scale.tickFormat = function(m) {
2444    return d3_scale_linearTickFormat(scale.domain(), m);
2445  };
2446
2447  scale.nice = function() {
2448    return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
2449  };
2450
2451  scale.exponent = function(x) {
2452    if (!arguments.length) return exponent;
2453    var domain = scale.domain();
2454    exponent = x;
2455    return scale.domain(domain);
2456  };
2457
2458  return d3_scale_linearRebind(scale, linear);
2459};
2460
2461function d3_scale_powPow(e) {
2462  return function(x) {
2463    return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
2464  };
2465}
2466d3.scale.sqrt = function() {
2467  return d3.scale.pow().exponent(.5);
2468};
2469d3.scale.ordinal = function() {
2470  var domain = [],
2471      index = {},
2472      range = [],
2473      rangeBand = 0,
2474      rerange = d3_noop;
2475
2476  function scale(x) {
2477    var i = x in index ? index[x] : (index[x] = domain.push(x) - 1);
2478    return range[i % range.length];
2479  }
2480
2481  scale.domain = function(x) {
2482    if (!arguments.length) return domain;
2483    domain = x;
2484    index = {};
2485    var i = -1, j = -1, n = domain.length; while (++i < n) {
2486      x = domain[i];
2487      if (!(x in index)) index[x] = ++j;
2488    }
2489    rerange();
2490    return scale;
2491  };
2492
2493  scale.range = function(x) {
2494    if (!arguments.length) return range;
2495    range = x;
2496    rerange = d3_noop;
2497    return scale;
2498  };
2499
2500  scale.rangePoints = function(x, padding) {
2501    if (arguments.length < 2) padding = 0;
2502    (rerange = function() {
2503      var start = x[0],
2504          stop = x[1],
2505          step = (stop - start) / (domain.length - 1 + padding);
2506      range = domain.length == 1
2507          ? [(start + stop) / 2]
2508          : d3.range(start + step * padding / 2, stop + step / 2, step);
2509      rangeBand = 0;
2510    })();
2511    return scale;
2512  };
2513
2514  scale.rangeBands = function(x, padding) {
2515    if (arguments.length < 2) padding = 0;
2516    (rerange = function() {
2517      var start = x[0],
2518          stop = x[1],
2519          step = (stop - start) / (domain.length + padding);
2520      range = d3.range(start + step * padding, stop, step);
2521      rangeBand = step * (1 - padding);
2522    })();
2523    return scale;
2524  };
2525
2526  scale.rangeRoundBands = function(x, padding) {
2527    if (arguments.length < 2) padding = 0;
2528    (rerange = function() {
2529      var start = x[0],
2530          stop = x[1],
2531          diff = stop - start,
2532          step = Math.floor(diff / (domain.length + padding)),
2533          err = diff - (domain.length - padding) * step;
2534      range = d3.range(start + Math.round(err / 2), stop, step);
2535      rangeBand = Math.round(step * (1 - padding));
2536    })();
2537    return scale;
2538  };
2539
2540  scale.rangeBand = function() {
2541    return rangeBand;
2542  };
2543
2544  return scale;
2545};
2546/*
2547 * This product includes color specifications and designs developed by Cynthia
2548 * Brewer (http://colorbrewer.org/). See lib/colorbrewer for more information.
2549 */
2550
2551d3.scale.category10 = function() {
2552  return d3.scale.ordinal().range(d3_category10);
2553};
2554
2555d3.scale.category20 = function() {
2556  return d3.scale.ordinal().range(d3_category20);
2557};
2558
2559d3.scale.category20b = function() {
2560  return d3.scale.ordinal().range(d3_category20b);
2561};
2562
2563d3.scale.category20c = function() {
2564  return d3.scale.ordinal().range(d3_category20c);
2565};
2566
2567var d3_category10 = [
2568  "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
2569  "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"
2570];
2571
2572var d3_category20 = [
2573  "#1f77b4", "#aec7e8",
2574  "#ff7f0e", "#ffbb78",
2575  "#2ca02c", "#98df8a",
2576  "#d62728", "#ff9896",
2577  "#9467bd", "#c5b0d5",
2578  "#8c564b", "#c49c94",
2579  "#e377c2", "#f7b6d2",
2580  "#7f7f7f", "#c7c7c7",
2581  "#bcbd22", "#dbdb8d",
2582  "#17becf", "#9edae5"
2583];
2584
2585var d3_category20b = [
2586  "#393b79", "#5254a3", "#6b6ecf", "#9c9ede",
2587  "#637939", "#8ca252", "#b5cf6b", "#cedb9c",
2588  "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94",
2589  "#843c39", "#ad494a", "#d6616b", "#e7969c",
2590  "#7b4173", "#a55194", "#ce6dbd", "#de9ed6"
2591];
2592
2593var d3_category20c = [
2594  "#3182bd", "#6baed6", "#9ecae1", "#c6dbef",
2595  "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2",
2596  "#31a354", "#74c476", "#a1d99b", "#c7e9c0",
2597  "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb",
2598  "#636363", "#969696", "#bdbdbd", "#d9d9d9"
2599];
2600d3.scale.quantile = function() {
2601  var domain = [],
2602      range = [],
2603      thresholds = [];
2604
2605  function rescale() {
2606    var k = 0,
2607        n = domain.length,
2608        q = range.length;
2609    thresholds.length = Math.max(0, q - 1);
2610    while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
2611  }
2612
2613  function scale(x) {
2614    if (isNaN(x = +x)) return NaN;
2615    return range[d3.bisect(thresholds, x)];
2616  }
2617
2618  scale.domain = function(x) {
2619    if (!arguments.length) return domain;
2620    domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending);
2621    rescale();
2622    return scale;
2623  };
2624
2625  scale.range = function(x) {
2626    if (!arguments.length) return range;
2627    range = x;
2628    rescale();
2629    return scale;
2630  };
2631
2632  scale.quantiles = function() {
2633    return thresholds;
2634  };
2635
2636  return scale;
2637};
2638d3.scale.quantize = function() {
2639  var x0 = 0,
2640      x1 = 1,
2641      kx = 2,
2642      i = 1,
2643      range = [0, 1];
2644
2645  function scale(x) {
2646    return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
2647  }
2648
2649  scale.domain = function(x) {
2650    if (!arguments.length) return [x0, x1];
2651    x0 = x[0];
2652    x1 = x[1];
2653    kx = range.length / (x1 - x0);
2654    return scale;
2655  };
2656
2657  scale.range = function(x) {
2658    if (!arguments.length) return range;
2659    range = x;
2660    kx = range.length / (x1 - x0);
2661    i = range.length - 1;
2662    return scale;
2663  };
2664
2665  return scale;
2666};
2667d3.svg = {};
2668d3.svg.arc = function() {
2669  var innerRadius = d3_svg_arcInnerRadius,
2670      outerRadius = d3_svg_arcOuterRadius,
2671      startAngle = d3_svg_arcStartAngle,
2672      endAngle = d3_svg_arcEndAngle;
2673
2674  function arc() {
2675    var r0 = innerRadius.apply(this, arguments),
2676        r1 = outerRadius.apply(this, arguments),
2677        a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset,
2678        a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset,
2679        da = a1 - a0,
2680        df = da < Math.PI ? "0" : "1",
2681        c0 = Math.cos(a0),
2682        s0 = Math.sin(a0),
2683        c1 = Math.cos(a1),
2684        s1 = Math.sin(a1);
2685    return da >= d3_svg_arcMax
2686      ? (r0
2687      ? "M0," + r1
2688      + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
2689      + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
2690      + "M0," + r0
2691      + "A" + r0 + "," + r0 + " 0 1,1 0," + (-r0)
2692      + "A" + r0 + "," + r0 + " 0 1,1 0," + r0
2693      + "Z"
2694      : "M0," + r1
2695      + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
2696      + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
2697      + "Z")
2698      : (r0
2699      ? "M" + r1 * c0 + "," + r1 * s0
2700      + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1
2701      + "L" + r0 * c1 + "," + r0 * s1
2702      + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0
2703      + "Z"
2704      : "M" + r1 * c0 + "," + r1 * s0
2705      + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1
2706      + "L0,0"
2707      + "Z");
2708  }
2709
2710  arc.innerRadius = function(v) {
2711    if (!arguments.length) return innerRadius;
2712    innerRadius = d3.functor(v);
2713    return arc;
2714  };
2715
2716  arc.outerRadius = function(v) {
2717    if (!arguments.length) return outerRadius;
2718    outerRadius = d3.functor(v);
2719    return arc;
2720  };
2721
2722  arc.startAngle = function(v) {
2723    if (!arguments.length) return startAngle;
2724    startAngle = d3.functor(v);
2725    return arc;
2726  };
2727
2728  arc.endAngle = function(v) {
2729    if (!arguments.length) return endAngle;
2730    endAngle = d3.functor(v);
2731    return arc;
2732  };
2733
2734  arc.centroid = function() {
2735    var r = (innerRadius.apply(this, arguments)
2736        + outerRadius.apply(this, arguments)) / 2,
2737        a = (startAngle.apply(this, arguments)
2738        + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
2739    return [Math.cos(a) * r, Math.sin(a) * r];
2740  };
2741
2742  return arc;
2743};
2744
2745var d3_svg_arcOffset = -Math.PI / 2,
2746    d3_svg_arcMax = 2 * Math.PI - 1e-6;
2747
2748function d3_svg_arcInnerRadius(d) {
2749  return d.innerRadius;
2750}
2751
2752function d3_svg_arcOuterRadius(d) {
2753  return d.outerRadius;
2754}
2755
2756function d3_svg_arcStartAngle(d) {
2757  return d.startAngle;
2758}
2759
2760function d3_svg_arcEndAngle(d) {
2761  return d.endAngle;
2762}
2763function d3_svg_line(projection) {
2764  var x = d3_svg_lineX,
2765      y = d3_svg_lineY,
2766      interpolate = "linear",
2767      interpolator = d3_svg_lineInterpolators[interpolate],
2768      tension = .7;
2769
2770  function line(d) {
2771    return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension);
2772  }
2773
2774  line.x = function(v) {
2775    if (!arguments.length) return x;
2776    x = v;
2777    return line;
2778  };
2779
2780  line.y = function(v) {
2781    if (!arguments.length) return y;
2782    y = v;
2783    return line;
2784  };
2785
2786  line.interpolate = function(v) {
2787    if (!arguments.length) return interpolate;
2788    interpolator = d3_svg_lineInterpolators[interpolate = v];
2789    return line;
2790  };
2791
2792  line.tension = function(v) {
2793    if (!arguments.length) return tension;
2794    tension = v;
2795    return line;
2796  };
2797
2798  return line;
2799}
2800
2801d3.svg.line = function() {
2802  return d3_svg_line(Object);
2803};
2804
2805// Converts the specified array of data into an array of points
2806// (x-y tuples), by evaluating the specified `x` and `y` functions on each
2807// data point. The `this` context of the evaluated functions is the specified
2808// "self" object; each function is passed the current datum and index.
2809function d3_svg_linePoints(self, d, x, y) {
2810  var points = [],
2811      i = -1,
2812      n = d.length,
2813      fx = typeof x === "function",
2814      fy = typeof y === "function",
2815      value;
2816  if (fx && fy) {
2817    while (++i < n) points.push([
2818      x.call(self, value = d[i], i),
2819      y.call(self, value, i)
2820    ]);
2821  } else if (fx) {
2822    while (++i < n) points.push([x.call(self, d[i], i), y]);
2823  } else if (fy) {
2824    while (++i < n) points.push([x, y.call(self, d[i], i)]);
2825  } else {
2826    while (++i < n) points.push([x, y]);
2827  }
2828  return points;
2829}
2830
2831// The default `x` property, which references d[0].
2832function d3_svg_lineX(d) {
2833  return d[0];
2834}
2835
2836// The default `y` property, which references d[1].
2837function d3_svg_lineY(d) {
2838  return d[1];
2839}
2840
2841// The various interpolators supported by the `line` class.
2842var d3_svg_lineInterpolators = {
2843  "linear": d3_svg_lineLinear,
2844  "step-before": d3_svg_lineStepBefore,
2845  "step-after": d3_svg_lineStepAfter,
2846  "basis": d3_svg_lineBasis,
2847  "basis-open": d3_svg_lineBasisOpen,
2848  "basis-closed": d3_svg_lineBasisClosed,
2849  "bundle": d3_svg_lineBundle,
2850  "cardinal": d3_svg_lineCardinal,
2851  "cardinal-open": d3_svg_lineCardinalOpen,
2852  "cardinal-closed": d3_svg_lineCardinalClosed,
2853  "monotone": d3_svg_lineMonotone
2854};
2855
2856// Linear interpolation; generates "L" commands.
2857function d3_svg_lineLinear(points) {
2858  var path = [],
2859      i = 0,
2860      n = points.length,
2861      p = points[0];
2862  path.push(p[0], ",", p[1]);
2863  while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]);
2864  return path.join("");
2865}
2866
2867// Step interpolation; generates "H" and "V" commands.
2868function d3_svg_lineStepBefore(points) {
2869  var path = [],
2870      i = 0,
2871      n = points.length,
2872      p = points[0];
2873  path.push(p[0], ",", p[1]);
2874  while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
2875  return path.join("");
2876}
2877
2878// Step interpolation; generates "H" and "V" commands.
2879function d3_svg_lineStepAfter(points) {
2880  var path = [],
2881      i = 0,
2882      n = points.length,
2883      p = points[0];
2884  path.push(p[0], ",", p[1]);
2885  while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
2886  return path.join("");
2887}
2888
2889// Open cardinal spline interpolation; generates "C" commands.
2890function d3_svg_lineCardinalOpen(points, tension) {
2891  return points.length < 4
2892      ? d3_svg_lineLinear(points)
2893      : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1),
2894        d3_svg_lineCardinalTangents(points, tension));
2895}
2896
2897// Closed cardinal spline interpolation; generates "C" commands.
2898function d3_svg_lineCardinalClosed(points, tension) {
2899  return points.length < 3
2900      ? d3_svg_lineLinear(points)
2901      : points[0] + d3_svg_lineHermite((points.push(points[0]), points),
2902        d3_svg_lineCardinalTangents([points[points.length - 2]]
2903        .concat(points, [points[1]]), tension));
2904}
2905
2906// Cardinal spline interpolation; generates "C" commands.
2907function d3_svg_lineCardinal(points, tension, closed) {
2908  return points.length < 3
2909      ? d3_svg_lineLinear(points)
2910      : points[0] + d3_svg_lineHermite(points,
2911        d3_svg_lineCardinalTangents(points, tension));
2912}
2913
2914// Hermite spline construction; generates "C" commands.
2915function d3_svg_lineHermite(points, tangents) {
2916  if (tangents.length < 1
2917      || (points.length != tangents.length
2918      && points.length != tangents.length + 2)) {
2919    return d3_svg_lineLinear(points);
2920  }
2921
2922  var quad = points.length != tangents.length,
2923      path = "",
2924      p0 = points[0],
2925      p = points[1],
2926      t0 = tangents[0],
2927      t = t0,
2928      pi = 1;
2929
2930  if (quad) {
2931    path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3)
2932        + "," + p[0] + "," + p[1];
2933    p0 = points[1];
2934    pi = 2;
2935  }
2936
2937  if (tangents.length > 1) {
2938    t = tangents[1];
2939    p = points[pi];
2940    pi++;
2941    path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1])
2942        + "," + (p[0] - t[0]) + "," + (p[1] - t[1])
2943        + "," + p[0] + "," + p[1];
2944    for (var i = 2; i < tangents.length; i++, pi++) {
2945      p = points[pi];
2946      t = tangents[i];
2947      path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1])
2948          + "," + p[0] + "," + p[1];
2949    }
2950  }
2951
2952  if (quad) {
2953    var lp = points[pi];
2954    path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3)
2955        + "," + lp[0] + "," + lp[1];
2956  }
2957
2958  return path;
2959}
2960
2961// Generates tangents for a cardinal spline.
2962function d3_svg_lineCardinalTangents(points, tension) {
2963  var tangents = [],
2964      a = (1 - tension) / 2,
2965      p0,
2966      p1 = points[0],
2967      p2 = points[1],
2968      i = 1,
2969      n = points.length;
2970  while (++i < n) {
2971    p0 = p1;
2972    p1 = p2;
2973    p2 = points[i];
2974    tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
2975  }
2976  return tangents;
2977}
2978
2979// B-spline interpolation; generates "C" commands.
2980function d3_svg_lineBasis(points) {
2981  if (points.length < 3) return d3_svg_lineLinear(points);
2982  var path = [],
2983      i = 1,
2984      n = points.length,
2985      pi = points[0],
2986      x0 = pi[0],
2987      y0 = pi[1],
2988      px = [x0, x0, x0, (pi = points[1])[0]],
2989      py = [y0, y0, y0, pi[1]];
2990  path.push(x0, ",", y0);
2991  d3_svg_lineBasisBezier(path, px, py);
2992  while (++i < n) {
2993    pi = points[i];
2994    px.shift(); px.push(pi[0]);
2995    py.shift(); py.push(pi[1]);
2996    d3_svg_lineBasisBezier(path, px, py);
2997  }
2998  i = -1;
2999  while (++i < 2) {
3000    px.shift(); px.push(pi[0]);
3001    py.shift(); py.push(pi[1]);
3002    d3_svg_lineBasisBezier(path, px, py);
3003  }
3004  return path.join("");
3005}
3006
3007// Open B-spline interpolation; generates "C" commands.
3008function d3_svg_lineBasisOpen(points) {
3009  if (points.length < 4) return d3_svg_lineLinear(points);
3010  var path = [],
3011      i = -1,
3012      n = points.length,
3013      pi,
3014      px = [0],
3015      py = [0];
3016  while (++i < 3) {
3017    pi = points[i];
3018    px.push(pi[0]);
3019    py.push(pi[1]);
3020  }
3021  path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px)
3022    + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
3023  --i; while (++i < n) {
3024    pi = points[i];
3025    px.shift(); px.push(pi[0]);
3026    py.shift(); py.push(pi[1]);
3027    d3_svg_lineBasisBezier(path, px, py);
3028  }
3029  return path.join("");
3030}
3031
3032// Closed B-spline interpolation; generates "C" commands.
3033function d3_svg_lineBasisClosed(points) {
3034  var path,
3035      i = -1,
3036      n = points.length,
3037      m = n + 4,
3038      pi,
3039      px = [],
3040      py = [];
3041  while (++i < 4) {
3042    pi = points[i % n];
3043    px.push(pi[0]);
3044    py.push(pi[1]);
3045  }
3046  path = [
3047    d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",",
3048    d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)
3049  ];
3050  --i; while (++i < m) {
3051    pi = points[i % n];
3052    px.shift(); px.push(pi[0]);
3053    py.shift(); py.push(pi[1]);
3054    d3_svg_lineBasisBezier(path, px, py);
3055  }
3056  return path.join("");
3057}
3058
3059function d3_svg_lineBundle(points, tension) {
3060  var n = points.length - 1,
3061      x0 = points[0][0],
3062      y0 = points[0][1],
3063      dx = points[n][0] - x0,
3064      dy = points[n][1] - y0,
3065      i = -1,
3066      p,
3067      t;
3068  while (++i <= n) {
3069    p = points[i];
3070    t = i / n;
3071    p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
3072    p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
3073  }
3074  return d3_svg_lineBasis(points);
3075}
3076
3077// Returns the dot product of the given four-element vectors.
3078function d3_svg_lineDot4(a, b) {
3079  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
3080}
3081
3082// Matrix to transform basis (b-spline) control points to bezier
3083// control points. Derived from FvD 11.2.8.
3084var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0],
3085    d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0],
3086    d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6];
3087
3088// Pushes a "C" Bézier curve onto the specified path array, given the
3089// two specified four-element arrays which define the control points.
3090function d3_svg_lineBasisBezier(path, x, y) {
3091  path.push(
3092      "C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x),
3093      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y),
3094      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x),
3095      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y),
3096      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x),
3097      ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
3098}
3099
3100// Computes the slope from points p0 to p1.
3101function d3_svg_lineSlope(p0, p1) {
3102  return (p1[1] - p0[1]) / (p1[0] - p0[0]);
3103}
3104
3105// Compute three-point differences for the given points.
3106// http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Finite_difference
3107function d3_svg_lineFiniteDifferences(points) {
3108  var i = 0,
3109      j = points.length - 1,
3110      m = [],
3111      p0 = points[0],
3112      p1 = points[1],
3113      d = m[0] = d3_svg_lineSlope(p0, p1);
3114  while (++i < j) {
3115    m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]));
3116  }
3117  m[i] = d;
3118  return m;
3119}
3120
3121// Interpolates the given points using Fritsch-Carlson Monotone cubic Hermite
3122// interpolation. Returns an array of tangent vectors. For details, see
3123// http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
3124function d3_svg_lineMonotoneTangents(points) {
3125  var tangents = [],
3126      d,
3127      a,
3128      b,
3129      s,
3130      m = d3_svg_lineFiniteDifferences(points),
3131      i = -1,
3132      j = points.length - 1;
3133
3134  // The first two steps are done by computing finite-differences:
3135  // 1. Compute the slopes of the secant lines between successive points.
3136  // 2. Initialize the tangents at every point as the average of the secants.
3137
3138  // Then, for each segment

3139  while (++i < j) {
3140    d = d3_svg_lineSlope(points[i], points[i + 1]);
3141
3142    // 3. If two successive yk = y{k + 1} are equal (i.e., d is zero), then set
3143    // mk = m{k + 1} = 0 as the spline connecting these points must be flat to
3144    // preserve monotonicity. Ignore step 4 and 5 for those k.
3145
3146    if (Math.abs(d) < 1e-6) {
3147      m[i] = m[i + 1] = 0;
3148    } else {
3149      // 4. Let ak = mk / dk and bk = m{k + 1} / dk.
3150      a = m[i] / d;
3151      b = m[i + 1] / d;
3152
3153      // 5. Prevent overshoot and ensure monotonicity by restricting the
3154      // magnitude of vector <ak, bk> to a circle of radius 3.
3155      s = a * a + b * b;
3156      if (s > 9) {
3157        s = d * 3 / Math.sqrt(s);
3158        m[i] = s * a;
3159        m[i + 1] = s * b;
3160      }
3161    }
3162  }
3163
3164  // Compute the normalized tangent vector from the slopes. Note that if x is
3165  // not monotonic, it's possible that the slope will be infinite, so we protect
3166  // against NaN by setting the coordinate to zero.
3167  i = -1; while (++i <= j) {
3168    s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0])
3169      / (6 * (1 + m[i] * m[i]));
3170    tangents.push([s || 0, m[i] * s || 0]);
3171  }
3172
3173  return tangents;
3174}
3175
3176function d3_svg_lineMonotone(points) {
3177  return points.length < 3
3178      ? d3_svg_lineLinear(points)
3179      : points[0] +
3180        d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
3181}
3182d3.svg.line.radial = function() {
3183  var line = d3_svg_line(d3_svg_lineRadial);
3184  line.radius = line.x, delete line.x;
3185  line.angle = line.y, delete line.y;
3186  return line;
3187};
3188
3189function d3_svg_lineRadial(points) {
3190  var point,
3191      i = -1,
3192      n = points.length,
3193      r,
3194      a;
3195  while (++i < n) {
3196    point = points[i];
3197    r = point[0];
3198    a = point[1] + d3_svg_arcOffset;
3199    point[0] = r * Math.cos(a);
3200    point[1] = r * Math.sin(a);
3201  }
3202  return points;
3203}
3204function d3_svg_area(projection) {
3205  var x0 = d3_svg_lineX,
3206      x1 = d3_svg_lineX,
3207      y0 = 0,
3208      y1 = d3_svg_lineY,
3209      interpolate = "linear",
3210      interpolator = d3_svg_lineInterpolators[interpolate],
3211      tension = .7;
3212
3213  function area(d) {
3214    if (d.length < 1) return null;
3215    var points0 = d3_svg_linePoints(this, d, x0, y0),
3216        points1 = d3_svg_linePoints(this, d, x0 === x1 ? d3_svg_areaX(points0) : x1, y0 === y1 ? d3_svg_areaY(points0) : y1);
3217    return "M" + interpolator(projection(points1), tension)
3218         + "L" + interpolator(projection(points0.reverse()), tension)
3219         + "Z";
3220  }
3221
3222  area.x = function(x) {
3223    if (!arguments.length) return x1;
3224    x0 = x1 = x;
3225    return area;
3226  };
3227
3228  area.x0 = function(x) {
3229    if (!arguments.length) return x0;
3230    x0 = x;
3231    return area;
3232  };
3233
3234  area.x1 = function(x) {
3235    if (!arguments.length) return x1;
3236    x1 = x;
3237    return area;
3238  };
3239
3240  area.y = function(y) {
3241    if (!arguments.length) return y1;
3242    y0 = y1 = y;
3243    return area;
3244  };
3245
3246  area.y0 = function(y) {
3247    if (!arguments.length) return y0;
3248    y0 = y;
3249    return area;
3250  };
3251
3252  area.y1 = function(y) {
3253    if (!arguments.length) return y1;
3254    y1 = y;
3255    return area;
3256  };
3257
3258  area.interpolate = function(x) {
3259    if (!arguments.length) return interpolate;
3260    interpolator = d3_svg_lineInterpolators[interpolate = x];
3261    return area;
3262  };
3263
3264  area.tension = function(x) {
3265    if (!arguments.length) return tension;
3266    tension = x;
3267    return area;
3268  };
3269
3270  return area;
3271}
3272
3273d3.svg.area = function() {
3274  return d3_svg_area(Object);
3275};
3276
3277function d3_svg_areaX(points) {
3278  return function(d, i) {
3279    return points[i][0];
3280  };
3281}
3282
3283function d3_svg_areaY(points) {
3284  return function(d, i) {
3285    return points[i][1];
3286  };
3287}
3288d3.svg.area.radial = function() {
3289  var area = d3_svg_area(d3_svg_lineRadial);
3290  area.radius = area.x, delete area.x;
3291  area.innerRadius = area.x0, delete area.x0;
3292  area.outerRadius = area.x1, delete area.x1;
3293  area.angle = area.y, delete area.y;
3294  area.startAngle = area.y0, delete area.y0;
3295  area.endAngle = area.y1, delete area.y1;
3296  return area;
3297};
3298d3.svg.chord = function() {
3299  var source = d3_svg_chordSource,
3300      target = d3_svg_chordTarget,
3301      radius = d3_svg_chordRadius,
3302      startAngle = d3_svg_arcStartAngle,
3303      endAngle = d3_svg_arcEndAngle;
3304
3305  // TODO Allow control point to be customized.
3306
3307  function chord(d, i) {
3308    var s = subgroup(this, source, d, i),
3309        t = subgroup(this, target, d, i);
3310    return "M" + s.p0
3311      + arc(s.r, s.p1) + (equals(s, t)
3312      ? curve(s.r, s.p1, s.r, s.p0)
3313      : curve(s.r, s.p1, t.r, t.p0)
3314      + arc(t.r, t.p1)
3315      + curve(t.r, t.p1, s.r, s.p0))
3316      + "Z";
3317  }
3318
3319  function subgroup(self, f, d, i) {
3320    var subgroup = f.call(self, d, i),
3321        r = radius.call(self, subgroup, i),
3322        a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset,
3323        a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
3324    return {
3325      r: r,
3326      a0: a0,
3327      a1: a1,
3328      p0: [r * Math.cos(a0), r * Math.sin(a0)],
3329      p1: [r * Math.cos(a1), r * Math.sin(a1)]
3330    };
3331  }
3332
3333  function equals(a, b) {
3334    return a.a0 == b.a0 && a.a1 == b.a1;
3335  }
3336
3337  function arc(r, p) {
3338    return "A" + r + "," + r + " 0 0,1 " + p;
3339  }
3340
3341  function curve(r0, p0, r1, p1) {
3342    return "Q 0,0 " + p1;
3343  }
3344
3345  chord.radius = function(v) {
3346    if (!arguments.length) return radius;
3347    radius = d3.functor(v);
3348    return chord;
3349  };
3350
3351  chord.source = function(v) {
3352    if (!arguments.length) return source;
3353    source = d3.functor(v);
3354    return chord;
3355  };
3356
3357  chord.target = function(v) {
3358    if (!arguments.length) return target;
3359    target = d3.functor(v);
3360    return chord;
3361  };
3362
3363  chord.startAngle = function(v) {
3364    if (!arguments.length) return startAngle;
3365    startAngle = d3.functor(v);
3366    return chord;
3367  };
3368
3369  chord.endAngle = function(v) {
3370    if (!arguments.length) return endAngle;
3371    endAngle = d3.functor(v);
3372    return chord;
3373  };
3374
3375  return chord;
3376};
3377
3378function d3_svg_chordSource(d) {
3379  return d.source;
3380}
3381
3382function d3_svg_chordTarget(d) {
3383  return d.target;
3384}
3385
3386function d3_svg_chordRadius(d) {
3387  return d.radius;
3388}
3389
3390function d3_svg_chordStartAngle(d) {
3391  return d.startAngle;
3392}
3393
3394function d3_svg_chordEndAngle(d) {
3395  return d.endAngle;
3396}
3397d3.svg.diagonal = function() {
3398  var source = d3_svg_chordSource,
3399      target = d3_svg_chordTarget,
3400      projection = d3_svg_diagonalProjection;
3401
3402  function diagonal(d, i) {
3403    var p0 = source.call(this, d, i),
3404        p3 = target.call(this, d, i),
3405        m = (p0.y + p3.y) / 2,
3406        p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3];
3407    p = p.map(projection);
3408    return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
3409  }
3410
3411  diagonal.source = function(x) {
3412    if (!arguments.length) return source;
3413    source = d3.functor(x);
3414    return diagonal;
3415  };
3416
3417  diagonal.target = function(x) {
3418    if (!arguments.length) return target;
3419    target = d3.functor(x);
3420    return diagonal;
3421  };
3422
3423  diagonal.projection = function(x) {
3424    if (!arguments.length) return projection;
3425    projection = x;
3426    return diagonal;
3427  };
3428
3429  return diagonal;
3430};
3431
3432function d3_svg_diagonalProjection(d) {
3433  return [d.x, d.y];
3434}
3435d3.svg.diagonal.radial = function() {
3436  var diagonal = d3.svg.diagonal(),
3437      projection = d3_svg_diagonalProjection,
3438      projection_ = diagonal.projection;
3439
3440  diagonal.projection = function(x) {
3441    return arguments.length
3442        ? projection_(d3_svg_diagonalRadialProjection(projection = x))
3443        : projection;
3444  };
3445
3446  return diagonal;
3447};
3448
3449function d3_svg_diagonalRadialProjection(projection) {
3450  return function() {
3451    var d = projection.apply(this, arguments),
3452        r = d[0],
3453        a = d[1] + d3_svg_arcOffset;
3454    return [r * Math.cos(a), r * Math.sin(a)];
3455  };
3456}
3457d3.svg.mouse = function(container) {
3458  return d3_svg_mousePoint(container, d3.event);
3459};
3460
3461// https://bugs.webkit.org/show_bug.cgi?id=44083
3462var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
3463
3464function d3_svg_mousePoint(container, e) {
3465  var point = (container.ownerSVGElement || container).createSVGPoint();
3466  if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) {
3467    var svg = d3.select(document.body)
3468      .append("svg:svg")
3469        .style("position", "absolute")
3470        .style("top", 0)
3471        .style("left", 0);
3472    var ctm = svg[0][0].getScreenCTM();
3473    d3_mouse_bug44083 = !(ctm.f || ctm.e);
3474    svg.remove();
3475  }
3476  if (d3_mouse_bug44083) {
3477    point.x = e.pageX;
3478    point.y = e.pageY;
3479  } else {
3480    point.x = e.clientX;
3481    point.y = e.clientY;
3482  }
3483  point = point.matrixTransform(container.getScreenCTM().inverse());
3484  return [point.x, point.y];
3485};
3486d3.svg.touches = function(container) {
3487  var touches = d3.event.touches;
3488  return touches ? d3_array(touches).map(function(touch) {
3489    var point = d3_svg_mousePoint(container, touch);
3490    point.identifier = touch.identifier;
3491    return point;
3492  }) : [];
3493};
3494d3.svg.symbol = function() {
3495  var type = d3_svg_symbolType,
3496      size = d3_svg_symbolSize;
3497
3498  function symbol(d, i) {
3499    return (d3_svg_symbols[type.call(this, d, i)]
3500        || d3_svg_symbols.circle)
3501        (size.call(this, d, i));
3502  }
3503
3504  symbol.type = function(x) {
3505    if (!arguments.length) return type;
3506    type = d3.functor(x);
3507    return symbol;
3508  };
3509
3510  // size of symbol in square pixels
3511  symbol.size = function(x) {
3512    if (!arguments.length) return size;
3513    size = d3.functor(x);
3514    return symbol;
3515  };
3516
3517  return symbol;
3518};
3519
3520function d3_svg_symbolSize() {
3521  return 64;
3522}
3523
3524function d3_svg_symbolType() {
3525  return "circle";
3526}
3527
3528// TODO cross-diagonal?
3529var d3_svg_symbols = {
3530  "circle": function(size) {
3531    var r = Math.sqrt(size / Math.PI);
3532    return "M0," + r
3533        + "A" + r + "," + r + " 0 1,1 0," + (-r)
3534        + "A" + r + "," + r + " 0 1,1 0," + r
3535        + "Z";
3536  },
3537  "cross": function(size) {
3538    var r = Math.sqrt(size / 5) / 2;
3539    return "M" + -3 * r + "," + -r
3540        + "H" + -r
3541        + "V" + -3 * r
3542        + "H" + r
3543        + "V" + -r
3544        + "H" + 3 * r
3545        + "V" + r
3546        + "H" + r
3547        + "V" + 3 * r
3548        + "H" + -r
3549        + "V" + r
3550        + "H" + -3 * r
3551        + "Z";
3552  },
3553  "diamond": function(size) {
3554    var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)),
3555        rx = ry * d3_svg_symbolTan30;
3556    return "M0," + -ry
3557        + "L" + rx + ",0"
3558        + " 0," + ry
3559        + " " + -rx + ",0"
3560        + "Z";
3561  },
3562  "square": function(size) {
3563    var r = Math.sqrt(size) / 2;
3564    return "M" + -r + "," + -r
3565        + "L" + r + "," + -r
3566        + " " + r + "," + r
3567        + " " + -r + "," + r
3568        + "Z";
3569  },
3570  "triangle-down": function(size) {
3571    var rx = Math.sqrt(size / d3_svg_symbolSqrt3),
3572        ry = rx * d3_svg_symbolSqrt3 / 2;
3573    return "M0," + ry
3574        + "L" + rx +"," + -ry
3575        + " " + -rx + "," + -ry
3576        + "Z";
3577  },
3578  "triangle-up": function(size) {
3579    var rx = Math.sqrt(size / d3_svg_symbolSqrt3),
3580        ry = rx * d3_svg_symbolSqrt3 / 2;
3581    return "M0," + -ry
3582        + "L" + rx +"," + ry
3583        + " " + -rx + "," + ry
3584        + "Z";
3585  }
3586};
3587
3588d3.svg.symbolTypes = d3.keys(d3_svg_symbols);
3589
3590var d3_svg_symbolSqrt3 = Math.sqrt(3),
3591    d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180);
3592})();
Note: See TracBrowser for help on using the repository browser.