ngx-d3-tooltip
Version:
Add tooltips to your d3 visualizations using Angular Components.
1,303 lines • 106 kB
JavaScript
import { ApplicationRef, Component, ComponentFactoryResolver, Directive, HostBinding, Injectable, Injector, Input, NgModule, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
var D3TooltipHostDirective = (function () {
/**
* @param {?} viewContainerRef
*/
function D3TooltipHostDirective(viewContainerRef) {
this.viewContainerRef = viewContainerRef;
}
return D3TooltipHostDirective;
}());
D3TooltipHostDirective.decorators = [
{ type: Directive, args: [{
selector: '[d3TooltipHost]'
},] },
];
/**
* @nocollapse
*/
D3TooltipHostDirective.ctorParameters = function () { return [
{ type: ViewContainerRef, },
]; };
var D3TooltipComponent = (function () {
/**
* @param {?} cfr
*/
function D3TooltipComponent(cfr) {
this.cfr = cfr;
/**
* Controls a class which sets the element opacity to 1 when present.
*/
this.isVisible = false;
}
Object.defineProperty(D3TooltipComponent.prototype, "cssTop", {
/**
* @return {?}
*/
get: function () {
return this.position.top + "px";
},
enumerable: true,
configurable: true
});
Object.defineProperty(D3TooltipComponent.prototype, "cssLeft", {
/**
* @return {?}
*/
get: function () {
return this.position.left + "px";
},
enumerable: true,
configurable: true
});
Object.defineProperty(D3TooltipComponent.prototype, "cssClasses", {
/**
* @return {?}
*/
get: function () {
return this.options.position + " " + this.options.cssClasses;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
D3TooltipComponent.prototype.loadComponent = function () {
var _this = this;
var /** @type {?} */ componentFactory = this.cfr.resolveComponentFactory(this.component);
var /** @type {?} */ viewContainerRef = this.componentHost.viewContainerRef;
viewContainerRef.clear();
var /** @type {?} */ componentRef = viewContainerRef.createComponent(componentFactory);
Object.keys(this.inputs).forEach(function (k) {
componentRef.instance[k] = _this.inputs[k];
});
Object.keys(this.outputs).forEach(function (k) {
componentRef.instance[k].subscribe(_this.outputs[k]);
});
};
/**
* @return {?}
*/
D3TooltipComponent.prototype.ngOnInit = function () {
var _this = this;
setTimeout(function () {
_this.isVisible = true;
}, 1);
};
return D3TooltipComponent;
}());
D3TooltipComponent.decorators = [
{ type: Component, args: [{
selector: 'd3-tooltip',
template: "\n <div class=\"ngx-d3-tooltip {{ cssClasses }}\" [ngClass]=\"{ 'ngx-d3-tooltip_visible': isVisible }\">\n <div class=\"arrow\"></div>\n <ng-template d3TooltipHost></ng-template>\n </div>\n ",
styles: ["\n d3-tooltip {\n position: absolute;\n width: 0;\n height: 0;\n overflow: visible;\n display: block;\n }\n d3-tooltip .ngx-d3-tooltip {\n display: inline-block;\n position: relative;\n background-color: #fff;\n border-color: #CCC;\n border-radius: 2px;\n -webkit-box-shadow: 0 1px 10px -3px rgba(0,0,0,0.3);\n box-shadow: 0 1px 10px -3px rgba(0,0,0,0.3);\n padding: 0.5rem 1rem;\n opacity: 0;\n -webkit-transition: opacity 0.2s ease-in;\n transition: opacity 0.2s ease-in;\n border: 1px solid #00000020;\n }\n d3-tooltip .ngx-d3-tooltip.ngx-d3-tooltip_visible {\n opacity: 1;\n }\n d3-tooltip .ngx-d3-tooltip .arrow {\n position: absolute;\n display: block;\n width: .8rem;\n height: .4rem;\n }\n d3-tooltip .ngx-d3-tooltip .arrow::before, d3-tooltip .ngx-d3-tooltip .arrow::after {\n position: absolute;\n display: block;\n border-color: #0000;\n border-style: solid;\n content: '';\n border-width: 10px;\n }\n /* TOP */\n d3-tooltip .ngx-d3-tooltip.top {\n -webkit-transform: translateX(-50%);\n transform: translateX(-50%);\n position: absolute;\n left: 0;\n bottom: 20px;\n }\n\n d3-tooltip .ngx-d3-tooltip.top .arrow {\n bottom: 0;\n left: 50%;\n }\n\n d3-tooltip .ngx-d3-tooltip.top .arrow::before {\n bottom: -20px;\n margin-left: -10px;\n border-top-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.top .arrow::after {\n bottom: -19px;\n margin-left: -10px;\n border-top-color: #fff;\n }\n\n /* BOTTOM */\n d3-tooltip .ngx-d3-tooltip.bottom {\n -webkit-transform: translateX(-50%);\n transform: translateX(-50%);\n position: absolute;\n left: 0;\n top: 20px;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottom .arrow {\n top: 0;\n left: 50%;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottom .arrow::before {\n top: -20px;\n margin-left: -10px;\n border-bottom-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottom .arrow::after {\n top: -19px;\n margin-left: -10px;\n border-bottom-color: #fff;\n }\n /* LEFT */\n d3-tooltip .ngx-d3-tooltip.left {\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n position: absolute;\n right: 20px;\n top: 0;\n }\n\n d3-tooltip .ngx-d3-tooltip.left .arrow {\n right: 0;\n top: 50%;\n }\n\n d3-tooltip .ngx-d3-tooltip.left .arrow::before {\n right: -20px;\n margin-top: -10px;\n border-left-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.left .arrow::after {\n right: -19px;\n margin-top: -10px;\n border-left-color: #fff;\n }\n\n /* RIGHT */\n d3-tooltip .ngx-d3-tooltip.right {\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n position: absolute;\n left: 20px;\n top: 0;\n }\n\n d3-tooltip .ngx-d3-tooltip.right .arrow {\n left: 0;\n top: 50%;\n }\n\n d3-tooltip .ngx-d3-tooltip.right .arrow::before {\n left: -20px;\n margin-top: -10px;\n border-right-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.right .arrow::after {\n left: -19px;\n margin-top: -10px;\n border-right-color: #fff;\n }\n\n /* TOPRIGHT */\n d3-tooltip .ngx-d3-tooltip.topRight {\n position: absolute;\n left: -15px;\n bottom: 20px;\n }\n\n d3-tooltip .ngx-d3-tooltip.topRight .arrow {\n bottom: 0;\n left: 15px;\n }\n\n d3-tooltip .ngx-d3-tooltip.topRight .arrow::before {\n bottom: -20px;\n margin-left: -10px;\n border-top-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.topRight .arrow::after {\n bottom: -19px;\n margin-left: -10px;\n border-top-color: #fff;\n }\n\n /* TOPLEFT */\n d3-tooltip .ngx-d3-tooltip.topLeft {\n position: absolute;\n right: -15px;\n bottom: 20px;\n }\n\n d3-tooltip .ngx-d3-tooltip.topLeft .arrow {\n bottom: 0;\n right: 15px;\n }\n\n d3-tooltip .ngx-d3-tooltip.topLeft .arrow::before {\n bottom: -20px;\n margin-right: -10px;\n border-top-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.topLeft .arrow::after {\n bottom: -19px;\n margin-right: -10px;\n border-top-color: #fff;\n }\n /* BOTTOMRIGHT */\n d3-tooltip .ngx-d3-tooltip.bottomRight {\n position: absolute;\n left: -15px;\n top: 25px;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomRight .arrow {\n top: 0;\n left: 15px;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomRight .arrow::before {\n top: -20px;\n margin-left: -10px;\n border-bottom-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomRight .arrow::after {\n top: -19px;\n margin-left: -10px;\n border-bottom-color: #fff;\n }\n\n /* BOTTOMLEFT */\n d3-tooltip .ngx-d3-tooltip.bottomLeft {\n position: absolute;\n right: -15px;\n top: 25px;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomLeft .arrow {\n top: 0;\n right: 15px;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomLeft .arrow::before {\n top: -20px;\n margin-right: -10px;\n border-bottom-color: #00000040;\n }\n\n d3-tooltip .ngx-d3-tooltip.bottomLeft .arrow::after {\n top: -19px;\n margin-right: -10px;\n border-bottom-color: #fff;\n }\n "],
encapsulation: ViewEncapsulation.None
},] },
];
/**
* @nocollapse
*/
D3TooltipComponent.ctorParameters = function () { return [
{ type: ComponentFactoryResolver, },
]; };
D3TooltipComponent.propDecorators = {
'component': [{ type: Input },],
'position': [{ type: Input },],
'options': [{ type: Input },],
'inputs': [{ type: Input },],
'outputs': [{ type: Input },],
'componentHost': [{ type: ViewChild, args: [D3TooltipHostDirective,] },],
'cssTop': [{ type: HostBinding, args: ['style.top',] },],
'cssLeft': [{ type: HostBinding, args: ['style.left',] },],
};
var ascending = function (a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
};
var bisector = function (compare) {
if (compare.length === 1)
compare = ascendingComparator(compare);
return {
left: function (a, x, lo, hi) {
if (lo == null)
lo = 0;
if (hi == null)
hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (compare(a[mid], x) < 0)
lo = mid + 1;
else
hi = mid;
}
return lo;
},
right: function (a, x, lo, hi) {
if (lo == null)
lo = 0;
if (hi == null)
hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (compare(a[mid], x) > 0)
hi = mid;
else
lo = mid + 1;
}
return lo;
}
};
};
function ascendingComparator(f) {
return function (d, x) {
return ascending(f(d), x);
};
}
var ascendingBisect = bisector(ascending);
var noop = { value: function () { } };
function dispatch() {
for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
if (!(t = arguments[i] + "") || (t in _))
throw new Error("illegal type: " + t);
_[t] = [];
}
return new Dispatch(_);
}
function Dispatch(_) {
this._ = _;
}
function parseTypenames(typenames, types) {
return typenames.trim().split(/^|\s+/).map(function (t) {
var name = "", i = t.indexOf(".");
if (i >= 0)
name = t.slice(i + 1), t = t.slice(0, i);
if (t && !types.hasOwnProperty(t))
throw new Error("unknown type: " + t);
return { type: t, name: name };
});
}
Dispatch.prototype = dispatch.prototype = {
constructor: Dispatch,
on: function (typename, callback) {
var _ = this._, T = parseTypenames(typename + "", _), t, i = -1, n = T.length;
// If no callback was specified, return the callback of the given type and name.
if (arguments.length < 2) {
while (++i < n)
if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name)))
return t;
return;
}
// If a type was specified, set the callback for the given type and name.
// Otherwise, if a null callback was specified, remove callbacks of the given name.
if (callback != null && typeof callback !== "function")
throw new Error("invalid callback: " + callback);
while (++i < n) {
if (t = (typename = T[i]).type)
_[t] = set(_[t], typename.name, callback);
else if (callback == null)
for (t in _)
_[t] = set(_[t], typename.name, null);
}
return this;
},
copy: function () {
var copy = {}, _ = this._;
for (var t in _)
copy[t] = _[t].slice();
return new Dispatch(copy);
},
call: function (type, that) {
if ((n = arguments.length - 2) > 0)
for (var args = new Array(n), i = 0, n, t; i < n; ++i)
args[i] = arguments[i + 2];
if (!this._.hasOwnProperty(type))
throw new Error("unknown type: " + type);
for (t = this._[type], i = 0, n = t.length; i < n; ++i)
t[i].value.apply(that, args);
},
apply: function (type, that, args) {
if (!this._.hasOwnProperty(type))
throw new Error("unknown type: " + type);
for (var t = this._[type], i = 0, n = t.length; i < n; ++i)
t[i].value.apply(that, args);
}
};
function get(type, name) {
for (var i = 0, n = type.length, c; i < n; ++i) {
if ((c = type[i]).name === name) {
return c.value;
}
}
}
function set(type, name, callback) {
for (var i = 0, n = type.length; i < n; ++i) {
if (type[i].name === name) {
type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
break;
}
}
if (callback != null)
type.push({ name: name, value: callback });
return type;
}
if (typeof document !== "undefined") {
var element = document.documentElement;
if (!element.matches) {
var vendorMatches = element.webkitMatchesSelector
|| element.msMatchesSelector
|| element.mozMatchesSelector
|| element.oMatchesSelector;
}
}
var event = null;
if (typeof document !== "undefined") {
var element$1 = document.documentElement;
}
var define = function (constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
};
function extend(parent, definition) {
var prototype = Object.create(parent.prototype);
for (var key in definition)
prototype[key] = definition[key];
return prototype;
}
function Color() { }
var darker = 0.7;
var brighter = 1 / darker;
var reI = "\\s*([+-]?\\d+)\\s*";
var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
var reHex3 = /^#([0-9a-f]{3})$/;
var reHex6 = /^#([0-9a-f]{6})$/;
var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
var named = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
};
define(Color, color, {
displayable: function () {
return this.rgb().displayable();
},
toString: function () {
return this.rgb() + "";
}
});
function color(format) {
var m;
format = (format + "").trim().toLowerCase();
return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00
: (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
: (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named.hasOwnProperty(format) ? rgbn(named[format])
: format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
: null;
}
function rgbn(n) {
return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}
function rgba(r, g, b, a) {
if (a <= 0)
r = g = b = NaN;
return new Rgb(r, g, b, a);
}
function rgbConvert(o) {
if (!(o instanceof Color))
o = color(o);
if (!o)
return new Rgb;
o = o.rgb();
return new Rgb(o.r, o.g, o.b, o.opacity);
}
function rgb(r, g, b, opacity) {
return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
}
function Rgb(r, g, b, opacity) {
this.r = +r;
this.g = +g;
this.b = +b;
this.opacity = +opacity;
}
define(Rgb, rgb, extend(Color, {
brighter: function (k) {
k = k == null ? brighter : Math.pow(brighter, k);
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
},
darker: function (k) {
k = k == null ? darker : Math.pow(darker, k);
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
},
rgb: function () {
return this;
},
displayable: function () {
return (0 <= this.r && this.r <= 255)
&& (0 <= this.g && this.g <= 255)
&& (0 <= this.b && this.b <= 255)
&& (0 <= this.opacity && this.opacity <= 1);
},
toString: function () {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "rgb(" : "rgba(")
+ Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
+ Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
+ Math.max(0, Math.min(255, Math.round(this.b) || 0))
+ (a === 1 ? ")" : ", " + a + ")");
}
}));
function hsla(h, s, l, a) {
if (a <= 0)
h = s = l = NaN;
else if (l <= 0 || l >= 1)
h = s = NaN;
else if (s <= 0)
h = NaN;
return new Hsl(h, s, l, a);
}
function hslConvert(o) {
if (o instanceof Hsl)
return new Hsl(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Color))
o = color(o);
if (!o)
return new Hsl;
if (o instanceof Hsl)
return o;
o = o.rgb();
var r = o.r / 255, g = o.g / 255, b = o.b / 255, min = Math.min(r, g, b), max = Math.max(r, g, b), h = NaN, s = max - min, l = (max + min) / 2;
if (s) {
if (r === max)
h = (g - b) / s + (g < b) * 6;
else if (g === max)
h = (b - r) / s + 2;
else
h = (r - g) / s + 4;
s /= l < 0.5 ? max + min : 2 - max - min;
h *= 60;
}
else {
s = l > 0 && l < 1 ? 0 : h;
}
return new Hsl(h, s, l, o.opacity);
}
function hsl(h, s, l, opacity) {
return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
}
function Hsl(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define(Hsl, hsl, extend(Color, {
brighter: function (k) {
k = k == null ? brighter : Math.pow(brighter, k);
return new Hsl(this.h, this.s, this.l * k, this.opacity);
},
darker: function (k) {
k = k == null ? darker : Math.pow(darker, k);
return new Hsl(this.h, this.s, this.l * k, this.opacity);
},
rgb: function () {
var h = this.h % 360 + (this.h < 0) * 360, s = isNaN(h) || isNaN(this.s) ? 0 : this.s, l = this.l, m2 = l + (l < 0.5 ? l : 1 - l) * s, m1 = 2 * l - m2;
return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
},
displayable: function () {
return (0 <= this.s && this.s <= 1 || isNaN(this.s))
&& (0 <= this.l && this.l <= 1)
&& (0 <= this.opacity && this.opacity <= 1);
}
}));
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb(h, m1, m2) {
return (h < 60 ? m1 + (m2 - m1) * h / 60
: h < 180 ? m2
: h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
: m1) * 255;
}
var deg2rad = Math.PI / 180;
var rad2deg = 180 / Math.PI;
var Kn = 18;
var Xn = 0.950470;
var Yn = 1;
var Zn = 1.088830;
var t0 = 4 / 29;
var t1 = 6 / 29;
var t2 = 3 * t1 * t1;
var t3 = t1 * t1 * t1;
function labConvert(o) {
if (o instanceof Lab)
return new Lab(o.l, o.a, o.b, o.opacity);
if (o instanceof Hcl) {
var h = o.h * deg2rad;
return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
}
if (!(o instanceof Rgb))
o = rgbConvert(o);
var b = rgb2xyz(o.r), a = rgb2xyz(o.g), l = rgb2xyz(o.b), x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
}
function lab(l, a, b, opacity) {
return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
}
function Lab(l, a, b, opacity) {
this.l = +l;
this.a = +a;
this.b = +b;
this.opacity = +opacity;
}
define(Lab, lab, extend(Color, {
brighter: function (k) {
return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
},
darker: function (k) {
return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
},
rgb: function () {
var y = (this.l + 16) / 116, x = isNaN(this.a) ? y : y + this.a / 500, z = isNaN(this.b) ? y : y - this.b / 200;
y = Yn * lab2xyz(y);
x = Xn * lab2xyz(x);
z = Zn * lab2xyz(z);
return new Rgb(xyz2rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), xyz2rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z), this.opacity);
}
}));
function xyz2lab(t) {
return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
}
function lab2xyz(t) {
return t > t1 ? t * t * t : t2 * (t - t0);
}
function xyz2rgb(x) {
return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
}
function rgb2xyz(x) {
return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
function hclConvert(o) {
if (o instanceof Hcl)
return new Hcl(o.h, o.c, o.l, o.opacity);
if (!(o instanceof Lab))
o = labConvert(o);
var h = Math.atan2(o.b, o.a) * rad2deg;
return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
}
function hcl(h, c, l, opacity) {
return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
}
function Hcl(h, c, l, opacity) {
this.h = +h;
this.c = +c;
this.l = +l;
this.opacity = +opacity;
}
define(Hcl, hcl, extend(Color, {
brighter: function (k) {
return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
},
darker: function (k) {
return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
},
rgb: function () {
return labConvert(this).rgb();
}
}));
var A = -0.14861;
var B = +1.78277;
var C = -0.29227;
var D = -0.90649;
var E = +1.97294;
var ED = E * D;
var EB = E * B;
var BC_DA = B * C - D * A;
function cubehelixConvert(o) {
if (o instanceof Cubehelix)
return new Cubehelix(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Rgb))
o = rgbConvert(o);
var r = o.r / 255, g = o.g / 255, b = o.b / 255, l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), bl = b - l, k = (E * (g - l) - C * bl) / D, s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
}
function cubehelix(h, s, l, opacity) {
return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
}
function Cubehelix(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define(Cubehelix, cubehelix, extend(Color, {
brighter: function (k) {
k = k == null ? brighter : Math.pow(brighter, k);
return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
},
darker: function (k) {
k = k == null ? darker : Math.pow(darker, k);
return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
},
rgb: function () {
var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, l = +this.l, a = isNaN(this.s) ? 0 : this.s * l * (1 - l), cosh = Math.cos(h), sinh = Math.sin(h);
return new Rgb(255 * (l + a * (A * cosh + B * sinh)), 255 * (l + a * (C * cosh + D * sinh)), 255 * (l + a * (E * cosh)), this.opacity);
}
}));
var constant$3 = function (x) {
return function () {
return x;
};
};
function linear(a, d) {
return function (t) {
return a + t * d;
};
}
function hue(a, b) {
var d = b - a;
return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
}
function nogamma(a, b) {
var d = b - a;
return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
}
var degrees = 180 / Math.PI;
var rho = Math.SQRT2;
function cubehelix$1(hue$$1) {
return (function cubehelixGamma(y) {
y = +y;
function cubehelix$$1(start, end) {
var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), s = nogamma(start.s, end.s), l = nogamma(start.l, end.l), opacity = nogamma(start.opacity, end.opacity);
return function (t) {
start.h = h(t);
start.s = s(t);
start.l = l(Math.pow(t, y));
start.opacity = opacity(t);
return start + "";
};
}
cubehelix$$1.gamma = cubehelixGamma;
return cubehelix$$1;
})(1);
}
cubehelix$1(hue);
var cubehelixLong = cubehelix$1(nogamma);
var clock = typeof performance === "object" && performance.now ? performance : Date;
var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) { setTimeout(f, 17); };
var emptyOn = dispatch("start", "end", "interrupt");
var pi = Math.PI;
var tau = 2 * Math.PI;
var X = {
name: "x",
handles: ["e", "w"].map(type),
input: function (x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
output: function (xy) { return xy && [xy[0][0], xy[1][0]]; }
};
var Y = {
name: "y",
handles: ["n", "s"].map(type),
input: function (y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
output: function (xy) { return xy && [xy[0][1], xy[1][1]]; }
};
var XY = {
name: "xy",
handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type),
input: function (xy) { return xy; },
output: function (xy) { return xy; }
};
function type(t) {
return { type: t };
}
var pi$1 = Math.PI;
var pi$2 = Math.PI;
var EOL = {};
var EOF = {};
var QUOTE = 34;
var NEWLINE = 10;
var RETURN = 13;
function objectConverter(columns) {
return new Function("d", "return {" + columns.map(function (name, i) {
return JSON.stringify(name) + ": d[" + i + "]";
}).join(",") + "}");
}
function customConverter(columns, f) {
var object = objectConverter(columns);
return function (row, i) {
return f(object(row), i, columns);
};
}
// Compute unique columns in order of discovery.
function inferColumns(rows) {
var columnSet = Object.create(null), columns = [];
rows.forEach(function (row) {
for (var column in row) {
if (!(column in columnSet)) {
columns.push(columnSet[column] = column);
}
}
});
return columns;
}
var dsv = function (delimiter) {
var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), DELIMITER = delimiter.charCodeAt(0);
function parse(text, f) {
var convert, columns, rows = parseRows(text, function (row, i) {
if (convert)
return convert(row, i - 1);
columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
});
rows.columns = columns;
return rows;
}
function parseRows(text, f) {
var rows = [], // output rows
N = text.length, I = 0, // current character index
n = 0, // current line number
t, // current token
eof = N <= 0, // current token followed by EOF?
eol = false; // current token followed by EOL?
// Strip the trailing newline.
if (text.charCodeAt(N - 1) === NEWLINE)
--N;
if (text.charCodeAt(N - 1) === RETURN)
--N;
function token() {
if (eof)
return EOF;
if (eol)
return eol = false, EOL;
// Unescape quotes.
var i, j = I, c;
if (text.charCodeAt(j) === QUOTE) {
while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE)
;
if ((i = I) >= N)
eof = true;
else if ((c = text.charCodeAt(I++)) === NEWLINE)
eol = true;
else if (c === RETURN) {
eol = true;
if (text.charCodeAt(I) === NEWLINE)
++I;
}
return text.slice(j + 1, i - 1).replace(/""/g, "\"");
}
// Find next delimiter or newline.
while (I < N) {
if ((c = text.charCodeAt(i = I++)) === NEWLINE)
eol = true;
else if (c === RETURN) {
eol = true;
if (text.charCodeAt(I) === NEWLINE)
++I;
}
else if (c !== DELIMITER)
continue;
return text.slice(j, i);
}
// Return last token before EOF.
return eof = true, text.slice(j, N);
}
while ((t = token()) !== EOF) {
var row = [];
while (t !== EOL && t !== EOF)
row.push(t), t = token();
if (f && (row = f(row, n++)) == null)
continue;
rows.push(row);
}
return rows;
}
function format(rows, columns) {
if (columns == null)
columns = inferColumns(rows);
return [columns.map(formatValue).join(delimiter)].concat(rows.map(function (row) {
return columns.map(function (column) {
return formatValue(row[column]);
}).join(delimiter);
})).join("\n");
}
function formatRows(rows) {
return rows.map(formatRow).join("\n");
}
function formatRow(row) {
return row.map(formatValue).join(delimiter);
}
function formatValue(text) {
return text == null ? ""
: reFormat.test(text += "") ? "\"" + text.replace(/"/g, "\"\"") + "\""
: text;
}
return {
parse: parse,
parseRows: parseRows,
format: format,
formatRows: formatRows
};
};
var csv = dsv(",");
var tsv = dsv("\t");
var tree_add = function (d) {
var x = +this._x.call(null, d), y = +this._y.call(null, d);
return add(this.cover(x, y), x, y, d);
};
function add(tree, x, y, d) {
if (isNaN(x) || isNaN(y))
return tree; // ignore invalid points
var parent, node = tree._root, leaf = { data: d }, x0 = tree._x0, y0 = tree._y0, x1 = tree._x1, y1 = tree._y1, xm, ym, xp, yp, right, bottom, i, j;
// If the tree is empty, initialize the root as a leaf.
if (!node)
return tree._root = leaf, tree;
// Find the existing leaf for the new point, or add it.
while (node.length) {
if (right = x >= (xm = (x0 + x1) / 2))
x0 = xm;
else
x1 = xm;
if (bottom = y >= (ym = (y0 + y1) / 2))
y0 = ym;
else
y1 = ym;
if (parent = node, !(node = node[i = bottom << 1 | right]))
return parent[i] = leaf, tree;
}
// Is the new point is exactly coincident with the existing point?
xp = +tree._x.call(null, node.data);
yp = +tree._y.call(null, node.data);
if (x === xp && y === yp)
return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
// Otherwise, split the leaf node until the old and new point are separated.
do {
parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
if (right = x >= (xm = (x0 + x1) / 2))
x0 = xm;
else
x1 = xm;
if (bottom = y >= (ym = (y0 + y1) / 2))
y0 = ym;
else
y1 = ym;
} while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
return parent[j] = node, parent[i] = leaf, tree;
}
function addAll(data) {
var d, i, n = data.length, x, y, xz = new Array(n), yz = new Array(n), x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
// Compute the points and their extent.
for (i = 0; i < n; ++i) {
if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d)))
continue;
xz[i] = x;
yz[i] = y;
if (x < x0)
x0 = x;
if (x > x1)
x1 = x;
if (y < y0)
y0 = y;
if (y > y1)
y1 = y;
}
// If there were no (valid) points, inherit the existing extent.
if (x1 < x0)
x0 = this._x0, x1 = this._x1;
if (y1 < y0)
y0 = this._y0, y1 = this._y1;
// Expand the tree to cover the new points.
this.cover(x0, y0).cover(x1, y1);
// Add the new points.
for (i = 0; i < n; ++i) {
add(this, xz[i], yz[i], data[i]);
}
return this;
}
var tree_cover = function (x, y) {
if (isNaN(x = +x) || isNaN(y = +y))
return this; // ignore invalid points
var x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1;
// If the quadtree has no extent, initialize them.
// Integer extent are necessary so that if we later double the extent,
// the existing quadrant boundaries don’t change due to floating point error!
if (isNaN(x0)) {
x1 = (x0 = Math.floor(x)) + 1;
y1 = (y0 = Math.floor(y)) + 1;
}
else if (x0 > x || x > x1 || y0 > y || y > y1) {
var z = x1 - x0, node = this._root, parent, i;
switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
case 0: {
do
parent = new Array(4), parent[i] = node, node = parent;
while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
break;
}
case 1: {
do
parent = new Array(4), parent[i] = node, node = parent;
while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
break;
}
case 2: {
do
parent = new Array(4), parent[i] = node, node = parent;
while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
break;
}
case 3: {
do
parent = new Array(4), parent[i] = node, node = parent;
while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
break;
}
}
if (this._root && this._root.length)
this._root = node;
}
else
return this;
this._x0 = x0;
this._y0 = y0;
this._x1 = x1;
this._y1 = y1;
return this;
};
var tree_data = function () {
var data = [];
this.visit(function (node) {
if (!node.length)
do
data.push(node.data);
while (node = node.next);
});
return data;
};
var tree_extent = function (_) {
return arguments.length
? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
: isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
};
var Quad = function (node, x0, y0, x1, y1) {
this.node = node;
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
};
var tree_find = function (x, y, radius) {
var data, x0 = this._x0, y0 = this._y0, x1, y1, x2, y2, x3 = this._x1, y3 = this._y1, quads = [], node = this._root, q, i;
if (node)
quads.push(new Quad(node, x0, y0, x3, y3));
if (radius == null)
radius = Infinity;
else {
x0 = x - radius, y0 = y - radius;
x3 = x + radius, y3 = y + radius;
radius *= radius;
}
while (q = quads.pop()) {
// Stop searching if this quadrant can’t contain a closer node.
if (!(node = q.node)
|| (x1 = q.x0) > x3
|| (y1 = q.y0) > y3
|| (x2 = q.x1) < x0
|| (y2 = q.y1) < y0)
continue;
// Bisect the current quadrant.
if (node.length) {
var xm = (x1 + x2) / 2, ym = (y1 + y2) / 2;
quads.push(new Quad(node[3], xm, ym, x2, y2), new Quad(node[2], x1, ym, xm, y2), new Quad(node[1], xm, y1, x2, ym), new Quad(node[0], x1, y1, xm, ym));
// Visit the closest quadrant first.
if (i = (y >= ym) << 1 | (x >= xm)) {
q = quads[quads.length - 1];
quads[quads.length - 1] = quads[quads.length - 1 - i];
quads[quads.length - 1 - i] = q;
}
}
else {
var dx = x - +this._x.call(null, node.data), dy = y - +this._y.call(null, node.data), d2 = dx * dx + dy * dy;
if (d2 < radius) {
var d = Math.sqrt(radius = d2);
x0 = x - d, y0 = y - d;
x3 = x + d, y3 = y + d;
data = node.data;
}
}
}
return data;
};
var tree_remove = function (d) {
if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d)))
return this; // ignore invalid points
var parent, node = this._root, retainer, previous, next, x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1, x, y, xm, ym, right, bottom, i, j;
// If the tree is empty, initialize the root as a leaf.
if (!node)
return this;
// Find the leaf node for the point.
// While descending, also retain the deepest parent with a non-removed sibling.
if (node.length)
while (true) {
if (right = x >= (xm = (x0 + x1) / 2))
x0 = xm;
else
x1 = xm;
if (bottom = y >= (ym = (y0 + y1) / 2))
y0 = ym;
else
y1 = ym;
if (!(parent = node, node = node[i = bottom << 1 | right]))
return this;
if (!node.length)
break;
if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3])
retainer = parent, j = i;
}
// Find the point to remove.
while (node.data !== d)
if (!(previous = node, node = node.next))
return this;
if (next = node.next)
delete node.next;
// If there are multiple coincident points, remove just the point.
if (previous)
return next ? previous.next = next : delete previous.next, this;
// If this is the root point, remove it.
if (!parent)
return this._root = next, this;
// Remove this leaf.
next ? parent[i] = next : delete parent[i];
// If the parent now contains exactly one leaf, collapse superfluous parents.
if ((node = parent[0] || parent[1] || parent[2] || parent[3])
&& node === (parent[3] || parent[2] || parent[1] || parent[0])
&& !node.length) {
if (retainer)
retainer[j] = node;
else
this._root = node;
}
return this;
};
function removeAll(data) {
for (var i = 0, n = data.length; i < n; ++i)
this.remove(data[i]);
return this;
}
var tree_root = function () {
return this._root;
};
var tree_size = function () {
var size = 0;
this.visit(function (node) {
if (!node.length)
do
++size;
while (node = node.next);
});
return size;
};
var tree_visit = function (callback) {
var quads = [], q, node = this._root, child, x0, y0, x1, y1;
if (node)
quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
while (q = quads.pop()) {
if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
if (child = node[3])
quads.push(new Quad(child, xm, ym, x1, y1));
if (child = node[2])
quads.push(new Quad(child, x0, ym, xm, y1));
if (child = node[1])
quads.push(new Quad(child, xm, y0, x1, ym));
if (child = node[0])
quads.push(new Quad(child, x0, y0, xm, ym));
}
}
return this;
};
var tree_visitAfter = function (callback) {
var quads = [], next = [], q;
if (this._root)
quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
while (q = quads.pop()) {
var node = q.node;
if (node.length) {
var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
if (child = node[0])
quads.push(new Quad(child, x0, y0, xm, ym));
if (child = node[1])
quads.push(new Quad(child, xm, y0, x1, ym));
if (child = node[2])
quads.push(new Quad(child, x0, ym, xm, y1));
if (child = node[3])
quads.push(new Quad(child, xm, ym, x1, y1));
}
next.push(q);
}
while (q = next.pop()) {
callback(q.node, q.x0, q.y0, q.x1, q.y1);
}
return this;
};
function defaultX(d) {
return d[0];
}
var tree_x = function (_) {
return arguments.length ? (this._x = _, this) : this._x;
};
function defaultY(d) {
return d[1];
}
var tree_y = function (_) {
return arguments.length ? (this._y = _, this) : this._y;
};
function quadtree(nodes, x, y) {
var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
return nodes == null ? tree : tree.addAll(nodes);
}
function Quadtree(x, y, x0, y0, x1, y1) {
this._x = x;
this._y = y;
this._x0 = x0;
this._y0 = y0;
this._x1 = x1;
this._y1 = y1;
this._root = undefined;
}
function leaf_copy(leaf) {
var copy = { data: leaf.data }, next = copy;
while (leaf = leaf.next)
next = next.next = { data: leaf.data };
return copy;
}
var treeProto = quadtree.prototype = Quadtree.prototype;
treeProto.copy = function () {
var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), node = this._root, nodes, child;
if (!node)
return copy;
if (!node.length)
return copy._root = leaf_copy(node), copy;
nodes = [{ source: node, target: copy._root = new Array(4) }];
while (node = nodes.pop()) {
for (var i = 0; i < 4; ++i) {
if (child = node.source[i]) {
if (child.length)
nodes.push({ source: child, target: node.target[i] = new Array(4) });
else
node.target[i] = leaf_copy(child);
}
}
}
return copy;
};
treeProto.add = tree_add;
treeProto.addAll = addAll;
treeProto.cover = tree_cover;
treeProto.data = tree_data;
treeProto.extent = tree_extent;
treeProto.find = tree_find;
treeProto.remove = tree_remove;
treeProto.removeAll = removeAll;
treeProto.root = tree_root;
treeProto.size = tree_size;
treeProto.visit = tree_visit;
treeProto.visitAfter = tree_visitAfter;
treeProto.x = tree_x;
treeProto.y = tree_y;
var initialAngle = Math.PI * (3 - Math.sqrt(5));
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimal(1.23) returns ["123", 0].
var formatDecimal = function (x, p) {
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0)
return null; // NaN, ±Infinity
var i, coefficient = x.slice(0, i);
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+x.slice(i + 1)
];
};
var exponent$1 = function (x) {
return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
};
var formatGroup = function (grouping, thousands) {
return function (value, width) {
var i = value.length, t = [], j = 0, g = grouping[0], length = 0;
while (i > 0 && g > 0) {
if (length + g + 1 > width)
g = Math.max(1, width - length);
t.push(value.substring(i -= g, i + g));
if ((length += g + 1) > width)
break;
g = grouping[j = (j + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
};
var formatNumerals = function (numerals) {
return function (value) {
return value.replace(/[0-9]/g, function (i) {
return numerals[+i];
});
};
};
var formatDefault = function (x, p) {
x = x.toPrecision(p);
out: for (var