2e23addfd2841b386b59cf497d06e47f483b12f2
[rails.git] / vendor / assets / iD / iD.js
1 (function(exports) {
2
3   var bootstrap = (typeof exports.bootstrap === "object") ?
4     exports.bootstrap :
5     (exports.bootstrap = {});
6
7   bootstrap.tooltip = function() {
8
9     var tooltip = function(selection) {
10         selection.each(setup);
11       },
12       animation = d3.functor(false),
13       html = d3.functor(false),
14       title = function() {
15         var title = this.getAttribute("data-original-title");
16         if (title) {
17           return title;
18         } else {
19           title = this.getAttribute("title");
20           this.removeAttribute("title");
21           this.setAttribute("data-original-title", title);
22         }
23         return title;
24       },
25       over = "mouseenter.tooltip",
26       out = "mouseleave.tooltip",
27       placements = "top left bottom right".split(" "),
28       placement = d3.functor("top");
29
30     tooltip.title = function(_) {
31       if (arguments.length) {
32         title = d3.functor(_);
33         return tooltip;
34       } else {
35         return title;
36       }
37     };
38
39     tooltip.html = function(_) {
40       if (arguments.length) {
41         html = d3.functor(_);
42         return tooltip;
43       } else {
44         return html;
45       }
46     };
47
48     tooltip.placement = function(_) {
49       if (arguments.length) {
50         placement = d3.functor(_);
51         return tooltip;
52       } else {
53         return placement;
54       }
55     };
56
57     tooltip.show = function(selection) {
58       selection.each(show);
59     };
60
61     tooltip.hide = function(selection) {
62       selection.each(hide);
63     };
64
65     tooltip.toggle = function(selection) {
66       selection.each(toggle);
67     };
68
69     tooltip.destroy = function(selection) {
70       selection
71         .on(over, null)
72         .on(out, null)
73         .attr("title", function() {
74           return this.getAttribute("data-original-title") || this.getAttribute("title");
75         })
76         .attr("data-original-title", null)
77         .select(".tooltip")
78         .remove();
79     };
80
81     function setup() {
82       var root = d3.select(this),
83           animate = animation.apply(this, arguments),
84           tip = root.append("div")
85             .attr("class", "tooltip");
86
87       if (animate) {
88         tip.classed("fade", true);
89       }
90
91       // TODO "inside" checks?
92
93       tip.append("div")
94         .attr("class", "tooltip-arrow");
95       tip.append("div")
96         .attr("class", "tooltip-inner");
97
98       var place = placement.apply(this, arguments);
99       tip.classed(place, true);
100
101       root.on(over, show);
102       root.on(out, hide);
103     }
104
105     function show() {
106       var root = d3.select(this),
107           content = title.apply(this, arguments),
108           tip = root.select(".tooltip")
109             .classed("in", true),
110           markup = html.apply(this, arguments),
111           innercontent = tip.select(".tooltip-inner")[markup ? "html" : "text"](content),
112           place = placement.apply(this, arguments),
113           outer = getPosition(root.node()),
114           inner = getPosition(tip.node()),
115           pos;
116
117       switch (place) {
118         case "top":
119           pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
120           break;
121         case "right":
122           pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
123           break;
124         case "left":
125           pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
126           break;
127         case "bottom":
128           pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
129           break;
130       }
131
132       tip.style(pos ?
133         {left: ~~pos.x + "px", top: ~~pos.y + "px"} :
134         {left: null, top: null});
135
136       this.tooltipVisible = true;
137     }
138
139     function hide() {
140       d3.select(this).select(".tooltip")
141         .classed("in", false);
142
143       this.tooltipVisible = false;
144     }
145
146     function toggle() {
147       if (this.tooltipVisible) {
148         hide.apply(this, arguments);
149       } else {
150         show.apply(this, arguments);
151       }
152     }
153
154     return tooltip;
155   };
156
157   function getPosition(node) {
158     var mode = d3.select(node).style('position');
159     if (mode === 'absolute' || mode === 'static') {
160       return {
161         x: node.offsetLeft,
162         y: node.offsetTop,
163         w: node.offsetWidth,
164         h: node.offsetHeight
165       };
166     } else {
167       return {
168         x: 0,
169         y: 0,
170         w: node.offsetWidth,
171         h: node.offsetHeight
172       };
173     }
174   }
175
176 })(this);
177 d3 = (function(){
178   var d3 = {version: "3.2.7"}; // semver
179 d3.ascending = function(a, b) {
180   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
181 };
182 d3.descending = function(a, b) {
183   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
184 };
185 d3.min = function(array, f) {
186   var i = -1,
187       n = array.length,
188       a,
189       b;
190   if (arguments.length === 1) {
191     while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
192     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
193   } else {
194     while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
195     while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
196   }
197   return a;
198 };
199 d3.max = function(array, f) {
200   var i = -1,
201       n = array.length,
202       a,
203       b;
204   if (arguments.length === 1) {
205     while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
206     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
207   } else {
208     while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
209     while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
210   }
211   return a;
212 };
213 d3.extent = function(array, f) {
214   var i = -1,
215       n = array.length,
216       a,
217       b,
218       c;
219   if (arguments.length === 1) {
220     while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;
221     while (++i < n) if ((b = array[i]) != null) {
222       if (a > b) a = b;
223       if (c < b) c = b;
224     }
225   } else {
226     while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
227     while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
228       if (a > b) a = b;
229       if (c < b) c = b;
230     }
231   }
232   return [a, c];
233 };
234 d3.sum = function(array, f) {
235   var s = 0,
236       n = array.length,
237       a,
238       i = -1;
239
240   if (arguments.length === 1) {
241     while (++i < n) if (!isNaN(a = +array[i])) s += a;
242   } else {
243     while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
244   }
245
246   return s;
247 };
248 function d3_number(x) {
249   return x != null && !isNaN(x);
250 }
251
252 d3.mean = function(array, f) {
253   var n = array.length,
254       a,
255       m = 0,
256       i = -1,
257       j = 0;
258   if (arguments.length === 1) {
259     while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
260   } else {
261     while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
262   }
263   return j ? m : undefined;
264 };
265 // R-7 per <http://en.wikipedia.org/wiki/Quantile>
266 d3.quantile = function(values, p) {
267   var H = (values.length - 1) * p + 1,
268       h = Math.floor(H),
269       v = +values[h - 1],
270       e = H - h;
271   return e ? v + e * (values[h] - v) : v;
272 };
273
274 d3.median = function(array, f) {
275   if (arguments.length > 1) array = array.map(f);
276   array = array.filter(d3_number);
277   return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
278 };
279 d3.bisector = function(f) {
280   return {
281     left: function(a, x, lo, hi) {
282       if (arguments.length < 3) lo = 0;
283       if (arguments.length < 4) hi = a.length;
284       while (lo < hi) {
285         var mid = lo + hi >>> 1;
286         if (f.call(a, a[mid], mid) < x) lo = mid + 1;
287         else hi = mid;
288       }
289       return lo;
290     },
291     right: function(a, x, lo, hi) {
292       if (arguments.length < 3) lo = 0;
293       if (arguments.length < 4) hi = a.length;
294       while (lo < hi) {
295         var mid = lo + hi >>> 1;
296         if (x < f.call(a, a[mid], mid)) hi = mid;
297         else lo = mid + 1;
298       }
299       return lo;
300     }
301   };
302 };
303
304 var d3_bisector = d3.bisector(function(d) { return d; });
305 d3.bisectLeft = d3_bisector.left;
306 d3.bisect = d3.bisectRight = d3_bisector.right;
307 d3.shuffle = function(array) {
308   var m = array.length, t, i;
309   while (m) {
310     i = Math.random() * m-- | 0;
311     t = array[m], array[m] = array[i], array[i] = t;
312   }
313   return array;
314 };
315 d3.permute = function(array, indexes) {
316   var permutes = [],
317       i = -1,
318       n = indexes.length;
319   while (++i < n) permutes[i] = array[indexes[i]];
320   return permutes;
321 };
322
323 d3.zip = function() {
324   if (!(n = arguments.length)) return [];
325   for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) {
326     for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) {
327       zip[j] = arguments[j][i];
328     }
329   }
330   return zips;
331 };
332
333 function d3_zipLength(d) {
334   return d.length;
335 }
336
337 d3.transpose = function(matrix) {
338   return d3.zip.apply(d3, matrix);
339 };
340 d3.keys = function(map) {
341   var keys = [];
342   for (var key in map) keys.push(key);
343   return keys;
344 };
345 d3.values = function(map) {
346   var values = [];
347   for (var key in map) values.push(map[key]);
348   return values;
349 };
350 d3.entries = function(map) {
351   var entries = [];
352   for (var key in map) entries.push({key: key, value: map[key]});
353   return entries;
354 };
355 d3.merge = function(arrays) {
356   return Array.prototype.concat.apply([], arrays);
357 };
358 d3.range = function(start, stop, step) {
359   if (arguments.length < 3) {
360     step = 1;
361     if (arguments.length < 2) {
362       stop = start;
363       start = 0;
364     }
365   }
366   if ((stop - start) / step === Infinity) throw new Error("infinite range");
367   var range = [],
368        k = d3_range_integerScale(Math.abs(step)),
369        i = -1,
370        j;
371   start *= k, stop *= k, step *= k;
372   if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k);
373   else while ((j = start + step * ++i) < stop) range.push(j / k);
374   return range;
375 };
376
377 function d3_range_integerScale(x) {
378   var k = 1;
379   while (x * k % 1) k *= 10;
380   return k;
381 }
382 function d3_class(ctor, properties) {
383   try {
384     for (var key in properties) {
385       Object.defineProperty(ctor.prototype, key, {
386         value: properties[key],
387         enumerable: false
388       });
389     }
390   } catch (e) {
391     ctor.prototype = properties;
392   }
393 }
394
395 d3.map = function(object) {
396   var map = new d3_Map;
397   for (var key in object) map.set(key, object[key]);
398   return map;
399 };
400
401 function d3_Map() {}
402
403 d3_class(d3_Map, {
404   has: function(key) {
405     return d3_map_prefix + key in this;
406   },
407   get: function(key) {
408     return this[d3_map_prefix + key];
409   },
410   set: function(key, value) {
411     return this[d3_map_prefix + key] = value;
412   },
413   remove: function(key) {
414     key = d3_map_prefix + key;
415     return key in this && delete this[key];
416   },
417   keys: function() {
418     var keys = [];
419     this.forEach(function(key) { keys.push(key); });
420     return keys;
421   },
422   values: function() {
423     var values = [];
424     this.forEach(function(key, value) { values.push(value); });
425     return values;
426   },
427   entries: function() {
428     var entries = [];
429     this.forEach(function(key, value) { entries.push({key: key, value: value}); });
430     return entries;
431   },
432   forEach: function(f) {
433     for (var key in this) {
434       if (key.charCodeAt(0) === d3_map_prefixCode) {
435         f.call(this, key.substring(1), this[key]);
436       }
437     }
438   }
439 });
440
441 var d3_map_prefix = "\0", // prevent collision with built-ins
442     d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
443
444 d3.nest = function() {
445   var nest = {},
446       keys = [],
447       sortKeys = [],
448       sortValues,
449       rollup;
450
451   function map(mapType, array, depth) {
452     if (depth >= keys.length) return rollup
453         ? rollup.call(nest, array) : (sortValues
454         ? array.sort(sortValues)
455         : array);
456
457     var i = -1,
458         n = array.length,
459         key = keys[depth++],
460         keyValue,
461         object,
462         setter,
463         valuesByKey = new d3_Map,
464         values;
465
466     while (++i < n) {
467       if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
468         values.push(object);
469       } else {
470         valuesByKey.set(keyValue, [object]);
471       }
472     }
473
474     if (mapType) {
475       object = mapType();
476       setter = function(keyValue, values) {
477         object.set(keyValue, map(mapType, values, depth));
478       };
479     } else {
480       object = {};
481       setter = function(keyValue, values) {
482         object[keyValue] = map(mapType, values, depth);
483       };
484     }
485
486     valuesByKey.forEach(setter);
487     return object;
488   }
489
490   function entries(map, depth) {
491     if (depth >= keys.length) return map;
492
493     var array = [],
494         sortKey = sortKeys[depth++];
495
496     map.forEach(function(key, keyMap) {
497       array.push({key: key, values: entries(keyMap, depth)});
498     });
499
500     return sortKey
501         ? array.sort(function(a, b) { return sortKey(a.key, b.key); })
502         : array;
503   }
504
505   nest.map = function(array, mapType) {
506     return map(mapType, array, 0);
507   };
508
509   nest.entries = function(array) {
510     return entries(map(d3.map, array, 0), 0);
511   };
512
513   nest.key = function(d) {
514     keys.push(d);
515     return nest;
516   };
517
518   // Specifies the order for the most-recently specified key.
519   // Note: only applies to entries. Map keys are unordered!
520   nest.sortKeys = function(order) {
521     sortKeys[keys.length - 1] = order;
522     return nest;
523   };
524
525   // Specifies the order for leaf values.
526   // Applies to both maps and entries array.
527   nest.sortValues = function(order) {
528     sortValues = order;
529     return nest;
530   };
531
532   nest.rollup = function(f) {
533     rollup = f;
534     return nest;
535   };
536
537   return nest;
538 };
539
540 d3.set = function(array) {
541   var set = new d3_Set();
542   if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);
543   return set;
544 };
545
546 function d3_Set() {}
547
548 d3_class(d3_Set, {
549   has: function(value) {
550     return d3_map_prefix + value in this;
551   },
552   add: function(value) {
553     this[d3_map_prefix + value] = true;
554     return value;
555   },
556   remove: function(value) {
557     value = d3_map_prefix + value;
558     return value in this && delete this[value];
559   },
560   values: function() {
561     var values = [];
562     this.forEach(function(value) {
563       values.push(value);
564     });
565     return values;
566   },
567   forEach: function(f) {
568     for (var value in this) {
569       if (value.charCodeAt(0) === d3_map_prefixCode) {
570         f.call(this, value.substring(1));
571       }
572     }
573   }
574 });
575 d3.behavior = {};
576 var d3_document = document,
577     d3_documentElement = d3_document.documentElement,
578     d3_window = window;
579 // Copies a variable number of methods from source to target.
580 d3.rebind = function(target, source) {
581   var i = 1, n = arguments.length, method;
582   while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
583   return target;
584 };
585
586 // Method is assumed to be a standard D3 getter-setter:
587 // If passed with no arguments, gets the value.
588 // If passed with arguments, sets the value and returns the target.
589 function d3_rebind(target, source, method) {
590   return function() {
591     var value = method.apply(source, arguments);
592     return value === source ? target : value;
593   };
594 }
595
596 function d3_vendorSymbol(object, name) {
597   if (name in object) return name;
598   name = name.charAt(0).toUpperCase() + name.substring(1);
599   for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
600     var prefixName = d3_vendorPrefixes[i] + name;
601     if (prefixName in object) return prefixName;
602   }
603 }
604
605 var d3_vendorPrefixes = ["webkit", "ms", "moz", "Moz", "o", "O"];
606
607 var d3_array = d3_arraySlice; // conversion for NodeLists
608
609 function d3_arrayCopy(pseudoarray) {
610   var i = -1, n = pseudoarray.length, array = [];
611   while (++i < n) array.push(pseudoarray[i]);
612   return array;
613 }
614
615 function d3_arraySlice(pseudoarray) {
616   return Array.prototype.slice.call(pseudoarray);
617 }
618
619 try {
620   d3_array(d3_documentElement.childNodes)[0].nodeType;
621 } catch(e) {
622   d3_array = d3_arrayCopy;
623 }
624 function d3_noop() {}
625
626 d3.dispatch = function() {
627   var dispatch = new d3_dispatch,
628       i = -1,
629       n = arguments.length;
630   while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
631   return dispatch;
632 };
633
634 function d3_dispatch() {}
635
636 d3_dispatch.prototype.on = function(type, listener) {
637   var i = type.indexOf("."),
638       name = "";
639
640   // Extract optional namespace, e.g., "click.foo"
641   if (i >= 0) {
642     name = type.substring(i + 1);
643     type = type.substring(0, i);
644   }
645
646   if (type) return arguments.length < 2
647       ? this[type].on(name)
648       : this[type].on(name, listener);
649
650   if (arguments.length === 2) {
651     if (listener == null) for (type in this) {
652       if (this.hasOwnProperty(type)) this[type].on(name, null);
653     }
654     return this;
655   }
656 };
657
658 function d3_dispatch_event(dispatch) {
659   var listeners = [],
660       listenerByName = new d3_Map;
661
662   function event() {
663     var z = listeners, // defensive reference
664         i = -1,
665         n = z.length,
666         l;
667     while (++i < n) if (l = z[i].on) l.apply(this, arguments);
668     return dispatch;
669   }
670
671   event.on = function(name, listener) {
672     var l = listenerByName.get(name),
673         i;
674
675     // return the current listener, if any
676     if (arguments.length < 2) return l && l.on;
677
678     // remove the old listener, if any (with copy-on-write)
679     if (l) {
680       l.on = null;
681       listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
682       listenerByName.remove(name);
683     }
684
685     // add the new listener, if any
686     if (listener) listeners.push(listenerByName.set(name, {on: listener}));
687
688     return dispatch;
689   };
690
691   return event;
692 }
693
694 d3.event = null;
695
696 function d3_eventPreventDefault() {
697   d3.event.preventDefault();
698 }
699
700 function d3_eventCancel() {
701   d3.event.preventDefault();
702   d3.event.stopPropagation();
703 }
704
705 function d3_eventSource() {
706   var e = d3.event, s;
707   while (s = e.sourceEvent) e = s;
708   return e;
709 }
710
711 // Like d3.dispatch, but for custom events abstracting native UI events. These
712 // events have a target component (such as a brush), a target element (such as
713 // the svg:g element containing the brush) and the standard arguments `d` (the
714 // target element's data) and `i` (the selection index of the target element).
715 function d3_eventDispatch(target) {
716   var dispatch = new d3_dispatch,
717       i = 0,
718       n = arguments.length;
719
720   while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
721
722   // Creates a dispatch context for the specified `thiz` (typically, the target
723   // DOM element that received the source event) and `argumentz` (typically, the
724   // data `d` and index `i` of the target element). The returned function can be
725   // used to dispatch an event to any registered listeners; the function takes a
726   // single argument as input, being the event to dispatch. The event must have
727   // a "type" attribute which corresponds to a type registered in the
728   // constructor. This context will automatically populate the "sourceEvent" and
729   // "target" attributes of the event, as well as setting the `d3.event` global
730   // for the duration of the notification.
731   dispatch.of = function(thiz, argumentz) {
732     return function(e1) {
733       try {
734         var e0 =
735         e1.sourceEvent = d3.event;
736         e1.target = target;
737         d3.event = e1;
738         dispatch[e1.type].apply(thiz, argumentz);
739       } finally {
740         d3.event = e0;
741       }
742     };
743   };
744
745   return dispatch;
746 }
747 d3.requote = function(s) {
748   return s.replace(d3_requote_re, "\\$&");
749 };
750
751 var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
752 var d3_subclass = {}.__proto__?
753
754 // Until ECMAScript supports array subclassing, prototype injection works well.
755 function(object, prototype) {
756   object.__proto__ = prototype;
757 }:
758
759 // And if your browser doesn't support __proto__, we'll use direct extension.
760 function(object, prototype) {
761   for (var property in prototype) object[property] = prototype[property];
762 };
763
764 function d3_selection(groups) {
765   d3_subclass(groups, d3_selectionPrototype);
766   return groups;
767 }
768
769 var d3_select = function(s, n) { return n.querySelector(s); },
770     d3_selectAll = function(s, n) { return n.querySelectorAll(s); },
771     d3_selectMatcher = d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")],
772     d3_selectMatches = function(n, s) { return d3_selectMatcher.call(n, s); };
773
774 // Prefer Sizzle, if available.
775 if (typeof Sizzle === "function") {
776   d3_select = function(s, n) { return Sizzle(s, n)[0] || null; };
777   d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); };
778   d3_selectMatches = Sizzle.matchesSelector;
779 }
780
781 d3.selection = function() {
782   return d3_selectionRoot;
783 };
784
785 var d3_selectionPrototype = d3.selection.prototype = [];
786
787
788 d3_selectionPrototype.select = function(selector) {
789   var subgroups = [],
790       subgroup,
791       subnode,
792       group,
793       node;
794
795   selector = d3_selection_selector(selector);
796
797   for (var j = -1, m = this.length; ++j < m;) {
798     subgroups.push(subgroup = []);
799     subgroup.parentNode = (group = this[j]).parentNode;
800     for (var i = -1, n = group.length; ++i < n;) {
801       if (node = group[i]) {
802         subgroup.push(subnode = selector.call(node, node.__data__, i, j));
803         if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
804       } else {
805         subgroup.push(null);
806       }
807     }
808   }
809
810   return d3_selection(subgroups);
811 };
812
813 function d3_selection_selector(selector) {
814   return typeof selector === "function" ? selector : function() {
815     return d3_select(selector, this);
816   };
817 }
818
819 d3_selectionPrototype.selectAll = function(selector) {
820   var subgroups = [],
821       subgroup,
822       node;
823
824   selector = d3_selection_selectorAll(selector);
825
826   for (var j = -1, m = this.length; ++j < m;) {
827     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
828       if (node = group[i]) {
829         subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
830         subgroup.parentNode = node;
831       }
832     }
833   }
834
835   return d3_selection(subgroups);
836 };
837
838 function d3_selection_selectorAll(selector) {
839   return typeof selector === "function" ? selector : function() {
840     return d3_selectAll(selector, this);
841   };
842 }
843 var d3_nsPrefix = {
844   svg: "http://www.w3.org/2000/svg",
845   xhtml: "http://www.w3.org/1999/xhtml",
846   xlink: "http://www.w3.org/1999/xlink",
847   xml: "http://www.w3.org/XML/1998/namespace",
848   xmlns: "http://www.w3.org/2000/xmlns/"
849 };
850
851 d3.ns = {
852   prefix: d3_nsPrefix,
853   qualify: function(name) {
854     var i = name.indexOf(":"),
855         prefix = name;
856     if (i >= 0) {
857       prefix = name.substring(0, i);
858       name = name.substring(i + 1);
859     }
860     return d3_nsPrefix.hasOwnProperty(prefix)
861         ? {space: d3_nsPrefix[prefix], local: name}
862         : name;
863   }
864 };
865
866 d3_selectionPrototype.attr = function(name, value) {
867   if (arguments.length < 2) {
868
869     // For attr(string), return the attribute value for the first node.
870     if (typeof name === "string") {
871       var node = this.node();
872       name = d3.ns.qualify(name);
873       return name.local
874           ? node.getAttributeNS(name.space, name.local)
875           : node.getAttribute(name);
876     }
877
878     // For attr(object), the object specifies the names and values of the
879     // attributes to set or remove. The values may be functions that are
880     // evaluated for each element.
881     for (value in name) this.each(d3_selection_attr(value, name[value]));
882     return this;
883   }
884
885   return this.each(d3_selection_attr(name, value));
886 };
887
888 function d3_selection_attr(name, value) {
889   name = d3.ns.qualify(name);
890
891   // For attr(string, null), remove the attribute with the specified name.
892   function attrNull() {
893     this.removeAttribute(name);
894   }
895   function attrNullNS() {
896     this.removeAttributeNS(name.space, name.local);
897   }
898
899   // For attr(string, string), set the attribute with the specified name.
900   function attrConstant() {
901     this.setAttribute(name, value);
902   }
903   function attrConstantNS() {
904     this.setAttributeNS(name.space, name.local, value);
905   }
906
907   // For attr(string, function), evaluate the function for each element, and set
908   // or remove the attribute as appropriate.
909   function attrFunction() {
910     var x = value.apply(this, arguments);
911     if (x == null) this.removeAttribute(name);
912     else this.setAttribute(name, x);
913   }
914   function attrFunctionNS() {
915     var x = value.apply(this, arguments);
916     if (x == null) this.removeAttributeNS(name.space, name.local);
917     else this.setAttributeNS(name.space, name.local, x);
918   }
919
920   return value == null
921       ? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
922       ? (name.local ? attrFunctionNS : attrFunction)
923       : (name.local ? attrConstantNS : attrConstant));
924 }
925 function d3_collapse(s) {
926   return s.trim().replace(/\s+/g, " ");
927 }
928
929 d3_selectionPrototype.classed = function(name, value) {
930   if (arguments.length < 2) {
931
932     // For classed(string), return true only if the first node has the specified
933     // class or classes. Note that even if the browser supports DOMTokenList, it
934     // probably doesn't support it on SVG elements (which can be animated).
935     if (typeof name === "string") {
936       var node = this.node(),
937           n = (name = name.trim().split(/^|\s+/g)).length,
938           i = -1;
939       if (value = node.classList) {
940         while (++i < n) if (!value.contains(name[i])) return false;
941       } else {
942         value = node.getAttribute("class");
943         while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
944       }
945       return true;
946     }
947
948     // For classed(object), the object specifies the names of classes to add or
949     // remove. The values may be functions that are evaluated for each element.
950     for (value in name) this.each(d3_selection_classed(value, name[value]));
951     return this;
952   }
953
954   // Otherwise, both a name and a value are specified, and are handled as below.
955   return this.each(d3_selection_classed(name, value));
956 };
957
958 function d3_selection_classedRe(name) {
959   return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
960 }
961
962 // Multiple class names are allowed (e.g., "foo bar").
963 function d3_selection_classed(name, value) {
964   name = name.trim().split(/\s+/).map(d3_selection_classedName);
965   var n = name.length;
966
967   function classedConstant() {
968     var i = -1;
969     while (++i < n) name[i](this, value);
970   }
971
972   // When the value is a function, the function is still evaluated only once per
973   // element even if there are multiple class names.
974   function classedFunction() {
975     var i = -1, x = value.apply(this, arguments);
976     while (++i < n) name[i](this, x);
977   }
978
979   return typeof value === "function"
980       ? classedFunction
981       : classedConstant;
982 }
983
984 function d3_selection_classedName(name) {
985   var re = d3_selection_classedRe(name);
986   return function(node, value) {
987     if (c = node.classList) return value ? c.add(name) : c.remove(name);
988     var c = node.getAttribute("class") || "";
989     if (value) {
990       re.lastIndex = 0;
991       if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
992     } else {
993       node.setAttribute("class", d3_collapse(c.replace(re, " ")));
994     }
995   };
996 }
997
998 d3_selectionPrototype.style = function(name, value, priority) {
999   var n = arguments.length;
1000   if (n < 3) {
1001
1002     // For style(object) or style(object, string), the object specifies the
1003     // names and values of the attributes to set or remove. The values may be
1004     // functions that are evaluated for each element. The optional string
1005     // specifies the priority.
1006     if (typeof name !== "string") {
1007       if (n < 2) value = "";
1008       for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
1009       return this;
1010     }
1011
1012     // For style(string), return the computed style value for the first node.
1013     if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
1014
1015     // For style(string, string) or style(string, function), use the default
1016     // priority. The priority is ignored for style(string, null).
1017     priority = "";
1018   }
1019
1020   // Otherwise, a name, value and priority are specified, and handled as below.
1021   return this.each(d3_selection_style(name, value, priority));
1022 };
1023
1024 function d3_selection_style(name, value, priority) {
1025
1026   // For style(name, null) or style(name, null, priority), remove the style
1027   // property with the specified name. The priority is ignored.
1028   function styleNull() {
1029     this.style.removeProperty(name);
1030   }
1031
1032   // For style(name, string) or style(name, string, priority), set the style
1033   // property with the specified name, using the specified priority.
1034   function styleConstant() {
1035     this.style.setProperty(name, value, priority);
1036   }
1037
1038   // For style(name, function) or style(name, function, priority), evaluate the
1039   // function for each element, and set or remove the style property as
1040   // appropriate. When setting, use the specified priority.
1041   function styleFunction() {
1042     var x = value.apply(this, arguments);
1043     if (x == null) this.style.removeProperty(name);
1044     else this.style.setProperty(name, x, priority);
1045   }
1046
1047   return value == null
1048       ? styleNull : (typeof value === "function"
1049       ? styleFunction : styleConstant);
1050 }
1051
1052 d3_selectionPrototype.property = function(name, value) {
1053   if (arguments.length < 2) {
1054
1055     // For property(string), return the property value for the first node.
1056     if (typeof name === "string") return this.node()[name];
1057
1058     // For property(object), the object specifies the names and values of the
1059     // properties to set or remove. The values may be functions that are
1060     // evaluated for each element.
1061     for (value in name) this.each(d3_selection_property(value, name[value]));
1062     return this;
1063   }
1064
1065   // Otherwise, both a name and a value are specified, and are handled as below.
1066   return this.each(d3_selection_property(name, value));
1067 };
1068
1069 function d3_selection_property(name, value) {
1070
1071   // For property(name, null), remove the property with the specified name.
1072   function propertyNull() {
1073     delete this[name];
1074   }
1075
1076   // For property(name, string), set the property with the specified name.
1077   function propertyConstant() {
1078     this[name] = value;
1079   }
1080
1081   // For property(name, function), evaluate the function for each element, and
1082   // set or remove the property as appropriate.
1083   function propertyFunction() {
1084     var x = value.apply(this, arguments);
1085     if (x == null) delete this[name];
1086     else this[name] = x;
1087   }
1088
1089   return value == null
1090       ? propertyNull : (typeof value === "function"
1091       ? propertyFunction : propertyConstant);
1092 }
1093
1094 d3_selectionPrototype.text = function(value) {
1095   return arguments.length
1096       ? this.each(typeof value === "function"
1097       ? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null
1098       ? function() { if (this.textContent !== "") this.textContent = ""; }
1099       : function() { if (this.textContent !== value) this.textContent = value; })
1100       : this.node().textContent;
1101 };
1102
1103 d3_selectionPrototype.html = function(value) {
1104   return arguments.length
1105       ? this.each(typeof value === "function"
1106       ? function() { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; } : value == null
1107       ? function() { this.innerHTML = ""; }
1108       : function() { this.innerHTML = value; })
1109       : this.node().innerHTML;
1110 };
1111
1112 d3_selectionPrototype.append = function(name) {
1113   name = d3_selection_creator(name);
1114   return this.select(function() {
1115     return this.appendChild(name.apply(this, arguments));
1116   });
1117 };
1118
1119 function d3_selection_creator(name) {
1120   return typeof name === "function" ? name
1121       : (name = d3.ns.qualify(name)).local ? function() { return d3_document.createElementNS(name.space, name.local); }
1122       : function() { return d3_document.createElementNS(this.namespaceURI, name); };
1123 }
1124
1125 d3_selectionPrototype.insert = function(name, before) {
1126   name = d3_selection_creator(name);
1127   before = d3_selection_selector(before);
1128   return this.select(function() {
1129     return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments));
1130   });
1131 };
1132
1133 // TODO remove(selector)?
1134 // TODO remove(node)?
1135 // TODO remove(function)?
1136 d3_selectionPrototype.remove = function() {
1137   return this.each(function() {
1138     var parent = this.parentNode;
1139     if (parent) parent.removeChild(this);
1140   });
1141 };
1142
1143 d3_selectionPrototype.data = function(value, key) {
1144   var i = -1,
1145       n = this.length,
1146       group,
1147       node;
1148
1149   // If no value is specified, return the first value.
1150   if (!arguments.length) {
1151     value = new Array(n = (group = this[0]).length);
1152     while (++i < n) {
1153       if (node = group[i]) {
1154         value[i] = node.__data__;
1155       }
1156     }
1157     return value;
1158   }
1159
1160   function bind(group, groupData) {
1161     var i,
1162         n = group.length,
1163         m = groupData.length,
1164         n0 = Math.min(n, m),
1165         updateNodes = new Array(m),
1166         enterNodes = new Array(m),
1167         exitNodes = new Array(n),
1168         node,
1169         nodeData;
1170
1171     if (key) {
1172       var nodeByKeyValue = new d3_Map,
1173           dataByKeyValue = new d3_Map,
1174           keyValues = [],
1175           keyValue;
1176
1177       for (i = -1; ++i < n;) {
1178         keyValue = key.call(node = group[i], node.__data__, i);
1179         if (nodeByKeyValue.has(keyValue)) {
1180           exitNodes[i] = node; // duplicate selection key
1181         } else {
1182           nodeByKeyValue.set(keyValue, node);
1183         }
1184         keyValues.push(keyValue);
1185       }
1186
1187       for (i = -1; ++i < m;) {
1188         keyValue = key.call(groupData, nodeData = groupData[i], i);
1189         if (node = nodeByKeyValue.get(keyValue)) {
1190           updateNodes[i] = node;
1191           node.__data__ = nodeData;
1192         } else if (!dataByKeyValue.has(keyValue)) { // no duplicate data key
1193           enterNodes[i] = d3_selection_dataNode(nodeData);
1194         }
1195         dataByKeyValue.set(keyValue, nodeData);
1196         nodeByKeyValue.remove(keyValue);
1197       }
1198
1199       for (i = -1; ++i < n;) {
1200         if (nodeByKeyValue.has(keyValues[i])) {
1201           exitNodes[i] = group[i];
1202         }
1203       }
1204     } else {
1205       for (i = -1; ++i < n0;) {
1206         node = group[i];
1207         nodeData = groupData[i];
1208         if (node) {
1209           node.__data__ = nodeData;
1210           updateNodes[i] = node;
1211         } else {
1212           enterNodes[i] = d3_selection_dataNode(nodeData);
1213         }
1214       }
1215       for (; i < m; ++i) {
1216         enterNodes[i] = d3_selection_dataNode(groupData[i]);
1217       }
1218       for (; i < n; ++i) {
1219         exitNodes[i] = group[i];
1220       }
1221     }
1222
1223     enterNodes.update
1224         = updateNodes;
1225
1226     enterNodes.parentNode
1227         = updateNodes.parentNode
1228         = exitNodes.parentNode
1229         = group.parentNode;
1230
1231     enter.push(enterNodes);
1232     update.push(updateNodes);
1233     exit.push(exitNodes);
1234   }
1235
1236   var enter = d3_selection_enter([]),
1237       update = d3_selection([]),
1238       exit = d3_selection([]);
1239
1240   if (typeof value === "function") {
1241     while (++i < n) {
1242       bind(group = this[i], value.call(group, group.parentNode.__data__, i));
1243     }
1244   } else {
1245     while (++i < n) {
1246       bind(group = this[i], value);
1247     }
1248   }
1249
1250   update.enter = function() { return enter; };
1251   update.exit = function() { return exit; };
1252   return update;
1253 };
1254
1255 function d3_selection_dataNode(data) {
1256   return {__data__: data};
1257 }
1258
1259 d3_selectionPrototype.datum = function(value) {
1260   return arguments.length
1261       ? this.property("__data__", value)
1262       : this.property("__data__");
1263 };
1264
1265 d3_selectionPrototype.filter = function(filter) {
1266   var subgroups = [],
1267       subgroup,
1268       group,
1269       node;
1270
1271   if (typeof filter !== "function") filter = d3_selection_filter(filter);
1272
1273   for (var j = 0, m = this.length; j < m; j++) {
1274     subgroups.push(subgroup = []);
1275     subgroup.parentNode = (group = this[j]).parentNode;
1276     for (var i = 0, n = group.length; i < n; i++) {
1277       if ((node = group[i]) && filter.call(node, node.__data__, i)) {
1278         subgroup.push(node);
1279       }
1280     }
1281   }
1282
1283   return d3_selection(subgroups);
1284 };
1285
1286 function d3_selection_filter(selector) {
1287   return function() {
1288     return d3_selectMatches(this, selector);
1289   };
1290 }
1291
1292 d3_selectionPrototype.order = function() {
1293   for (var j = -1, m = this.length; ++j < m;) {
1294     for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
1295       if (node = group[i]) {
1296         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
1297         next = node;
1298       }
1299     }
1300   }
1301   return this;
1302 };
1303
1304 d3_selectionPrototype.sort = function(comparator) {
1305   comparator = d3_selection_sortComparator.apply(this, arguments);
1306   for (var j = -1, m = this.length; ++j < m;) this[j].sort(comparator);
1307   return this.order();
1308 };
1309
1310 function d3_selection_sortComparator(comparator) {
1311   if (!arguments.length) comparator = d3.ascending;
1312   return function(a, b) {
1313     return (!a - !b) || comparator(a.__data__, b.__data__);
1314   };
1315 }
1316
1317 d3_selectionPrototype.each = function(callback) {
1318   return d3_selection_each(this, function(node, i, j) {
1319     callback.call(node, node.__data__, i, j);
1320   });
1321 };
1322
1323 function d3_selection_each(groups, callback) {
1324   for (var j = 0, m = groups.length; j < m; j++) {
1325     for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
1326       if (node = group[i]) callback(node, i, j);
1327     }
1328   }
1329   return groups;
1330 }
1331
1332 d3_selectionPrototype.call = function(callback) {
1333   var args = d3_array(arguments);
1334   callback.apply(args[0] = this, args);
1335   return this;
1336 };
1337
1338 d3_selectionPrototype.empty = function() {
1339   return !this.node();
1340 };
1341
1342 d3_selectionPrototype.node = function() {
1343   for (var j = 0, m = this.length; j < m; j++) {
1344     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
1345       var node = group[i];
1346       if (node) return node;
1347     }
1348   }
1349   return null;
1350 };
1351
1352 d3_selectionPrototype.size = function() {
1353   var n = 0;
1354   this.each(function() { ++n; });
1355   return n;
1356 };
1357
1358 function d3_selection_enter(selection) {
1359   d3_subclass(selection, d3_selection_enterPrototype);
1360   return selection;
1361 }
1362
1363 var d3_selection_enterPrototype = [];
1364
1365 d3.selection.enter = d3_selection_enter;
1366 d3.selection.enter.prototype = d3_selection_enterPrototype;
1367
1368 d3_selection_enterPrototype.append = d3_selectionPrototype.append;
1369 d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
1370 d3_selection_enterPrototype.node = d3_selectionPrototype.node;
1371 d3_selection_enterPrototype.call = d3_selectionPrototype.call;
1372 d3_selection_enterPrototype.size = d3_selectionPrototype.size;
1373
1374
1375 d3_selection_enterPrototype.select = function(selector) {
1376   var subgroups = [],
1377       subgroup,
1378       subnode,
1379       upgroup,
1380       group,
1381       node;
1382
1383   for (var j = -1, m = this.length; ++j < m;) {
1384     upgroup = (group = this[j]).update;
1385     subgroups.push(subgroup = []);
1386     subgroup.parentNode = group.parentNode;
1387     for (var i = -1, n = group.length; ++i < n;) {
1388       if (node = group[i]) {
1389         subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
1390         subnode.__data__ = node.__data__;
1391       } else {
1392         subgroup.push(null);
1393       }
1394     }
1395   }
1396
1397   return d3_selection(subgroups);
1398 };
1399
1400 d3_selection_enterPrototype.insert = function(name, before) {
1401   if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
1402   return d3_selectionPrototype.insert.call(this, name, before);
1403 };
1404
1405 function d3_selection_enterInsertBefore(enter) {
1406   var i0, j0;
1407   return function(d, i, j) {
1408     var group = enter[j].update,
1409         n = group.length,
1410         node;
1411     if (j != j0) j0 = j, i0 = 0;
1412     if (i >= i0) i0 = i + 1;
1413     while (!(node = group[i0]) && ++i0 < n);
1414     return node;
1415   };
1416 }
1417
1418 d3_selectionPrototype.transition = function() {
1419   var id = d3_transitionInheritId || ++d3_transitionId,
1420       subgroups = [],
1421       subgroup,
1422       node,
1423       transition = d3_transitionInherit || {time: Date.now(), ease: d3_ease_cubicInOut, delay: 0, duration: 250};
1424
1425   for (var j = -1, m = this.length; ++j < m;) {
1426     subgroups.push(subgroup = []);
1427     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
1428       if (node = group[i]) d3_transitionNode(node, i, id, transition);
1429       subgroup.push(node);
1430     }
1431   }
1432
1433   return d3_transition(subgroups, id);
1434 };
1435
1436 // TODO fast singleton implementation?
1437 d3.select = function(node) {
1438   var group = [typeof node === "string" ? d3_select(node, d3_document) : node];
1439   group.parentNode = d3_documentElement;
1440   return d3_selection([group]);
1441 };
1442
1443 d3.selectAll = function(nodes) {
1444   var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
1445   group.parentNode = d3_documentElement;
1446   return d3_selection([group]);
1447 };
1448
1449 var d3_selectionRoot = d3.select(d3_documentElement);
1450
1451 d3_selectionPrototype.on = function(type, listener, capture) {
1452   var n = arguments.length;
1453   if (n < 3) {
1454
1455     // For on(object) or on(object, boolean), the object specifies the event
1456     // types and listeners to add or remove. The optional boolean specifies
1457     // whether the listener captures events.
1458     if (typeof type !== "string") {
1459       if (n < 2) listener = false;
1460       for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
1461       return this;
1462     }
1463
1464     // For on(string), return the listener for the first node.
1465     if (n < 2) return (n = this.node()["__on" + type]) && n._;
1466
1467     // For on(string, function), use the default capture.
1468     capture = false;
1469   }
1470
1471   // Otherwise, a type, listener and capture are specified, and handled as below.
1472   return this.each(d3_selection_on(type, listener, capture));
1473 };
1474
1475 function d3_selection_on(type, listener, capture) {
1476   var name = "__on" + type,
1477       i = type.indexOf("."),
1478       wrap = d3_selection_onListener;
1479
1480   if (i > 0) type = type.substring(0, i);
1481   var filter = d3_selection_onFilters.get(type);
1482   if (filter) type = filter, wrap = d3_selection_onFilter;
1483
1484   function onRemove() {
1485     var l = this[name];
1486     if (l) {
1487       this.removeEventListener(type, l, l.$);
1488       delete this[name];
1489     }
1490   }
1491
1492   function onAdd() {
1493     var l = wrap(listener, d3_array(arguments));
1494     if (typeof Raven !== 'undefined') l = Raven.wrap(l);
1495     onRemove.call(this);
1496     this.addEventListener(type, this[name] = l, l.$ = capture);
1497     l._ = listener;
1498   }
1499
1500   function removeAll() {
1501     var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"),
1502         match;
1503     for (var name in this) {
1504       if (match = name.match(re)) {
1505         var l = this[name];
1506         this.removeEventListener(match[1], l, l.$);
1507         delete this[name];
1508       }
1509     }
1510   }
1511
1512   return i
1513       ? listener ? onAdd : onRemove
1514       : listener ? d3_noop : removeAll;
1515 }
1516
1517 var d3_selection_onFilters = d3.map({
1518   mouseenter: "mouseover",
1519   mouseleave: "mouseout"
1520 });
1521
1522 d3_selection_onFilters.forEach(function(k) {
1523   if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
1524 });
1525
1526 function d3_selection_onListener(listener, argumentz) {
1527   return function(e) {
1528     var o = d3.event; // Events can be reentrant (e.g., focus).
1529     d3.event = e;
1530     argumentz[0] = this.__data__;
1531     try {
1532       listener.apply(this, argumentz);
1533     } finally {
1534       d3.event = o;
1535     }
1536   };
1537 }
1538
1539 function d3_selection_onFilter(listener, argumentz) {
1540   var l = d3_selection_onListener(listener, argumentz);
1541   return function(e) {
1542     var target = this, related = e.relatedTarget;
1543     if (!related || (related !== target && !(related.compareDocumentPosition(target) & 8))) {
1544       l.call(target, e);
1545     }
1546   };
1547 }
1548
1549 var d3_event_dragSelect = d3_vendorSymbol(d3_documentElement.style, "userSelect"),
1550     d3_event_dragId = 0;
1551
1552 function d3_event_dragSuppress() {
1553   var name = ".dragsuppress-" + ++d3_event_dragId,
1554       touchmove = "touchmove" + name,
1555       selectstart = "selectstart" + name,
1556       dragstart = "dragstart" + name,
1557       click = "click" + name,
1558       w = d3.select(d3_window).on(touchmove, d3_eventPreventDefault).on(selectstart, d3_eventPreventDefault).on(dragstart, d3_eventPreventDefault),
1559       style = d3_documentElement.style,
1560       select = style[d3_event_dragSelect];
1561   style[d3_event_dragSelect] = "none";
1562   return function(suppressClick) {
1563     w.on(name, null);
1564     style[d3_event_dragSelect] = select;
1565     if (suppressClick) { // suppress the next click, but only if it’s immediate
1566       function off() { w.on(click, null); }
1567       w.on(click, function() { d3_eventCancel(); off(); }, true);
1568       setTimeout(off, 0);
1569     }
1570   };
1571 }
1572
1573 d3.mouse = function(container) {
1574   return d3_mousePoint(container, d3_eventSource());
1575 };
1576
1577 // https://bugs.webkit.org/show_bug.cgi?id=44083
1578 var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
1579
1580 function d3_mousePoint(container, e) {
1581   var svg = container.ownerSVGElement || container;
1582   if (svg.createSVGPoint) {
1583     var point = svg.createSVGPoint();
1584     if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {
1585       svg = d3.select("body").append("svg").style({
1586         position: "absolute",
1587         top: 0,
1588         left: 0,
1589         margin: 0,
1590         padding: 0,
1591         border: "none"
1592       }, "important");
1593       var ctm = svg[0][0].getScreenCTM();
1594       d3_mouse_bug44083 = !(ctm.f || ctm.e);
1595       svg.remove();
1596     }
1597     if (d3_mouse_bug44083) {
1598       point.x = e.pageX;
1599       point.y = e.pageY;
1600     } else {
1601       point.x = e.clientX;
1602       point.y = e.clientY;
1603     }
1604     point = point.matrixTransform(container.getScreenCTM().inverse());
1605     return [point.x, point.y];
1606   }
1607   var rect = container.getBoundingClientRect();
1608   return [e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop];
1609 };
1610
1611 d3.touches = function(container, touches) {
1612   if (arguments.length < 2) touches = d3_eventSource().touches;
1613   return touches ? d3_array(touches).map(function(touch) {
1614     var point = d3_mousePoint(container, touch);
1615     point.identifier = touch.identifier;
1616     return point;
1617   }) : [];
1618 };
1619
1620 d3.behavior.zoom = function() {
1621   var translate = [0, 0],
1622       translate0, // translate when we started zooming (to avoid drift)
1623       scale = 1,
1624       scaleExtent = d3_behavior_zoomInfinity,
1625       mousedown = "mousedown.zoom",
1626       mousemove = "mousemove.zoom",
1627       mouseup = "mouseup.zoom",
1628       event = d3_eventDispatch(zoom, "zoom"),
1629       x0,
1630       x1,
1631       y0,
1632       y1,
1633       touchtime; // time of last touchstart (to detect double-tap)
1634
1635   function zoom() {
1636     this.on(mousedown, mousedowned)
1637         .on(d3_behavior_zoomWheel + ".zoom", mousewheeled)
1638         .on(mousemove, mousewheelreset)
1639         .on("dblclick.zoom", dblclicked)
1640         .on("touchstart.zoom", touchstarted);
1641   }
1642
1643   zoom.translate = function(x) {
1644     if (!arguments.length) return translate;
1645     translate = x.map(Number);
1646     rescale();
1647     return zoom;
1648   };
1649
1650   zoom.scale = function(x) {
1651     if (!arguments.length) return scale;
1652     scale = +x;
1653     rescale();
1654     return zoom;
1655   };
1656
1657   zoom.scaleExtent = function(x) {
1658     if (!arguments.length) return scaleExtent;
1659     scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
1660     return zoom;
1661   };
1662
1663   zoom.x = function(z) {
1664     if (!arguments.length) return x1;
1665     x1 = z;
1666     x0 = z.copy();
1667     translate = [0, 0];
1668     scale = 1;
1669     return zoom;
1670   };
1671
1672   zoom.y = function(z) {
1673     if (!arguments.length) return y1;
1674     y1 = z;
1675     y0 = z.copy();
1676     translate = [0, 0];
1677     scale = 1;
1678     return zoom;
1679   };
1680
1681   function location(p) {
1682     return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
1683   }
1684
1685   function point(l) {
1686     return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
1687   }
1688
1689   function scaleTo(s) {
1690     scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
1691   }
1692
1693   function translateTo(p, l) {
1694     l = point(l);
1695     translate[0] += p[0] - l[0];
1696     translate[1] += p[1] - l[1];
1697   }
1698
1699   function rescale() {
1700     if (x1) x1.domain(x0.range().map(function(x) { return (x - translate[0]) / scale; }).map(x0.invert));
1701     if (y1) y1.domain(y0.range().map(function(y) { return (y - translate[1]) / scale; }).map(y0.invert));
1702   }
1703
1704   function dispatch(event) {
1705     rescale();
1706     event({type: "zoom", scale: scale, translate: translate});
1707   }
1708
1709   function mousedowned() {
1710     var target = this,
1711         event_ = event.of(target, arguments),
1712         eventTarget = d3.event.target,
1713         dragged = 0,
1714         w = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended),
1715         l = location(d3.mouse(target)),
1716         dragRestore = d3_event_dragSuppress();
1717
1718     function moved() {
1719       dragged = 1;
1720       translateTo(d3.mouse(target), l);
1721       dispatch(event_);
1722     }
1723
1724     function ended() {
1725       w.on(mousemove, d3_window === target ? mousewheelreset : null).on(mouseup, null);
1726       dragRestore(dragged && d3.event.target === eventTarget);
1727     }
1728   }
1729
1730   function touchstarted() {
1731     var target = this,
1732         event_ = event.of(target, arguments),
1733         touches = d3.touches(target),
1734         locations = {},
1735         distance0 = 0, // distance² between initial touches
1736         scale0 = scale, // scale when we started touching
1737         now = Date.now(),
1738         name = "zoom-" + d3.event.changedTouches[0].identifier,
1739         touchmove = "touchmove." + name,
1740         touchend = "touchend." + name,
1741         w = d3.select(d3_window).on(touchmove, moved).on(touchend, ended),
1742         t = d3.select(target).on(mousedown, null), // prevent duplicate events
1743         dragRestore = d3_event_dragSuppress();
1744
1745     touches.forEach(function(t) { locations[t.identifier] = location(t); });
1746
1747     if (touches.length === 1) {
1748       if (now - touchtime < 500) { // dbltap
1749         var p = touches[0], l = location(touches[0]);
1750         scaleTo(scale * 2);
1751         translateTo(p, l);
1752         d3_eventPreventDefault();
1753         dispatch(event_);
1754       }
1755       touchtime = now;
1756     } else if (touches.length > 1) {
1757       var p = touches[0], q = touches[1],
1758           dx = p[0] - q[0], dy = p[1] - q[1];
1759       distance0 = dx * dx + dy * dy;
1760     }
1761
1762     function moved() {
1763       var touches = d3.touches(target),
1764           p0 = touches[0],
1765           l0 = locations[p0.identifier];
1766
1767       if (p1 = touches[1]) {
1768         var p1, l1 = locations[p1.identifier],
1769             scale1 = d3.event.scale;
1770         if (scale1 == null) {
1771           var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1;
1772           scale1 = distance0 && Math.sqrt(distance1 / distance0);
1773         }
1774         p0 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
1775         l0 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
1776         scaleTo(scale1 * scale0);
1777       }
1778
1779       touchtime = null;
1780       translateTo(p0, l0);
1781       dispatch(event_);
1782     }
1783
1784     function ended() {
1785       w.on(touchmove, null).on(touchend, null);
1786       t.on(mousedown, mousedowned);
1787       dragRestore();
1788     }
1789   }
1790
1791   function mousewheeled() {
1792     d3_eventPreventDefault();
1793     if (!translate0) translate0 = location(d3.mouse(this));
1794     scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
1795     translateTo(d3.mouse(this), translate0);
1796     dispatch(event.of(this, arguments));
1797   }
1798
1799   function mousewheelreset() {
1800     translate0 = null;
1801   }
1802
1803   function dblclicked() {
1804     var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;
1805     scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
1806     translateTo(p, l);
1807     dispatch(event.of(this, arguments));
1808   }
1809
1810   return d3.rebind(zoom, event, "on");
1811 };
1812
1813 var d3_behavior_zoomInfinity = [0, Infinity]; // default scale extent
1814
1815 // https://developer.mozilla.org/en-US/docs/Mozilla_event_reference/wheel
1816 var d3_behavior_zoomDelta, d3_behavior_zoomWheel
1817     = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); }, "wheel")
1818     : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { return d3.event.wheelDelta; }, "mousewheel")
1819     : (d3_behavior_zoomDelta = function() { return -d3.event.detail; }, "MozMousePixelScroll");
1820 function d3_functor(v) {
1821   return typeof v === "function" ? v : function() { return v; };
1822 }
1823
1824 d3.functor = d3_functor;
1825
1826 var d3_timer_queueHead,
1827     d3_timer_queueTail,
1828     d3_timer_interval, // is an interval (or frame) active?
1829     d3_timer_timeout, // is a timeout active?
1830     d3_timer_active, // active timer object
1831     d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { setTimeout(callback, 17); };
1832
1833 // The timer will continue to fire until callback returns true.
1834 d3.timer = function(callback, delay, then) {
1835   var n = arguments.length;
1836   if (n < 2) delay = 0;
1837   if (n < 3) then = Date.now();
1838
1839   // Add the callback to the tail of the queue.
1840   var time = then + delay, timer = {callback: callback, time: time, next: null};
1841   if (d3_timer_queueTail) d3_timer_queueTail.next = timer;
1842   else d3_timer_queueHead = timer;
1843   d3_timer_queueTail = timer;
1844
1845   // Start animatin'!
1846   if (!d3_timer_interval) {
1847     d3_timer_timeout = clearTimeout(d3_timer_timeout);
1848     d3_timer_interval = 1;
1849     d3_timer_frame(d3_timer_step);
1850   }
1851 };
1852
1853 function d3_timer_step() {
1854   var now = d3_timer_mark(),
1855       delay = d3_timer_sweep() - now;
1856   if (delay > 24) {
1857     if (isFinite(delay)) {
1858       clearTimeout(d3_timer_timeout);
1859       d3_timer_timeout = setTimeout(d3_timer_step, delay);
1860     }
1861     d3_timer_interval = 0;
1862   } else {
1863     d3_timer_interval = 1;
1864     d3_timer_frame(d3_timer_step);
1865   }
1866 }
1867
1868 d3.timer.flush = function() {
1869   d3_timer_mark();
1870   d3_timer_sweep();
1871 };
1872
1873 function d3_timer_replace(callback, delay, then) {
1874   var n = arguments.length;
1875   if (n < 2) delay = 0;
1876   if (n < 3) then = Date.now();
1877   d3_timer_active.callback = callback;
1878   d3_timer_active.time = then + delay;
1879 }
1880
1881 function d3_timer_mark() {
1882   var now = Date.now();
1883   d3_timer_active = d3_timer_queueHead;
1884   while (d3_timer_active) {
1885     if (now >= d3_timer_active.time) d3_timer_active.flush = d3_timer_active.callback(now - d3_timer_active.time);
1886     d3_timer_active = d3_timer_active.next;
1887   }
1888   return now;
1889 }
1890
1891 // Flush after callbacks to avoid concurrent queue modification.
1892 // Returns the time of the earliest active timer, post-sweep.
1893 function d3_timer_sweep() {
1894   var t0,
1895       t1 = d3_timer_queueHead,
1896       time = Infinity;
1897   while (t1) {
1898     if (t1.flush) {
1899       t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
1900     } else {
1901       if (t1.time < time) time = t1.time;
1902       t1 = (t0 = t1).next;
1903     }
1904   }
1905   d3_timer_queueTail = t0;
1906   return time;
1907 }
1908 var π = Math.PI,
1909     ε = 1e-6,
1910     ε2 = ε * ε,
1911     d3_radians = π / 180,
1912     d3_degrees = 180 / π;
1913
1914 function d3_sgn(x) {
1915   return x > 0 ? 1 : x < 0 ? -1 : 0;
1916 }
1917
1918 function d3_acos(x) {
1919   return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
1920 }
1921
1922 function d3_asin(x) {
1923   return x > 1 ? π / 2 : x < -1 ? -π / 2 : Math.asin(x);
1924 }
1925
1926 function d3_sinh(x) {
1927   return (Math.exp(x) - Math.exp(-x)) / 2;
1928 }
1929
1930 function d3_cosh(x) {
1931   return (Math.exp(x) + Math.exp(-x)) / 2;
1932 }
1933
1934 function d3_haversin(x) {
1935   return (x = Math.sin(x / 2)) * x;
1936 }
1937 d3.geo = {};
1938 function d3_identity(d) {
1939   return d;
1940 }
1941 function d3_true() {
1942   return true;
1943 }
1944
1945 function d3_geo_spherical(cartesian) {
1946   return [
1947     Math.atan2(cartesian[1], cartesian[0]),
1948     d3_asin(cartesian[2])
1949   ];
1950 }
1951
1952 function d3_geo_sphericalEqual(a, b) {
1953   return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
1954 }
1955
1956 // General spherical polygon clipping algorithm: takes a polygon, cuts it into
1957 // visible line segments and rejoins the segments by interpolating along the
1958 // clip edge.
1959 function d3_geo_clipPolygon(segments, compare, inside, interpolate, listener) {
1960   var subject = [],
1961       clip = [];
1962
1963   segments.forEach(function(segment) {
1964     if ((n = segment.length - 1) <= 0) return;
1965     var n, p0 = segment[0], p1 = segment[n];
1966
1967     // If the first and last points of a segment are coincident, then treat as
1968     // a closed ring.
1969     // TODO if all rings are closed, then the winding order of the exterior
1970     // ring should be checked.
1971     if (d3_geo_sphericalEqual(p0, p1)) {
1972       listener.lineStart();
1973       for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
1974       listener.lineEnd();
1975       return;
1976     }
1977
1978     var a = {point: p0, points: segment, other: null, visited: false, entry: true, subject: true},
1979         b = {point: p0, points: [p0], other: a, visited: false, entry: false, subject: false};
1980     a.other = b;
1981     subject.push(a);
1982     clip.push(b);
1983     a = {point: p1, points: [p1], other: null, visited: false, entry: false, subject: true};
1984     b = {point: p1, points: [p1], other: a, visited: false, entry: true, subject: false};
1985     a.other = b;
1986     subject.push(a);
1987     clip.push(b);
1988   });
1989   clip.sort(compare);
1990   d3_geo_clipPolygonLinkCircular(subject);
1991   d3_geo_clipPolygonLinkCircular(clip);
1992   if (!subject.length) return;
1993
1994   if (inside) for (var i = 1, e = !inside(clip[0].point), n = clip.length; i < n; ++i) {
1995     clip[i].entry = (e = !e);
1996   }
1997
1998   var start = subject[0],
1999       current,
2000       points,
2001       point;
2002   while (1) {
2003     // Find first unvisited intersection.
2004     current = start;
2005     while (current.visited) if ((current = current.next) === start) return;
2006     points = current.points;
2007     listener.lineStart();
2008     do {
2009       current.visited = current.other.visited = true;
2010       if (current.entry) {
2011         if (current.subject) {
2012           for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
2013         } else {
2014           interpolate(current.point, current.next.point, 1, listener);
2015         }
2016         current = current.next;
2017       } else {
2018         if (current.subject) {
2019           points = current.prev.points;
2020           for (var i = points.length; --i >= 0;) listener.point((point = points[i])[0], point[1]);
2021         } else {
2022           interpolate(current.point, current.prev.point, -1, listener);
2023         }
2024         current = current.prev;
2025       }
2026       current = current.other;
2027       points = current.points;
2028     } while (!current.visited);
2029     listener.lineEnd();
2030   }
2031 }
2032
2033 function d3_geo_clipPolygonLinkCircular(array) {
2034   if (!(n = array.length)) return;
2035   var n,
2036       i = 0,
2037       a = array[0],
2038       b;
2039   while (++i < n) {
2040     a.next = b = array[i];
2041     b.prev = a;
2042     a = b;
2043   }
2044   a.next = b = array[0];
2045   b.prev = a;
2046 }
2047
2048 function d3_geo_clip(pointVisible, clipLine, interpolate, polygonContains) {
2049   return function(listener) {
2050     var line = clipLine(listener);
2051
2052     var clip = {
2053       point: point,
2054       lineStart: lineStart,
2055       lineEnd: lineEnd,
2056       polygonStart: function() {
2057         clip.point = pointRing;
2058         clip.lineStart = ringStart;
2059         clip.lineEnd = ringEnd;
2060         segments = [];
2061         polygon = [];
2062         listener.polygonStart();
2063       },
2064       polygonEnd: function() {
2065         clip.point = point;
2066         clip.lineStart = lineStart;
2067         clip.lineEnd = lineEnd;
2068
2069         segments = d3.merge(segments);
2070         if (segments.length) {
2071           d3_geo_clipPolygon(segments, d3_geo_clipSort, null, interpolate, listener);
2072         } else if (polygonContains(polygon)) {
2073           listener.lineStart();
2074           interpolate(null, null, 1, listener);
2075           listener.lineEnd();
2076         }
2077         listener.polygonEnd();
2078         segments = polygon = null;
2079       },
2080       sphere: function() {
2081         listener.polygonStart();
2082         listener.lineStart();
2083         interpolate(null, null, 1, listener);
2084         listener.lineEnd();
2085         listener.polygonEnd();
2086       }
2087     };
2088
2089     function point(λ, φ) { if (pointVisible(λ, φ)) listener.point(λ, φ); }
2090     function pointLine(λ, φ) { line.point(λ, φ); }
2091     function lineStart() { clip.point = pointLine; line.lineStart(); }
2092     function lineEnd() { clip.point = point; line.lineEnd(); }
2093
2094     var segments;
2095
2096     var buffer = d3_geo_clipBufferListener(),
2097         ringListener = clipLine(buffer),
2098         polygon,
2099         ring;
2100
2101     function pointRing(λ, φ) {
2102       ringListener.point(λ, φ);
2103       ring.push([λ, φ]);
2104     }
2105
2106     function ringStart() {
2107       ringListener.lineStart();
2108       ring = [];
2109     }
2110
2111     function ringEnd() {
2112       pointRing(ring[0][0], ring[0][1]);
2113       ringListener.lineEnd();
2114
2115       var clean = ringListener.clean(),
2116           ringSegments = buffer.buffer(),
2117           segment,
2118           n = ringSegments.length;
2119
2120       ring.pop();
2121       polygon.push(ring);
2122       ring = null;
2123
2124       if (!n) return;
2125
2126       // No intersections.
2127       if (clean & 1) {
2128         segment = ringSegments[0];
2129         var n = segment.length - 1,
2130             i = -1,
2131             point;
2132         listener.lineStart();
2133         while (++i < n) listener.point((point = segment[i])[0], point[1]);
2134         listener.lineEnd();
2135         return;
2136       }
2137
2138       // Rejoin connected segments.
2139       // TODO reuse bufferListener.rejoin()?
2140       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
2141
2142       segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
2143     }
2144
2145     return clip;
2146   };
2147 }
2148
2149 function d3_geo_clipSegmentLength1(segment) {
2150   return segment.length > 1;
2151 }
2152
2153 function d3_geo_clipBufferListener() {
2154   var lines = [],
2155       line;
2156   return {
2157     lineStart: function() { lines.push(line = []); },
2158     point: function(λ, φ) { line.push([λ, φ]); },
2159     lineEnd: d3_noop,
2160     buffer: function() {
2161       var buffer = lines;
2162       lines = [];
2163       line = null;
2164       return buffer;
2165     },
2166     rejoin: function() {
2167       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
2168     }
2169   };
2170 }
2171
2172 // Intersection points are sorted along the clip edge. For both antimeridian
2173 // cutting and circle clipping, the same comparison is used.
2174 function d3_geo_clipSort(a, b) {
2175   return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1])
2176        - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]);
2177 }
2178 // Adds floating point numbers with twice the normal precision.
2179 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
2180 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
2181 // 305–363 (1997).
2182 // Code adapted from GeographicLib by Charles F. F. Karney,
2183 // http://geographiclib.sourceforge.net/
2184 // See lib/geographiclib/LICENSE for details.
2185
2186 function d3_adder() {}
2187
2188 d3_adder.prototype = {
2189   s: 0, // rounded value
2190   t: 0, // exact error
2191   add: function(y) {
2192     d3_adderSum(y, this.t, d3_adderTemp);
2193     d3_adderSum(d3_adderTemp.s, this.s, this);
2194     if (this.s) this.t += d3_adderTemp.t;
2195     else this.s = d3_adderTemp.t;
2196   },
2197   reset: function() {
2198     this.s = this.t = 0;
2199   },
2200   valueOf: function() {
2201     return this.s;
2202   }
2203 };
2204
2205 var d3_adderTemp = new d3_adder;
2206
2207 function d3_adderSum(a, b, o) {
2208   var x = o.s = a + b, // a + b
2209       bv = x - a, av = x - bv; // b_virtual & a_virtual
2210   o.t = (a - av) + (b - bv); // a_roundoff + b_roundoff
2211 }
2212
2213 d3.geo.stream = function(object, listener) {
2214   if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
2215     d3_geo_streamObjectType[object.type](object, listener);
2216   } else {
2217     d3_geo_streamGeometry(object, listener);
2218   }
2219 };
2220
2221 function d3_geo_streamGeometry(geometry, listener) {
2222   if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
2223     d3_geo_streamGeometryType[geometry.type](geometry, listener);
2224   }
2225 }
2226
2227 var d3_geo_streamObjectType = {
2228   Feature: function(feature, listener) {
2229     d3_geo_streamGeometry(feature.geometry, listener);
2230   },
2231   FeatureCollection: function(object, listener) {
2232     var features = object.features, i = -1, n = features.length;
2233     while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
2234   }
2235 };
2236
2237 var d3_geo_streamGeometryType = {
2238   Sphere: function(object, listener) {
2239     listener.sphere();
2240   },
2241   Point: function(object, listener) {
2242     var coordinate = object.coordinates;
2243     listener.point(coordinate[0], coordinate[1]);
2244   },
2245   MultiPoint: function(object, listener) {
2246     var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;
2247     while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
2248   },
2249   LineString: function(object, listener) {
2250     d3_geo_streamLine(object.coordinates, listener, 0);
2251   },
2252   MultiLineString: function(object, listener) {
2253     var coordinates = object.coordinates, i = -1, n = coordinates.length;
2254     while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
2255   },
2256   Polygon: function(object, listener) {
2257     d3_geo_streamPolygon(object.coordinates, listener);
2258   },
2259   MultiPolygon: function(object, listener) {
2260     var coordinates = object.coordinates, i = -1, n = coordinates.length;
2261     while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
2262   },
2263   GeometryCollection: function(object, listener) {
2264     var geometries = object.geometries, i = -1, n = geometries.length;
2265     while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
2266   }
2267 };
2268
2269 function d3_geo_streamLine(coordinates, listener, closed) {
2270   var i = -1, n = coordinates.length - closed, coordinate;
2271   listener.lineStart();
2272   while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
2273   listener.lineEnd();
2274 }
2275
2276 function d3_geo_streamPolygon(coordinates, listener) {
2277   var i = -1, n = coordinates.length;
2278   listener.polygonStart();
2279   while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
2280   listener.polygonEnd();
2281 }
2282
2283 d3.geo.area = function(object) {
2284   d3_geo_areaSum = 0;
2285   d3.geo.stream(object, d3_geo_area);
2286   return d3_geo_areaSum;
2287 };
2288
2289 var d3_geo_areaSum,
2290     d3_geo_areaRingSum = new d3_adder;
2291
2292 var d3_geo_area = {
2293   sphere: function() { d3_geo_areaSum += 4 * π; },
2294   point: d3_noop,
2295   lineStart: d3_noop,
2296   lineEnd: d3_noop,
2297
2298   // Only count area for polygon rings.
2299   polygonStart: function() {
2300     d3_geo_areaRingSum.reset();
2301     d3_geo_area.lineStart = d3_geo_areaRingStart;
2302   },
2303   polygonEnd: function() {
2304     var area = 2 * d3_geo_areaRingSum;
2305     d3_geo_areaSum += area < 0 ? 4 * π + area : area;
2306     d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
2307   }
2308 };
2309
2310 function d3_geo_areaRingStart() {
2311   var λ00, φ00, λ0, cosφ0, sinφ0; // start point and previous point
2312
2313   // For the first point, …
2314   d3_geo_area.point = function(λ, φ) {
2315     d3_geo_area.point = nextPoint;
2316     λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), sinφ0 = Math.sin(φ);
2317   };
2318
2319   // For subsequent points, …
2320   function nextPoint(λ, φ) {
2321     λ *= d3_radians;
2322     φ = φ * d3_radians / 2 + π / 4; // half the angular distance from south pole
2323
2324     // Spherical excess E for a spherical triangle with vertices: south pole,
2325     // previous point, current point.  Uses a formula derived from Cagnoli’s
2326     // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
2327     var dλ = λ - λ0,
2328         cosφ = Math.cos(φ),
2329         sinφ = Math.sin(φ),
2330         k = sinφ0 * sinφ,
2331         u = cosφ0 * cosφ + k * Math.cos(dλ),
2332         v = k * Math.sin(dλ);
2333     d3_geo_areaRingSum.add(Math.atan2(v, u));
2334
2335     // Advance the previous points.
2336     λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
2337   }
2338
2339   // For the last point, return to the start.
2340   d3_geo_area.lineEnd = function() {
2341     nextPoint(λ00, φ00);
2342   };
2343 }
2344 // TODO
2345 // cross and scale return new vectors,
2346 // whereas add and normalize operate in-place
2347
2348 function d3_geo_cartesian(spherical) {
2349   var λ = spherical[0],
2350       φ = spherical[1],
2351       cosφ = Math.cos(φ);
2352   return [
2353     cosφ * Math.cos(λ),
2354     cosφ * Math.sin(λ),
2355     Math.sin(φ)
2356   ];
2357 }
2358
2359 function d3_geo_cartesianDot(a, b) {
2360   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
2361 }
2362
2363 function d3_geo_cartesianCross(a, b) {
2364   return [
2365     a[1] * b[2] - a[2] * b[1],
2366     a[2] * b[0] - a[0] * b[2],
2367     a[0] * b[1] - a[1] * b[0]
2368   ];
2369 }
2370
2371 function d3_geo_cartesianAdd(a, b) {
2372   a[0] += b[0];
2373   a[1] += b[1];
2374   a[2] += b[2];
2375 }
2376
2377 function d3_geo_cartesianScale(vector, k) {
2378   return [
2379     vector[0] * k,
2380     vector[1] * k,
2381     vector[2] * k
2382   ];
2383 }
2384
2385 function d3_geo_cartesianNormalize(d) {
2386   var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
2387   d[0] /= l;
2388   d[1] /= l;
2389   d[2] /= l;
2390 }
2391
2392 function d3_geo_pointInPolygon(point, polygon) {
2393   var meridian = point[0],
2394       parallel = point[1],
2395       meridianNormal = [Math.sin(meridian), -Math.cos(meridian), 0],
2396       polarAngle = 0,
2397       polar = false,
2398       southPole = false,
2399       winding = 0;
2400   d3_geo_areaRingSum.reset();
2401
2402   for (var i = 0, n = polygon.length; i < n; ++i) {
2403     var ring = polygon[i],
2404         m = ring.length;
2405     if (!m) continue;
2406     var point0 = ring[0],
2407         λ0 = point0[0],
2408         φ0 = point0[1] / 2 + π / 4,
2409         sinφ0 = Math.sin(φ0),
2410         cosφ0 = Math.cos(φ0),
2411         j = 1;
2412
2413     while (true) {
2414       if (j === m) j = 0;
2415       point = ring[j];
2416       var λ = point[0],
2417           φ = point[1] / 2 + π / 4,
2418           sinφ = Math.sin(φ),
2419           cosφ = Math.cos(φ),
2420           dλ = λ - λ0,
2421           antimeridian = Math.abs(dλ) > π,
2422           k = sinφ0 * sinφ;
2423       d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(dλ), cosφ0 * cosφ + k * Math.cos(dλ)));
2424
2425       if (Math.abs(φ) < ε) southPole = true;
2426       polarAngle += antimeridian ? dλ + (dλ >= 0 ? 2 : -2) * π : dλ;
2427
2428       // Are the longitudes either side of the point's meridian, and are the
2429       // latitudes smaller than the parallel?
2430       if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
2431         var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
2432         d3_geo_cartesianNormalize(arc);
2433         var intersection = d3_geo_cartesianCross(meridianNormal, arc);
2434         d3_geo_cartesianNormalize(intersection);
2435         var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
2436         if (parallel > φarc) {
2437           winding += antimeridian ^ dλ >= 0 ? 1 : -1;
2438         }
2439       }
2440       if (!j++) break;
2441       λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
2442     }
2443     if (Math.abs(polarAngle) > ε) polar = true;
2444   }
2445
2446   // First, determine whether the South pole is inside or outside:
2447   //
2448   // It is inside if:
2449   // * the polygon doesn't wind around it, and its area is negative (counter-clockwise).
2450   // * otherwise, if the polygon winds around it in a clockwise direction.
2451   //
2452   // Second, count the (signed) number of times a segment crosses a meridian
2453   // from the point to the South pole.  If it is zero, then the point is the
2454   // same side as the South pole.
2455
2456   return (!southPole && !polar && d3_geo_areaRingSum < 0 || polarAngle < -ε) ^ (winding & 1);
2457 }
2458
2459 var d3_geo_clipAntimeridian = d3_geo_clip(
2460     d3_true,
2461     d3_geo_clipAntimeridianLine,
2462     d3_geo_clipAntimeridianInterpolate,
2463     d3_geo_clipAntimeridianPolygonContains);
2464
2465 // Takes a line and cuts into visible segments. Return values:
2466 //   0: there were intersections or the line was empty.
2467 //   1: no intersections.
2468 //   2: there were intersections, and the first and last segments should be
2469 //      rejoined.
2470 function d3_geo_clipAntimeridianLine(listener) {
2471   var λ0 = NaN,
2472       φ0 = NaN,
2473       sλ0 = NaN,
2474       clean; // no intersections
2475
2476   return {
2477     lineStart: function() {
2478       listener.lineStart();
2479       clean = 1;
2480     },
2481     point: function(λ1, φ1) {
2482       var sλ1 = λ1 > 0 ? π : -π,
2483           dλ = Math.abs(λ1 - λ0);
2484       if (Math.abs(dλ - π) < ε) { // line crosses a pole
2485         listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2);
2486         listener.point(sλ0, φ0);
2487         listener.lineEnd();
2488         listener.lineStart();
2489         listener.point(sλ1, φ0);
2490         listener.point( λ1, φ0);
2491         clean = 0;
2492       } else if (sλ0 !== sλ1 && dλ >= π) { // line crosses antimeridian
2493         // handle degeneracies
2494         if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
2495         if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
2496         φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
2497         listener.point(sλ0, φ0);
2498         listener.lineEnd();
2499         listener.lineStart();
2500         listener.point(sλ1, φ0);
2501         clean = 0;
2502       }
2503       listener.point(λ0 = λ1, φ0 = φ1);
2504       sλ0 = sλ1;
2505     },
2506     lineEnd: function() {
2507       listener.lineEnd();
2508       λ0 = φ0 = NaN;
2509     },
2510     // if there are intersections, we always rejoin the first and last segments.
2511     clean: function() { return 2 - clean; }
2512   };
2513 }
2514
2515 function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
2516   var cosφ0,
2517       cosφ1,
2518       sinλ0_λ1 = Math.sin(λ0 - λ1);
2519   return Math.abs(sinλ0_λ1) > ε
2520       ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1)
2521                  - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0))
2522                  / (cosφ0 * cosφ1 * sinλ0_λ1))
2523       : (φ0 + φ1) / 2;
2524 }
2525
2526 function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
2527   var φ;
2528   if (from == null) {
2529     φ = direction * π / 2;
2530     listener.point(-π,  φ);
2531     listener.point( 0,  φ);
2532     listener.point( π,  φ);
2533     listener.point( π,  0);
2534     listener.point( π, -φ);
2535     listener.point( 0, -φ);
2536     listener.point(-π, -φ);
2537     listener.point(-π,  0);
2538     listener.point(-π,  φ);
2539   } else if (Math.abs(from[0] - to[0]) > ε) {
2540     var s = (from[0] < to[0] ? 1 : -1) * π;
2541     φ = direction * s / 2;
2542     listener.point(-s, φ);
2543     listener.point( 0, φ);
2544     listener.point( s, φ);
2545   } else {
2546     listener.point(to[0], to[1]);
2547   }
2548 }
2549
2550 var d3_geo_clipAntimeridianPoint = [-π, 0];
2551
2552 function d3_geo_clipAntimeridianPolygonContains(polygon) {
2553   return d3_geo_pointInPolygon(d3_geo_clipAntimeridianPoint, polygon);
2554 }
2555
2556 function d3_geo_equirectangular(λ, φ) {
2557   return [λ, φ];
2558 }
2559
2560 (d3.geo.equirectangular = function() {
2561   return d3_geo_projection(d3_geo_equirectangular);
2562 }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
2563
2564 d3.geo.rotation = function(rotate) {
2565   rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
2566
2567   function forward(coordinates) {
2568     coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
2569     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
2570   }
2571
2572   forward.invert = function(coordinates) {
2573     coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
2574     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
2575   };
2576
2577   return forward;
2578 };
2579
2580 // Note: |δλ| must be < 2π
2581 function d3_geo_rotation(δλ, δφ, δγ) {
2582   return δλ ? (δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ))
2583     : d3_geo_rotationλ(δλ))
2584     : (δφ || δγ ? d3_geo_rotationφγ(δφ, δγ)
2585     : d3_geo_equirectangular);
2586 }
2587
2588 function d3_geo_forwardRotationλ(δλ) {
2589   return function(λ, φ) {
2590     return λ += δλ, [λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ];
2591   };
2592 }
2593
2594 function d3_geo_rotationλ(δλ) {
2595   var rotation = d3_geo_forwardRotationλ(δλ);
2596   rotation.invert = d3_geo_forwardRotationλ(-δλ);
2597   return rotation;
2598 }
2599
2600 function d3_geo_rotationφγ(δφ, δγ) {
2601   var cosδφ = Math.cos(δφ),
2602       sinδφ = Math.sin(δφ),
2603       cosδγ = Math.cos(δγ),
2604       sinδγ = Math.sin(δγ);
2605
2606   function rotation(λ, φ) {
2607     var cosφ = Math.cos(φ),
2608         x = Math.cos(λ) * cosφ,
2609         y = Math.sin(λ) * cosφ,
2610         z = Math.sin(φ),
2611         k = z * cosδφ + x * sinδφ;
2612     return [
2613       Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ),
2614       d3_asin(k * cosδγ + y * sinδγ)
2615     ];
2616   }
2617
2618   rotation.invert = function(λ, φ) {
2619     var cosφ = Math.cos(φ),
2620         x = Math.cos(λ) * cosφ,
2621         y = Math.sin(λ) * cosφ,
2622         z = Math.sin(φ),
2623         k = z * cosδγ - y * sinδγ;
2624     return [
2625       Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ),
2626       d3_asin(k * cosδφ - x * sinδφ)
2627     ];
2628   };
2629
2630   return rotation;
2631 }
2632
2633 d3.geo.circle = function() {
2634   var origin = [0, 0],
2635       angle,
2636       precision = 6,
2637       interpolate;
2638
2639   function circle() {
2640     var center = typeof origin === "function" ? origin.apply(this, arguments) : origin,
2641         rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert,
2642         ring = [];
2643
2644     interpolate(null, null, 1, {
2645       point: function(x, y) {
2646         ring.push(x = rotate(x, y));
2647         x[0] *= d3_degrees, x[1] *= d3_degrees;
2648       }
2649     });
2650
2651     return {type: "Polygon", coordinates: [ring]};
2652   }
2653
2654   circle.origin = function(x) {
2655     if (!arguments.length) return origin;
2656     origin = x;
2657     return circle;
2658   };
2659
2660   circle.angle = function(x) {
2661     if (!arguments.length) return angle;
2662     interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
2663     return circle;
2664   };
2665
2666   circle.precision = function(_) {
2667     if (!arguments.length) return precision;
2668     interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
2669     return circle;
2670   };
2671
2672   return circle.angle(90);
2673 };
2674
2675 // Interpolates along a circle centered at [0°, 0°], with a given radius and
2676 // precision.
2677 function d3_geo_circleInterpolate(radius, precision) {
2678   var cr = Math.cos(radius),
2679       sr = Math.sin(radius);
2680   return function(from, to, direction, listener) {
2681     if (from != null) {
2682       from = d3_geo_circleAngle(cr, from);
2683       to = d3_geo_circleAngle(cr, to);
2684       if (direction > 0 ? from < to: from > to) from += direction * 2 * π;
2685     } else {
2686       from = radius + direction * 2 * π;
2687       to = radius;
2688     }
2689     var point;
2690     for (var step = direction * precision, t = from; direction > 0 ? t > to : t < to; t -= step) {
2691       listener.point((point = d3_geo_spherical([
2692         cr,
2693         -sr * Math.cos(t),
2694         -sr * Math.sin(t)
2695       ]))[0], point[1]);
2696     }
2697   };
2698 }
2699
2700 // Signed angle of a cartesian point relative to [cr, 0, 0].
2701 function d3_geo_circleAngle(cr, point) {
2702   var a = d3_geo_cartesian(point);
2703   a[0] -= cr;
2704   d3_geo_cartesianNormalize(a);
2705   var angle = d3_acos(-a[1]);
2706   return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
2707 }
2708
2709 // Clip features against a small circle centered at [0°, 0°].
2710 function d3_geo_clipCircle(radius) {
2711   var cr = Math.cos(radius),
2712       smallRadius = cr > 0,
2713       point = [radius, 0],
2714       notHemisphere = Math.abs(cr) > ε, // TODO optimise for this common case
2715       interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
2716
2717   return d3_geo_clip(visible, clipLine, interpolate, polygonContains);
2718
2719   function visible(λ, φ) {
2720     return Math.cos(λ) * Math.cos(φ) > cr;
2721   }
2722
2723   // Takes a line and cuts into visible segments. Return values used for
2724   // polygon clipping:
2725   //   0: there were intersections or the line was empty.
2726   //   1: no intersections.
2727   //   2: there were intersections, and the first and last segments should be
2728   //      rejoined.
2729   function clipLine(listener) {
2730     var point0, // previous point
2731         c0, // code for previous point
2732         v0, // visibility of previous point
2733         v00, // visibility of first point
2734         clean; // no intersections
2735     return {
2736       lineStart: function() {
2737         v00 = v0 = false;
2738         clean = 1;
2739       },
2740       point: function(λ, φ) {
2741         var point1 = [λ, φ],
2742             point2,
2743             v = visible(λ, φ),
2744             c = smallRadius
2745               ? v ? 0 : code(λ, φ)
2746               : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
2747         if (!point0 && (v00 = v0 = v)) listener.lineStart();
2748         // Handle degeneracies.
2749         // TODO ignore if not clipping polygons.
2750         if (v !== v0) {
2751           point2 = intersect(point0, point1);
2752           if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
2753             point1[0] += ε;
2754             point1[1] += ε;
2755             v = visible(point1[0], point1[1]);
2756           }
2757         }
2758         if (v !== v0) {
2759           clean = 0;
2760           if (v) {
2761             // outside going in
2762             listener.lineStart();
2763             point2 = intersect(point1, point0);
2764             listener.point(point2[0], point2[1]);
2765           } else {
2766             // inside going out
2767             point2 = intersect(point0, point1);
2768             listener.point(point2[0], point2[1]);
2769             listener.lineEnd();
2770           }
2771           point0 = point2;
2772         } else if (notHemisphere && point0 && smallRadius ^ v) {
2773           var t;
2774           // If the codes for two points are different, or are both zero,
2775           // and there this segment intersects with the small circle.
2776           if (!(c & c0) && (t = intersect(point1, point0, true))) {
2777             clean = 0;
2778             if (smallRadius) {
2779               listener.lineStart();
2780               listener.point(t[0][0], t[0][1]);
2781               listener.point(t[1][0], t[1][1]);
2782               listener.lineEnd();
2783             } else {
2784               listener.point(t[1][0], t[1][1]);
2785               listener.lineEnd();
2786               listener.lineStart();
2787               listener.point(t[0][0], t[0][1]);
2788             }
2789           }
2790         }
2791         if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
2792           listener.point(point1[0], point1[1]);
2793         }
2794         point0 = point1, v0 = v, c0 = c;
2795       },
2796       lineEnd: function() {
2797         if (v0) listener.lineEnd();
2798         point0 = null;
2799       },
2800       // Rejoin first and last segments if there were intersections and the first
2801       // and last points were visible.
2802       clean: function() { return clean | ((v00 && v0) << 1); }
2803     };
2804   }
2805
2806   // Intersects the great circle between a and b with the clip circle.
2807   function intersect(a, b, two) {
2808     var pa = d3_geo_cartesian(a),
2809         pb = d3_geo_cartesian(b);
2810
2811     // We have two planes, n1.p = d1 and n2.p = d2.
2812     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
2813     var n1 = [1, 0, 0], // normal
2814         n2 = d3_geo_cartesianCross(pa, pb),
2815         n2n2 = d3_geo_cartesianDot(n2, n2),
2816         n1n2 = n2[0], // d3_geo_cartesianDot(n1, n2),
2817         determinant = n2n2 - n1n2 * n1n2;
2818
2819     // Two polar points.
2820     if (!determinant) return !two && a;
2821
2822     var c1 =  cr * n2n2 / determinant,
2823         c2 = -cr * n1n2 / determinant,
2824         n1xn2 = d3_geo_cartesianCross(n1, n2),
2825         A = d3_geo_cartesianScale(n1, c1),
2826         B = d3_geo_cartesianScale(n2, c2);
2827     d3_geo_cartesianAdd(A, B);
2828
2829     // Solve |p(t)|^2 = 1.
2830     var u = n1xn2,
2831         w = d3_geo_cartesianDot(A, u),
2832         uu = d3_geo_cartesianDot(u, u),
2833         t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
2834
2835     if (t2 < 0) return;
2836
2837     var t = Math.sqrt(t2),
2838         q = d3_geo_cartesianScale(u, (-w - t) / uu);
2839     d3_geo_cartesianAdd(q, A);
2840     q = d3_geo_spherical(q);
2841     if (!two) return q;
2842
2843     // Two intersection points.
2844     var λ0 = a[0],
2845         λ1 = b[0],
2846         φ0 = a[1],
2847         φ1 = b[1],
2848         z;
2849     if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
2850     var δλ = λ1 - λ0,
2851         polar = Math.abs(δλ - π) < ε,
2852         meridian = polar || δλ < ε;
2853
2854     if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
2855
2856     // Check that the first point is between a and b.
2857     if (meridian
2858         ? polar
2859           ? φ0 + φ1 > 0 ^ q[1] < (Math.abs(q[0] - λ0) < ε ? φ0 : φ1)
2860           : φ0 <= q[1] && q[1] <= φ1
2861         : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
2862       var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
2863       d3_geo_cartesianAdd(q1, A);
2864       return [q, d3_geo_spherical(q1)];
2865     }
2866   }
2867
2868   // Generates a 4-bit vector representing the location of a point relative to
2869   // the small circle's bounding box.
2870   function code(λ, φ) {
2871     var r = smallRadius ? radius : π - radius,
2872         code = 0;
2873     if (λ < -r) code |= 1; // left
2874     else if (λ > r) code |= 2; // right
2875     if (φ < -r) code |= 4; // below
2876     else if (φ > r) code |= 8; // above
2877     return code;
2878   }
2879
2880   function polygonContains(polygon) {
2881     return d3_geo_pointInPolygon(point, polygon);
2882   }
2883 }
2884
2885 var d3_geo_clipViewMAX = 1e9;
2886
2887 function d3_geo_clipView(x0, y0, x1, y1) {
2888   return function(listener) {
2889     var listener_ = listener,
2890         bufferListener = d3_geo_clipBufferListener(),
2891         segments,
2892         polygon,
2893         ring;
2894
2895     var clip = {
2896       point: point,
2897       lineStart: lineStart,
2898       lineEnd: lineEnd,
2899       polygonStart: function() {
2900         listener = bufferListener;
2901         segments = [];
2902         polygon = [];
2903       },
2904       polygonEnd: function() {
2905         listener = listener_;
2906         if ((segments = d3.merge(segments)).length) {
2907           listener.polygonStart();
2908           d3_geo_clipPolygon(segments, compare, inside, interpolate, listener);
2909           listener.polygonEnd();
2910         } else if (insidePolygon([x0, y0])) {
2911           listener.polygonStart(), listener.lineStart();
2912           interpolate(null, null, 1, listener);
2913           listener.lineEnd(), listener.polygonEnd();
2914         }
2915         segments = polygon = ring = null;
2916       }
2917     };
2918
2919     function inside(point) {
2920       var a = corner(point, -1),
2921           i = insidePolygon([a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0]);
2922       return i;
2923     }
2924
2925     function insidePolygon(p) {
2926       var wn = 0, // the winding number counter
2927           n = polygon.length,
2928           y = p[1];
2929
2930       for (var i = 0; i < n; ++i) {
2931         for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
2932           b = v[j];
2933           if (a[1] <= y) {
2934             if (b[1] >  y && isLeft(a, b, p) > 0) ++wn;
2935           } else {
2936             if (b[1] <= y && isLeft(a, b, p) < 0) --wn;
2937           }
2938           a = b;
2939         }
2940       }
2941       return wn !== 0;
2942     }
2943
2944     function isLeft(a, b, c) {
2945       return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
2946     }
2947
2948     function interpolate(from, to, direction, listener) {
2949       var a = 0, a1 = 0;
2950       if (from == null ||
2951           (a = corner(from, direction)) !== (a1 = corner(to, direction)) ||
2952           comparePoints(from, to) < 0 ^ direction > 0) {
2953         do {
2954           listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
2955         } while ((a = (a + direction + 4) % 4) !== a1);
2956       } else {
2957         listener.point(to[0], to[1]);
2958       }
2959     }
2960
2961     function visible(x, y) {
2962       return x0 <= x && x <= x1 && y0 <= y && y <= y1;
2963     }
2964
2965     function point(x, y) {
2966       if (visible(x, y)) listener.point(x, y);
2967     }
2968
2969     var x__, y__, v__, // first point
2970         x_, y_, v_, // previous point
2971         first;
2972
2973     function lineStart() {
2974       clip.point = linePoint;
2975       if (polygon) polygon.push(ring = []);
2976       first = true;
2977       v_ = false;
2978       x_ = y_ = NaN;
2979     }
2980
2981     function lineEnd() {
2982       // TODO rather than special-case polygons, simply handle them separately.
2983       // Ideally, coincident intersection points should be jittered to avoid
2984       // clipping issues.
2985       if (segments) {
2986         linePoint(x__, y__);
2987         if (v__ && v_) bufferListener.rejoin();
2988         segments.push(bufferListener.buffer());
2989       }
2990       clip.point = point;
2991       if (v_) listener.lineEnd();
2992     }
2993
2994     function linePoint(x, y) {
2995       x = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, x));
2996       y = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, y));
2997       var v = visible(x, y);
2998       if (polygon) ring.push([x, y]);
2999       if (first) {
3000         x__ = x, y__ = y, v__ = v;
3001         first = false;
3002         if (v) {
3003           listener.lineStart();
3004           listener.point(x, y);
3005         }
3006       } else {
3007         if (v && v_) listener.point(x, y);
3008         else {
3009           var a = [x_, y_],
3010               b = [x, y];
3011           if (clipLine(a, b)) {
3012             if (!v_) {
3013               listener.lineStart();
3014               listener.point(a[0], a[1]);
3015             }
3016             listener.point(b[0], b[1]);
3017             if (!v) listener.lineEnd();
3018           } else if (v) {
3019             listener.lineStart();
3020             listener.point(x, y);
3021           }
3022         }
3023       }
3024       x_ = x, y_ = y, v_ = v;
3025     }
3026
3027     return clip;
3028   };
3029
3030   function corner(p, direction) {
3031     return Math.abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3
3032         : Math.abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1
3033         : Math.abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0
3034         : direction > 0 ? 3 : 2; // Math.abs(p[1] - y1) < ε
3035   }
3036
3037   function compare(a, b) {
3038     return comparePoints(a.point, b.point);
3039   }
3040
3041   function comparePoints(a, b) {
3042     var ca = corner(a, 1),
3043         cb = corner(b, 1);
3044     return ca !== cb ? ca - cb
3045         : ca === 0 ? b[1] - a[1]
3046         : ca === 1 ? a[0] - b[0]
3047         : ca === 2 ? a[1] - b[1]
3048         : b[0] - a[0];
3049   }
3050
3051   // Liang–Barsky line clipping.
3052   function clipLine(a, b) {
3053     var dx = b[0] - a[0],
3054         dy = b[1] - a[1],
3055         t = [0, 1];
3056
3057     if (Math.abs(dx) < ε && Math.abs(dy) < ε) return x0 <= a[0] && a[0] <= x1 && y0 <= a[1] && a[1] <= y1;
3058
3059     if (d3_geo_clipViewT(x0 - a[0],  dx, t) &&
3060         d3_geo_clipViewT(a[0] - x1, -dx, t) &&
3061         d3_geo_clipViewT(y0 - a[1],  dy, t) &&
3062         d3_geo_clipViewT(a[1] - y1, -dy, t)) {
3063       if (t[1] < 1) {
3064         b[0] = a[0] + t[1] * dx;
3065         b[1] = a[1] + t[1] * dy;
3066       }
3067       if (t[0] > 0) {
3068         a[0] += t[0] * dx;
3069         a[1] += t[0] * dy;
3070       }
3071       return true;
3072     }
3073
3074     return false;
3075   }
3076 }
3077
3078 function d3_geo_clipViewT(num, denominator, t) {
3079   if (Math.abs(denominator) < ε) return num <= 0;
3080
3081   var u = num / denominator;
3082
3083   if (denominator > 0) {
3084     if (u > t[1]) return false;
3085     if (u > t[0]) t[0] = u;
3086   } else {
3087     if (u < t[0]) return false;
3088     if (u < t[1]) t[1] = u;
3089   }
3090   return true;
3091 }
3092 function d3_geo_compose(a, b) {
3093
3094   function compose(x, y) {
3095     return x = a(x, y), b(x[0], x[1]);
3096   }
3097
3098   if (a.invert && b.invert) compose.invert = function(x, y) {
3099     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
3100   };
3101
3102   return compose;
3103 }
3104
3105 function d3_geo_conic(projectAt) {
3106   var φ0 = 0,
3107       φ1 = π / 3,
3108       m = d3_geo_projectionMutator(projectAt),
3109       p = m(φ0, φ1);
3110
3111   p.parallels = function(_) {
3112     if (!arguments.length) return [φ0 / π * 180, φ1 / π * 180];
3113     return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
3114   };
3115
3116   return p;
3117 }
3118
3119 function d3_geo_conicEqualArea(φ0, φ1) {
3120   var sinφ0 = Math.sin(φ0),
3121       n = (sinφ0 + Math.sin(φ1)) / 2,
3122       C = 1 + sinφ0 * (2 * n - sinφ0),
3123       ρ0 = Math.sqrt(C) / n;
3124
3125   function forward(λ, φ) {
3126     var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
3127     return [
3128       ρ * Math.sin(λ *= n),
3129       ρ0 - ρ * Math.cos(λ)
3130     ];
3131   }
3132
3133   forward.invert = function(x, y) {
3134     var ρ0_y = ρ0 - y;
3135     return [
3136       Math.atan2(x, ρ0_y) / n,
3137       d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n))
3138     ];
3139   };
3140
3141   return forward;
3142 }
3143
3144 (d3.geo.conicEqualArea = function() {
3145   return d3_geo_conic(d3_geo_conicEqualArea);
3146 }).raw = d3_geo_conicEqualArea;
3147
3148 // ESRI:102003
3149 d3.geo.albers = function() {
3150   return d3.geo.conicEqualArea()
3151       .rotate([96, 0])
3152       .center([-.6, 38.7])
3153       .parallels([29.5, 45.5])
3154       .scale(1070);
3155 };
3156
3157 // A composite projection for the United States, configured by default for
3158 // 960×500. Also works quite well at 960×600 with scale 1285. The set of
3159 // standard parallels for each region comes from USGS, which is published here:
3160 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
3161 d3.geo.albersUsa = function() {
3162   var lower48 = d3.geo.albers();
3163
3164   // EPSG:3338
3165   var alaska = d3.geo.conicEqualArea()
3166       .rotate([154, 0])
3167       .center([-2, 58.5])
3168       .parallels([55, 65]);
3169
3170   // ESRI:102007
3171   var hawaii = d3.geo.conicEqualArea()
3172       .rotate([157, 0])
3173       .center([-3, 19.9])
3174       .parallels([8, 18]);
3175
3176   var point,
3177       pointStream = {point: function(x, y) { point = [x, y]; }},
3178       lower48Point,
3179       alaskaPoint,
3180       hawaiiPoint;
3181
3182   function albersUsa(coordinates) {
3183     var x = coordinates[0], y = coordinates[1];
3184     point = null;
3185     (lower48Point(x, y), point)
3186         || (alaskaPoint(x, y), point)
3187         || hawaiiPoint(x, y);
3188     return point;
3189   }
3190
3191   albersUsa.invert = function(coordinates) {
3192     var k = lower48.scale(),
3193         t = lower48.translate(),
3194         x = (coordinates[0] - t[0]) / k,
3195         y = (coordinates[1] - t[1]) / k;
3196     return (y >= .120 && y < .234 && x >= -.425 && x < -.214 ? alaska
3197         : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii
3198         : lower48).invert(coordinates);
3199   };
3200
3201   // A naïve multi-projection stream.
3202   // The projections must have mutually exclusive clip regions on the sphere,
3203   // as this will avoid emitting interleaving lines and polygons.
3204   albersUsa.stream = function(stream) {
3205     var lower48Stream = lower48.stream(stream),
3206         alaskaStream = alaska.stream(stream),
3207         hawaiiStream = hawaii.stream(stream);
3208     return {
3209       point: function(x, y) {
3210         lower48Stream.point(x, y);
3211         alaskaStream.point(x, y);
3212         hawaiiStream.point(x, y);
3213       },
3214       sphere: function() {
3215         lower48Stream.sphere();
3216         alaskaStream.sphere();
3217         hawaiiStream.sphere();
3218       },
3219       lineStart: function() {
3220         lower48Stream.lineStart();
3221         alaskaStream.lineStart();
3222         hawaiiStream.lineStart();
3223       },
3224       lineEnd: function() {
3225         lower48Stream.lineEnd();
3226         alaskaStream.lineEnd();
3227         hawaiiStream.lineEnd();
3228       },
3229       polygonStart: function() {
3230         lower48Stream.polygonStart();
3231         alaskaStream.polygonStart();
3232         hawaiiStream.polygonStart();
3233       },
3234       polygonEnd: function() {
3235         lower48Stream.polygonEnd();
3236         alaskaStream.polygonEnd();
3237         hawaiiStream.polygonEnd();
3238       }
3239     };
3240   };
3241
3242   albersUsa.precision = function(_) {
3243     if (!arguments.length) return lower48.precision();
3244     lower48.precision(_);
3245     alaska.precision(_);
3246     hawaii.precision(_);
3247     return albersUsa;
3248   };
3249
3250   albersUsa.scale = function(_) {
3251     if (!arguments.length) return lower48.scale();
3252     lower48.scale(_);
3253     alaska.scale(_ * .35);
3254     hawaii.scale(_);
3255     return albersUsa.translate(lower48.translate());
3256   };
3257
3258   albersUsa.translate = function(_) {
3259     if (!arguments.length) return lower48.translate();
3260     var k = lower48.scale(), x = +_[0], y = +_[1];
3261
3262     lower48Point = lower48
3263         .translate(_)
3264         .clipExtent([[x - .455 * k, y - .238 * k], [x + .455 * k, y + .238 * k]])
3265         .stream(pointStream).point;
3266
3267     alaskaPoint = alaska
3268         .translate([x - .307 * k, y + .201 * k])
3269         .clipExtent([[x - .425 * k + ε, y + .120 * k + ε], [x - .214 * k - ε, y + .234 * k - ε]])
3270         .stream(pointStream).point;
3271
3272     hawaiiPoint = hawaii
3273         .translate([x - .205 * k, y + .212 * k])
3274         .clipExtent([[x - .214 * k + ε, y + .166 * k + ε], [x - .115 * k - ε, y + .234 * k - ε]])
3275         .stream(pointStream).point;
3276
3277     return albersUsa;
3278   };
3279
3280   return albersUsa.scale(1070);
3281 };
3282
3283 d3.geo.bounds = (function() {
3284   var λ0, φ0, λ1, φ1, // bounds
3285       λ_, // previous λ-coordinate
3286       λ__, φ__, // first point
3287       p0, // previous 3D point
3288       dλSum,
3289       ranges,
3290       range;
3291
3292   var bound = {
3293     point: point,
3294     lineStart: lineStart,
3295     lineEnd: lineEnd,
3296
3297     polygonStart: function() {
3298       bound.point = ringPoint;
3299       bound.lineStart = ringStart;
3300       bound.lineEnd = ringEnd;
3301       dλSum = 0;
3302       d3_geo_area.polygonStart();
3303     },
3304     polygonEnd: function() {
3305       d3_geo_area.polygonEnd();
3306       bound.point = point;
3307       bound.lineStart = lineStart;
3308       bound.lineEnd = lineEnd;
3309       if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90);
3310       else if (dλSum > ε) φ1 = 90;
3311       else if (dλSum < -ε) φ0 = -90;
3312       range[0] = λ0, range[1] = λ1;
3313     }
3314   };
3315
3316   function point(λ, φ) {
3317     ranges.push(range = [λ0 = λ, λ1 = λ]);
3318     if (φ < φ0) φ0 = φ;
3319     if (φ > φ1) φ1 = φ;
3320   }
3321
3322   function linePoint(λ, φ) {
3323     var p = d3_geo_cartesian([λ * d3_radians, φ * d3_radians]);
3324     if (p0) {
3325       var normal = d3_geo_cartesianCross(p0, p),
3326           equatorial = [normal[1], -normal[0], 0],
3327           inflection = d3_geo_cartesianCross(equatorial, normal);
3328       d3_geo_cartesianNormalize(inflection);
3329       inflection = d3_geo_spherical(inflection);
3330       var dλ = λ - λ_,
3331           s = dλ > 0 ? 1 : -1,
3332           λi = inflection[0] * d3_degrees * s,
3333           antimeridian = Math.abs(dλ) > 180;
3334       if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
3335         var φi = inflection[1] * d3_degrees;
3336         if (φi > φ1) φ1 = φi;
3337       } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
3338         var φi = -inflection[1] * d3_degrees;
3339         if (φi < φ0) φ0 = φi;
3340       } else {
3341         if (φ < φ0) φ0 = φ;
3342         if (φ > φ1) φ1 = φ;
3343       }
3344       if (antimeridian) {
3345         if (λ < λ_) {
3346           if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
3347         } else {
3348           if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
3349         }
3350       } else {
3351         if (λ1 >= λ0) {
3352           if (λ < λ0) λ0 = λ;
3353           if (λ > λ1) λ1 = λ;
3354         } else {
3355           if (λ > λ_) {
3356             if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
3357           } else {
3358             if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
3359           }
3360         }
3361       }
3362     } else {
3363       point(λ, φ);
3364     }
3365     p0 = p, λ_ = λ;
3366   }
3367
3368   function lineStart() { bound.point = linePoint; }
3369   function lineEnd() {
3370     range[0] = λ0, range[1] = λ1;
3371     bound.point = point;
3372     p0 = null;
3373   }
3374
3375   function ringPoint(λ, φ) {
3376     if (p0) {
3377       var dλ = λ - λ_;
3378       dλSum += Math.abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
3379     } else λ__ = λ, φ__ = φ;
3380     d3_geo_area.point(λ, φ);
3381     linePoint(λ, φ);
3382   }
3383
3384   function ringStart() {
3385     d3_geo_area.lineStart();
3386   }
3387
3388   function ringEnd() {
3389     ringPoint(λ__, φ__);
3390     d3_geo_area.lineEnd();
3391     if (Math.abs(dλSum) > ε) λ0 = -(λ1 = 180);
3392     range[0] = λ0, range[1] = λ1;
3393     p0 = null;
3394   }
3395
3396   // Finds the left-right distance between two longitudes.
3397   // This is almost the same as (λ1 - λ0 + 360°) % 360°, except that we want
3398   // the distance between ±180° to be 360°.
3399   function angle(λ0, λ1) { return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; }
3400
3401   function compareRanges(a, b) { return a[0] - b[0]; }
3402
3403   function withinRange(x, range) {
3404     return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
3405   }
3406
3407   return function(feature) {
3408     φ1 = λ1 = -(λ0 = φ0 = Infinity);
3409     ranges = [];
3410
3411     d3.geo.stream(feature, bound);
3412
3413     var n = ranges.length;
3414     if (n) {
3415       // First, sort ranges by their minimum longitudes.
3416       ranges.sort(compareRanges);
3417
3418       // Then, merge any ranges that overlap.
3419       for (var i = 1, a = ranges[0], b, merged = [a]; i < n; ++i) {
3420         b = ranges[i];
3421         if (withinRange(b[0], a) || withinRange(b[1], a)) {
3422           if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
3423           if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
3424         } else {
3425           merged.push(a = b);
3426         }
3427       }
3428
3429       // Finally, find the largest gap between the merged ranges.
3430       // The final bounding box will be the inverse of this gap.
3431       var best = -Infinity, dλ;
3432       for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
3433         b = merged[i];
3434         if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
3435       }
3436     }
3437     ranges = range = null;
3438
3439     return λ0 === Infinity || φ0 === Infinity
3440         ? [[NaN, NaN], [NaN, NaN]]
3441         : [[λ0, φ0], [λ1, φ1]];
3442   };
3443 })();
3444
3445 d3.geo.centroid = function(object) {
3446   d3_geo_centroidW0 = d3_geo_centroidW1 =
3447   d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
3448   d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
3449   d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
3450   d3.geo.stream(object, d3_geo_centroid);
3451
3452   var x = d3_geo_centroidX2,
3453       y = d3_geo_centroidY2,
3454       z = d3_geo_centroidZ2,
3455       m = x * x + y * y + z * z;
3456
3457   // If the area-weighted centroid is undefined, fall back to length-weighted centroid.
3458   if (m < ε2) {
3459     x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
3460     // If the feature has zero length, fall back to arithmetic mean of point vectors.
3461     if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
3462     m = x * x + y * y + z * z;
3463     // If the feature still has an undefined centroid, then return.
3464     if (m < ε2) return [NaN, NaN];
3465   }
3466
3467   return [Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees];
3468 };
3469
3470 var d3_geo_centroidW0,
3471     d3_geo_centroidW1,
3472     d3_geo_centroidX0,
3473     d3_geo_centroidY0,
3474     d3_geo_centroidZ0,
3475     d3_geo_centroidX1,
3476     d3_geo_centroidY1,
3477     d3_geo_centroidZ1,
3478     d3_geo_centroidX2,
3479     d3_geo_centroidY2,
3480     d3_geo_centroidZ2;
3481
3482 var d3_geo_centroid = {
3483   sphere: d3_noop,
3484   point: d3_geo_centroidPoint,
3485   lineStart: d3_geo_centroidLineStart,
3486   lineEnd: d3_geo_centroidLineEnd,
3487   polygonStart: function() {
3488     d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
3489   },
3490   polygonEnd: function() {
3491     d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
3492   }
3493 };
3494
3495 // Arithmetic mean of Cartesian vectors.
3496 function d3_geo_centroidPoint(λ, φ) {
3497   λ *= d3_radians;
3498   var cosφ = Math.cos(φ *= d3_radians);
3499   d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
3500 }
3501
3502 function d3_geo_centroidPointXYZ(x, y, z) {
3503   ++d3_geo_centroidW0;
3504   d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
3505   d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
3506   d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
3507 }
3508
3509 function d3_geo_centroidLineStart() {
3510   var x0, y0, z0; // previous point
3511
3512   d3_geo_centroid.point = function(λ, φ) {
3513     λ *= d3_radians;
3514     var cosφ = Math.cos(φ *= d3_radians);
3515     x0 = cosφ * Math.cos(λ);
3516     y0 = cosφ * Math.sin(λ);
3517     z0 = Math.sin(φ);
3518     d3_geo_centroid.point = nextPoint;
3519     d3_geo_centroidPointXYZ(x0, y0, z0);
3520   };
3521
3522   function nextPoint(λ, φ) {
3523     λ *= d3_radians;
3524     var cosφ = Math.cos(φ *= d3_radians),
3525         x = cosφ * Math.cos(λ),
3526         y = cosφ * Math.sin(λ),
3527         z = Math.sin(φ),
3528         w = Math.atan2(
3529           Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w),
3530           x0 * x + y0 * y + z0 * z);
3531     d3_geo_centroidW1 += w;
3532     d3_geo_centroidX1 += w * (x0 + (x0 = x));
3533     d3_geo_centroidY1 += w * (y0 + (y0 = y));
3534     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
3535     d3_geo_centroidPointXYZ(x0, y0, z0);
3536   }
3537 }
3538
3539 function d3_geo_centroidLineEnd() {
3540   d3_geo_centroid.point = d3_geo_centroidPoint;
3541 }
3542
3543 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
3544 // J. Applied Mechanics 42, 239 (1975).
3545 function d3_geo_centroidRingStart() {
3546   var λ00, φ00, // first point
3547       x0, y0, z0; // previous point
3548
3549   d3_geo_centroid.point = function(λ, φ) {
3550     λ00 = λ, φ00 = φ;
3551     d3_geo_centroid.point = nextPoint;
3552     λ *= d3_radians;
3553     var cosφ = Math.cos(φ *= d3_radians);
3554     x0 = cosφ * Math.cos(λ);
3555     y0 = cosφ * Math.sin(λ);
3556     z0 = Math.sin(φ);
3557     d3_geo_centroidPointXYZ(x0, y0, z0);
3558   };
3559
3560   d3_geo_centroid.lineEnd = function() {
3561     nextPoint(λ00, φ00);
3562     d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
3563     d3_geo_centroid.point = d3_geo_centroidPoint;
3564   };
3565
3566   function nextPoint(λ, φ) {
3567     λ *= d3_radians;
3568     var cosφ = Math.cos(φ *= d3_radians),
3569         x = cosφ * Math.cos(λ),
3570         y = cosφ * Math.sin(λ),
3571         z = Math.sin(φ),
3572         cx = y0 * z - z0 * y,
3573         cy = z0 * x - x0 * z,
3574         cz = x0 * y - y0 * x,
3575         m = Math.sqrt(cx * cx + cy * cy + cz * cz),
3576         u = x0 * x + y0 * y + z0 * z,
3577         v = m && -d3_acos(u) / m, // area weight
3578         w = Math.atan2(m, u); // line weight
3579     d3_geo_centroidX2 += v * cx;
3580     d3_geo_centroidY2 += v * cy;
3581     d3_geo_centroidZ2 += v * cz;
3582     d3_geo_centroidW1 += w;
3583     d3_geo_centroidX1 += w * (x0 + (x0 = x));
3584     d3_geo_centroidY1 += w * (y0 + (y0 = y));
3585     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
3586     d3_geo_centroidPointXYZ(x0, y0, z0);
3587   }
3588 }
3589
3590 // TODO Unify this code with d3.geom.polygon area?
3591
3592 var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
3593   point: d3_noop,
3594   lineStart: d3_noop,
3595   lineEnd: d3_noop,
3596
3597   // Only count area for polygon rings.
3598   polygonStart: function() {
3599     d3_geo_pathAreaPolygon = 0;
3600     d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
3601   },
3602   polygonEnd: function() {
3603     d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
3604     d3_geo_pathAreaSum += Math.abs(d3_geo_pathAreaPolygon / 2);
3605   }
3606 };
3607
3608 function d3_geo_pathAreaRingStart() {
3609   var x00, y00, x0, y0;
3610
3611   // For the first point, …
3612   d3_geo_pathArea.point = function(x, y) {
3613     d3_geo_pathArea.point = nextPoint;
3614     x00 = x0 = x, y00 = y0 = y;
3615   };
3616
3617   // For subsequent points, …
3618   function nextPoint(x, y) {
3619     d3_geo_pathAreaPolygon += y0 * x - x0 * y;
3620     x0 = x, y0 = y;
3621   }
3622
3623   // For the last point, return to the start.
3624   d3_geo_pathArea.lineEnd = function() {
3625     nextPoint(x00, y00);
3626   };
3627 }
3628
3629 var d3_geo_pathBoundsX0,
3630     d3_geo_pathBoundsY0,
3631     d3_geo_pathBoundsX1,
3632     d3_geo_pathBoundsY1;
3633
3634 var d3_geo_pathBounds = {
3635   point: d3_geo_pathBoundsPoint,
3636   lineStart: d3_noop,
3637   lineEnd: d3_noop,
3638   polygonStart: d3_noop,
3639   polygonEnd: d3_noop
3640 };
3641
3642 function d3_geo_pathBoundsPoint(x, y) {
3643   if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
3644   if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
3645   if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
3646   if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
3647 }
3648 function d3_geo_pathBuffer() {
3649   var pointCircle = d3_geo_pathBufferCircle(4.5),
3650       buffer = [];
3651
3652   var stream = {
3653     point: point,
3654
3655     // While inside a line, override point to moveTo then lineTo.
3656     lineStart: function() { stream.point = pointLineStart; },
3657     lineEnd: lineEnd,
3658
3659     // While inside a polygon, override lineEnd to closePath.
3660     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
3661     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
3662
3663     pointRadius: function(_) {
3664       pointCircle = d3_geo_pathBufferCircle(_);
3665       return stream;
3666     },
3667
3668     result: function() {
3669       if (buffer.length) {
3670         var result = buffer.join("");
3671         buffer = [];
3672         return result;
3673       }
3674     }
3675   };
3676
3677   function point(x, y) {
3678     buffer.push("M", x, ",", y, pointCircle);
3679   }
3680
3681   function pointLineStart(x, y) {
3682     buffer.push("M", x, ",", y);
3683     stream.point = pointLine;
3684   }
3685
3686   function pointLine(x, y) {
3687     buffer.push("L", x, ",", y);
3688   }
3689
3690   function lineEnd() {
3691     stream.point = point;
3692   }
3693
3694   function lineEndPolygon() {
3695     buffer.push("Z");
3696   }
3697
3698   return stream;
3699 }
3700
3701 function d3_geo_pathBufferCircle(radius) {
3702   return "m0," + radius
3703       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
3704       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
3705       + "z";
3706 }
3707
3708 // TODO Unify this code with d3.geom.polygon centroid?
3709 // TODO Enforce positive area for exterior, negative area for interior?
3710
3711 var d3_geo_pathCentroid = {
3712   point: d3_geo_pathCentroidPoint,
3713
3714   // For lines, weight by length.
3715   lineStart: d3_geo_pathCentroidLineStart,
3716   lineEnd: d3_geo_pathCentroidLineEnd,
3717
3718   // For polygons, weight by area.
3719   polygonStart: function() {
3720     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
3721   },
3722   polygonEnd: function() {
3723     d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
3724     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
3725     d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
3726   }
3727 };
3728
3729 function d3_geo_pathCentroidPoint(x, y) {
3730   d3_geo_centroidX0 += x;
3731   d3_geo_centroidY0 += y;
3732   ++d3_geo_centroidZ0;
3733 }
3734
3735 function d3_geo_pathCentroidLineStart() {
3736   var x0, y0;
3737
3738   d3_geo_pathCentroid.point = function(x, y) {
3739     d3_geo_pathCentroid.point = nextPoint;
3740     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
3741   };
3742
3743   function nextPoint(x, y) {
3744     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
3745     d3_geo_centroidX1 += z * (x0 + x) / 2;
3746     d3_geo_centroidY1 += z * (y0 + y) / 2;
3747     d3_geo_centroidZ1 += z;
3748     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
3749   }
3750 }
3751
3752 function d3_geo_pathCentroidLineEnd() {
3753   d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
3754 }
3755
3756 function d3_geo_pathCentroidRingStart() {
3757   var x00, y00, x0, y0;
3758
3759   // For the first point, …
3760   d3_geo_pathCentroid.point = function(x, y) {
3761     d3_geo_pathCentroid.point = nextPoint;
3762     d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
3763   };
3764
3765   // For subsequent points, …
3766   function nextPoint(x, y) {
3767     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
3768     d3_geo_centroidX1 += z * (x0 + x) / 2;
3769     d3_geo_centroidY1 += z * (y0 + y) / 2;
3770     d3_geo_centroidZ1 += z;
3771
3772     z = y0 * x - x0 * y;
3773     d3_geo_centroidX2 += z * (x0 + x);
3774     d3_geo_centroidY2 += z * (y0 + y);
3775     d3_geo_centroidZ2 += z * 3;
3776     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
3777   }
3778
3779   // For the last point, return to the start.
3780   d3_geo_pathCentroid.lineEnd = function() {
3781     nextPoint(x00, y00);
3782   };
3783 }
3784
3785 function d3_geo_pathContext(context) {
3786   var pointRadius = 4.5;
3787
3788   var stream = {
3789     point: point,
3790
3791     // While inside a line, override point to moveTo then lineTo.
3792     lineStart: function() { stream.point = pointLineStart; },
3793     lineEnd: lineEnd,
3794
3795     // While inside a polygon, override lineEnd to closePath.
3796     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
3797     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
3798
3799     pointRadius: function(_) {
3800       pointRadius = _;
3801       return stream;
3802     },
3803
3804     result: d3_noop
3805   };
3806
3807   function point(x, y) {
3808     context.moveTo(x, y);
3809     context.arc(x, y, pointRadius, 0, 2 * π);
3810   }
3811
3812   function pointLineStart(x, y) {
3813     context.moveTo(x, y);
3814     stream.point = pointLine;
3815   }
3816
3817   function pointLine(x, y) {
3818     context.lineTo(x, y);
3819   }
3820
3821   function lineEnd() {
3822     stream.point = point;
3823   }
3824
3825   function lineEndPolygon() {
3826     context.closePath();
3827   }
3828
3829   return stream;
3830 }
3831
3832 function d3_geo_resample(project) {
3833   var δ2 = .5, // precision, px²
3834       cosMinDistance = Math.cos(30 * d3_radians), // cos(minimum angular distance)
3835       maxDepth = 16;
3836
3837   function resample(stream) {
3838     var λ00, φ00, x00, y00, a00, b00, c00, // first point
3839         λ0, x0, y0, a0, b0, c0; // previous point
3840
3841     var resample = {
3842       point: point,
3843       lineStart: lineStart,
3844       lineEnd: lineEnd,
3845       polygonStart: function() { stream.polygonStart(); resample.lineStart = ringStart; },
3846       polygonEnd: function() { stream.polygonEnd(); resample.lineStart = lineStart; }
3847     };
3848
3849     function point(x, y) {
3850       x = project(x, y);
3851       stream.point(x[0], x[1]);
3852     }
3853
3854     function lineStart() {
3855       x0 = NaN;
3856       resample.point = linePoint;
3857       stream.lineStart();
3858     }
3859
3860     function linePoint(λ, φ) {
3861       var c = d3_geo_cartesian([λ, φ]), p = project(λ, φ);
3862       resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
3863       stream.point(x0, y0);
3864     }
3865
3866     function lineEnd() {
3867       resample.point = point;
3868       stream.lineEnd();
3869     }
3870
3871     function ringStart() {
3872       lineStart();
3873       resample.point = ringPoint;
3874       resample.lineEnd = ringEnd;
3875     }
3876
3877     function ringPoint(λ, φ) {
3878       linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
3879       resample.point = linePoint;
3880     }
3881
3882     function ringEnd() {
3883       resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
3884       resample.lineEnd = lineEnd;
3885       lineEnd();
3886     }
3887
3888     return resample;
3889   }
3890
3891   function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
3892     var dx = x1 - x0,
3893         dy = y1 - y0,
3894         d2 = dx * dx + dy * dy;
3895     if (d2 > 4 * δ2 && depth--) {
3896       var a = a0 + a1,
3897           b = b0 + b1,
3898           c = c0 + c1,
3899           m = Math.sqrt(a * a + b * b + c * c),
3900           φ2 = Math.asin(c /= m),
3901           λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a),
3902           p = project(λ2, φ2),
3903           x2 = p[0],
3904           y2 = p[1],
3905           dx2 = x2 - x0,
3906           dy2 = y2 - y0,
3907           dz = dy * dx2 - dx * dy2;
3908       if (dz * dz / d2 > δ2 // perpendicular projected distance
3909           || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 // midpoint close to an end
3910           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
3911         resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
3912         stream.point(x2, y2);
3913         resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
3914       }
3915     }
3916   }
3917
3918   resample.precision = function(_) {
3919     if (!arguments.length) return Math.sqrt(δ2);
3920     maxDepth = (δ2 = _ * _) > 0 && 16;
3921     return resample;
3922   };
3923
3924   return resample;
3925 }
3926
3927 d3.geo.path = function() {
3928   var pointRadius = 4.5,
3929       projection,
3930       context,
3931       projectStream,
3932       contextStream,
3933       cacheStream;
3934
3935   function path(object) {
3936     if (object) {
3937       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
3938       if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
3939       d3.geo.stream(object, cacheStream);
3940     }
3941     return contextStream.result();
3942   }
3943
3944   path.area = function(object) {
3945     d3_geo_pathAreaSum = 0;
3946     d3.geo.stream(object, projectStream(d3_geo_pathArea));
3947     return d3_geo_pathAreaSum;
3948   };
3949
3950   path.centroid = function(object) {
3951     d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
3952     d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
3953     d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
3954     d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
3955     return d3_geo_centroidZ2 ? [d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2]
3956         : d3_geo_centroidZ1 ? [d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1]
3957         : d3_geo_centroidZ0 ? [d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0]
3958         : [NaN, NaN];
3959   };
3960
3961   path.bounds = function(object) {
3962     d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
3963     d3.geo.stream(object, projectStream(d3_geo_pathBounds));
3964     return [[d3_geo_pathBoundsX0, d3_geo_pathBoundsY0], [d3_geo_pathBoundsX1, d3_geo_pathBoundsY1]];
3965   };
3966
3967   path.projection = function(_) {
3968     if (!arguments.length) return projection;
3969     projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
3970     return reset();
3971   };
3972
3973   path.context = function(_) {
3974     if (!arguments.length) return context;
3975     contextStream = (context = _) == null ? new d3_geo_pathBuffer : new d3_geo_pathContext(_);
3976     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
3977     return reset();
3978   };
3979
3980   path.pointRadius = function(_) {
3981     if (!arguments.length) return pointRadius;
3982     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
3983     return path;
3984   };
3985
3986   function reset() {
3987     cacheStream = null;
3988     return path;
3989   }
3990
3991   return path.projection(d3.geo.albersUsa()).context(null);
3992 };
3993
3994 function d3_geo_pathProjectStream(project) {
3995   var resample = d3_geo_resample(function(λ, φ) { return project([λ * d3_degrees, φ * d3_degrees]); });
3996   return function(stream) {
3997     stream = resample(stream);
3998     return {
3999       point: function(λ, φ) { stream.point(λ * d3_radians, φ * d3_radians); },
4000       sphere: function() { stream.sphere(); },
4001       lineStart: function() { stream.lineStart(); },
4002       lineEnd: function() { stream.lineEnd(); },
4003       polygonStart: function() { stream.polygonStart(); },
4004       polygonEnd: function() { stream.polygonEnd(); }
4005     };
4006   };
4007 }
4008
4009 d3.geo.projection = d3_geo_projection;
4010 d3.geo.projectionMutator = d3_geo_projectionMutator;
4011
4012 function d3_geo_projection(project) {
4013   return d3_geo_projectionMutator(function() { return project; })();
4014 }
4015
4016 function d3_geo_projectionMutator(projectAt) {
4017   var project,
4018       rotate,
4019       projectRotate,
4020       projectResample = d3_geo_resample(function(x, y) { x = project(x, y); return [x[0] * k + δx, δy - x[1] * k]; }),
4021       k = 150, // scale
4022       x = 480, y = 250, // translate
4023       λ = 0, φ = 0, // center
4024       δλ = 0, δφ = 0, δγ = 0, // rotate
4025       δx, δy, // center
4026       preclip = d3_geo_clipAntimeridian,
4027       postclip = d3_identity,
4028       clipAngle = null,
4029       clipExtent = null,
4030       stream;
4031
4032   function projection(point) {
4033     point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
4034     return [point[0] * k + δx, δy - point[1] * k];
4035   }
4036
4037   function invert(point) {
4038     point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
4039     return point && [point[0] * d3_degrees, point[1] * d3_degrees];
4040   }
4041
4042   projection.stream = function(output) {
4043     if (stream) stream.valid = false;
4044     stream = d3_geo_projectionRadiansRotate(rotate, preclip(projectResample(postclip(output))));
4045     stream.valid = true; // allow caching by d3.geo.path
4046     return stream;
4047   };
4048
4049   projection.clipAngle = function(_) {
4050     if (!arguments.length) return clipAngle;
4051     preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
4052     return invalidate();
4053   };
4054
4055   projection.clipExtent = function(_) {
4056     if (!arguments.length) return clipExtent;
4057     clipExtent = _;
4058     postclip = _ == null ? d3_identity : d3_geo_clipView(_[0][0], _[0][1], _[1][0], _[1][1]);
4059     return invalidate();
4060   };
4061
4062   projection.scale = function(_) {
4063     if (!arguments.length) return k;
4064     k = +_;
4065     return reset();
4066   };
4067
4068   projection.translate = function(_) {
4069     if (!arguments.length) return [x, y];
4070     x = +_[0];
4071     y = +_[1];
4072     return reset();
4073   };
4074
4075   projection.center = function(_) {
4076     if (!arguments.length) return [λ * d3_degrees, φ * d3_degrees];
4077     λ = _[0] % 360 * d3_radians;
4078     φ = _[1] % 360 * d3_radians;
4079     return reset();
4080   };
4081
4082   projection.rotate = function(_) {
4083     if (!arguments.length) return [δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees];
4084     δλ = _[0] % 360 * d3_radians;
4085     δφ = _[1] % 360 * d3_radians;
4086     δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
4087     return reset();
4088   };
4089
4090   d3.rebind(projection, projectResample, "precision");
4091
4092   function reset() {
4093     projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
4094     var center = project(λ, φ);
4095     δx = x - center[0] * k;
4096     δy = y + center[1] * k;
4097     return invalidate();
4098   }
4099
4100   function invalidate() {
4101     if (stream) {
4102       stream.valid = false;
4103       stream = null;
4104     }
4105     return projection;
4106   }
4107
4108   return function() {
4109     project = projectAt.apply(this, arguments);
4110     projection.invert = project.invert && invert;
4111     return reset();
4112   };
4113 }
4114
4115 function d3_geo_projectionRadiansRotate(rotate, stream) {
4116   return {
4117     point: function(x, y) {
4118       y = rotate(x * d3_radians, y * d3_radians), x = y[0];
4119       stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]);
4120     },
4121     sphere: function() { stream.sphere(); },
4122     lineStart: function() { stream.lineStart(); },
4123     lineEnd: function() { stream.lineEnd(); },
4124     polygonStart: function() { stream.polygonStart(); },
4125     polygonEnd: function() { stream.polygonEnd(); }
4126   };
4127 }
4128
4129 function d3_geo_mercator(λ, φ) {
4130   return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
4131 }
4132
4133 d3_geo_mercator.invert = function(x, y) {
4134   return [x, 2 * Math.atan(Math.exp(y)) - π / 2];
4135 };
4136
4137 function d3_geo_mercatorProjection(project) {
4138   var m = d3_geo_projection(project),
4139       scale = m.scale,
4140       translate = m.translate,
4141       clipExtent = m.clipExtent,
4142       clipAuto;
4143
4144   m.scale = function() {
4145     var v = scale.apply(m, arguments);
4146     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
4147   };
4148
4149   m.translate = function() {
4150     var v = translate.apply(m, arguments);
4151     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
4152   };
4153
4154   m.clipExtent = function(_) {
4155     var v = clipExtent.apply(m, arguments);
4156     if (v === m) {
4157       if (clipAuto = _ == null) {
4158         var k = π * scale(), t = translate();
4159         clipExtent([[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]);
4160       }
4161     } else if (clipAuto) {
4162       v = null;
4163     }
4164     return v;
4165   };
4166
4167   return m.clipExtent(null);
4168 }
4169
4170 (d3.geo.mercator = function() {
4171   return d3_geo_mercatorProjection(d3_geo_mercator);
4172 }).raw = d3_geo_mercator;
4173 d3.geom = {};
4174
4175 d3.geom.polygon = function(coordinates) {
4176   d3_subclass(coordinates, d3_geom_polygonPrototype);
4177   return coordinates;
4178 };
4179
4180 var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
4181
4182 d3_geom_polygonPrototype.area = function() {
4183   var i = -1,
4184       n = this.length,
4185       a,
4186       b = this[n - 1],
4187       area = 0;
4188
4189   while (++i < n) {
4190     a = b;
4191     b = this[i];
4192     area += a[1] * b[0] - a[0] * b[1];
4193   }
4194
4195   return area * .5;
4196 };
4197
4198 d3_geom_polygonPrototype.centroid = function(k) {
4199   var i = -1,
4200       n = this.length,
4201       x = 0,
4202       y = 0,
4203       a,
4204       b = this[n - 1],
4205       c;
4206
4207   if (!arguments.length) k = -1 / (6 * this.area());
4208
4209   while (++i < n) {
4210     a = b;
4211     b = this[i];
4212     c = a[0] * b[1] - b[0] * a[1];
4213     x += (a[0] + b[0]) * c;
4214     y += (a[1] + b[1]) * c;
4215   }
4216
4217   return [x * k, y * k];
4218 };
4219
4220 // The Sutherland-Hodgman clipping algorithm.
4221 // Note: requires the clip polygon to be counterclockwise and convex.
4222 d3_geom_polygonPrototype.clip = function(subject) {
4223   var input,
4224       closed = d3_geom_polygonClosed(subject),
4225       i = -1,
4226       n = this.length - d3_geom_polygonClosed(this),
4227       j,
4228       m,
4229       a = this[n - 1],
4230       b,
4231       c,
4232       d;
4233
4234   while (++i < n) {
4235     input = subject.slice();
4236     subject.length = 0;
4237     b = this[i];
4238     c = input[(m = input.length - closed) - 1];
4239     j = -1;
4240     while (++j < m) {
4241       d = input[j];
4242       if (d3_geom_polygonInside(d, a, b)) {
4243         if (!d3_geom_polygonInside(c, a, b)) {
4244           subject.push(d3_geom_polygonIntersect(c, d, a, b));
4245         }
4246         subject.push(d);
4247       } else if (d3_geom_polygonInside(c, a, b)) {
4248         subject.push(d3_geom_polygonIntersect(c, d, a, b));
4249       }
4250       c = d;
4251     }
4252     if (closed) subject.push(subject[0]);
4253     a = b;
4254   }
4255
4256   return subject;
4257 };
4258
4259 function d3_geom_polygonInside(p, a, b) {
4260   return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
4261 }
4262
4263 // Intersect two infinite lines cd and ab.
4264 function d3_geom_polygonIntersect(c, d, a, b) {
4265   var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
4266       y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
4267       ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
4268   return [x1 + ua * x21, y1 + ua * y21];
4269 }
4270
4271 // Returns true if the polygon is closed.
4272 function d3_geom_polygonClosed(coordinates) {
4273   var a = coordinates[0],
4274       b = coordinates[coordinates.length - 1];
4275   return !(a[0] - b[0] || a[1] - b[1]);
4276 }
4277
4278 var d3_ease_default = function() { return d3_identity; };
4279
4280 var d3_ease = d3.map({
4281   linear: d3_ease_default,
4282   poly: d3_ease_poly,
4283   quad: function() { return d3_ease_quad; },
4284   cubic: function() { return d3_ease_cubic; },
4285   sin: function() { return d3_ease_sin; },
4286   exp: function() { return d3_ease_exp; },
4287   circle: function() { return d3_ease_circle; },
4288   elastic: d3_ease_elastic,
4289   back: d3_ease_back,
4290   bounce: function() { return d3_ease_bounce; }
4291 });
4292
4293 var d3_ease_mode = d3.map({
4294   "in": d3_identity,
4295   "out": d3_ease_reverse,
4296   "in-out": d3_ease_reflect,
4297   "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); }
4298 });
4299
4300 d3.ease = function(name) {
4301   var i = name.indexOf("-"),
4302       t = i >= 0 ? name.substring(0, i) : name,
4303       m = i >= 0 ? name.substring(i + 1) : "in";
4304   t = d3_ease.get(t) || d3_ease_default;
4305   m = d3_ease_mode.get(m) || d3_identity;
4306   return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));
4307 };
4308
4309 function d3_ease_clamp(f) {
4310   return function(t) {
4311     return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
4312   };
4313 }
4314
4315 function d3_ease_reverse(f) {
4316   return function(t) {
4317     return 1 - f(1 - t);
4318   };
4319 }
4320
4321 function d3_ease_reflect(f) {
4322   return function(t) {
4323     return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
4324   };
4325 }
4326
4327 function d3_ease_quad(t) {
4328   return t * t;
4329 }
4330
4331 function d3_ease_cubic(t) {
4332   return t * t * t;
4333 }
4334
4335 // Optimized clamp(reflect(poly(3))).
4336 function d3_ease_cubicInOut(t) {
4337   if (t <= 0) return 0;
4338   if (t >= 1) return 1;
4339   var t2 = t * t, t3 = t2 * t;
4340   return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
4341 }
4342
4343 function d3_ease_poly(e) {
4344   return function(t) {
4345     return Math.pow(t, e);
4346   };
4347 }
4348
4349 function d3_ease_sin(t) {
4350   return 1 - Math.cos(t * π / 2);
4351 }
4352
4353 function d3_ease_exp(t) {
4354   return Math.pow(2, 10 * (t - 1));
4355 }
4356
4357 function d3_ease_circle(t) {
4358   return 1 - Math.sqrt(1 - t * t);
4359 }
4360
4361 function d3_ease_elastic(a, p) {
4362   var s;
4363   if (arguments.length < 2) p = 0.45;
4364   if (arguments.length) s = p / (2 * π) * Math.asin(1 / a);
4365   else a = 1, s = p / 4;
4366   return function(t) {
4367     return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * π / p);
4368   };
4369 }
4370
4371 function d3_ease_back(s) {
4372   if (!s) s = 1.70158;
4373   return function(t) {
4374     return t * t * ((s + 1) * t - s);
4375   };
4376 }
4377
4378 function d3_ease_bounce(t) {
4379   return t < 1 / 2.75 ? 7.5625 * t * t
4380       : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
4381       : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
4382       : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
4383 }
4384
4385 function d3_transition(groups, id) {
4386   d3_subclass(groups, d3_transitionPrototype);
4387
4388   groups.id = id; // Note: read-only!
4389
4390   return groups;
4391 }
4392
4393 var d3_transitionPrototype = [],
4394     d3_transitionId = 0,
4395     d3_transitionInheritId,
4396     d3_transitionInherit;
4397
4398 d3_transitionPrototype.call = d3_selectionPrototype.call;
4399 d3_transitionPrototype.empty = d3_selectionPrototype.empty;
4400 d3_transitionPrototype.node = d3_selectionPrototype.node;
4401 d3_transitionPrototype.size = d3_selectionPrototype.size;
4402
4403 d3.transition = function(selection) {
4404   return arguments.length
4405       ? (d3_transitionInheritId ? selection.transition() : selection)
4406       : d3_selectionRoot.transition();
4407 };
4408
4409 d3.transition.prototype = d3_transitionPrototype;
4410
4411
4412 d3_transitionPrototype.select = function(selector) {
4413   var id = this.id,
4414       subgroups = [],
4415       subgroup,
4416       subnode,
4417       node;
4418
4419   selector = d3_selection_selector(selector);
4420
4421   for (var j = -1, m = this.length; ++j < m;) {
4422     subgroups.push(subgroup = []);
4423     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
4424       if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
4425         if ("__data__" in node) subnode.__data__ = node.__data__;
4426         d3_transitionNode(subnode, i, id, node.__transition__[id]);
4427         subgroup.push(subnode);
4428       } else {
4429         subgroup.push(null);
4430       }
4431     }
4432   }
4433
4434   return d3_transition(subgroups, id);
4435 };
4436
4437 d3_transitionPrototype.selectAll = function(selector) {
4438   var id = this.id,
4439       subgroups = [],
4440       subgroup,
4441       subnodes,
4442       node,
4443       subnode,
4444       transition;
4445
4446   selector = d3_selection_selectorAll(selector);
4447
4448   for (var j = -1, m = this.length; ++j < m;) {
4449     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
4450       if (node = group[i]) {
4451         transition = node.__transition__[id];
4452         subnodes = selector.call(node, node.__data__, i, j);
4453         subgroups.push(subgroup = []);
4454         for (var k = -1, o = subnodes.length; ++k < o;) {
4455           if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
4456           subgroup.push(subnode);
4457         }
4458       }
4459     }
4460   }
4461
4462   return d3_transition(subgroups, id);
4463 };
4464
4465 d3_transitionPrototype.filter = function(filter) {
4466   var subgroups = [],
4467       subgroup,
4468       group,
4469       node;
4470
4471   if (typeof filter !== "function") filter = d3_selection_filter(filter);
4472
4473   for (var j = 0, m = this.length; j < m; j++) {
4474     subgroups.push(subgroup = []);
4475     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
4476       if ((node = group[i]) && filter.call(node, node.__data__, i)) {
4477         subgroup.push(node);
4478       }
4479     }
4480   }
4481
4482   return d3_transition(subgroups, this.id);
4483 };
4484 function d3_Color() {}
4485
4486 d3_Color.prototype.toString = function() {
4487   return this.rgb() + "";
4488 };
4489
4490 d3.hsl = function(h, s, l) {
4491   return arguments.length === 1
4492       ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l)
4493       : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
4494       : d3_hsl(+h, +s, +l);
4495 };
4496
4497 function d3_hsl(h, s, l) {
4498   return new d3_Hsl(h, s, l);
4499 }
4500
4501 function d3_Hsl(h, s, l) {
4502   this.h = h;
4503   this.s = s;
4504   this.l = l;
4505 }
4506
4507 var d3_hslPrototype = d3_Hsl.prototype = new d3_Color;
4508
4509 d3_hslPrototype.brighter = function(k) {
4510   k = Math.pow(0.7, arguments.length ? k : 1);
4511   return d3_hsl(this.h, this.s, this.l / k);
4512 };
4513
4514 d3_hslPrototype.darker = function(k) {
4515   k = Math.pow(0.7, arguments.length ? k : 1);
4516   return d3_hsl(this.h, this.s, k * this.l);
4517 };
4518
4519 d3_hslPrototype.rgb = function() {
4520   return d3_hsl_rgb(this.h, this.s, this.l);
4521 };
4522
4523 function d3_hsl_rgb(h, s, l) {
4524   var m1,
4525       m2;
4526
4527   /* Some simple corrections for h, s and l. */
4528   h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
4529   s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
4530   l = l < 0 ? 0 : l > 1 ? 1 : l;
4531
4532   /* From FvD 13.37, CSS Color Module Level 3 */
4533   m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
4534   m1 = 2 * l - m2;
4535
4536   function v(h) {
4537     if (h > 360) h -= 360;
4538     else if (h < 0) h += 360;
4539     if (h < 60) return m1 + (m2 - m1) * h / 60;
4540     if (h < 180) return m2;
4541     if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
4542     return m1;
4543   }
4544
4545   function vv(h) {
4546     return Math.round(v(h) * 255);
4547   }
4548
4549   return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
4550 }
4551
4552 d3.hcl = function(h, c, l) {
4553   return arguments.length === 1
4554       ? (h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l)
4555       : (h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b)
4556       : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b)))
4557       : d3_hcl(+h, +c, +l);
4558 };
4559
4560 function d3_hcl(h, c, l) {
4561   return new d3_Hcl(h, c, l);
4562 }
4563
4564 function d3_Hcl(h, c, l) {
4565   this.h = h;
4566   this.c = c;
4567   this.l = l;
4568 }
4569
4570 var d3_hclPrototype = d3_Hcl.prototype = new d3_Color;
4571
4572 d3_hclPrototype.brighter = function(k) {
4573   return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
4574 };
4575
4576 d3_hclPrototype.darker = function(k) {
4577   return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
4578 };
4579
4580 d3_hclPrototype.rgb = function() {
4581   return d3_hcl_lab(this.h, this.c, this.l).rgb();
4582 };
4583
4584 function d3_hcl_lab(h, c, l) {
4585   if (isNaN(h)) h = 0;
4586   if (isNaN(c)) c = 0;
4587   return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
4588 }
4589
4590 d3.lab = function(l, a, b) {
4591   return arguments.length === 1
4592       ? (l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b)
4593       : (l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h)
4594       : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b)))
4595       : d3_lab(+l, +a, +b);
4596 };
4597
4598 function d3_lab(l, a, b) {
4599   return new d3_Lab(l, a, b);
4600 }
4601
4602 function d3_Lab(l, a, b) {
4603   this.l = l;
4604   this.a = a;
4605   this.b = b;
4606 }
4607
4608 // Corresponds roughly to RGB brighter/darker
4609 var d3_lab_K = 18;
4610
4611 // D65 standard referent
4612 var d3_lab_X = 0.950470,
4613     d3_lab_Y = 1,
4614     d3_lab_Z = 1.088830;
4615
4616 var d3_labPrototype = d3_Lab.prototype = new d3_Color;
4617
4618 d3_labPrototype.brighter = function(k) {
4619   return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
4620 };
4621
4622 d3_labPrototype.darker = function(k) {
4623   return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
4624 };
4625
4626 d3_labPrototype.rgb = function() {
4627   return d3_lab_rgb(this.l, this.a, this.b);
4628 };
4629
4630 function d3_lab_rgb(l, a, b) {
4631   var y = (l + 16) / 116,
4632       x = y + a / 500,
4633       z = y - b / 200;
4634   x = d3_lab_xyz(x) * d3_lab_X;
4635   y = d3_lab_xyz(y) * d3_lab_Y;
4636   z = d3_lab_xyz(z) * d3_lab_Z;
4637   return d3_rgb(
4638     d3_xyz_rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z),
4639     d3_xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
4640     d3_xyz_rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z)
4641   );
4642 }
4643
4644 function d3_lab_hcl(l, a, b) {
4645   return l > 0
4646       ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l)
4647       : d3_hcl(NaN, NaN, l);
4648 }
4649
4650 function d3_lab_xyz(x) {
4651   return x > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
4652 }
4653 function d3_xyz_lab(x) {
4654   return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
4655 }
4656
4657 function d3_xyz_rgb(r) {
4658   return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055));
4659 }
4660
4661 d3.rgb = function(r, g, b) {
4662   return arguments.length === 1
4663       ? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b)
4664       : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
4665       : d3_rgb(~~r, ~~g, ~~b);
4666 };
4667
4668 function d3_rgbNumber(value) {
4669   return d3_rgb(value >> 16, value >> 8 & 0xff, value & 0xff);
4670 }
4671
4672 function d3_rgbString(value) {
4673   return d3_rgbNumber(value) + "";
4674 }
4675
4676 function d3_rgb(r, g, b) {
4677   return new d3_Rgb(r, g, b);
4678 }
4679
4680 function d3_Rgb(r, g, b) {
4681   this.r = r;
4682   this.g = g;
4683   this.b = b;
4684 }
4685
4686 var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color;
4687
4688 d3_rgbPrototype.brighter = function(k) {
4689   k = Math.pow(0.7, arguments.length ? k : 1);
4690   var r = this.r,
4691       g = this.g,
4692       b = this.b,
4693       i = 30;
4694   if (!r && !g && !b) return d3_rgb(i, i, i);
4695   if (r && r < i) r = i;
4696   if (g && g < i) g = i;
4697   if (b && b < i) b = i;
4698   return d3_rgb(Math.min(255, ~~(r / k)), Math.min(255, ~~(g / k)), Math.min(255, ~~(b / k)));
4699 };
4700
4701 d3_rgbPrototype.darker = function(k) {
4702   k = Math.pow(0.7, arguments.length ? k : 1);
4703   return d3_rgb(~~(k * this.r), ~~(k * this.g), ~~(k * this.b));
4704 };
4705
4706 d3_rgbPrototype.hsl = function() {
4707   return d3_rgb_hsl(this.r, this.g, this.b);
4708 };
4709
4710 d3_rgbPrototype.toString = function() {
4711   return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
4712 };
4713
4714 function d3_rgb_hex(v) {
4715   return v < 0x10
4716       ? "0" + Math.max(0, v).toString(16)
4717       : Math.min(255, v).toString(16);
4718 }
4719
4720 function d3_rgb_parse(format, rgb, hsl) {
4721   var r = 0, // red channel; int in [0, 255]
4722       g = 0, // green channel; int in [0, 255]
4723       b = 0, // blue channel; int in [0, 255]
4724       m1, // CSS color specification match
4725       m2, // CSS color specification type (e.g., rgb)
4726       name;
4727
4728   /* Handle hsl, rgb. */
4729   m1 = /([a-z]+)\((.*)\)/i.exec(format);
4730   if (m1) {
4731     m2 = m1[2].split(",");
4732     switch (m1[1]) {
4733       case "hsl": {
4734         return hsl(
4735           parseFloat(m2[0]), // degrees
4736           parseFloat(m2[1]) / 100, // percentage
4737           parseFloat(m2[2]) / 100 // percentage
4738         );
4739       }
4740       case "rgb": {
4741         return rgb(
4742           d3_rgb_parseNumber(m2[0]),
4743           d3_rgb_parseNumber(m2[1]),
4744           d3_rgb_parseNumber(m2[2])
4745         );
4746       }
4747     }
4748   }
4749
4750   /* Named colors. */
4751   if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
4752
4753   /* Hexadecimal colors: #rgb and #rrggbb. */
4754   if (format != null && format.charAt(0) === "#") {
4755     if (format.length === 4) {
4756       r = format.charAt(1); r += r;
4757       g = format.charAt(2); g += g;
4758       b = format.charAt(3); b += b;
4759     } else if (format.length === 7) {
4760       r = format.substring(1, 3);
4761       g = format.substring(3, 5);
4762       b = format.substring(5, 7);
4763     }
4764     r = parseInt(r, 16);
4765     g = parseInt(g, 16);
4766     b = parseInt(b, 16);
4767   }
4768
4769   return rgb(r, g, b);
4770 }
4771
4772 function d3_rgb_hsl(r, g, b) {
4773   var min = Math.min(r /= 255, g /= 255, b /= 255),
4774       max = Math.max(r, g, b),
4775       d = max - min,
4776       h,
4777       s,
4778       l = (max + min) / 2;
4779   if (d) {
4780     s = l < .5 ? d / (max + min) : d / (2 - max - min);
4781     if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
4782     else if (g == max) h = (b - r) / d + 2;
4783     else h = (r - g) / d + 4;
4784     h *= 60;
4785   } else {
4786     h = NaN;
4787     s = l > 0 && l < 1 ? 0 : h;
4788   }
4789   return d3_hsl(h, s, l);
4790 }
4791
4792 function d3_rgb_lab(r, g, b) {
4793   r = d3_rgb_xyz(r);
4794   g = d3_rgb_xyz(g);
4795   b = d3_rgb_xyz(b);
4796   var x = d3_xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / d3_lab_X),
4797       y = d3_xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / d3_lab_Y),
4798       z = d3_xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / d3_lab_Z);
4799   return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
4800 }
4801
4802 function d3_rgb_xyz(r) {
4803   return (r /= 255) <= 0.04045 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
4804 }
4805
4806 function d3_rgb_parseNumber(c) { // either integer or percentage
4807   var f = parseFloat(c);
4808   return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
4809 }
4810
4811 var d3_rgb_names = d3.map({
4812   aliceblue: 0xf0f8ff,
4813   antiquewhite: 0xfaebd7,
4814   aqua: 0x00ffff,
4815   aquamarine: 0x7fffd4,
4816   azure: 0xf0ffff,
4817   beige: 0xf5f5dc,
4818   bisque: 0xffe4c4,
4819   black: 0x000000,
4820   blanchedalmond: 0xffebcd,
4821   blue: 0x0000ff,
4822   blueviolet: 0x8a2be2,
4823   brown: 0xa52a2a,
4824   burlywood: 0xdeb887,
4825   cadetblue: 0x5f9ea0,
4826   chartreuse: 0x7fff00,
4827   chocolate: 0xd2691e,
4828   coral: 0xff7f50,
4829   cornflowerblue: 0x6495ed,
4830   cornsilk: 0xfff8dc,
4831   crimson: 0xdc143c,
4832   cyan: 0x00ffff,
4833   darkblue: 0x00008b,
4834   darkcyan: 0x008b8b,
4835   darkgoldenrod: 0xb8860b,
4836   darkgray: 0xa9a9a9,
4837   darkgreen: 0x006400,
4838   darkgrey: 0xa9a9a9,
4839   darkkhaki: 0xbdb76b,
4840   darkmagenta: 0x8b008b,
4841   darkolivegreen: 0x556b2f,
4842   darkorange: 0xff8c00,
4843   darkorchid: 0x9932cc,
4844   darkred: 0x8b0000,
4845   darksalmon: 0xe9967a,
4846   darkseagreen: 0x8fbc8f,
4847   darkslateblue: 0x483d8b,