To dev:
yarn && yarn run start
Edit script.js and the page will update without a full reload.
Trying to remake Hurricane Irma Is One of the Strongest Storms In History with regl using line examples and rreusser's demo.
To dev:
yarn && yarn run start
Edit script.js and the page will update without a full reload.
Trying to remake Hurricane Irma Is One of the Strongest Storms In History with regl using line examples and rreusser's demo.
try { window.regltick.cancel() } catch(e){} | |
console.clear() | |
window.regl ? run(null, regl) : reglLib({onDone: run}) | |
function run(err, regl){ | |
window.regl = regl | |
// regl.clear({color: [0, 0, 0, 1], depth: 1}) | |
var n = 10000 | |
var lines = 50 | |
var data = d3.range(lines).map(d => { | |
var i = Math.floor(n*Math.random()) | |
return d3.range(i, i + 20).map((i) => [i, i + 1]) | |
}) | |
var colors = linspace(ndarray([], [n]), 1, 0) | |
function circlePoints(n){ | |
return function(i){ | |
var theta = 2.0 * Math.PI * i / n | |
return [ Math.sin(theta), Math.cos(theta) ] | |
} | |
} | |
function randomPoints(n){ | |
return function(){ | |
return [Math.random()*2 - 1, Math.random()*2 - 1] | |
} | |
} | |
var datasets = [] | |
var curIndex = 0 | |
var lastSwitchTime = 0 | |
var switchInterval = 1 | |
var switchDuration = 1 | |
function createDatasets(){ | |
datasets = [circlePoints, randomPoints, randomPoints].map(fn => | |
regl.buffer(vectorFill(ndarray([], [n, 2]), fn(n))) | |
) | |
} | |
createDatasets() | |
var drawPoints = regl({ | |
vert: ` | |
precision mediump float; | |
attribute vec2 xy0, xy1; | |
attribute float basis; | |
varying float c; | |
uniform float interp; | |
void main() { | |
c = basis; | |
vec2 pos = mix(xy0, xy1, interp); | |
gl_Position = vec4(pos, 0, 1); | |
}`, | |
frag: ` | |
precision mediump float; | |
varying float c; | |
void main() { | |
gl_FragColor = vec4(c/2.0 + 0.5, 0, 1, 1); | |
}`, | |
lineWidth: 1, | |
attributes: { | |
xy0: () => datasets[curIndex % datasets.length], | |
xy1: () => datasets[(curIndex + 1) % datasets.length], | |
basis: colors, | |
}, | |
uniforms: { | |
interp: (ctx, props) => Math.max(0, Math.min(1, props.interp)) | |
}, | |
elements: regl.elements({ | |
data, | |
type: 'uint16', | |
usage: 'static', | |
primitive: 'lines' | |
}), | |
}) | |
window.regltick = regl.frame(({time}) => { | |
// Check how long it's been since the last switch, and cycle the buffers | |
// and reset the timer if it's time for a switch: | |
if ((time - lastSwitchTime) > switchInterval) { | |
lastSwitchTime = time | |
curIndex++ | |
} | |
drawPoints({interp: ease((time - lastSwitchTime) / switchDuration)}) | |
}) | |
} |
<!DOCTYPE html> | |
<html> | |
<head> | |
<body></body> | |
<script src='lib-build.js'></script> | |
<script src='_script.js'></script> | |
</html> |
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
var libs = { | |
glsl: require('glslify'), | |
linspace: require('ndarray-linspace'), | |
vectorFill: require('ndarray-vector-fill'), | |
ndarray: require('ndarray'), | |
ease: require('eases/cubic-in-out'), | |
reglLib: require('regl'), | |
d3: require('d3'), | |
} | |
var glsl = require('glslify') | |
libs.glslViridis = glsl(["#define GLSLIFY 1\nvec4 viridis (float x) {\n const float e0 = 0.0;\n const vec4 v0 = vec4(0.26666666666666666,0.00392156862745098,0.32941176470588235,1);\n const float e1 = 0.13;\n const vec4 v1 = vec4(0.2784313725490196,0.17254901960784313,0.47843137254901963,1);\n const float e2 = 0.25;\n const vec4 v2 = vec4(0.23137254901960785,0.3176470588235294,0.5450980392156862,1);\n const float e3 = 0.38;\n const vec4 v3 = vec4(0.17254901960784313,0.44313725490196076,0.5568627450980392,1);\n const float e4 = 0.5;\n const vec4 v4 = vec4(0.12941176470588237,0.5647058823529412,0.5529411764705883,1);\n const float e5 = 0.63;\n const vec4 v5 = vec4(0.15294117647058825,0.6784313725490196,0.5058823529411764,1);\n const float e6 = 0.75;\n const vec4 v6 = vec4(0.3607843137254902,0.7843137254901961,0.38823529411764707,1);\n const float e7 = 0.88;\n const vec4 v7 = vec4(0.6666666666666666,0.8627450980392157,0.19607843137254902,1);\n const float e8 = 1.0;\n const vec4 v8 = vec4(0.9921568627450981,0.9058823529411765,0.1450980392156863,1);\n float a0 = smoothstep(e0,e1,x);\n float a1 = smoothstep(e1,e2,x);\n float a2 = smoothstep(e2,e3,x);\n float a3 = smoothstep(e3,e4,x);\n float a4 = smoothstep(e4,e5,x);\n float a5 = smoothstep(e5,e6,x);\n float a6 = smoothstep(e6,e7,x);\n float a7 = smoothstep(e7,e8,x);\n return max(mix(v0,v1,a0)*step(e0,x)*step(x,e1),\n max(mix(v1,v2,a1)*step(e1,x)*step(x,e2),\n max(mix(v2,v3,a2)*step(e2,x)*step(x,e3),\n max(mix(v3,v4,a3)*step(e3,x)*step(x,e4),\n max(mix(v4,v5,a4)*step(e4,x)*step(x,e5),\n max(mix(v5,v6,a5)*step(e5,x)*step(x,e6),\n max(mix(v6,v7,a6)*step(e6,x)*step(x,e7),mix(v7,v8,a7)*step(e7,x)*step(x,e8)\n )))))));\n}\n\n",""]) | |
for (key in libs) window[key] = libs[key] | |
},{"d3":45,"eases/cubic-in-out":46,"glslify":49,"ndarray":59,"ndarray-linspace":57,"ndarray-vector-fill":58,"regl":76}],2:[function(require,module,exports){ | |
'use strict' | |
exports.byteLength = byteLength | |
exports.toByteArray = toByteArray | |
exports.fromByteArray = fromByteArray | |
var lookup = [] | |
var revLookup = [] | |
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array | |
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
for (var i = 0, len = code.length; i < len; ++i) { | |
lookup[i] = code[i] | |
revLookup[code.charCodeAt(i)] = i | |
} | |
revLookup['-'.charCodeAt(0)] = 62 | |
revLookup['_'.charCodeAt(0)] = 63 | |
function placeHoldersCount (b64) { | |
var len = b64.length | |
if (len % 4 > 0) { | |
throw new Error('Invalid string. Length must be a multiple of 4') | |
} | |
// the number of equal signs (place holders) | |
// if there are two placeholders, than the two characters before it | |
// represent one byte | |
// if there is only one, then the three characters before it represent 2 bytes | |
// this is just a cheap hack to not do indexOf twice | |
return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 | |
} | |
function byteLength (b64) { | |
// base64 is 4/3 + up to two characters of the original data | |
return b64.length * 3 / 4 - placeHoldersCount(b64) | |
} | |
function toByteArray (b64) { | |
var i, j, l, tmp, placeHolders, arr | |
var len = b64.length | |
placeHolders = placeHoldersCount(b64) | |
arr = new Arr(len * 3 / 4 - placeHolders) | |
// if there are placeholders, only get up to the last complete 4 chars | |
l = placeHolders > 0 ? len - 4 : len | |
var L = 0 | |
for (i = 0, j = 0; i < l; i += 4, j += 3) { | |
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] | |
arr[L++] = (tmp >> 16) & 0xFF | |
arr[L++] = (tmp >> 8) & 0xFF | |
arr[L++] = tmp & 0xFF | |
} | |
if (placeHolders === 2) { | |
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) | |
arr[L++] = tmp & 0xFF | |
} else if (placeHolders === 1) { | |
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) | |
arr[L++] = (tmp >> 8) & 0xFF | |
arr[L++] = tmp & 0xFF | |
} | |
return arr | |
} | |
function tripletToBase64 (num) { | |
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] | |
} | |
function encodeChunk (uint8, start, end) { | |
var tmp | |
var output = [] | |
for (var i = start; i < end; i += 3) { | |
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) | |
output.push(tripletToBase64(tmp)) | |
} | |
return output.join('') | |
} | |
function fromByteArray (uint8) { | |
var tmp | |
var len = uint8.length | |
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes | |
var output = '' | |
var parts = [] | |
var maxChunkLength = 16383 // must be multiple of 3 | |
// go through the array every three bytes, we'll deal with trailing stuff later | |
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { | |
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) | |
} | |
// pad the end with zeros, but make sure to not forget the extra bytes | |
if (extraBytes === 1) { | |
tmp = uint8[len - 1] | |
output += lookup[tmp >> 2] | |
output += lookup[(tmp << 4) & 0x3F] | |
output += '==' | |
} else if (extraBytes === 2) { | |
tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) | |
output += lookup[tmp >> 10] | |
output += lookup[(tmp >> 4) & 0x3F] | |
output += lookup[(tmp << 2) & 0x3F] | |
output += '=' | |
} | |
parts.push(output) | |
return parts.join('') | |
} | |
},{}],3:[function(require,module,exports){ | |
},{}],4:[function(require,module,exports){ | |
arguments[4][3][0].apply(exports,arguments) | |
},{"dup":3}],5:[function(require,module,exports){ | |
(function (global){ | |
'use strict'; | |
var buffer = require('buffer'); | |
var Buffer = buffer.Buffer; | |
var SlowBuffer = buffer.SlowBuffer; | |
var MAX_LEN = buffer.kMaxLength || 2147483647; | |
exports.alloc = function alloc(size, fill, encoding) { | |
if (typeof Buffer.alloc === 'function') { | |
return Buffer.alloc(size, fill, encoding); | |
} | |
if (typeof encoding === 'number') { | |
throw new TypeError('encoding must not be number'); | |
} | |
if (typeof size !== 'number') { | |
throw new TypeError('size must be a number'); | |
} | |
if (size > MAX_LEN) { | |
throw new RangeError('size is too large'); | |
} | |
var enc = encoding; | |
var _fill = fill; | |
if (_fill === undefined) { | |
enc = undefined; | |
_fill = 0; | |
} | |
var buf = new Buffer(size); | |
if (typeof _fill === 'string') { | |
var fillBuf = new Buffer(_fill, enc); | |
var flen = fillBuf.length; | |
var i = -1; | |
while (++i < size) { | |
buf[i] = fillBuf[i % flen]; | |
} | |
} else { | |
buf.fill(_fill); | |
} | |
return buf; | |
} | |
exports.allocUnsafe = function allocUnsafe(size) { | |
if (typeof Buffer.allocUnsafe === 'function') { | |
return Buffer.allocUnsafe(size); | |
} | |
if (typeof size !== 'number') { | |
throw new TypeError('size must be a number'); | |
} | |
if (size > MAX_LEN) { | |
throw new RangeError('size is too large'); | |
} | |
return new Buffer(size); | |
} | |
exports.from = function from(value, encodingOrOffset, length) { | |
if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { | |
return Buffer.from(value, encodingOrOffset, length); | |
} | |
if (typeof value === 'number') { | |
throw new TypeError('"value" argument must not be a number'); | |
} | |
if (typeof value === 'string') { | |
return new Buffer(value, encodingOrOffset); | |
} | |
if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { | |
var offset = encodingOrOffset; | |
if (arguments.length === 1) { | |
return new Buffer(value); | |
} | |
if (typeof offset === 'undefined') { | |
offset = 0; | |
} | |
var len = length; | |
if (typeof len === 'undefined') { | |
len = value.byteLength - offset; | |
} | |
if (offset >= value.byteLength) { | |
throw new RangeError('\'offset\' is out of bounds'); | |
} | |
if (len > value.byteLength - offset) { | |
throw new RangeError('\'length\' is out of bounds'); | |
} | |
return new Buffer(value.slice(offset, offset + len)); | |
} | |
if (Buffer.isBuffer(value)) { | |
var out = new Buffer(value.length); | |
value.copy(out, 0, 0, value.length); | |
return out; | |
} | |
if (value) { | |
if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { | |
return new Buffer(value); | |
} | |
if (value.type === 'Buffer' && Array.isArray(value.data)) { | |
return new Buffer(value.data); | |
} | |
} | |
throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); | |
} | |
exports.allocUnsafeSlow = function allocUnsafeSlow(size) { | |
if (typeof Buffer.allocUnsafeSlow === 'function') { | |
return Buffer.allocUnsafeSlow(size); | |
} | |
if (typeof size !== 'number') { | |
throw new TypeError('size must be a number'); | |
} | |
if (size >= MAX_LEN) { | |
throw new RangeError('size is too large'); | |
} | |
return new SlowBuffer(size); | |
} | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"buffer":6}],6:[function(require,module,exports){ | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> | |
* @license MIT | |
*/ | |
/* eslint-disable no-proto */ | |
'use strict' | |
var base64 = require('base64-js') | |
var ieee754 = require('ieee754') | |
exports.Buffer = Buffer | |
exports.SlowBuffer = SlowBuffer | |
exports.INSPECT_MAX_BYTES = 50 | |
var K_MAX_LENGTH = 0x7fffffff | |
exports.kMaxLength = K_MAX_LENGTH | |
/** | |
* If `Buffer.TYPED_ARRAY_SUPPORT`: | |
* === true Use Uint8Array implementation (fastest) | |
* === false Print warning and recommend using `buffer` v4.x which has an Object | |
* implementation (most compatible, even IE6) | |
* | |
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, | |
* Opera 11.6+, iOS 4.2+. | |
* | |
* We report that the browser does not support typed arrays if the are not subclassable | |
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` | |
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support | |
* for __proto__ and has a buggy typed array implementation. | |
*/ | |
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() | |
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && | |
typeof console.error === 'function') { | |
console.error( | |
'This browser lacks typed array (Uint8Array) support which is required by ' + | |
'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' | |
) | |
} | |
function typedArraySupport () { | |
// Can typed array instances can be augmented? | |
try { | |
var arr = new Uint8Array(1) | |
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} | |
return arr.foo() === 42 | |
} catch (e) { | |
return false | |
} | |
} | |
function createBuffer (length) { | |
if (length > K_MAX_LENGTH) { | |
throw new RangeError('Invalid typed array length') | |
} | |
// Return an augmented `Uint8Array` instance | |
var buf = new Uint8Array(length) | |
buf.__proto__ = Buffer.prototype | |
return buf | |
} | |
/** | |
* The Buffer constructor returns instances of `Uint8Array` that have their | |
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of | |
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods | |
* and the `Uint8Array` methods. Square bracket notation works as expected -- it | |
* returns a single octet. | |
* | |
* The `Uint8Array` prototype remains unmodified. | |
*/ | |
function Buffer (arg, encodingOrOffset, length) { | |
// Common case. | |
if (typeof arg === 'number') { | |
if (typeof encodingOrOffset === 'string') { | |
throw new Error( | |
'If encoding is specified then the first argument must be a string' | |
) | |
} | |
return allocUnsafe(arg) | |
} | |
return from(arg, encodingOrOffset, length) | |
} | |
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 | |
if (typeof Symbol !== 'undefined' && Symbol.species && | |
Buffer[Symbol.species] === Buffer) { | |
Object.defineProperty(Buffer, Symbol.species, { | |
value: null, | |
configurable: true, | |
enumerable: false, | |
writable: false | |
}) | |
} | |
Buffer.poolSize = 8192 // not used by this implementation | |
function from (value, encodingOrOffset, length) { | |
if (typeof value === 'number') { | |
throw new TypeError('"value" argument must not be a number') | |
} | |
if (value instanceof ArrayBuffer) { | |
return fromArrayBuffer(value, encodingOrOffset, length) | |
} | |
if (typeof value === 'string') { | |
return fromString(value, encodingOrOffset) | |
} | |
return fromObject(value) | |
} | |
/** | |
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError | |
* if value is a number. | |
* Buffer.from(str[, encoding]) | |
* Buffer.from(array) | |
* Buffer.from(buffer) | |
* Buffer.from(arrayBuffer[, byteOffset[, length]]) | |
**/ | |
Buffer.from = function (value, encodingOrOffset, length) { | |
return from(value, encodingOrOffset, length) | |
} | |
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: | |
// https://github.com/feross/buffer/pull/148 | |
Buffer.prototype.__proto__ = Uint8Array.prototype | |
Buffer.__proto__ = Uint8Array | |
function assertSize (size) { | |
if (typeof size !== 'number') { | |
throw new TypeError('"size" argument must be a number') | |
} else if (size < 0) { | |
throw new RangeError('"size" argument must not be negative') | |
} | |
} | |
function alloc (size, fill, encoding) { | |
assertSize(size) | |
if (size <= 0) { | |
return createBuffer(size) | |
} | |
if (fill !== undefined) { | |
// Only pay attention to encoding if it's a string. This | |
// prevents accidentally sending in a number that would | |
// be interpretted as a start offset. | |
return typeof encoding === 'string' | |
? createBuffer(size).fill(fill, encoding) | |
: createBuffer(size).fill(fill) | |
} | |
return createBuffer(size) | |
} | |
/** | |
* Creates a new filled Buffer instance. | |
* alloc(size[, fill[, encoding]]) | |
**/ | |
Buffer.alloc = function (size, fill, encoding) { | |
return alloc(size, fill, encoding) | |
} | |
function allocUnsafe (size) { | |
assertSize(size) | |
return createBuffer(size < 0 ? 0 : checked(size) | 0) | |
} | |
/** | |
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. | |
* */ | |
Buffer.allocUnsafe = function (size) { | |
return allocUnsafe(size) | |
} | |
/** | |
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. | |
*/ | |
Buffer.allocUnsafeSlow = function (size) { | |
return allocUnsafe(size) | |
} | |
function fromString (string, encoding) { | |
if (typeof encoding !== 'string' || encoding === '') { | |
encoding = 'utf8' | |
} | |
if (!Buffer.isEncoding(encoding)) { | |
throw new TypeError('"encoding" must be a valid string encoding') | |
} | |
var length = byteLength(string, encoding) | 0 | |
var buf = createBuffer(length) | |
var actual = buf.write(string, encoding) | |
if (actual !== length) { | |
// Writing a hex string, for example, that contains invalid characters will | |
// cause everything after the first invalid character to be ignored. (e.g. | |
// 'abxxcd' will be treated as 'ab') | |
buf = buf.slice(0, actual) | |
} | |
return buf | |
} | |
function fromArrayLike (array) { | |
var length = array.length < 0 ? 0 : checked(array.length) | 0 | |
var buf = createBuffer(length) | |
for (var i = 0; i < length; i += 1) { | |
buf[i] = array[i] & 255 | |
} | |
return buf | |
} | |
function fromArrayBuffer (array, byteOffset, length) { | |
if (byteOffset < 0 || array.byteLength < byteOffset) { | |
throw new RangeError('\'offset\' is out of bounds') | |
} | |
if (array.byteLength < byteOffset + (length || 0)) { | |
throw new RangeError('\'length\' is out of bounds') | |
} | |
var buf | |
if (byteOffset === undefined && length === undefined) { | |
buf = new Uint8Array(array) | |
} else if (length === undefined) { | |
buf = new Uint8Array(array, byteOffset) | |
} else { | |
buf = new Uint8Array(array, byteOffset, length) | |
} | |
// Return an augmented `Uint8Array` instance | |
buf.__proto__ = Buffer.prototype | |
return buf | |
} | |
function fromObject (obj) { | |
if (Buffer.isBuffer(obj)) { | |
var len = checked(obj.length) | 0 | |
var buf = createBuffer(len) | |
if (buf.length === 0) { | |
return buf | |
} | |
obj.copy(buf, 0, 0, len) | |
return buf | |
} | |
if (obj) { | |
if (isArrayBufferView(obj) || 'length' in obj) { | |
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { | |
return createBuffer(0) | |
} | |
return fromArrayLike(obj) | |
} | |
if (obj.type === 'Buffer' && Array.isArray(obj.data)) { | |
return fromArrayLike(obj.data) | |
} | |
} | |
throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') | |
} | |
function checked (length) { | |
// Note: cannot use `length < K_MAX_LENGTH` here because that fails when | |
// length is NaN (which is otherwise coerced to zero.) | |
if (length >= K_MAX_LENGTH) { | |
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + | |
'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') | |
} | |
return length | 0 | |
} | |
function SlowBuffer (length) { | |
if (+length != length) { // eslint-disable-line eqeqeq | |
length = 0 | |
} | |
return Buffer.alloc(+length) | |
} | |
Buffer.isBuffer = function isBuffer (b) { | |
return b != null && b._isBuffer === true | |
} | |
Buffer.compare = function compare (a, b) { | |
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { | |
throw new TypeError('Arguments must be Buffers') | |
} | |
if (a === b) return 0 | |
var x = a.length | |
var y = b.length | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i] | |
y = b[i] | |
break | |
} | |
} | |
if (x < y) return -1 | |
if (y < x) return 1 | |
return 0 | |
} | |
Buffer.isEncoding = function isEncoding (encoding) { | |
switch (String(encoding).toLowerCase()) { | |
case 'hex': | |
case 'utf8': | |
case 'utf-8': | |
case 'ascii': | |
case 'latin1': | |
case 'binary': | |
case 'base64': | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return true | |
default: | |
return false | |
} | |
} | |
Buffer.concat = function concat (list, length) { | |
if (!Array.isArray(list)) { | |
throw new TypeError('"list" argument must be an Array of Buffers') | |
} | |
if (list.length === 0) { | |
return Buffer.alloc(0) | |
} | |
var i | |
if (length === undefined) { | |
length = 0 | |
for (i = 0; i < list.length; ++i) { | |
length += list[i].length | |
} | |
} | |
var buffer = Buffer.allocUnsafe(length) | |
var pos = 0 | |
for (i = 0; i < list.length; ++i) { | |
var buf = list[i] | |
if (!Buffer.isBuffer(buf)) { | |
throw new TypeError('"list" argument must be an Array of Buffers') | |
} | |
buf.copy(buffer, pos) | |
pos += buf.length | |
} | |
return buffer | |
} | |
function byteLength (string, encoding) { | |
if (Buffer.isBuffer(string)) { | |
return string.length | |
} | |
if (isArrayBufferView(string) || string instanceof ArrayBuffer) { | |
return string.byteLength | |
} | |
if (typeof string !== 'string') { | |
string = '' + string | |
} | |
var len = string.length | |
if (len === 0) return 0 | |
// Use a for loop to avoid recursion | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'ascii': | |
case 'latin1': | |
case 'binary': | |
return len | |
case 'utf8': | |
case 'utf-8': | |
case undefined: | |
return utf8ToBytes(string).length | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return len * 2 | |
case 'hex': | |
return len >>> 1 | |
case 'base64': | |
return base64ToBytes(string).length | |
default: | |
if (loweredCase) return utf8ToBytes(string).length // assume utf8 | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.byteLength = byteLength | |
function slowToString (encoding, start, end) { | |
var loweredCase = false | |
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only | |
// property of a typed array. | |
// This behaves neither like String nor Uint8Array in that we set start/end | |
// to their upper/lower bounds if the value passed is out of range. | |
// undefined is handled specially as per ECMA-262 6th Edition, | |
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. | |
if (start === undefined || start < 0) { | |
start = 0 | |
} | |
// Return early if start > this.length. Done here to prevent potential uint32 | |
// coercion fail below. | |
if (start > this.length) { | |
return '' | |
} | |
if (end === undefined || end > this.length) { | |
end = this.length | |
} | |
if (end <= 0) { | |
return '' | |
} | |
// Force coersion to uint32. This will also coerce falsey/NaN values to 0. | |
end >>>= 0 | |
start >>>= 0 | |
if (end <= start) { | |
return '' | |
} | |
if (!encoding) encoding = 'utf8' | |
while (true) { | |
switch (encoding) { | |
case 'hex': | |
return hexSlice(this, start, end) | |
case 'utf8': | |
case 'utf-8': | |
return utf8Slice(this, start, end) | |
case 'ascii': | |
return asciiSlice(this, start, end) | |
case 'latin1': | |
case 'binary': | |
return latin1Slice(this, start, end) | |
case 'base64': | |
return base64Slice(this, start, end) | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return utf16leSlice(this, start, end) | |
default: | |
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) | |
encoding = (encoding + '').toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) | |
// to detect a Buffer instance. It's not possible to use `instanceof Buffer` | |
// reliably in a browserify context because there could be multiple different | |
// copies of the 'buffer' package in use. This method works even for Buffer | |
// instances that were created from another copy of the `buffer` package. | |
// See: https://github.com/feross/buffer/issues/154 | |
Buffer.prototype._isBuffer = true | |
function swap (b, n, m) { | |
var i = b[n] | |
b[n] = b[m] | |
b[m] = i | |
} | |
Buffer.prototype.swap16 = function swap16 () { | |
var len = this.length | |
if (len % 2 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 16-bits') | |
} | |
for (var i = 0; i < len; i += 2) { | |
swap(this, i, i + 1) | |
} | |
return this | |
} | |
Buffer.prototype.swap32 = function swap32 () { | |
var len = this.length | |
if (len % 4 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 32-bits') | |
} | |
for (var i = 0; i < len; i += 4) { | |
swap(this, i, i + 3) | |
swap(this, i + 1, i + 2) | |
} | |
return this | |
} | |
Buffer.prototype.swap64 = function swap64 () { | |
var len = this.length | |
if (len % 8 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 64-bits') | |
} | |
for (var i = 0; i < len; i += 8) { | |
swap(this, i, i + 7) | |
swap(this, i + 1, i + 6) | |
swap(this, i + 2, i + 5) | |
swap(this, i + 3, i + 4) | |
} | |
return this | |
} | |
Buffer.prototype.toString = function toString () { | |
var length = this.length | |
if (length === 0) return '' | |
if (arguments.length === 0) return utf8Slice(this, 0, length) | |
return slowToString.apply(this, arguments) | |
} | |
Buffer.prototype.equals = function equals (b) { | |
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') | |
if (this === b) return true | |
return Buffer.compare(this, b) === 0 | |
} | |
Buffer.prototype.inspect = function inspect () { | |
var str = '' | |
var max = exports.INSPECT_MAX_BYTES | |
if (this.length > 0) { | |
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') | |
if (this.length > max) str += ' ... ' | |
} | |
return '<Buffer ' + str + '>' | |
} | |
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { | |
if (!Buffer.isBuffer(target)) { | |
throw new TypeError('Argument must be a Buffer') | |
} | |
if (start === undefined) { | |
start = 0 | |
} | |
if (end === undefined) { | |
end = target ? target.length : 0 | |
} | |
if (thisStart === undefined) { | |
thisStart = 0 | |
} | |
if (thisEnd === undefined) { | |
thisEnd = this.length | |
} | |
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { | |
throw new RangeError('out of range index') | |
} | |
if (thisStart >= thisEnd && start >= end) { | |
return 0 | |
} | |
if (thisStart >= thisEnd) { | |
return -1 | |
} | |
if (start >= end) { | |
return 1 | |
} | |
start >>>= 0 | |
end >>>= 0 | |
thisStart >>>= 0 | |
thisEnd >>>= 0 | |
if (this === target) return 0 | |
var x = thisEnd - thisStart | |
var y = end - start | |
var len = Math.min(x, y) | |
var thisCopy = this.slice(thisStart, thisEnd) | |
var targetCopy = target.slice(start, end) | |
for (var i = 0; i < len; ++i) { | |
if (thisCopy[i] !== targetCopy[i]) { | |
x = thisCopy[i] | |
y = targetCopy[i] | |
break | |
} | |
} | |
if (x < y) return -1 | |
if (y < x) return 1 | |
return 0 | |
} | |
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, | |
// OR the last index of `val` in `buffer` at offset <= `byteOffset`. | |
// | |
// Arguments: | |
// - buffer - a Buffer to search | |
// - val - a string, Buffer, or number | |
// - byteOffset - an index into `buffer`; will be clamped to an int32 | |
// - encoding - an optional encoding, relevant is val is a string | |
// - dir - true for indexOf, false for lastIndexOf | |
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { | |
// Empty buffer means no match | |
if (buffer.length === 0) return -1 | |
// Normalize byteOffset | |
if (typeof byteOffset === 'string') { | |
encoding = byteOffset | |
byteOffset = 0 | |
} else if (byteOffset > 0x7fffffff) { | |
byteOffset = 0x7fffffff | |
} else if (byteOffset < -0x80000000) { | |
byteOffset = -0x80000000 | |
} | |
byteOffset = +byteOffset // Coerce to Number. | |
if (numberIsNaN(byteOffset)) { | |
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer | |
byteOffset = dir ? 0 : (buffer.length - 1) | |
} | |
// Normalize byteOffset: negative offsets start from the end of the buffer | |
if (byteOffset < 0) byteOffset = buffer.length + byteOffset | |
if (byteOffset >= buffer.length) { | |
if (dir) return -1 | |
else byteOffset = buffer.length - 1 | |
} else if (byteOffset < 0) { | |
if (dir) byteOffset = 0 | |
else return -1 | |
} | |
// Normalize val | |
if (typeof val === 'string') { | |
val = Buffer.from(val, encoding) | |
} | |
// Finally, search either indexOf (if dir is true) or lastIndexOf | |
if (Buffer.isBuffer(val)) { | |
// Special case: looking for empty string/buffer always fails | |
if (val.length === 0) { | |
return -1 | |
} | |
return arrayIndexOf(buffer, val, byteOffset, encoding, dir) | |
} else if (typeof val === 'number') { | |
val = val & 0xFF // Search for a byte value [0-255] | |
if (typeof Uint8Array.prototype.indexOf === 'function') { | |
if (dir) { | |
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) | |
} else { | |
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) | |
} | |
} | |
return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) | |
} | |
throw new TypeError('val must be string, number or Buffer') | |
} | |
function arrayIndexOf (arr, val, byteOffset, encoding, dir) { | |
var indexSize = 1 | |
var arrLength = arr.length | |
var valLength = val.length | |
if (encoding !== undefined) { | |
encoding = String(encoding).toLowerCase() | |
if (encoding === 'ucs2' || encoding === 'ucs-2' || | |
encoding === 'utf16le' || encoding === 'utf-16le') { | |
if (arr.length < 2 || val.length < 2) { | |
return -1 | |
} | |
indexSize = 2 | |
arrLength /= 2 | |
valLength /= 2 | |
byteOffset /= 2 | |
} | |
} | |
function read (buf, i) { | |
if (indexSize === 1) { | |
return buf[i] | |
} else { | |
return buf.readUInt16BE(i * indexSize) | |
} | |
} | |
var i | |
if (dir) { | |
var foundIndex = -1 | |
for (i = byteOffset; i < arrLength; i++) { | |
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { | |
if (foundIndex === -1) foundIndex = i | |
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize | |
} else { | |
if (foundIndex !== -1) i -= i - foundIndex | |
foundIndex = -1 | |
} | |
} | |
} else { | |
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength | |
for (i = byteOffset; i >= 0; i--) { | |
var found = true | |
for (var j = 0; j < valLength; j++) { | |
if (read(arr, i + j) !== read(val, j)) { | |
found = false | |
break | |
} | |
} | |
if (found) return i | |
} | |
} | |
return -1 | |
} | |
Buffer.prototype.includes = function includes (val, byteOffset, encoding) { | |
return this.indexOf(val, byteOffset, encoding) !== -1 | |
} | |
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, true) | |
} | |
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, false) | |
} | |
function hexWrite (buf, string, offset, length) { | |
offset = Number(offset) || 0 | |
var remaining = buf.length - offset | |
if (!length) { | |
length = remaining | |
} else { | |
length = Number(length) | |
if (length > remaining) { | |
length = remaining | |
} | |
} | |
// must be an even number of digits | |
var strLen = string.length | |
if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') | |
if (length > strLen / 2) { | |
length = strLen / 2 | |
} | |
for (var i = 0; i < length; ++i) { | |
var parsed = parseInt(string.substr(i * 2, 2), 16) | |
if (numberIsNaN(parsed)) return i | |
buf[offset + i] = parsed | |
} | |
return i | |
} | |
function utf8Write (buf, string, offset, length) { | |
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
function asciiWrite (buf, string, offset, length) { | |
return blitBuffer(asciiToBytes(string), buf, offset, length) | |
} | |
function latin1Write (buf, string, offset, length) { | |
return asciiWrite(buf, string, offset, length) | |
} | |
function base64Write (buf, string, offset, length) { | |
return blitBuffer(base64ToBytes(string), buf, offset, length) | |
} | |
function ucs2Write (buf, string, offset, length) { | |
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
Buffer.prototype.write = function write (string, offset, length, encoding) { | |
// Buffer#write(string) | |
if (offset === undefined) { | |
encoding = 'utf8' | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, encoding) | |
} else if (length === undefined && typeof offset === 'string') { | |
encoding = offset | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, offset[, length][, encoding]) | |
} else if (isFinite(offset)) { | |
offset = offset >>> 0 | |
if (isFinite(length)) { | |
length = length >>> 0 | |
if (encoding === undefined) encoding = 'utf8' | |
} else { | |
encoding = length | |
length = undefined | |
} | |
} else { | |
throw new Error( | |
'Buffer.write(string, encoding, offset[, length]) is no longer supported' | |
) | |
} | |
var remaining = this.length - offset | |
if (length === undefined || length > remaining) length = remaining | |
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { | |
throw new RangeError('Attempt to write outside buffer bounds') | |
} | |
if (!encoding) encoding = 'utf8' | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'hex': | |
return hexWrite(this, string, offset, length) | |
case 'utf8': | |
case 'utf-8': | |
return utf8Write(this, string, offset, length) | |
case 'ascii': | |
return asciiWrite(this, string, offset, length) | |
case 'latin1': | |
case 'binary': | |
return latin1Write(this, string, offset, length) | |
case 'base64': | |
// Warning: maxLength not taken into account in base64Write | |
return base64Write(this, string, offset, length) | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return ucs2Write(this, string, offset, length) | |
default: | |
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.prototype.toJSON = function toJSON () { | |
return { | |
type: 'Buffer', | |
data: Array.prototype.slice.call(this._arr || this, 0) | |
} | |
} | |
function base64Slice (buf, start, end) { | |
if (start === 0 && end === buf.length) { | |
return base64.fromByteArray(buf) | |
} else { | |
return base64.fromByteArray(buf.slice(start, end)) | |
} | |
} | |
function utf8Slice (buf, start, end) { | |
end = Math.min(buf.length, end) | |
var res = [] | |
var i = start | |
while (i < end) { | |
var firstByte = buf[i] | |
var codePoint = null | |
var bytesPerSequence = (firstByte > 0xEF) ? 4 | |
: (firstByte > 0xDF) ? 3 | |
: (firstByte > 0xBF) ? 2 | |
: 1 | |
if (i + bytesPerSequence <= end) { | |
var secondByte, thirdByte, fourthByte, tempCodePoint | |
switch (bytesPerSequence) { | |
case 1: | |
if (firstByte < 0x80) { | |
codePoint = firstByte | |
} | |
break | |
case 2: | |
secondByte = buf[i + 1] | |
if ((secondByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) | |
if (tempCodePoint > 0x7F) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 3: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) | |
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 4: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
fourthByte = buf[i + 3] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) | |
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { | |
codePoint = tempCodePoint | |
} | |
} | |
} | |
} | |
if (codePoint === null) { | |
// we did not generate a valid codePoint so insert a | |
// replacement char (U+FFFD) and advance only 1 byte | |
codePoint = 0xFFFD | |
bytesPerSequence = 1 | |
} else if (codePoint > 0xFFFF) { | |
// encode to utf16 (surrogate pair dance) | |
codePoint -= 0x10000 | |
res.push(codePoint >>> 10 & 0x3FF | 0xD800) | |
codePoint = 0xDC00 | codePoint & 0x3FF | |
} | |
res.push(codePoint) | |
i += bytesPerSequence | |
} | |
return decodeCodePointsArray(res) | |
} | |
// Based on http://stackoverflow.com/a/22747272/680742, the browser with | |
// the lowest limit is Chrome, with 0x10000 args. | |
// We go 1 magnitude less, for safety | |
var MAX_ARGUMENTS_LENGTH = 0x1000 | |
function decodeCodePointsArray (codePoints) { | |
var len = codePoints.length | |
if (len <= MAX_ARGUMENTS_LENGTH) { | |
return String.fromCharCode.apply(String, codePoints) // avoid extra slice() | |
} | |
// Decode in chunks to avoid "call stack size exceeded". | |
var res = '' | |
var i = 0 | |
while (i < len) { | |
res += String.fromCharCode.apply( | |
String, | |
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) | |
) | |
} | |
return res | |
} | |
function asciiSlice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i] & 0x7F) | |
} | |
return ret | |
} | |
function latin1Slice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i]) | |
} | |
return ret | |
} | |
function hexSlice (buf, start, end) { | |
var len = buf.length | |
if (!start || start < 0) start = 0 | |
if (!end || end < 0 || end > len) end = len | |
var out = '' | |
for (var i = start; i < end; ++i) { | |
out += toHex(buf[i]) | |
} | |
return out | |
} | |
function utf16leSlice (buf, start, end) { | |
var bytes = buf.slice(start, end) | |
var res = '' | |
for (var i = 0; i < bytes.length; i += 2) { | |
res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) | |
} | |
return res | |
} | |
Buffer.prototype.slice = function slice (start, end) { | |
var len = this.length | |
start = ~~start | |
end = end === undefined ? len : ~~end | |
if (start < 0) { | |
start += len | |
if (start < 0) start = 0 | |
} else if (start > len) { | |
start = len | |
} | |
if (end < 0) { | |
end += len | |
if (end < 0) end = 0 | |
} else if (end > len) { | |
end = len | |
} | |
if (end < start) end = start | |
var newBuf = this.subarray(start, end) | |
// Return an augmented `Uint8Array` instance | |
newBuf.__proto__ = Buffer.prototype | |
return newBuf | |
} | |
/* | |
* Need to make sure that buffer isn't trying to write out of bounds. | |
*/ | |
function checkOffset (offset, ext, length) { | |
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') | |
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') | |
} | |
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
checkOffset(offset, byteLength, this.length) | |
} | |
var val = this[offset + --byteLength] | |
var mul = 1 | |
while (byteLength > 0 && (mul *= 0x100)) { | |
val += this[offset + --byteLength] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
return this[offset] | |
} | |
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return this[offset] | (this[offset + 1] << 8) | |
} | |
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return (this[offset] << 8) | this[offset + 1] | |
} | |
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ((this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16)) + | |
(this[offset + 3] * 0x1000000) | |
} | |
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] * 0x1000000) + | |
((this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
this[offset + 3]) | |
} | |
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var i = byteLength | |
var mul = 1 | |
var val = this[offset + --i] | |
while (i > 0 && (mul *= 0x100)) { | |
val += this[offset + --i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
if (!(this[offset] & 0x80)) return (this[offset]) | |
return ((0xff - this[offset] + 1) * -1) | |
} | |
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset] | (this[offset + 1] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset + 1] | (this[offset] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16) | | |
(this[offset + 3] << 24) | |
} | |
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] << 24) | | |
(this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
(this[offset + 3]) | |
} | |
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, true, 23, 4) | |
} | |
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, false, 23, 4) | |
} | |
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, true, 52, 8) | |
} | |
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, false, 52, 8) | |
} | |
function checkInt (buf, value, offset, ext, max, min) { | |
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') | |
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') | |
if (offset + ext > buf.length) throw new RangeError('Index out of range') | |
} | |
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength) - 1 | |
checkInt(this, value, offset, byteLength, maxBytes, 0) | |
} | |
var mul = 1 | |
var i = 0 | |
this[offset] = value & 0xFF | |
while (++i < byteLength && (mul *= 0x100)) { | |
this[offset + i] = (value / mul) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength) - 1 | |
checkInt(this, value, offset, byteLength, maxBytes, 0) | |
} | |
var i = byteLength - 1 | |
var mul = 1 | |
this[offset + i] = value & 0xFF | |
while (--i >= 0 && (mul *= 0x100)) { | |
this[offset + i] = (value / mul) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
return offset + 2 | |
} | |
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
return offset + 2 | |
} | |
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
this[offset + 3] = (value >>> 24) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 1] = (value >>> 8) | |
this[offset] = (value & 0xff) | |
return offset + 4 | |
} | |
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
return offset + 4 | |
} | |
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, (8 * byteLength) - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = 0 | |
var mul = 1 | |
var sub = 0 | |
this[offset] = value & 0xFF | |
while (++i < byteLength && (mul *= 0x100)) { | |
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { | |
sub = 1 | |
} | |
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, (8 * byteLength) - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = byteLength - 1 | |
var mul = 1 | |
var sub = 0 | |
this[offset + i] = value & 0xFF | |
while (--i >= 0 && (mul *= 0x100)) { | |
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { | |
sub = 1 | |
} | |
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) | |
if (value < 0) value = 0xff + value + 1 | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 3] = (value >>> 24) | |
return offset + 4 | |
} | |
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
if (value < 0) value = 0xffffffff + value + 1 | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
return offset + 4 | |
} | |
function checkIEEE754 (buf, value, offset, ext, max, min) { | |
if (offset + ext > buf.length) throw new RangeError('Index out of range') | |
if (offset < 0) throw new RangeError('Index out of range') | |
} | |
function writeFloat (buf, value, offset, littleEndian, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) | |
} | |
ieee754.write(buf, value, offset, littleEndian, 23, 4) | |
return offset + 4 | |
} | |
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, false, noAssert) | |
} | |
function writeDouble (buf, value, offset, littleEndian, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) | |
} | |
ieee754.write(buf, value, offset, littleEndian, 52, 8) | |
return offset + 8 | |
} | |
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, false, noAssert) | |
} | |
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | |
Buffer.prototype.copy = function copy (target, targetStart, start, end) { | |
if (!start) start = 0 | |
if (!end && end !== 0) end = this.length | |
if (targetStart >= target.length) targetStart = target.length | |
if (!targetStart) targetStart = 0 | |
if (end > 0 && end < start) end = start | |
// Copy 0 bytes; we're done | |
if (end === start) return 0 | |
if (target.length === 0 || this.length === 0) return 0 | |
// Fatal error conditions | |
if (targetStart < 0) { | |
throw new RangeError('targetStart out of bounds') | |
} | |
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') | |
if (end < 0) throw new RangeError('sourceEnd out of bounds') | |
// Are we oob? | |
if (end > this.length) end = this.length | |
if (target.length - targetStart < end - start) { | |
end = target.length - targetStart + start | |
} | |
var len = end - start | |
var i | |
if (this === target && start < targetStart && targetStart < end) { | |
// descending copy from end | |
for (i = len - 1; i >= 0; --i) { | |
target[i + targetStart] = this[i + start] | |
} | |
} else if (len < 1000) { | |
// ascending copy from start | |
for (i = 0; i < len; ++i) { | |
target[i + targetStart] = this[i + start] | |
} | |
} else { | |
Uint8Array.prototype.set.call( | |
target, | |
this.subarray(start, start + len), | |
targetStart | |
) | |
} | |
return len | |
} | |
// Usage: | |
// buffer.fill(number[, offset[, end]]) | |
// buffer.fill(buffer[, offset[, end]]) | |
// buffer.fill(string[, offset[, end]][, encoding]) | |
Buffer.prototype.fill = function fill (val, start, end, encoding) { | |
// Handle string cases: | |
if (typeof val === 'string') { | |
if (typeof start === 'string') { | |
encoding = start | |
start = 0 | |
end = this.length | |
} else if (typeof end === 'string') { | |
encoding = end | |
end = this.length | |
} | |
if (val.length === 1) { | |
var code = val.charCodeAt(0) | |
if (code < 256) { | |
val = code | |
} | |
} | |
if (encoding !== undefined && typeof encoding !== 'string') { | |
throw new TypeError('encoding must be a string') | |
} | |
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { | |
throw new TypeError('Unknown encoding: ' + encoding) | |
} | |
} else if (typeof val === 'number') { | |
val = val & 255 | |
} | |
// Invalid ranges are not set to a default, so can range check early. | |
if (start < 0 || this.length < start || this.length < end) { | |
throw new RangeError('Out of range index') | |
} | |
if (end <= start) { | |
return this | |
} | |
start = start >>> 0 | |
end = end === undefined ? this.length : end >>> 0 | |
if (!val) val = 0 | |
var i | |
if (typeof val === 'number') { | |
for (i = start; i < end; ++i) { | |
this[i] = val | |
} | |
} else { | |
var bytes = Buffer.isBuffer(val) | |
? val | |
: new Buffer(val, encoding) | |
var len = bytes.length | |
for (i = 0; i < end - start; ++i) { | |
this[i + start] = bytes[i % len] | |
} | |
} | |
return this | |
} | |
// HELPER FUNCTIONS | |
// ================ | |
var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g | |
function base64clean (str) { | |
// Node strips out invalid characters like \n and \t from the string, base64-js does not | |
str = str.trim().replace(INVALID_BASE64_RE, '') | |
// Node converts strings with length < 2 to '' | |
if (str.length < 2) return '' | |
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not | |
while (str.length % 4 !== 0) { | |
str = str + '=' | |
} | |
return str | |
} | |
function toHex (n) { | |
if (n < 16) return '0' + n.toString(16) | |
return n.toString(16) | |
} | |
function utf8ToBytes (string, units) { | |
units = units || Infinity | |
var codePoint | |
var length = string.length | |
var leadSurrogate = null | |
var bytes = [] | |
for (var i = 0; i < length; ++i) { | |
codePoint = string.charCodeAt(i) | |
// is surrogate component | |
if (codePoint > 0xD7FF && codePoint < 0xE000) { | |
// last char was a lead | |
if (!leadSurrogate) { | |
// no lead yet | |
if (codePoint > 0xDBFF) { | |
// unexpected trail | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} else if (i + 1 === length) { | |
// unpaired lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} | |
// valid lead | |
leadSurrogate = codePoint | |
continue | |
} | |
// 2 leads in a row | |
if (codePoint < 0xDC00) { | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
leadSurrogate = codePoint | |
continue | |
} | |
// valid surrogate pair | |
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 | |
} else if (leadSurrogate) { | |
// valid bmp char, but last char was a lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
} | |
leadSurrogate = null | |
// encode utf8 | |
if (codePoint < 0x80) { | |
if ((units -= 1) < 0) break | |
bytes.push(codePoint) | |
} else if (codePoint < 0x800) { | |
if ((units -= 2) < 0) break | |
bytes.push( | |
codePoint >> 0x6 | 0xC0, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x10000) { | |
if ((units -= 3) < 0) break | |
bytes.push( | |
codePoint >> 0xC | 0xE0, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x110000) { | |
if ((units -= 4) < 0) break | |
bytes.push( | |
codePoint >> 0x12 | 0xF0, | |
codePoint >> 0xC & 0x3F | 0x80, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else { | |
throw new Error('Invalid code point') | |
} | |
} | |
return bytes | |
} | |
function asciiToBytes (str) { | |
var byteArray = [] | |
for (var i = 0; i < str.length; ++i) { | |
// Node's code seems to be doing this and not & 0x7F.. | |
byteArray.push(str.charCodeAt(i) & 0xFF) | |
} | |
return byteArray | |
} | |
function utf16leToBytes (str, units) { | |
var c, hi, lo | |
var byteArray = [] | |
for (var i = 0; i < str.length; ++i) { | |
if ((units -= 2) < 0) break | |
c = str.charCodeAt(i) | |
hi = c >> 8 | |
lo = c % 256 | |
byteArray.push(lo) | |
byteArray.push(hi) | |
} | |
return byteArray | |
} | |
function base64ToBytes (str) { | |
return base64.toByteArray(base64clean(str)) | |
} | |
function blitBuffer (src, dst, offset, length) { | |
for (var i = 0; i < length; ++i) { | |
if ((i + offset >= dst.length) || (i >= src.length)) break | |
dst[i + offset] = src[i] | |
} | |
return i | |
} | |
// Node 0.10 supports `ArrayBuffer` but lacks `ArrayBuffer.isView` | |
function isArrayBufferView (obj) { | |
return (typeof ArrayBuffer.isView === 'function') && ArrayBuffer.isView(obj) | |
} | |
function numberIsNaN (obj) { | |
return obj !== obj // eslint-disable-line no-self-compare | |
} | |
},{"base64-js":2,"ieee754":51}],7:[function(require,module,exports){ | |
module.exports = { | |
"100": "Continue", | |
"101": "Switching Protocols", | |
"102": "Processing", | |
"200": "OK", | |
"201": "Created", | |
"202": "Accepted", | |
"203": "Non-Authoritative Information", | |
"204": "No Content", | |
"205": "Reset Content", | |
"206": "Partial Content", | |
"207": "Multi-Status", | |
"208": "Already Reported", | |
"226": "IM Used", | |
"300": "Multiple Choices", | |
"301": "Moved Permanently", | |
"302": "Found", | |
"303": "See Other", | |
"304": "Not Modified", | |
"305": "Use Proxy", | |
"307": "Temporary Redirect", | |
"308": "Permanent Redirect", | |
"400": "Bad Request", | |
"401": "Unauthorized", | |
"402": "Payment Required", | |
"403": "Forbidden", | |
"404": "Not Found", | |
"405": "Method Not Allowed", | |
"406": "Not Acceptable", | |
"407": "Proxy Authentication Required", | |
"408": "Request Timeout", | |
"409": "Conflict", | |
"410": "Gone", | |
"411": "Length Required", | |
"412": "Precondition Failed", | |
"413": "Payload Too Large", | |
"414": "URI Too Long", | |
"415": "Unsupported Media Type", | |
"416": "Range Not Satisfiable", | |
"417": "Expectation Failed", | |
"418": "I'm a teapot", | |
"421": "Misdirected Request", | |
"422": "Unprocessable Entity", | |
"423": "Locked", | |
"424": "Failed Dependency", | |
"425": "Unordered Collection", | |
"426": "Upgrade Required", | |
"428": "Precondition Required", | |
"429": "Too Many Requests", | |
"431": "Request Header Fields Too Large", | |
"451": "Unavailable For Legal Reasons", | |
"500": "Internal Server Error", | |
"501": "Not Implemented", | |
"502": "Bad Gateway", | |
"503": "Service Unavailable", | |
"504": "Gateway Timeout", | |
"505": "HTTP Version Not Supported", | |
"506": "Variant Also Negotiates", | |
"507": "Insufficient Storage", | |
"508": "Loop Detected", | |
"509": "Bandwidth Limit Exceeded", | |
"510": "Not Extended", | |
"511": "Network Authentication Required" | |
} | |
},{}],8:[function(require,module,exports){ | |
(function (Buffer){ | |
// Copyright Joyent, Inc. and other Node contributors. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a | |
// copy of this software and associated documentation files (the | |
// "Software"), to deal in the Software without restriction, including | |
// without limitation the rights to use, copy, modify, merge, publish, | |
// distribute, sublicense, and/or sell copies of the Software, and to permit | |
// persons to whom the Software is furnished to do so, subject to the | |
// following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included | |
// in all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | |
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | |
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | |
// USE OR OTHER DEALINGS IN THE SOFTWARE. | |
// NOTE: These type checking functions intentionally don't use `instanceof` | |
// because it is fragile and can be easily faked with `Object.create()`. | |
function isArray(arg) { | |
if (Array.isArray) { | |
return Array.isArray(arg); | |
} | |
return objectToString(arg) === '[object Array]'; | |
} | |
exports.isArray = isArray; | |
function isBoolean(arg) { | |
return typeof arg === 'boolean'; | |
} | |
exports.isBoolean = isBoolean; | |
function isNull(arg) { | |
return arg === null; | |
} | |
exports.isNull = isNull; | |
function isNullOrUndefined(arg) { | |
return arg == null; | |
} | |
exports.isNullOrUndefined = isNullOrUndefined; | |
function isNumber(arg) { | |
return typeof arg === 'number'; | |
} | |
exports.isNumber = isNumber; | |
function isString(arg) { | |
return typeof arg === 'string'; | |
} | |
exports.isString = isString; | |
function isSymbol(arg) { | |
return typeof arg === 'symbol'; | |
} | |
exports.isSymbol = isSymbol; | |
function isUndefined(arg) { | |
return arg === void 0; | |
} | |
exports.isUndefined = isUndefined; | |
function isRegExp(re) { | |
return objectToString(re) === '[object RegExp]'; | |
} | |
exports.isRegExp = isRegExp; | |
function isObject(arg) { | |
return typeof arg === 'object' && arg !== null; | |
} | |
exports.isObject = isObject; | |
function isDate(d) { | |
return objectToString(d) === '[object Date]'; | |
} | |
exports.isDate = isDate; | |
function isError(e) { | |
return (objectToString(e) === '[object Error]' || e instanceof Error); | |
} | |
exports.isError = isError; | |
function isFunction(arg) { | |
return typeof arg === 'function'; | |
} | |
exports.isFunction = isFunction; | |
function isPrimitive(arg) { | |
return arg === null || | |
typeof arg === 'boolean' || | |
typeof arg === 'number' || | |
typeof arg === 'string' || | |
typeof arg === 'symbol' || // ES6 symbol | |
typeof arg === 'undefined'; | |
} | |
exports.isPrimitive = isPrimitive; | |
exports.isBuffer = Buffer.isBuffer; | |
function objectToString(o) { | |
return Object.prototype.toString.call(o); | |
} | |
}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) | |
},{"../../is-buffer/index.js":54}],9:[function(require,module,exports){ | |
"use strict" | |
var createThunk = require("./lib/thunk.js") | |
function Procedure() { | |
this.argTypes = [] | |
this.shimArgs = [] | |
this.arrayArgs = [] | |
this.arrayBlockIndices = [] | |
this.scalarArgs = [] | |
this.offsetArgs = [] | |
this.offsetArgIndex = [] | |
this.indexArgs = [] | |
this.shapeArgs = [] | |
this.funcName = "" | |
this.pre = null | |
this.body = null | |
this.post = null | |
this.debug = false | |
} | |
function compileCwise(user_args) { | |
//Create procedure | |
var proc = new Procedure() | |
//Parse blocks | |
proc.pre = user_args.pre | |
proc.body = user_args.body | |
proc.post = user_args.post | |
//Parse arguments | |
var proc_args = user_args.args.slice(0) | |
proc.argTypes = proc_args | |
for(var i=0; i<proc_args.length; ++i) { | |
var arg_type = proc_args[i] | |
if(arg_type === "array" || (typeof arg_type === "object" && arg_type.blockIndices)) { | |
proc.argTypes[i] = "array" | |
proc.arrayArgs.push(i) | |
proc.arrayBlockIndices.push(arg_type.blockIndices ? arg_type.blockIndices : 0) | |
proc.shimArgs.push("array" + i) | |
if(i < proc.pre.args.length && proc.pre.args[i].count>0) { | |
throw new Error("cwise: pre() block may not reference array args") | |
} | |
if(i < proc.post.args.length && proc.post.args[i].count>0) { | |
throw new Error("cwise: post() block may not reference array args") | |
} | |
} else if(arg_type === "scalar") { | |
proc.scalarArgs.push(i) | |
proc.shimArgs.push("scalar" + i) | |
} else if(arg_type === "index") { | |
proc.indexArgs.push(i) | |
if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { | |
throw new Error("cwise: pre() block may not reference array index") | |
} | |
if(i < proc.body.args.length && proc.body.args[i].lvalue) { | |
throw new Error("cwise: body() block may not write to array index") | |
} | |
if(i < proc.post.args.length && proc.post.args[i].count > 0) { | |
throw new Error("cwise: post() block may not reference array index") | |
} | |
} else if(arg_type === "shape") { | |
proc.shapeArgs.push(i) | |
if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { | |
throw new Error("cwise: pre() block may not write to array shape") | |
} | |
if(i < proc.body.args.length && proc.body.args[i].lvalue) { | |
throw new Error("cwise: body() block may not write to array shape") | |
} | |
if(i < proc.post.args.length && proc.post.args[i].lvalue) { | |
throw new Error("cwise: post() block may not write to array shape") | |
} | |
} else if(typeof arg_type === "object" && arg_type.offset) { | |
proc.argTypes[i] = "offset" | |
proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) | |
proc.offsetArgIndex.push(i) | |
} else { | |
throw new Error("cwise: Unknown argument type " + proc_args[i]) | |
} | |
} | |
//Make sure at least one array argument was specified | |
if(proc.arrayArgs.length <= 0) { | |
throw new Error("cwise: No array arguments specified") | |
} | |
//Make sure arguments are correct | |
if(proc.pre.args.length > proc_args.length) { | |
throw new Error("cwise: Too many arguments in pre() block") | |
} | |
if(proc.body.args.length > proc_args.length) { | |
throw new Error("cwise: Too many arguments in body() block") | |
} | |
if(proc.post.args.length > proc_args.length) { | |
throw new Error("cwise: Too many arguments in post() block") | |
} | |
//Check debug flag | |
proc.debug = !!user_args.printCode || !!user_args.debug | |
//Retrieve name | |
proc.funcName = user_args.funcName || "cwise" | |
//Read in block size | |
proc.blockSize = user_args.blockSize || 64 | |
return createThunk(proc) | |
} | |
module.exports = compileCwise | |
},{"./lib/thunk.js":11}],10:[function(require,module,exports){ | |
"use strict" | |
var uniq = require("uniq") | |
// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index) | |
// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments. | |
function innerFill(order, proc, body) { | |
var dimension = order.length | |
, nargs = proc.arrayArgs.length | |
, has_index = proc.indexArgs.length>0 | |
, code = [] | |
, vars = [] | |
, idx=0, pidx=0, i, j | |
for(i=0; i<dimension; ++i) { // Iteration variables | |
vars.push(["i",i,"=0"].join("")) | |
} | |
//Compute scan deltas | |
for(j=0; j<nargs; ++j) { | |
for(i=0; i<dimension; ++i) { | |
pidx = idx | |
idx = order[i] | |
if(i === 0) { // The innermost/fastest dimension's delta is simply its stride | |
vars.push(["d",j,"s",i,"=t",j,"p",idx].join("")) | |
} else { // For other dimensions the delta is basically the stride minus something which essentially "rewinds" the previous (more inner) dimension | |
vars.push(["d",j,"s",i,"=(t",j,"p",idx,"-s",pidx,"*t",j,"p",pidx,")"].join("")) | |
} | |
} | |
} | |
code.push("var " + vars.join(",")) | |
//Scan loop | |
for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards | |
idx = order[i] | |
code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join("")) | |
} | |
//Push body of inner loop | |
code.push(body) | |
//Advance scan pointers | |
for(i=0; i<dimension; ++i) { | |
pidx = idx | |
idx = order[i] | |
for(j=0; j<nargs; ++j) { | |
code.push(["p",j,"+=d",j,"s",i].join("")) | |
} | |
if(has_index) { | |
if(i > 0) { | |
code.push(["index[",pidx,"]-=s",pidx].join("")) | |
} | |
code.push(["++index[",idx,"]"].join("")) | |
} | |
code.push("}") | |
} | |
return code.join("\n") | |
} | |
// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block. | |
// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. | |
// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used. | |
function outerFill(matched, order, proc, body) { | |
var dimension = order.length | |
, nargs = proc.arrayArgs.length | |
, blockSize = proc.blockSize | |
, has_index = proc.indexArgs.length > 0 | |
, code = [] | |
for(var i=0; i<nargs; ++i) { | |
code.push(["var offset",i,"=p",i].join("")) | |
} | |
//Generate loops for unmatched dimensions | |
// The order in which these dimensions are traversed is fairly arbitrary (from small stride to large stride, for the first argument) | |
// TODO: It would be nice if the order in which these loops are placed would also be somehow "optimal" (at the very least we should check that it really doesn't hurt us if they're not). | |
for(var i=matched; i<dimension; ++i) { | |
code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join("")) // Iterate back to front | |
code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). | |
code.push(["s",order[i],"=j",i].join("")) | |
code.push(["j",i,"=0"].join("")) | |
code.push(["}else{s",order[i],"=",blockSize].join("")) | |
code.push(["j",i,"-=",blockSize,"}"].join("")) | |
if(has_index) { | |
code.push(["index[",order[i],"]=j",i].join("")) | |
} | |
} | |
for(var i=0; i<nargs; ++i) { | |
var indexStr = ["offset"+i] | |
for(var j=matched; j<dimension; ++j) { | |
indexStr.push(["j",j,"*t",i,"p",order[j]].join("")) | |
} | |
code.push(["p",i,"=(",indexStr.join("+"),")"].join("")) | |
} | |
code.push(innerFill(order, proc, body)) | |
for(var i=matched; i<dimension; ++i) { | |
code.push("}") | |
} | |
return code.join("\n") | |
} | |
//Count the number of compatible inner orders | |
// This is the length of the longest common prefix of the arrays in orders. | |
// Each array in orders lists the dimensions of the correspond ndarray in order of increasing stride. | |
// This is thus the maximum number of dimensions that can be efficiently traversed by simple nested loops for all arrays. | |
function countMatches(orders) { | |
var matched = 0, dimension = orders[0].length | |
while(matched < dimension) { | |
for(var j=1; j<orders.length; ++j) { | |
if(orders[j][matched] !== orders[0][matched]) { | |
return matched | |
} | |
} | |
++matched | |
} | |
return matched | |
} | |
//Processes a block according to the given data types | |
// Replaces variable names by different ones, either "local" ones (that are then ferried in and out of the given array) or ones matching the arguments that the function performing the ultimate loop will accept. | |
function processBlock(block, proc, dtypes) { | |
var code = block.body | |
var pre = [] | |
var post = [] | |
for(var i=0; i<block.args.length; ++i) { | |
var carg = block.args[i] | |
if(carg.count <= 0) { | |
continue | |
} | |
var re = new RegExp(carg.name, "g") | |
var ptrStr = "" | |
var arrNum = proc.arrayArgs.indexOf(i) | |
switch(proc.argTypes[i]) { | |
case "offset": | |
var offArgIndex = proc.offsetArgIndex.indexOf(i) | |
var offArg = proc.offsetArgs[offArgIndex] | |
arrNum = offArg.array | |
ptrStr = "+q" + offArgIndex // Adds offset to the "pointer" in the array | |
case "array": | |
ptrStr = "p" + arrNum + ptrStr | |
var localStr = "l" + i | |
var arrStr = "a" + arrNum | |
if (proc.arrayBlockIndices[arrNum] === 0) { // Argument to body is just a single value from this array | |
if(carg.count === 1) { // Argument/array used only once(?) | |
if(dtypes[arrNum] === "generic") { | |
if(carg.lvalue) { | |
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue) | |
code = code.replace(re, localStr) | |
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join("")) | |
} else { | |
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join("")) | |
} | |
} else { | |
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join("")) | |
} | |
} else if(dtypes[arrNum] === "generic") { | |
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // TODO: Could we optimize by checking for carg.rvalue? | |
code = code.replace(re, localStr) | |
if(carg.lvalue) { | |
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join("")) | |
} | |
} else { | |
pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join("")) // TODO: Could we optimize by checking for carg.rvalue? | |
code = code.replace(re, localStr) | |
if(carg.lvalue) { | |
post.push([arrStr, "[", ptrStr, "]=", localStr].join("")) | |
} | |
} | |
} else { // Argument to body is a "block" | |
var reStrArr = [carg.name], ptrStrArr = [ptrStr] | |
for(var j=0; j<Math.abs(proc.arrayBlockIndices[arrNum]); j++) { | |
reStrArr.push("\\s*\\[([^\\]]+)\\]") | |
ptrStrArr.push("$" + (j+1) + "*t" + arrNum + "b" + j) // Matched index times stride | |
} | |
re = new RegExp(reStrArr.join(""), "g") | |
ptrStr = ptrStrArr.join("+") | |
if(dtypes[arrNum] === "generic") { | |
/*if(carg.lvalue) { | |
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue) | |
code = code.replace(re, localStr) | |
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join("")) | |
} else { | |
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join("")) | |
}*/ | |
throw new Error("cwise: Generic arrays not supported in combination with blocks!") | |
} else { | |
// This does not produce any local variables, even if variables are used multiple times. It would be possible to do so, but it would complicate things quite a bit. | |
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join("")) | |
} | |
} | |
break | |
case "scalar": | |
code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i)) | |
break | |
case "index": | |
code = code.replace(re, "index") | |
break | |
case "shape": | |
code = code.replace(re, "shape") | |
break | |
} | |
} | |
return [pre.join("\n"), code, post.join("\n")].join("\n").trim() | |
} | |
function typeSummary(dtypes) { | |
var summary = new Array(dtypes.length) | |
var allEqual = true | |
for(var i=0; i<dtypes.length; ++i) { | |
var t = dtypes[i] | |
var digits = t.match(/\d+/) | |
if(!digits) { | |
digits = "" | |
} else { | |
digits = digits[0] | |
} | |
if(t.charAt(0) === 0) { | |
summary[i] = "u" + t.charAt(1) + digits | |
} else { | |
summary[i] = t.charAt(0) + digits | |
} | |
if(i > 0) { | |
allEqual = allEqual && summary[i] === summary[i-1] | |
} | |
} | |
if(allEqual) { | |
return summary[0] | |
} | |
return summary.join("") | |
} | |
//Generates a cwise operator | |
function generateCWiseOp(proc, typesig) { | |
//Compute dimension | |
// Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg. | |
var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 | |
var orders = new Array(proc.arrayArgs.length) | |
var dtypes = new Array(proc.arrayArgs.length) | |
for(var i=0; i<proc.arrayArgs.length; ++i) { | |
dtypes[i] = typesig[2*i] | |
orders[i] = typesig[2*i+1] | |
} | |
//Determine where block and loop indices start and end | |
var blockBegin = [], blockEnd = [] // These indices are exposed as blocks | |
var loopBegin = [], loopEnd = [] // These indices are iterated over | |
var loopOrders = [] // orders restricted to the loop indices | |
for(var i=0; i<proc.arrayArgs.length; ++i) { | |
if (proc.arrayBlockIndices[i]<0) { | |
loopBegin.push(0) | |
loopEnd.push(dimension) | |
blockBegin.push(dimension) | |
blockEnd.push(dimension+proc.arrayBlockIndices[i]) | |
} else { | |
loopBegin.push(proc.arrayBlockIndices[i]) // Non-negative | |
loopEnd.push(proc.arrayBlockIndices[i]+dimension) | |
blockBegin.push(0) | |
blockEnd.push(proc.arrayBlockIndices[i]) | |
} | |
var newOrder = [] | |
for(var j=0; j<orders[i].length; j++) { | |
if (loopBegin[i]<=orders[i][j] && orders[i][j]<loopEnd[i]) { | |
newOrder.push(orders[i][j]-loopBegin[i]) // If this is a loop index, put it in newOrder, subtracting loopBegin, to make sure that all loopOrders are using a common set of indices. | |
} | |
} | |
loopOrders.push(newOrder) | |
} | |
//First create arguments for procedure | |
var arglist = ["SS"] // SS is the overall shape over which we iterate | |
var code = ["'use strict'"] | |
var vars = [] | |
for(var j=0; j<dimension; ++j) { | |
vars.push(["s", j, "=SS[", j, "]"].join("")) // The limits for each dimension. | |
} | |
for(var i=0; i<proc.arrayArgs.length; ++i) { | |
arglist.push("a"+i) // Actual data array | |
arglist.push("t"+i) // Strides | |
arglist.push("p"+i) // Offset in the array at which the data starts (also used for iterating over the data) | |
for(var j=0; j<dimension; ++j) { // Unpack the strides into vars for looping | |
vars.push(["t",i,"p",j,"=t",i,"[",loopBegin[i]+j,"]"].join("")) | |
} | |
for(var j=0; j<Math.abs(proc.arrayBlockIndices[i]); ++j) { // Unpack the strides into vars for block iteration | |
vars.push(["t",i,"b",j,"=t",i,"[",blockBegin[i]+j,"]"].join("")) | |
} | |
} | |
for(var i=0; i<proc.scalarArgs.length; ++i) { | |
arglist.push("Y" + i) | |
} | |
if(proc.shapeArgs.length > 0) { | |
vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example) | |
} | |
if(proc.indexArgs.length > 0) { | |
// Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. | |
var zeros = new Array(dimension) | |
for(var i=0; i<dimension; ++i) { | |
zeros[i] = "0" | |
} | |
vars.push(["index=[", zeros.join(","), "]"].join("")) | |
} | |
for(var i=0; i<proc.offsetArgs.length; ++i) { // Offset arguments used for stencil operations | |
var off_arg = proc.offsetArgs[i] | |
var init_string = [] | |
for(var j=0; j<off_arg.offset.length; ++j) { | |
if(off_arg.offset[j] === 0) { | |
continue | |
} else if(off_arg.offset[j] === 1) { | |
init_string.push(["t", off_arg.array, "p", j].join("")) | |
} else { | |
init_string.push([off_arg.offset[j], "*t", off_arg.array, "p", j].join("")) | |
} | |
} | |
if(init_string.length === 0) { | |
vars.push("q" + i + "=0") | |
} else { | |
vars.push(["q", i, "=", init_string.join("+")].join("")) | |
} | |
} | |
//Prepare this variables | |
var thisVars = uniq([].concat(proc.pre.thisVars) | |
.concat(proc.body.thisVars) | |
.concat(proc.post.thisVars)) | |
vars = vars.concat(thisVars) | |
code.push("var " + vars.join(",")) | |
for(var i=0; i<proc.arrayArgs.length; ++i) { | |
code.push("p"+i+"|=0") | |
} | |
//Inline prelude | |
if(proc.pre.body.length > 3) { | |
code.push(processBlock(proc.pre, proc, dtypes)) | |
} | |
//Process body | |
var body = processBlock(proc.body, proc, dtypes) | |
var matched = countMatches(loopOrders) | |
if(matched < dimension) { | |
code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example. | |
} else { | |
code.push(innerFill(loopOrders[0], proc, body)) | |
} | |
//Inline epilog | |
if(proc.post.body.length > 3) { | |
code.push(processBlock(proc.post, proc, dtypes)) | |
} | |
if(proc.debug) { | |
console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") | |
} | |
var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") | |
var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) | |
return f() | |
} | |
module.exports = generateCWiseOp | |
},{"uniq":82}],11:[function(require,module,exports){ | |
"use strict" | |
// The function below is called when constructing a cwise function object, and does the following: | |
// A function object is constructed which accepts as argument a compilation function and returns another function. | |
// It is this other function that is eventually returned by createThunk, and this function is the one that actually | |
// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. | |
// The compilation passed to the first function object is used for compiling new functions. | |
// Once this function object is created, it is called with compile as argument, where the first argument of compile | |
// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). | |
// So createThunk roughly works like this: | |
// function createThunk(proc) { | |
// var thunk = function(compileBound) { | |
// var CACHED = {} | |
// return function(arrays and scalars) { | |
// if (dtype and order of arrays in CACHED) { | |
// var func = CACHED[dtype and order of arrays] | |
// } else { | |
// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) | |
// } | |
// return func(arrays and scalars) | |
// } | |
// } | |
// return thunk(compile.bind1(proc)) | |
// } | |
var compile = require("./compile.js") | |
function createThunk(proc) { | |
var code = ["'use strict'", "var CACHED={}"] | |
var vars = [] | |
var thunkName = proc.funcName + "_cwise_thunk" | |
//Build thunk | |
code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) | |
var typesig = [] | |
var string_typesig = [] | |
var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS). | |
Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")] | |
var shapeLengthConditions = [], shapeConditions = [] | |
// Process array arguments | |
for(var i=0; i<proc.arrayArgs.length; ++i) { | |
var j = proc.arrayArgs[i] | |
vars.push(["t", j, "=array", j, ".dtype,", | |
"r", j, "=array", j, ".order"].join("")) | |
typesig.push("t" + j) | |
typesig.push("r" + j) | |
string_typesig.push("t"+j) | |
string_typesig.push("r"+j+".join()") | |
proc_args.push("array" + j + ".data") | |
proc_args.push("array" + j + ".stride") | |
proc_args.push("array" + j + ".offset|0") | |
if (i>0) { // Gather conditions to check for shape equality (ignoring block indices) | |
shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i]))) | |
shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]") | |
} | |
} | |
// Check for shape equality | |
if (proc.arrayArgs.length > 1) { | |
code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')") | |
code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {") | |
code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") | |
code.push("}") | |
} | |
// Process scalar arguments | |
for(var i=0; i<proc.scalarArgs.length; ++i) { | |
proc_args.push("scalar" + proc.scalarArgs[i]) | |
} | |
// Check for cached function (and if not present, generate it) | |
vars.push(["type=[", string_typesig.join(","), "].join()"].join("")) | |
vars.push("proc=CACHED[type]") | |
code.push("var " + vars.join(",")) | |
code.push(["if(!proc){", | |
"CACHED[type]=proc=compile([", typesig.join(","), "])}", | |
"return proc(", proc_args.join(","), ")}"].join("")) | |
if(proc.debug) { | |
console.log("-----Generated thunk:\n" + code.join("\n") + "\n----------") | |
} | |
//Compile thunk | |
var thunk = new Function("compile", code.join("\n")) | |
return thunk(compile.bind(undefined, proc)) | |
} | |
module.exports = createThunk | |
},{"./compile.js":10}],12:[function(require,module,exports){ | |
(function (global){ | |
"use strict" | |
var esprima = require("esprima") | |
var uniq = require("uniq") | |
var PREFIX_COUNTER = 0 | |
function CompiledArgument(name, lvalue, rvalue) { | |
this.name = name | |
this.lvalue = lvalue | |
this.rvalue = rvalue | |
this.count = 0 | |
} | |
function CompiledRoutine(body, args, thisVars, localVars) { | |
this.body = body | |
this.args = args | |
this.thisVars = thisVars | |
this.localVars = localVars | |
} | |
function isGlobal(identifier) { | |
if(identifier === "eval") { | |
throw new Error("cwise-parser: eval() not allowed") | |
} | |
if(typeof window !== "undefined") { | |
return identifier in window | |
} else if(typeof global !== "undefined") { | |
return identifier in global | |
} else if(typeof self !== "undefined") { | |
return identifier in self | |
} else { | |
return false | |
} | |
} | |
function getArgNames(ast) { | |
var params = ast.body[0].expression.callee.params | |
var names = new Array(params.length) | |
for(var i=0; i<params.length; ++i) { | |
names[i] = params[i].name | |
} | |
return names | |
} | |
function preprocess(func) { | |
var src = ["(", func, ")()"].join("") | |
var ast = esprima.parse(src, { range: true }) | |
//Compute new prefix | |
var prefix = "_inline_" + (PREFIX_COUNTER++) + "_" | |
//Parse out arguments | |
var argNames = getArgNames(ast) | |
var compiledArgs = new Array(argNames.length) | |
for(var i=0; i<argNames.length; ++i) { | |
compiledArgs[i] = new CompiledArgument([prefix, "arg", i, "_"].join(""), false, false) | |
} | |
//Create temporary data structure for source rewriting | |
var exploded = new Array(src.length) | |
for(var i=0, n=src.length; i<n; ++i) { | |
exploded[i] = src.charAt(i) | |
} | |
//Local variables | |
var localVars = [] | |
var thisVars = [] | |
var computedThis = false | |
//Retrieves a local variable | |
function createLocal(id) { | |
var nstr = prefix + id.replace(/\_/g, "__") | |
localVars.push(nstr) | |
return nstr | |
} | |
//Creates a this variable | |
function createThisVar(id) { | |
var nstr = "this_" + id.replace(/\_/g, "__") | |
thisVars.push(nstr) | |
return nstr | |
} | |
//Rewrites an ast node | |
function rewrite(node, nstr) { | |
var lo = node.range[0], hi = node.range[1] | |
for(var i=lo+1; i<hi; ++i) { | |
exploded[i] = "" | |
} | |
exploded[lo] = nstr | |
} | |
//Remove any underscores | |
function escapeString(str) { | |
return "'"+(str.replace(/\_/g, "\\_").replace(/\'/g, "\'"))+"'" | |
} | |
//Returns the source of an identifier | |
function source(node) { | |
return exploded.slice(node.range[0], node.range[1]).join("") | |
} | |
//Computes the usage of a node | |
var LVALUE = 1 | |
var RVALUE = 2 | |
function getUsage(node) { | |
if(node.parent.type === "AssignmentExpression") { | |
if(node.parent.left === node) { | |
if(node.parent.operator === "=") { | |
return LVALUE | |
} | |
return LVALUE|RVALUE | |
} | |
} | |
if(node.parent.type === "UpdateExpression") { | |
return LVALUE|RVALUE | |
} | |
return RVALUE | |
} | |
//Handle visiting a node | |
(function visit(node, parent) { | |
node.parent = parent | |
if(node.type === "MemberExpression") { | |
//Handle member expression | |
if(node.computed) { | |
visit(node.object, node) | |
visit(node.property, node) | |
} else if(node.object.type === "ThisExpression") { | |
rewrite(node, createThisVar(node.property.name)) | |
} else { | |
visit(node.object, node) | |
} | |
} else if(node.type === "ThisExpression") { | |
throw new Error("cwise-parser: Computed this is not allowed") | |
} else if(node.type === "Identifier") { | |
//Handle identifier | |
var name = node.name | |
var argNo = argNames.indexOf(name) | |
if(argNo >= 0) { | |
var carg = compiledArgs[argNo] | |
var usage = getUsage(node) | |
if(usage & LVALUE) { | |
carg.lvalue = true | |
} | |
if(usage & RVALUE) { | |
carg.rvalue = true | |
} | |
++carg.count | |
rewrite(node, carg.name) | |
} else if(isGlobal(name)) { | |
//Don't rewrite globals | |
} else { | |
rewrite(node, createLocal(name)) | |
} | |
} else if(node.type === "Literal") { | |
if(typeof node.value === "string") { | |
rewrite(node, escapeString(node.value)) | |
} | |
} else if(node.type === "WithStatement") { | |
throw new Error("cwise-parser: with() statements not allowed") | |
} else { | |
//Visit all children | |
var keys = Object.keys(node) | |
for(var i=0, n=keys.length; i<n; ++i) { | |
if(keys[i] === "parent") { | |
continue | |
} | |
var value = node[keys[i]] | |
if(value) { | |
if(value instanceof Array) { | |
for(var j=0; j<value.length; ++j) { | |
if(value[j] && typeof value[j].type === "string") { | |
visit(value[j], node) | |
} | |
} | |
} else if(typeof value.type === "string") { | |
visit(value, node) | |
} | |
} | |
} | |
} | |
})(ast.body[0].expression.callee.body, undefined) | |
//Remove duplicate variables | |
uniq(localVars) | |
uniq(thisVars) | |
//Return body | |
var routine = new CompiledRoutine(source(ast.body[0].expression.callee.body), compiledArgs, thisVars, localVars) | |
return routine | |
} | |
module.exports = preprocess | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"esprima":47,"uniq":82}],13:[function(require,module,exports){ | |
"use strict" | |
var parse = require("cwise-parser") | |
var compile = require("cwise-compiler") | |
var REQUIRED_FIELDS = [ "args", "body" ] | |
var OPTIONAL_FIELDS = [ "pre", "post", "printCode", "funcName", "blockSize" ] | |
function createCWise(user_args) { | |
//Check parameters | |
for(var id in user_args) { | |
if(REQUIRED_FIELDS.indexOf(id) < 0 && | |
OPTIONAL_FIELDS.indexOf(id) < 0) { | |
console.warn("cwise: Unknown argument '"+id+"' passed to expression compiler") | |
} | |
} | |
for(var i=0; i<REQUIRED_FIELDS.length; ++i) { | |
if(!user_args[REQUIRED_FIELDS[i]]) { | |
throw new Error("cwise: Missing argument: " + REQUIRED_FIELDS[i]) | |
} | |
} | |
//Parse blocks | |
return compile({ | |
args: user_args.args, | |
pre: parse(user_args.pre || function(){}), | |
body: parse(user_args.body), | |
post: parse(user_args.post || function(){}), | |
debug: !!user_args.printCode, | |
funcName: user_args.funcName || user_args.body.name || "cwise", | |
blockSize: user_args.blockSize || 64 | |
}) | |
} | |
module.exports = createCWise | |
},{"cwise-compiler":9,"cwise-parser":12}],14:[function(require,module,exports){ | |
module.exports = require("cwise-compiler") | |
},{"cwise-compiler":9}],15:[function(require,module,exports){ | |
// https://d3js.org/d3-array/ Version 1.2.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
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 bisectRight = ascendingBisect.right; | |
var bisectLeft = ascendingBisect.left; | |
var pairs = function(array, f) { | |
if (f == null) f = pair; | |
var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); | |
while (i < n) pairs[i] = f(p, p = array[++i]); | |
return pairs; | |
}; | |
function pair(a, b) { | |
return [a, b]; | |
} | |
var cross = function(values0, values1, reduce) { | |
var n0 = values0.length, | |
n1 = values1.length, | |
values = new Array(n0 * n1), | |
i0, | |
i1, | |
i, | |
value0; | |
if (reduce == null) reduce = pair; | |
for (i0 = i = 0; i0 < n0; ++i0) { | |
for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { | |
values[i] = reduce(value0, values1[i1]); | |
} | |
} | |
return values; | |
}; | |
var descending = function(a, b) { | |
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; | |
}; | |
var number = function(x) { | |
return x === null ? NaN : +x; | |
}; | |
var variance = function(values, valueof) { | |
var n = values.length, | |
m = 0, | |
i = -1, | |
mean = 0, | |
value, | |
delta, | |
sum = 0; | |
if (valueof == null) { | |
while (++i < n) { | |
if (!isNaN(value = number(values[i]))) { | |
delta = value - mean; | |
mean += delta / ++m; | |
sum += delta * (value - mean); | |
} | |
} | |
} | |
else { | |
while (++i < n) { | |
if (!isNaN(value = number(valueof(values[i], i, values)))) { | |
delta = value - mean; | |
mean += delta / ++m; | |
sum += delta * (value - mean); | |
} | |
} | |
} | |
if (m > 1) return sum / (m - 1); | |
}; | |
var deviation = function(array, f) { | |
var v = variance(array, f); | |
return v ? Math.sqrt(v) : v; | |
}; | |
var extent = function(values, valueof) { | |
var n = values.length, | |
i = -1, | |
value, | |
min, | |
max; | |
if (valueof == null) { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = values[i]) != null && value >= value) { | |
min = max = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = values[i]) != null) { | |
if (min > value) min = value; | |
if (max < value) max = value; | |
} | |
} | |
} | |
} | |
} | |
else { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = valueof(values[i], i, values)) != null && value >= value) { | |
min = max = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = valueof(values[i], i, values)) != null) { | |
if (min > value) min = value; | |
if (max < value) max = value; | |
} | |
} | |
} | |
} | |
} | |
return [min, max]; | |
}; | |
var array = Array.prototype; | |
var slice = array.slice; | |
var map = array.map; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var identity = function(x) { | |
return x; | |
}; | |
var range = function(start, stop, step) { | |
start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; | |
var i = -1, | |
n = Math.max(0, Math.ceil((stop - start) / step)) | 0, | |
range = new Array(n); | |
while (++i < n) { | |
range[i] = start + i * step; | |
} | |
return range; | |
}; | |
var e10 = Math.sqrt(50); | |
var e5 = Math.sqrt(10); | |
var e2 = Math.sqrt(2); | |
var ticks = function(start, stop, count) { | |
var reverse = stop < start, | |
i = -1, | |
n, | |
ticks, | |
step; | |
if (reverse) n = start, start = stop, stop = n; | |
if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; | |
if (step > 0) { | |
start = Math.ceil(start / step); | |
stop = Math.floor(stop / step); | |
ticks = new Array(n = Math.ceil(stop - start + 1)); | |
while (++i < n) ticks[i] = (start + i) * step; | |
} else { | |
start = Math.floor(start * step); | |
stop = Math.ceil(stop * step); | |
ticks = new Array(n = Math.ceil(start - stop + 1)); | |
while (++i < n) ticks[i] = (start - i) / step; | |
} | |
if (reverse) ticks.reverse(); | |
return ticks; | |
}; | |
function tickIncrement(start, stop, count) { | |
var step = (stop - start) / Math.max(0, count), | |
power = Math.floor(Math.log(step) / Math.LN10), | |
error = step / Math.pow(10, power); | |
return power >= 0 | |
? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) | |
: -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); | |
} | |
function tickStep(start, stop, count) { | |
var step0 = Math.abs(stop - start) / Math.max(0, count), | |
step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), | |
error = step0 / step1; | |
if (error >= e10) step1 *= 10; | |
else if (error >= e5) step1 *= 5; | |
else if (error >= e2) step1 *= 2; | |
return stop < start ? -step1 : step1; | |
} | |
var sturges = function(values) { | |
return Math.ceil(Math.log(values.length) / Math.LN2) + 1; | |
}; | |
var histogram = function() { | |
var value = identity, | |
domain = extent, | |
threshold = sturges; | |
function histogram(data) { | |
var i, | |
n = data.length, | |
x, | |
values = new Array(n); | |
for (i = 0; i < n; ++i) { | |
values[i] = value(data[i], i, data); | |
} | |
var xz = domain(values), | |
x0 = xz[0], | |
x1 = xz[1], | |
tz = threshold(values, x0, x1); | |
// Convert number of thresholds into uniform thresholds. | |
if (!Array.isArray(tz)) { | |
tz = tickStep(x0, x1, tz); | |
tz = range(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive | |
} | |
// Remove any thresholds outside the domain. | |
var m = tz.length; | |
while (tz[0] <= x0) tz.shift(), --m; | |
while (tz[m - 1] > x1) tz.pop(), --m; | |
var bins = new Array(m + 1), | |
bin; | |
// Initialize bins. | |
for (i = 0; i <= m; ++i) { | |
bin = bins[i] = []; | |
bin.x0 = i > 0 ? tz[i - 1] : x0; | |
bin.x1 = i < m ? tz[i] : x1; | |
} | |
// Assign data to bins by value, ignoring any outside the domain. | |
for (i = 0; i < n; ++i) { | |
x = values[i]; | |
if (x0 <= x && x <= x1) { | |
bins[bisectRight(tz, x, 0, m)].push(data[i]); | |
} | |
} | |
return bins; | |
} | |
histogram.value = function(_) { | |
return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; | |
}; | |
histogram.domain = function(_) { | |
return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; | |
}; | |
histogram.thresholds = function(_) { | |
return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; | |
}; | |
return histogram; | |
}; | |
var quantile = function(values, p, valueof) { | |
if (valueof == null) valueof = number; | |
if (!(n = values.length)) return; | |
if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); | |
if (p >= 1) return +valueof(values[n - 1], n - 1, values); | |
var n, | |
i = (n - 1) * p, | |
i0 = Math.floor(i), | |
value0 = +valueof(values[i0], i0, values), | |
value1 = +valueof(values[i0 + 1], i0 + 1, values); | |
return value0 + (value1 - value0) * (i - i0); | |
}; | |
var freedmanDiaconis = function(values, min, max) { | |
values = map.call(values, number).sort(ascending); | |
return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); | |
}; | |
var scott = function(values, min, max) { | |
return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); | |
}; | |
var max = function(values, valueof) { | |
var n = values.length, | |
i = -1, | |
value, | |
max; | |
if (valueof == null) { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = values[i]) != null && value >= value) { | |
max = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = values[i]) != null && value > max) { | |
max = value; | |
} | |
} | |
} | |
} | |
} | |
else { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = valueof(values[i], i, values)) != null && value >= value) { | |
max = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = valueof(values[i], i, values)) != null && value > max) { | |
max = value; | |
} | |
} | |
} | |
} | |
} | |
return max; | |
}; | |
var mean = function(values, valueof) { | |
var n = values.length, | |
m = n, | |
i = -1, | |
value, | |
sum = 0; | |
if (valueof == null) { | |
while (++i < n) { | |
if (!isNaN(value = number(values[i]))) sum += value; | |
else --m; | |
} | |
} | |
else { | |
while (++i < n) { | |
if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; | |
else --m; | |
} | |
} | |
if (m) return sum / m; | |
}; | |
var median = function(values, valueof) { | |
var n = values.length, | |
i = -1, | |
value, | |
numbers = []; | |
if (valueof == null) { | |
while (++i < n) { | |
if (!isNaN(value = number(values[i]))) { | |
numbers.push(value); | |
} | |
} | |
} | |
else { | |
while (++i < n) { | |
if (!isNaN(value = number(valueof(values[i], i, values)))) { | |
numbers.push(value); | |
} | |
} | |
} | |
return quantile(numbers.sort(ascending), 0.5); | |
}; | |
var merge = function(arrays) { | |
var n = arrays.length, | |
m, | |
i = -1, | |
j = 0, | |
merged, | |
array; | |
while (++i < n) j += arrays[i].length; | |
merged = new Array(j); | |
while (--n >= 0) { | |
array = arrays[n]; | |
m = array.length; | |
while (--m >= 0) { | |
merged[--j] = array[m]; | |
} | |
} | |
return merged; | |
}; | |
var min = function(values, valueof) { | |
var n = values.length, | |
i = -1, | |
value, | |
min; | |
if (valueof == null) { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = values[i]) != null && value >= value) { | |
min = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = values[i]) != null && min > value) { | |
min = value; | |
} | |
} | |
} | |
} | |
} | |
else { | |
while (++i < n) { // Find the first comparable value. | |
if ((value = valueof(values[i], i, values)) != null && value >= value) { | |
min = value; | |
while (++i < n) { // Compare the remaining values. | |
if ((value = valueof(values[i], i, values)) != null && min > value) { | |
min = value; | |
} | |
} | |
} | |
} | |
} | |
return min; | |
}; | |
var permute = function(array, indexes) { | |
var i = indexes.length, permutes = new Array(i); | |
while (i--) permutes[i] = array[indexes[i]]; | |
return permutes; | |
}; | |
var scan = function(values, compare) { | |
if (!(n = values.length)) return; | |
var n, | |
i = 0, | |
j = 0, | |
xi, | |
xj = values[j]; | |
if (compare == null) compare = ascending; | |
while (++i < n) { | |
if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { | |
xj = xi, j = i; | |
} | |
} | |
if (compare(xj, xj) === 0) return j; | |
}; | |
var shuffle = function(array, i0, i1) { | |
var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), | |
t, | |
i; | |
while (m) { | |
i = Math.random() * m-- | 0; | |
t = array[m + i0]; | |
array[m + i0] = array[i + i0]; | |
array[i + i0] = t; | |
} | |
return array; | |
}; | |
var sum = function(values, valueof) { | |
var n = values.length, | |
i = -1, | |
value, | |
sum = 0; | |
if (valueof == null) { | |
while (++i < n) { | |
if (value = +values[i]) sum += value; // Note: zero and null are equivalent. | |
} | |
} | |
else { | |
while (++i < n) { | |
if (value = +valueof(values[i], i, values)) sum += value; | |
} | |
} | |
return sum; | |
}; | |
var transpose = function(matrix) { | |
if (!(n = matrix.length)) return []; | |
for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { | |
for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { | |
row[j] = matrix[j][i]; | |
} | |
} | |
return transpose; | |
}; | |
function length(d) { | |
return d.length; | |
} | |
var zip = function() { | |
return transpose(arguments); | |
}; | |
exports.bisect = bisectRight; | |
exports.bisectRight = bisectRight; | |
exports.bisectLeft = bisectLeft; | |
exports.ascending = ascending; | |
exports.bisector = bisector; | |
exports.cross = cross; | |
exports.descending = descending; | |
exports.deviation = deviation; | |
exports.extent = extent; | |
exports.histogram = histogram; | |
exports.thresholdFreedmanDiaconis = freedmanDiaconis; | |
exports.thresholdScott = scott; | |
exports.thresholdSturges = sturges; | |
exports.max = max; | |
exports.mean = mean; | |
exports.median = median; | |
exports.merge = merge; | |
exports.min = min; | |
exports.pairs = pairs; | |
exports.permute = permute; | |
exports.quantile = quantile; | |
exports.range = range; | |
exports.scan = scan; | |
exports.shuffle = shuffle; | |
exports.sum = sum; | |
exports.ticks = ticks; | |
exports.tickIncrement = tickIncrement; | |
exports.tickStep = tickStep; | |
exports.transpose = transpose; | |
exports.variance = variance; | |
exports.zip = zip; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],16:[function(require,module,exports){ | |
// https://d3js.org/d3-axis/ Version 1.0.8. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var slice = Array.prototype.slice; | |
var identity = function(x) { | |
return x; | |
}; | |
var top = 1; | |
var right = 2; | |
var bottom = 3; | |
var left = 4; | |
var epsilon = 1e-6; | |
function translateX(x) { | |
return "translate(" + (x + 0.5) + ",0)"; | |
} | |
function translateY(y) { | |
return "translate(0," + (y + 0.5) + ")"; | |
} | |
function number(scale) { | |
return function(d) { | |
return +scale(d); | |
}; | |
} | |
function center(scale) { | |
var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. | |
if (scale.round()) offset = Math.round(offset); | |
return function(d) { | |
return +scale(d) + offset; | |
}; | |
} | |
function entering() { | |
return !this.__axis; | |
} | |
function axis(orient, scale) { | |
var tickArguments = [], | |
tickValues = null, | |
tickFormat = null, | |
tickSizeInner = 6, | |
tickSizeOuter = 6, | |
tickPadding = 3, | |
k = orient === top || orient === left ? -1 : 1, | |
x = orient === left || orient === right ? "x" : "y", | |
transform = orient === top || orient === bottom ? translateX : translateY; | |
function axis(context) { | |
var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, | |
format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity) : tickFormat, | |
spacing = Math.max(tickSizeInner, 0) + tickPadding, | |
range = scale.range(), | |
range0 = +range[0] + 0.5, | |
range1 = +range[range.length - 1] + 0.5, | |
position = (scale.bandwidth ? center : number)(scale.copy()), | |
selection = context.selection ? context.selection() : context, | |
path = selection.selectAll(".domain").data([null]), | |
tick = selection.selectAll(".tick").data(values, scale).order(), | |
tickExit = tick.exit(), | |
tickEnter = tick.enter().append("g").attr("class", "tick"), | |
line = tick.select("line"), | |
text = tick.select("text"); | |
path = path.merge(path.enter().insert("path", ".tick") | |
.attr("class", "domain") | |
.attr("stroke", "#000")); | |
tick = tick.merge(tickEnter); | |
line = line.merge(tickEnter.append("line") | |
.attr("stroke", "#000") | |
.attr(x + "2", k * tickSizeInner)); | |
text = text.merge(tickEnter.append("text") | |
.attr("fill", "#000") | |
.attr(x, k * spacing) | |
.attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); | |
if (context !== selection) { | |
path = path.transition(context); | |
tick = tick.transition(context); | |
line = line.transition(context); | |
text = text.transition(context); | |
tickExit = tickExit.transition(context) | |
.attr("opacity", epsilon) | |
.attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); }); | |
tickEnter | |
.attr("opacity", epsilon) | |
.attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); }); | |
} | |
tickExit.remove(); | |
path | |
.attr("d", orient === left || orient == right | |
? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter | |
: "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); | |
tick | |
.attr("opacity", 1) | |
.attr("transform", function(d) { return transform(position(d)); }); | |
line | |
.attr(x + "2", k * tickSizeInner); | |
text | |
.attr(x, k * spacing) | |
.text(format); | |
selection.filter(entering) | |
.attr("fill", "none") | |
.attr("font-size", 10) | |
.attr("font-family", "sans-serif") | |
.attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); | |
selection | |
.each(function() { this.__axis = position; }); | |
} | |
axis.scale = function(_) { | |
return arguments.length ? (scale = _, axis) : scale; | |
}; | |
axis.ticks = function() { | |
return tickArguments = slice.call(arguments), axis; | |
}; | |
axis.tickArguments = function(_) { | |
return arguments.length ? (tickArguments = _ == null ? [] : slice.call(_), axis) : tickArguments.slice(); | |
}; | |
axis.tickValues = function(_) { | |
return arguments.length ? (tickValues = _ == null ? null : slice.call(_), axis) : tickValues && tickValues.slice(); | |
}; | |
axis.tickFormat = function(_) { | |
return arguments.length ? (tickFormat = _, axis) : tickFormat; | |
}; | |
axis.tickSize = function(_) { | |
return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; | |
}; | |
axis.tickSizeInner = function(_) { | |
return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; | |
}; | |
axis.tickSizeOuter = function(_) { | |
return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; | |
}; | |
axis.tickPadding = function(_) { | |
return arguments.length ? (tickPadding = +_, axis) : tickPadding; | |
}; | |
return axis; | |
} | |
function axisTop(scale) { | |
return axis(top, scale); | |
} | |
function axisRight(scale) { | |
return axis(right, scale); | |
} | |
function axisBottom(scale) { | |
return axis(bottom, scale); | |
} | |
function axisLeft(scale) { | |
return axis(left, scale); | |
} | |
exports.axisTop = axisTop; | |
exports.axisRight = axisRight; | |
exports.axisBottom = axisBottom; | |
exports.axisLeft = axisLeft; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],17:[function(require,module,exports){ | |
// https://d3js.org/d3-brush/ Version 1.0.4. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-selection'), require('d3-transition')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-selection', 'd3-transition'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3)); | |
}(this, (function (exports,d3Dispatch,d3Drag,d3Interpolate,d3Selection,d3Transition) { 'use strict'; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var BrushEvent = function(target, type, selection) { | |
this.target = target; | |
this.type = type; | |
this.selection = selection; | |
}; | |
function nopropagation() { | |
d3Selection.event.stopImmediatePropagation(); | |
} | |
var noevent = function() { | |
d3Selection.event.preventDefault(); | |
d3Selection.event.stopImmediatePropagation(); | |
}; | |
var MODE_DRAG = {name: "drag"}; | |
var MODE_SPACE = {name: "space"}; | |
var MODE_HANDLE = {name: "handle"}; | |
var MODE_CENTER = {name: "center"}; | |
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; } | |
}; | |
var cursors = { | |
overlay: "crosshair", | |
selection: "move", | |
n: "ns-resize", | |
e: "ew-resize", | |
s: "ns-resize", | |
w: "ew-resize", | |
nw: "nwse-resize", | |
ne: "nesw-resize", | |
se: "nwse-resize", | |
sw: "nesw-resize" | |
}; | |
var flipX = { | |
e: "w", | |
w: "e", | |
nw: "ne", | |
ne: "nw", | |
se: "sw", | |
sw: "se" | |
}; | |
var flipY = { | |
n: "s", | |
s: "n", | |
nw: "sw", | |
ne: "se", | |
se: "ne", | |
sw: "nw" | |
}; | |
var signsX = { | |
overlay: +1, | |
selection: +1, | |
n: null, | |
e: +1, | |
s: null, | |
w: -1, | |
nw: -1, | |
ne: +1, | |
se: +1, | |
sw: -1 | |
}; | |
var signsY = { | |
overlay: +1, | |
selection: +1, | |
n: -1, | |
e: null, | |
s: +1, | |
w: null, | |
nw: -1, | |
ne: -1, | |
se: +1, | |
sw: +1 | |
}; | |
function type(t) { | |
return {type: t}; | |
} | |
// Ignore right-click, since that should open the context menu. | |
function defaultFilter() { | |
return !d3Selection.event.button; | |
} | |
function defaultExtent() { | |
var svg = this.ownerSVGElement || this; | |
return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; | |
} | |
// Like d3.local, but with the name “__brush” rather than auto-generated. | |
function local(node) { | |
while (!node.__brush) if (!(node = node.parentNode)) return; | |
return node.__brush; | |
} | |
function empty(extent) { | |
return extent[0][0] === extent[1][0] | |
|| extent[0][1] === extent[1][1]; | |
} | |
function brushSelection(node) { | |
var state = node.__brush; | |
return state ? state.dim.output(state.selection) : null; | |
} | |
function brushX() { | |
return brush$1(X); | |
} | |
function brushY() { | |
return brush$1(Y); | |
} | |
var brush = function() { | |
return brush$1(XY); | |
}; | |
function brush$1(dim) { | |
var extent = defaultExtent, | |
filter = defaultFilter, | |
listeners = d3Dispatch.dispatch(brush, "start", "brush", "end"), | |
handleSize = 6, | |
touchending; | |
function brush(group) { | |
var overlay = group | |
.property("__brush", initialize) | |
.selectAll(".overlay") | |
.data([type("overlay")]); | |
overlay.enter().append("rect") | |
.attr("class", "overlay") | |
.attr("pointer-events", "all") | |
.attr("cursor", cursors.overlay) | |
.merge(overlay) | |
.each(function() { | |
var extent = local(this).extent; | |
d3Selection.select(this) | |
.attr("x", extent[0][0]) | |
.attr("y", extent[0][1]) | |
.attr("width", extent[1][0] - extent[0][0]) | |
.attr("height", extent[1][1] - extent[0][1]); | |
}); | |
group.selectAll(".selection") | |
.data([type("selection")]) | |
.enter().append("rect") | |
.attr("class", "selection") | |
.attr("cursor", cursors.selection) | |
.attr("fill", "#777") | |
.attr("fill-opacity", 0.3) | |
.attr("stroke", "#fff") | |
.attr("shape-rendering", "crispEdges"); | |
var handle = group.selectAll(".handle") | |
.data(dim.handles, function(d) { return d.type; }); | |
handle.exit().remove(); | |
handle.enter().append("rect") | |
.attr("class", function(d) { return "handle handle--" + d.type; }) | |
.attr("cursor", function(d) { return cursors[d.type]; }); | |
group | |
.each(redraw) | |
.attr("fill", "none") | |
.attr("pointer-events", "all") | |
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") | |
.on("mousedown.brush touchstart.brush", started); | |
} | |
brush.move = function(group, selection) { | |
if (group.selection) { | |
group | |
.on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) | |
.on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) | |
.tween("brush", function() { | |
var that = this, | |
state = that.__brush, | |
emit = emitter(that, arguments), | |
selection0 = state.selection, | |
selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent), | |
i = d3Interpolate.interpolate(selection0, selection1); | |
function tween(t) { | |
state.selection = t === 1 && empty(selection1) ? null : i(t); | |
redraw.call(that); | |
emit.brush(); | |
} | |
return selection0 && selection1 ? tween : tween(1); | |
}); | |
} else { | |
group | |
.each(function() { | |
var that = this, | |
args = arguments, | |
state = that.__brush, | |
selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent), | |
emit = emitter(that, args).beforestart(); | |
d3Transition.interrupt(that); | |
state.selection = selection1 == null || empty(selection1) ? null : selection1; | |
redraw.call(that); | |
emit.start().brush().end(); | |
}); | |
} | |
}; | |
function redraw() { | |
var group = d3Selection.select(this), | |
selection = local(this).selection; | |
if (selection) { | |
group.selectAll(".selection") | |
.style("display", null) | |
.attr("x", selection[0][0]) | |
.attr("y", selection[0][1]) | |
.attr("width", selection[1][0] - selection[0][0]) | |
.attr("height", selection[1][1] - selection[0][1]); | |
group.selectAll(".handle") | |
.style("display", null) | |
.attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; }) | |
.attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; }) | |
.attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; }) | |
.attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; }); | |
} | |
else { | |
group.selectAll(".selection,.handle") | |
.style("display", "none") | |
.attr("x", null) | |
.attr("y", null) | |
.attr("width", null) | |
.attr("height", null); | |
} | |
} | |
function emitter(that, args) { | |
return that.__brush.emitter || new Emitter(that, args); | |
} | |
function Emitter(that, args) { | |
this.that = that; | |
this.args = args; | |
this.state = that.__brush; | |
this.active = 0; | |
} | |
Emitter.prototype = { | |
beforestart: function() { | |
if (++this.active === 1) this.state.emitter = this, this.starting = true; | |
return this; | |
}, | |
start: function() { | |
if (this.starting) this.starting = false, this.emit("start"); | |
return this; | |
}, | |
brush: function() { | |
this.emit("brush"); | |
return this; | |
}, | |
end: function() { | |
if (--this.active === 0) delete this.state.emitter, this.emit("end"); | |
return this; | |
}, | |
emit: function(type) { | |
d3Selection.customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); | |
} | |
}; | |
function started() { | |
if (d3Selection.event.touches) { if (d3Selection.event.changedTouches.length < d3Selection.event.touches.length) return noevent(); } | |
else if (touchending) return; | |
if (!filter.apply(this, arguments)) return; | |
var that = this, | |
type = d3Selection.event.target.__data__.type, | |
mode = (d3Selection.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (d3Selection.event.altKey ? MODE_CENTER : MODE_HANDLE), | |
signX = dim === Y ? null : signsX[type], | |
signY = dim === X ? null : signsY[type], | |
state = local(that), | |
extent = state.extent, | |
selection = state.selection, | |
W = extent[0][0], w0, w1, | |
N = extent[0][1], n0, n1, | |
E = extent[1][0], e0, e1, | |
S = extent[1][1], s0, s1, | |
dx, | |
dy, | |
moving, | |
shifting = signX && signY && d3Selection.event.shiftKey, | |
lockX, | |
lockY, | |
point0 = d3Selection.mouse(that), | |
point = point0, | |
emit = emitter(that, arguments).beforestart(); | |
if (type === "overlay") { | |
state.selection = selection = [ | |
[w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], | |
[e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] | |
]; | |
} else { | |
w0 = selection[0][0]; | |
n0 = selection[0][1]; | |
e0 = selection[1][0]; | |
s0 = selection[1][1]; | |
} | |
w1 = w0; | |
n1 = n0; | |
e1 = e0; | |
s1 = s0; | |
var group = d3Selection.select(that) | |
.attr("pointer-events", "none"); | |
var overlay = group.selectAll(".overlay") | |
.attr("cursor", cursors[type]); | |
if (d3Selection.event.touches) { | |
group | |
.on("touchmove.brush", moved, true) | |
.on("touchend.brush touchcancel.brush", ended, true); | |
} else { | |
var view = d3Selection.select(d3Selection.event.view) | |
.on("keydown.brush", keydowned, true) | |
.on("keyup.brush", keyupped, true) | |
.on("mousemove.brush", moved, true) | |
.on("mouseup.brush", ended, true); | |
d3Drag.dragDisable(d3Selection.event.view); | |
} | |
nopropagation(); | |
d3Transition.interrupt(that); | |
redraw.call(that); | |
emit.start(); | |
function moved() { | |
var point1 = d3Selection.mouse(that); | |
if (shifting && !lockX && !lockY) { | |
if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; | |
else lockX = true; | |
} | |
point = point1; | |
moving = true; | |
noevent(); | |
move(); | |
} | |
function move() { | |
var t; | |
dx = point[0] - point0[0]; | |
dy = point[1] - point0[1]; | |
switch (mode) { | |
case MODE_SPACE: | |
case MODE_DRAG: { | |
if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; | |
if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; | |
break; | |
} | |
case MODE_HANDLE: { | |
if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; | |
else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; | |
if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; | |
else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; | |
break; | |
} | |
case MODE_CENTER: { | |
if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); | |
if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); | |
break; | |
} | |
} | |
if (e1 < w1) { | |
signX *= -1; | |
t = w0, w0 = e0, e0 = t; | |
t = w1, w1 = e1, e1 = t; | |
if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); | |
} | |
if (s1 < n1) { | |
signY *= -1; | |
t = n0, n0 = s0, s0 = t; | |
t = n1, n1 = s1, s1 = t; | |
if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); | |
} | |
if (state.selection) selection = state.selection; // May be set by brush.move! | |
if (lockX) w1 = selection[0][0], e1 = selection[1][0]; | |
if (lockY) n1 = selection[0][1], s1 = selection[1][1]; | |
if (selection[0][0] !== w1 | |
|| selection[0][1] !== n1 | |
|| selection[1][0] !== e1 | |
|| selection[1][1] !== s1) { | |
state.selection = [[w1, n1], [e1, s1]]; | |
redraw.call(that); | |
emit.brush(); | |
} | |
} | |
function ended() { | |
nopropagation(); | |
if (d3Selection.event.touches) { | |
if (d3Selection.event.touches.length) return; | |
if (touchending) clearTimeout(touchending); | |
touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! | |
group.on("touchmove.brush touchend.brush touchcancel.brush", null); | |
} else { | |
d3Drag.dragEnable(d3Selection.event.view, moving); | |
view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); | |
} | |
group.attr("pointer-events", "all"); | |
overlay.attr("cursor", cursors.overlay); | |
if (state.selection) selection = state.selection; // May be set by brush.move (on start)! | |
if (empty(selection)) state.selection = null, redraw.call(that); | |
emit.end(); | |
} | |
function keydowned() { | |
switch (d3Selection.event.keyCode) { | |
case 16: { // SHIFT | |
shifting = signX && signY; | |
break; | |
} | |
case 18: { // ALT | |
if (mode === MODE_HANDLE) { | |
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; | |
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; | |
mode = MODE_CENTER; | |
move(); | |
} | |
break; | |
} | |
case 32: { // SPACE; takes priority over ALT | |
if (mode === MODE_HANDLE || mode === MODE_CENTER) { | |
if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; | |
if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; | |
mode = MODE_SPACE; | |
overlay.attr("cursor", cursors.selection); | |
move(); | |
} | |
break; | |
} | |
default: return; | |
} | |
noevent(); | |
} | |
function keyupped() { | |
switch (d3Selection.event.keyCode) { | |
case 16: { // SHIFT | |
if (shifting) { | |
lockX = lockY = shifting = false; | |
move(); | |
} | |
break; | |
} | |
case 18: { // ALT | |
if (mode === MODE_CENTER) { | |
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; | |
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; | |
mode = MODE_HANDLE; | |
move(); | |
} | |
break; | |
} | |
case 32: { // SPACE | |
if (mode === MODE_SPACE) { | |
if (d3Selection.event.altKey) { | |
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; | |
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; | |
mode = MODE_CENTER; | |
} else { | |
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; | |
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; | |
mode = MODE_HANDLE; | |
} | |
overlay.attr("cursor", cursors[type]); | |
move(); | |
} | |
break; | |
} | |
default: return; | |
} | |
noevent(); | |
} | |
} | |
function initialize() { | |
var state = this.__brush || {selection: null}; | |
state.extent = extent.apply(this, arguments); | |
state.dim = dim; | |
return state; | |
} | |
brush.extent = function(_) { | |
return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; | |
}; | |
brush.filter = function(_) { | |
return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter; | |
}; | |
brush.handleSize = function(_) { | |
return arguments.length ? (handleSize = +_, brush) : handleSize; | |
}; | |
brush.on = function() { | |
var value = listeners.on.apply(listeners, arguments); | |
return value === listeners ? brush : value; | |
}; | |
return brush; | |
} | |
exports.brush = brush; | |
exports.brushX = brushX; | |
exports.brushY = brushY; | |
exports.brushSelection = brushSelection; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-dispatch":21,"d3-drag":22,"d3-interpolate":29,"d3-selection":37,"d3-transition":42}],18:[function(require,module,exports){ | |
// https://d3js.org/d3-chord/ Version 1.0.4. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-path')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-path'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3)); | |
}(this, (function (exports,d3Array,d3Path) { 'use strict'; | |
var cos = Math.cos; | |
var sin = Math.sin; | |
var pi = Math.PI; | |
var halfPi = pi / 2; | |
var tau = pi * 2; | |
var max = Math.max; | |
function compareValue(compare) { | |
return function(a, b) { | |
return compare( | |
a.source.value + a.target.value, | |
b.source.value + b.target.value | |
); | |
}; | |
} | |
var chord = function() { | |
var padAngle = 0, | |
sortGroups = null, | |
sortSubgroups = null, | |
sortChords = null; | |
function chord(matrix) { | |
var n = matrix.length, | |
groupSums = [], | |
groupIndex = d3Array.range(n), | |
subgroupIndex = [], | |
chords = [], | |
groups = chords.groups = new Array(n), | |
subgroups = new Array(n * n), | |
k, | |
x, | |
x0, | |
dx, | |
i, | |
j; | |
// Compute the sum. | |
k = 0, i = -1; while (++i < n) { | |
x = 0, j = -1; while (++j < n) { | |
x += matrix[i][j]; | |
} | |
groupSums.push(x); | |
subgroupIndex.push(d3Array.range(n)); | |
k += x; | |
} | |
// Sort groups… | |
if (sortGroups) groupIndex.sort(function(a, b) { | |
return sortGroups(groupSums[a], groupSums[b]); | |
}); | |
// Sort subgroups… | |
if (sortSubgroups) subgroupIndex.forEach(function(d, i) { | |
d.sort(function(a, b) { | |
return sortSubgroups(matrix[i][a], matrix[i][b]); | |
}); | |
}); | |
// Convert the sum to scaling factor for [0, 2pi]. | |
// TODO Allow start and end angle to be specified? | |
// TODO Allow padding to be specified as percentage? | |
k = max(0, tau - padAngle * n) / k; | |
dx = k ? padAngle : tau / n; | |
// Compute the start and end angle for each group and subgroup. | |
// Note: Opera has a bug reordering object literal properties! | |
x = 0, i = -1; while (++i < n) { | |
x0 = x, j = -1; while (++j < n) { | |
var di = groupIndex[i], | |
dj = subgroupIndex[di][j], | |
v = matrix[di][dj], | |
a0 = x, | |
a1 = x += v * k; | |
subgroups[dj * n + di] = { | |
index: di, | |
subindex: dj, | |
startAngle: a0, | |
endAngle: a1, | |
value: v | |
}; | |
} | |
groups[di] = { | |
index: di, | |
startAngle: x0, | |
endAngle: x, | |
value: groupSums[di] | |
}; | |
x += dx; | |
} | |
// Generate chords for each (non-empty) subgroup-subgroup link. | |
i = -1; while (++i < n) { | |
j = i - 1; while (++j < n) { | |
var source = subgroups[j * n + i], | |
target = subgroups[i * n + j]; | |
if (source.value || target.value) { | |
chords.push(source.value < target.value | |
? {source: target, target: source} | |
: {source: source, target: target}); | |
} | |
} | |
} | |
return sortChords ? chords.sort(sortChords) : chords; | |
} | |
chord.padAngle = function(_) { | |
return arguments.length ? (padAngle = max(0, _), chord) : padAngle; | |
}; | |
chord.sortGroups = function(_) { | |
return arguments.length ? (sortGroups = _, chord) : sortGroups; | |
}; | |
chord.sortSubgroups = function(_) { | |
return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; | |
}; | |
chord.sortChords = function(_) { | |
return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; | |
}; | |
return chord; | |
}; | |
var slice = Array.prototype.slice; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
function defaultSource(d) { | |
return d.source; | |
} | |
function defaultTarget(d) { | |
return d.target; | |
} | |
function defaultRadius(d) { | |
return d.radius; | |
} | |
function defaultStartAngle(d) { | |
return d.startAngle; | |
} | |
function defaultEndAngle(d) { | |
return d.endAngle; | |
} | |
var ribbon = function() { | |
var source = defaultSource, | |
target = defaultTarget, | |
radius = defaultRadius, | |
startAngle = defaultStartAngle, | |
endAngle = defaultEndAngle, | |
context = null; | |
function ribbon() { | |
var buffer, | |
argv = slice.call(arguments), | |
s = source.apply(this, argv), | |
t = target.apply(this, argv), | |
sr = +radius.apply(this, (argv[0] = s, argv)), | |
sa0 = startAngle.apply(this, argv) - halfPi, | |
sa1 = endAngle.apply(this, argv) - halfPi, | |
sx0 = sr * cos(sa0), | |
sy0 = sr * sin(sa0), | |
tr = +radius.apply(this, (argv[0] = t, argv)), | |
ta0 = startAngle.apply(this, argv) - halfPi, | |
ta1 = endAngle.apply(this, argv) - halfPi; | |
if (!context) context = buffer = d3Path.path(); | |
context.moveTo(sx0, sy0); | |
context.arc(0, 0, sr, sa0, sa1); | |
if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? | |
context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); | |
context.arc(0, 0, tr, ta0, ta1); | |
} | |
context.quadraticCurveTo(0, 0, sx0, sy0); | |
context.closePath(); | |
if (buffer) return context = null, buffer + "" || null; | |
} | |
ribbon.radius = function(_) { | |
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), ribbon) : radius; | |
}; | |
ribbon.startAngle = function(_) { | |
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : startAngle; | |
}; | |
ribbon.endAngle = function(_) { | |
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : endAngle; | |
}; | |
ribbon.source = function(_) { | |
return arguments.length ? (source = _, ribbon) : source; | |
}; | |
ribbon.target = function(_) { | |
return arguments.length ? (target = _, ribbon) : target; | |
}; | |
ribbon.context = function(_) { | |
return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; | |
}; | |
return ribbon; | |
}; | |
exports.chord = chord; | |
exports.ribbon = ribbon; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-array":15,"d3-path":30}],19:[function(require,module,exports){ | |
// https://d3js.org/d3-collection/ Version 1.0.4. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var prefix = "$"; | |
function Map() {} | |
Map.prototype = map.prototype = { | |
constructor: Map, | |
has: function(key) { | |
return (prefix + key) in this; | |
}, | |
get: function(key) { | |
return this[prefix + key]; | |
}, | |
set: function(key, value) { | |
this[prefix + key] = value; | |
return this; | |
}, | |
remove: function(key) { | |
var property = prefix + key; | |
return property in this && delete this[property]; | |
}, | |
clear: function() { | |
for (var property in this) if (property[0] === prefix) delete this[property]; | |
}, | |
keys: function() { | |
var keys = []; | |
for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); | |
return keys; | |
}, | |
values: function() { | |
var values = []; | |
for (var property in this) if (property[0] === prefix) values.push(this[property]); | |
return values; | |
}, | |
entries: function() { | |
var entries = []; | |
for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); | |
return entries; | |
}, | |
size: function() { | |
var size = 0; | |
for (var property in this) if (property[0] === prefix) ++size; | |
return size; | |
}, | |
empty: function() { | |
for (var property in this) if (property[0] === prefix) return false; | |
return true; | |
}, | |
each: function(f) { | |
for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); | |
} | |
}; | |
function map(object, f) { | |
var map = new Map; | |
// Copy constructor. | |
if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); | |
// Index array by numeric index or specified key function. | |
else if (Array.isArray(object)) { | |
var i = -1, | |
n = object.length, | |
o; | |
if (f == null) while (++i < n) map.set(i, object[i]); | |
else while (++i < n) map.set(f(o = object[i], i, object), o); | |
} | |
// Convert object to map. | |
else if (object) for (var key in object) map.set(key, object[key]); | |
return map; | |
} | |
var nest = function() { | |
var keys = [], | |
sortKeys = [], | |
sortValues, | |
rollup, | |
nest; | |
function apply(array, depth, createResult, setResult) { | |
if (depth >= keys.length) { | |
if (sortValues != null) array.sort(sortValues); | |
return rollup != null ? rollup(array) : array; | |
} | |
var i = -1, | |
n = array.length, | |
key = keys[depth++], | |
keyValue, | |
value, | |
valuesByKey = map(), | |
values, | |
result = createResult(); | |
while (++i < n) { | |
if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { | |
values.push(value); | |
} else { | |
valuesByKey.set(keyValue, [value]); | |
} | |
} | |
valuesByKey.each(function(values, key) { | |
setResult(result, key, apply(values, depth, createResult, setResult)); | |
}); | |
return result; | |
} | |
function entries(map$$1, depth) { | |
if (++depth > keys.length) return map$$1; | |
var array, sortKey = sortKeys[depth - 1]; | |
if (rollup != null && depth >= keys.length) array = map$$1.entries(); | |
else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); | |
return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; | |
} | |
return nest = { | |
object: function(array) { return apply(array, 0, createObject, setObject); }, | |
map: function(array) { return apply(array, 0, createMap, setMap); }, | |
entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, | |
key: function(d) { keys.push(d); return nest; }, | |
sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, | |
sortValues: function(order) { sortValues = order; return nest; }, | |
rollup: function(f) { rollup = f; return nest; } | |
}; | |
}; | |
function createObject() { | |
return {}; | |
} | |
function setObject(object, key, value) { | |
object[key] = value; | |
} | |
function createMap() { | |
return map(); | |
} | |
function setMap(map$$1, key, value) { | |
map$$1.set(key, value); | |
} | |
function Set() {} | |
var proto = map.prototype; | |
Set.prototype = set.prototype = { | |
constructor: Set, | |
has: proto.has, | |
add: function(value) { | |
value += ""; | |
this[prefix + value] = value; | |
return this; | |
}, | |
remove: proto.remove, | |
clear: proto.clear, | |
values: proto.keys, | |
size: proto.size, | |
empty: proto.empty, | |
each: proto.each | |
}; | |
function set(object, f) { | |
var set = new Set; | |
// Copy constructor. | |
if (object instanceof Set) object.each(function(value) { set.add(value); }); | |
// Otherwise, assume it’s an array. | |
else if (object) { | |
var i = -1, n = object.length; | |
if (f == null) while (++i < n) set.add(object[i]); | |
else while (++i < n) set.add(f(object[i], i, object)); | |
} | |
return set; | |
} | |
var keys = function(map) { | |
var keys = []; | |
for (var key in map) keys.push(key); | |
return keys; | |
}; | |
var values = function(map) { | |
var values = []; | |
for (var key in map) values.push(map[key]); | |
return values; | |
}; | |
var entries = function(map) { | |
var entries = []; | |
for (var key in map) entries.push({key: key, value: map[key]}); | |
return entries; | |
}; | |
exports.nest = nest; | |
exports.set = set; | |
exports.map = map; | |
exports.keys = keys; | |
exports.values = values; | |
exports.entries = entries; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],20:[function(require,module,exports){ | |
// https://d3js.org/d3-color/ Version 1.0.3. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
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 | |
); | |
} | |
})); | |
exports.color = color; | |
exports.rgb = rgb; | |
exports.hsl = hsl; | |
exports.lab = lab; | |
exports.hcl = hcl; | |
exports.cubehelix = cubehelix; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],21:[function(require,module,exports){ | |
// https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
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; | |
} | |
exports.dispatch = dispatch; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],22:[function(require,module,exports){ | |
// https://d3js.org/d3-drag/ Version 1.1.1. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-selection')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-selection'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3)); | |
}(this, (function (exports,d3Dispatch,d3Selection) { 'use strict'; | |
function nopropagation() { | |
d3Selection.event.stopImmediatePropagation(); | |
} | |
var noevent = function() { | |
d3Selection.event.preventDefault(); | |
d3Selection.event.stopImmediatePropagation(); | |
}; | |
var nodrag = function(view) { | |
var root = view.document.documentElement, | |
selection = d3Selection.select(view).on("dragstart.drag", noevent, true); | |
if ("onselectstart" in root) { | |
selection.on("selectstart.drag", noevent, true); | |
} else { | |
root.__noselect = root.style.MozUserSelect; | |
root.style.MozUserSelect = "none"; | |
} | |
}; | |
function yesdrag(view, noclick) { | |
var root = view.document.documentElement, | |
selection = d3Selection.select(view).on("dragstart.drag", null); | |
if (noclick) { | |
selection.on("click.drag", noevent, true); | |
setTimeout(function() { selection.on("click.drag", null); }, 0); | |
} | |
if ("onselectstart" in root) { | |
selection.on("selectstart.drag", null); | |
} else { | |
root.style.MozUserSelect = root.__noselect; | |
delete root.__noselect; | |
} | |
} | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch$$1) { | |
this.target = target; | |
this.type = type; | |
this.subject = subject; | |
this.identifier = id; | |
this.active = active; | |
this.x = x; | |
this.y = y; | |
this.dx = dx; | |
this.dy = dy; | |
this._ = dispatch$$1; | |
} | |
DragEvent.prototype.on = function() { | |
var value = this._.on.apply(this._, arguments); | |
return value === this._ ? this : value; | |
}; | |
// Ignore right-click, since that should open the context menu. | |
function defaultFilter() { | |
return !d3Selection.event.button; | |
} | |
function defaultContainer() { | |
return this.parentNode; | |
} | |
function defaultSubject(d) { | |
return d == null ? {x: d3Selection.event.x, y: d3Selection.event.y} : d; | |
} | |
function touchable() { | |
return "ontouchstart" in this; | |
} | |
var drag = function() { | |
var filter = defaultFilter, | |
container = defaultContainer, | |
subject = defaultSubject, | |
gestures = {}, | |
listeners = d3Dispatch.dispatch("start", "drag", "end"), | |
active = 0, | |
mousedownx, | |
mousedowny, | |
mousemoving, | |
touchending, | |
clickDistance2 = 0; | |
function drag(selection) { | |
selection | |
.on("mousedown.drag", mousedowned) | |
.filter(touchable) | |
.on("touchstart.drag", touchstarted) | |
.on("touchmove.drag", touchmoved) | |
.on("touchend.drag touchcancel.drag", touchended) | |
.style("touch-action", "none") | |
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); | |
} | |
function mousedowned() { | |
if (touchending || !filter.apply(this, arguments)) return; | |
var gesture = beforestart("mouse", container.apply(this, arguments), d3Selection.mouse, this, arguments); | |
if (!gesture) return; | |
d3Selection.select(d3Selection.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); | |
nodrag(d3Selection.event.view); | |
nopropagation(); | |
mousemoving = false; | |
mousedownx = d3Selection.event.clientX; | |
mousedowny = d3Selection.event.clientY; | |
gesture("start"); | |
} | |
function mousemoved() { | |
noevent(); | |
if (!mousemoving) { | |
var dx = d3Selection.event.clientX - mousedownx, dy = d3Selection.event.clientY - mousedowny; | |
mousemoving = dx * dx + dy * dy > clickDistance2; | |
} | |
gestures.mouse("drag"); | |
} | |
function mouseupped() { | |
d3Selection.select(d3Selection.event.view).on("mousemove.drag mouseup.drag", null); | |
yesdrag(d3Selection.event.view, mousemoving); | |
noevent(); | |
gestures.mouse("end"); | |
} | |
function touchstarted() { | |
if (!filter.apply(this, arguments)) return; | |
var touches = d3Selection.event.changedTouches, | |
c = container.apply(this, arguments), | |
n = touches.length, i, gesture; | |
for (i = 0; i < n; ++i) { | |
if (gesture = beforestart(touches[i].identifier, c, d3Selection.touch, this, arguments)) { | |
nopropagation(); | |
gesture("start"); | |
} | |
} | |
} | |
function touchmoved() { | |
var touches = d3Selection.event.changedTouches, | |
n = touches.length, i, gesture; | |
for (i = 0; i < n; ++i) { | |
if (gesture = gestures[touches[i].identifier]) { | |
noevent(); | |
gesture("drag"); | |
} | |
} | |
} | |
function touchended() { | |
var touches = d3Selection.event.changedTouches, | |
n = touches.length, i, gesture; | |
if (touchending) clearTimeout(touchending); | |
touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! | |
for (i = 0; i < n; ++i) { | |
if (gesture = gestures[touches[i].identifier]) { | |
nopropagation(); | |
gesture("end"); | |
} | |
} | |
} | |
function beforestart(id, container, point, that, args) { | |
var p = point(container, id), s, dx, dy, | |
sublisteners = listeners.copy(); | |
if (!d3Selection.customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { | |
if ((d3Selection.event.subject = s = subject.apply(that, args)) == null) return false; | |
dx = s.x - p[0] || 0; | |
dy = s.y - p[1] || 0; | |
return true; | |
})) return; | |
return function gesture(type) { | |
var p0 = p, n; | |
switch (type) { | |
case "start": gestures[id] = gesture, n = active++; break; | |
case "end": delete gestures[id], --active; // nobreak | |
case "drag": p = point(container, id), n = active; break; | |
} | |
d3Selection.customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); | |
}; | |
} | |
drag.filter = function(_) { | |
return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter; | |
}; | |
drag.container = function(_) { | |
return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container; | |
}; | |
drag.subject = function(_) { | |
return arguments.length ? (subject = typeof _ === "function" ? _ : constant(_), drag) : subject; | |
}; | |
drag.on = function() { | |
var value = listeners.on.apply(listeners, arguments); | |
return value === listeners ? drag : value; | |
}; | |
drag.clickDistance = function(_) { | |
return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); | |
}; | |
return drag; | |
}; | |
exports.drag = drag; | |
exports.dragDisable = nodrag; | |
exports.dragEnable = yesdrag; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-dispatch":21,"d3-selection":37}],23:[function(require,module,exports){ | |
// https://d3js.org/d3-dsv/ Version 1.0.7. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
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 csvParse = csv.parse; | |
var csvParseRows = csv.parseRows; | |
var csvFormat = csv.format; | |
var csvFormatRows = csv.formatRows; | |
var tsv = dsv("\t"); | |
var tsvParse = tsv.parse; | |
var tsvParseRows = tsv.parseRows; | |
var tsvFormat = tsv.format; | |
var tsvFormatRows = tsv.formatRows; | |
exports.dsvFormat = dsv; | |
exports.csvParse = csvParse; | |
exports.csvParseRows = csvParseRows; | |
exports.csvFormat = csvFormat; | |
exports.csvFormatRows = csvFormatRows; | |
exports.tsvParse = tsvParse; | |
exports.tsvParseRows = tsvParseRows; | |
exports.tsvFormat = tsvFormat; | |
exports.tsvFormatRows = tsvFormatRows; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],24:[function(require,module,exports){ | |
// https://d3js.org/d3-ease/ Version 1.0.3. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
function linear(t) { | |
return +t; | |
} | |
function quadIn(t) { | |
return t * t; | |
} | |
function quadOut(t) { | |
return t * (2 - t); | |
} | |
function quadInOut(t) { | |
return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; | |
} | |
function cubicIn(t) { | |
return t * t * t; | |
} | |
function cubicOut(t) { | |
return --t * t * t + 1; | |
} | |
function cubicInOut(t) { | |
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; | |
} | |
var exponent = 3; | |
var polyIn = (function custom(e) { | |
e = +e; | |
function polyIn(t) { | |
return Math.pow(t, e); | |
} | |
polyIn.exponent = custom; | |
return polyIn; | |
})(exponent); | |
var polyOut = (function custom(e) { | |
e = +e; | |
function polyOut(t) { | |
return 1 - Math.pow(1 - t, e); | |
} | |
polyOut.exponent = custom; | |
return polyOut; | |
})(exponent); | |
var polyInOut = (function custom(e) { | |
e = +e; | |
function polyInOut(t) { | |
return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; | |
} | |
polyInOut.exponent = custom; | |
return polyInOut; | |
})(exponent); | |
var pi = Math.PI; | |
var halfPi = pi / 2; | |
function sinIn(t) { | |
return 1 - Math.cos(t * halfPi); | |
} | |
function sinOut(t) { | |
return Math.sin(t * halfPi); | |
} | |
function sinInOut(t) { | |
return (1 - Math.cos(pi * t)) / 2; | |
} | |
function expIn(t) { | |
return Math.pow(2, 10 * t - 10); | |
} | |
function expOut(t) { | |
return 1 - Math.pow(2, -10 * t); | |
} | |
function expInOut(t) { | |
return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; | |
} | |
function circleIn(t) { | |
return 1 - Math.sqrt(1 - t * t); | |
} | |
function circleOut(t) { | |
return Math.sqrt(1 - --t * t); | |
} | |
function circleInOut(t) { | |
return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; | |
} | |
var b1 = 4 / 11; | |
var b2 = 6 / 11; | |
var b3 = 8 / 11; | |
var b4 = 3 / 4; | |
var b5 = 9 / 11; | |
var b6 = 10 / 11; | |
var b7 = 15 / 16; | |
var b8 = 21 / 22; | |
var b9 = 63 / 64; | |
var b0 = 1 / b1 / b1; | |
function bounceIn(t) { | |
return 1 - bounceOut(1 - t); | |
} | |
function bounceOut(t) { | |
return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; | |
} | |
function bounceInOut(t) { | |
return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; | |
} | |
var overshoot = 1.70158; | |
var backIn = (function custom(s) { | |
s = +s; | |
function backIn(t) { | |
return t * t * ((s + 1) * t - s); | |
} | |
backIn.overshoot = custom; | |
return backIn; | |
})(overshoot); | |
var backOut = (function custom(s) { | |
s = +s; | |
function backOut(t) { | |
return --t * t * ((s + 1) * t + s) + 1; | |
} | |
backOut.overshoot = custom; | |
return backOut; | |
})(overshoot); | |
var backInOut = (function custom(s) { | |
s = +s; | |
function backInOut(t) { | |
return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; | |
} | |
backInOut.overshoot = custom; | |
return backInOut; | |
})(overshoot); | |
var tau = 2 * Math.PI; | |
var amplitude = 1; | |
var period = 0.3; | |
var elasticIn = (function custom(a, p) { | |
var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); | |
function elasticIn(t) { | |
return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); | |
} | |
elasticIn.amplitude = function(a) { return custom(a, p * tau); }; | |
elasticIn.period = function(p) { return custom(a, p); }; | |
return elasticIn; | |
})(amplitude, period); | |
var elasticOut = (function custom(a, p) { | |
var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); | |
function elasticOut(t) { | |
return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); | |
} | |
elasticOut.amplitude = function(a) { return custom(a, p * tau); }; | |
elasticOut.period = function(p) { return custom(a, p); }; | |
return elasticOut; | |
})(amplitude, period); | |
var elasticInOut = (function custom(a, p) { | |
var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); | |
function elasticInOut(t) { | |
return ((t = t * 2 - 1) < 0 | |
? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) | |
: 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; | |
} | |
elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; | |
elasticInOut.period = function(p) { return custom(a, p); }; | |
return elasticInOut; | |
})(amplitude, period); | |
exports.easeLinear = linear; | |
exports.easeQuad = quadInOut; | |
exports.easeQuadIn = quadIn; | |
exports.easeQuadOut = quadOut; | |
exports.easeQuadInOut = quadInOut; | |
exports.easeCubic = cubicInOut; | |
exports.easeCubicIn = cubicIn; | |
exports.easeCubicOut = cubicOut; | |
exports.easeCubicInOut = cubicInOut; | |
exports.easePoly = polyInOut; | |
exports.easePolyIn = polyIn; | |
exports.easePolyOut = polyOut; | |
exports.easePolyInOut = polyInOut; | |
exports.easeSin = sinInOut; | |
exports.easeSinIn = sinIn; | |
exports.easeSinOut = sinOut; | |
exports.easeSinInOut = sinInOut; | |
exports.easeExp = expInOut; | |
exports.easeExpIn = expIn; | |
exports.easeExpOut = expOut; | |
exports.easeExpInOut = expInOut; | |
exports.easeCircle = circleInOut; | |
exports.easeCircleIn = circleIn; | |
exports.easeCircleOut = circleOut; | |
exports.easeCircleInOut = circleInOut; | |
exports.easeBounce = bounceOut; | |
exports.easeBounceIn = bounceIn; | |
exports.easeBounceOut = bounceOut; | |
exports.easeBounceInOut = bounceInOut; | |
exports.easeBack = backInOut; | |
exports.easeBackIn = backIn; | |
exports.easeBackOut = backOut; | |
exports.easeBackInOut = backInOut; | |
exports.easeElastic = elasticOut; | |
exports.easeElasticIn = elasticIn; | |
exports.easeElasticOut = elasticOut; | |
exports.easeElasticInOut = elasticInOut; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],25:[function(require,module,exports){ | |
// https://d3js.org/d3-force/ Version 1.0.6. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-quadtree'), require('d3-collection'), require('d3-dispatch'), require('d3-timer')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-quadtree', 'd3-collection', 'd3-dispatch', 'd3-timer'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3)); | |
}(this, (function (exports,d3Quadtree,d3Collection,d3Dispatch,d3Timer) { 'use strict'; | |
var center = function(x, y) { | |
var nodes; | |
if (x == null) x = 0; | |
if (y == null) y = 0; | |
function force() { | |
var i, | |
n = nodes.length, | |
node, | |
sx = 0, | |
sy = 0; | |
for (i = 0; i < n; ++i) { | |
node = nodes[i], sx += node.x, sy += node.y; | |
} | |
for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { | |
node = nodes[i], node.x -= sx, node.y -= sy; | |
} | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
}; | |
force.x = function(_) { | |
return arguments.length ? (x = +_, force) : x; | |
}; | |
force.y = function(_) { | |
return arguments.length ? (y = +_, force) : y; | |
}; | |
return force; | |
}; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var jiggle = function() { | |
return (Math.random() - 0.5) * 1e-6; | |
}; | |
function x(d) { | |
return d.x + d.vx; | |
} | |
function y(d) { | |
return d.y + d.vy; | |
} | |
var collide = function(radius) { | |
var nodes, | |
radii, | |
strength = 1, | |
iterations = 1; | |
if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius); | |
function force() { | |
var i, n = nodes.length, | |
tree, | |
node, | |
xi, | |
yi, | |
ri, | |
ri2; | |
for (var k = 0; k < iterations; ++k) { | |
tree = d3Quadtree.quadtree(nodes, x, y).visitAfter(prepare); | |
for (i = 0; i < n; ++i) { | |
node = nodes[i]; | |
ri = radii[node.index], ri2 = ri * ri; | |
xi = node.x + node.vx; | |
yi = node.y + node.vy; | |
tree.visit(apply); | |
} | |
} | |
function apply(quad, x0, y0, x1, y1) { | |
var data = quad.data, rj = quad.r, r = ri + rj; | |
if (data) { | |
if (data.index > node.index) { | |
var x = xi - data.x - data.vx, | |
y = yi - data.y - data.vy, | |
l = x * x + y * y; | |
if (l < r * r) { | |
if (x === 0) x = jiggle(), l += x * x; | |
if (y === 0) y = jiggle(), l += y * y; | |
l = (r - (l = Math.sqrt(l))) / l * strength; | |
node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); | |
node.vy += (y *= l) * r; | |
data.vx -= x * (r = 1 - r); | |
data.vy -= y * r; | |
} | |
} | |
return; | |
} | |
return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; | |
} | |
} | |
function prepare(quad) { | |
if (quad.data) return quad.r = radii[quad.data.index]; | |
for (var i = quad.r = 0; i < 4; ++i) { | |
if (quad[i] && quad[i].r > quad.r) { | |
quad.r = quad[i].r; | |
} | |
} | |
} | |
function initialize() { | |
if (!nodes) return; | |
var i, n = nodes.length, node; | |
radii = new Array(n); | |
for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
initialize(); | |
}; | |
force.iterations = function(_) { | |
return arguments.length ? (iterations = +_, force) : iterations; | |
}; | |
force.strength = function(_) { | |
return arguments.length ? (strength = +_, force) : strength; | |
}; | |
force.radius = function(_) { | |
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; | |
}; | |
return force; | |
}; | |
function index(d) { | |
return d.index; | |
} | |
function find(nodeById, nodeId) { | |
var node = nodeById.get(nodeId); | |
if (!node) throw new Error("missing: " + nodeId); | |
return node; | |
} | |
var link = function(links) { | |
var id = index, | |
strength = defaultStrength, | |
strengths, | |
distance = constant(30), | |
distances, | |
nodes, | |
count, | |
bias, | |
iterations = 1; | |
if (links == null) links = []; | |
function defaultStrength(link) { | |
return 1 / Math.min(count[link.source.index], count[link.target.index]); | |
} | |
function force(alpha) { | |
for (var k = 0, n = links.length; k < iterations; ++k) { | |
for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { | |
link = links[i], source = link.source, target = link.target; | |
x = target.x + target.vx - source.x - source.vx || jiggle(); | |
y = target.y + target.vy - source.y - source.vy || jiggle(); | |
l = Math.sqrt(x * x + y * y); | |
l = (l - distances[i]) / l * alpha * strengths[i]; | |
x *= l, y *= l; | |
target.vx -= x * (b = bias[i]); | |
target.vy -= y * b; | |
source.vx += x * (b = 1 - b); | |
source.vy += y * b; | |
} | |
} | |
} | |
function initialize() { | |
if (!nodes) return; | |
var i, | |
n = nodes.length, | |
m = links.length, | |
nodeById = d3Collection.map(nodes, id), | |
link; | |
for (i = 0, count = new Array(n); i < m; ++i) { | |
link = links[i], link.index = i; | |
if (typeof link.source !== "object") link.source = find(nodeById, link.source); | |
if (typeof link.target !== "object") link.target = find(nodeById, link.target); | |
count[link.source.index] = (count[link.source.index] || 0) + 1; | |
count[link.target.index] = (count[link.target.index] || 0) + 1; | |
} | |
for (i = 0, bias = new Array(m); i < m; ++i) { | |
link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); | |
} | |
strengths = new Array(m), initializeStrength(); | |
distances = new Array(m), initializeDistance(); | |
} | |
function initializeStrength() { | |
if (!nodes) return; | |
for (var i = 0, n = links.length; i < n; ++i) { | |
strengths[i] = +strength(links[i], i, links); | |
} | |
} | |
function initializeDistance() { | |
if (!nodes) return; | |
for (var i = 0, n = links.length; i < n; ++i) { | |
distances[i] = +distance(links[i], i, links); | |
} | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
initialize(); | |
}; | |
force.links = function(_) { | |
return arguments.length ? (links = _, initialize(), force) : links; | |
}; | |
force.id = function(_) { | |
return arguments.length ? (id = _, force) : id; | |
}; | |
force.iterations = function(_) { | |
return arguments.length ? (iterations = +_, force) : iterations; | |
}; | |
force.strength = function(_) { | |
return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; | |
}; | |
force.distance = function(_) { | |
return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; | |
}; | |
return force; | |
}; | |
function x$1(d) { | |
return d.x; | |
} | |
function y$1(d) { | |
return d.y; | |
} | |
var initialRadius = 10; | |
var initialAngle = Math.PI * (3 - Math.sqrt(5)); | |
var simulation = function(nodes) { | |
var simulation, | |
alpha = 1, | |
alphaMin = 0.001, | |
alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), | |
alphaTarget = 0, | |
velocityDecay = 0.6, | |
forces = d3Collection.map(), | |
stepper = d3Timer.timer(step), | |
event = d3Dispatch.dispatch("tick", "end"); | |
if (nodes == null) nodes = []; | |
function step() { | |
tick(); | |
event.call("tick", simulation); | |
if (alpha < alphaMin) { | |
stepper.stop(); | |
event.call("end", simulation); | |
} | |
} | |
function tick() { | |
var i, n = nodes.length, node; | |
alpha += (alphaTarget - alpha) * alphaDecay; | |
forces.each(function(force) { | |
force(alpha); | |
}); | |
for (i = 0; i < n; ++i) { | |
node = nodes[i]; | |
if (node.fx == null) node.x += node.vx *= velocityDecay; | |
else node.x = node.fx, node.vx = 0; | |
if (node.fy == null) node.y += node.vy *= velocityDecay; | |
else node.y = node.fy, node.vy = 0; | |
} | |
} | |
function initializeNodes() { | |
for (var i = 0, n = nodes.length, node; i < n; ++i) { | |
node = nodes[i], node.index = i; | |
if (isNaN(node.x) || isNaN(node.y)) { | |
var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; | |
node.x = radius * Math.cos(angle); | |
node.y = radius * Math.sin(angle); | |
} | |
if (isNaN(node.vx) || isNaN(node.vy)) { | |
node.vx = node.vy = 0; | |
} | |
} | |
} | |
function initializeForce(force) { | |
if (force.initialize) force.initialize(nodes); | |
return force; | |
} | |
initializeNodes(); | |
return simulation = { | |
tick: tick, | |
restart: function() { | |
return stepper.restart(step), simulation; | |
}, | |
stop: function() { | |
return stepper.stop(), simulation; | |
}, | |
nodes: function(_) { | |
return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; | |
}, | |
alpha: function(_) { | |
return arguments.length ? (alpha = +_, simulation) : alpha; | |
}, | |
alphaMin: function(_) { | |
return arguments.length ? (alphaMin = +_, simulation) : alphaMin; | |
}, | |
alphaDecay: function(_) { | |
return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; | |
}, | |
alphaTarget: function(_) { | |
return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; | |
}, | |
velocityDecay: function(_) { | |
return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; | |
}, | |
force: function(name, _) { | |
return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); | |
}, | |
find: function(x, y, radius) { | |
var i = 0, | |
n = nodes.length, | |
dx, | |
dy, | |
d2, | |
node, | |
closest; | |
if (radius == null) radius = Infinity; | |
else radius *= radius; | |
for (i = 0; i < n; ++i) { | |
node = nodes[i]; | |
dx = x - node.x; | |
dy = y - node.y; | |
d2 = dx * dx + dy * dy; | |
if (d2 < radius) closest = node, radius = d2; | |
} | |
return closest; | |
}, | |
on: function(name, _) { | |
return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); | |
} | |
}; | |
}; | |
var manyBody = function() { | |
var nodes, | |
node, | |
alpha, | |
strength = constant(-30), | |
strengths, | |
distanceMin2 = 1, | |
distanceMax2 = Infinity, | |
theta2 = 0.81; | |
function force(_) { | |
var i, n = nodes.length, tree = d3Quadtree.quadtree(nodes, x$1, y$1).visitAfter(accumulate); | |
for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); | |
} | |
function initialize() { | |
if (!nodes) return; | |
var i, n = nodes.length, node; | |
strengths = new Array(n); | |
for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); | |
} | |
function accumulate(quad) { | |
var strength = 0, q, c, x$$1, y$$1, i; | |
// For internal nodes, accumulate forces from child quadrants. | |
if (quad.length) { | |
for (x$$1 = y$$1 = i = 0; i < 4; ++i) { | |
if ((q = quad[i]) && (c = q.value)) { | |
strength += c, x$$1 += c * q.x, y$$1 += c * q.y; | |
} | |
} | |
quad.x = x$$1 / strength; | |
quad.y = y$$1 / strength; | |
} | |
// For leaf nodes, accumulate forces from coincident quadrants. | |
else { | |
q = quad; | |
q.x = q.data.x; | |
q.y = q.data.y; | |
do strength += strengths[q.data.index]; | |
while (q = q.next); | |
} | |
quad.value = strength; | |
} | |
function apply(quad, x1, _, x2) { | |
if (!quad.value) return true; | |
var x$$1 = quad.x - node.x, | |
y$$1 = quad.y - node.y, | |
w = x2 - x1, | |
l = x$$1 * x$$1 + y$$1 * y$$1; | |
// Apply the Barnes-Hut approximation if possible. | |
// Limit forces for very close nodes; randomize direction if coincident. | |
if (w * w / theta2 < l) { | |
if (l < distanceMax2) { | |
if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; | |
if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; | |
if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); | |
node.vx += x$$1 * quad.value * alpha / l; | |
node.vy += y$$1 * quad.value * alpha / l; | |
} | |
return true; | |
} | |
// Otherwise, process points directly. | |
else if (quad.length || l >= distanceMax2) return; | |
// Limit forces for very close nodes; randomize direction if coincident. | |
if (quad.data !== node || quad.next) { | |
if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1; | |
if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1; | |
if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); | |
} | |
do if (quad.data !== node) { | |
w = strengths[quad.data.index] * alpha / l; | |
node.vx += x$$1 * w; | |
node.vy += y$$1 * w; | |
} while (quad = quad.next); | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
initialize(); | |
}; | |
force.strength = function(_) { | |
return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; | |
}; | |
force.distanceMin = function(_) { | |
return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); | |
}; | |
force.distanceMax = function(_) { | |
return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); | |
}; | |
force.theta = function(_) { | |
return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); | |
}; | |
return force; | |
}; | |
var x$2 = function(x) { | |
var strength = constant(0.1), | |
nodes, | |
strengths, | |
xz; | |
if (typeof x !== "function") x = constant(x == null ? 0 : +x); | |
function force(alpha) { | |
for (var i = 0, n = nodes.length, node; i < n; ++i) { | |
node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; | |
} | |
} | |
function initialize() { | |
if (!nodes) return; | |
var i, n = nodes.length; | |
strengths = new Array(n); | |
xz = new Array(n); | |
for (i = 0; i < n; ++i) { | |
strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); | |
} | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
initialize(); | |
}; | |
force.strength = function(_) { | |
return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; | |
}; | |
force.x = function(_) { | |
return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x; | |
}; | |
return force; | |
}; | |
var y$2 = function(y) { | |
var strength = constant(0.1), | |
nodes, | |
strengths, | |
yz; | |
if (typeof y !== "function") y = constant(y == null ? 0 : +y); | |
function force(alpha) { | |
for (var i = 0, n = nodes.length, node; i < n; ++i) { | |
node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; | |
} | |
} | |
function initialize() { | |
if (!nodes) return; | |
var i, n = nodes.length; | |
strengths = new Array(n); | |
yz = new Array(n); | |
for (i = 0; i < n; ++i) { | |
strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); | |
} | |
} | |
force.initialize = function(_) { | |
nodes = _; | |
initialize(); | |
}; | |
force.strength = function(_) { | |
return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; | |
}; | |
force.y = function(_) { | |
return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y; | |
}; | |
return force; | |
}; | |
exports.forceCenter = center; | |
exports.forceCollide = collide; | |
exports.forceLink = link; | |
exports.forceManyBody = manyBody; | |
exports.forceSimulation = simulation; | |
exports.forceX = x$2; | |
exports.forceY = y$2; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-collection":19,"d3-dispatch":21,"d3-quadtree":32,"d3-timer":41}],26:[function(require,module,exports){ | |
// https://d3js.org/d3-format/ Version 1.2.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
// 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 = 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 n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { | |
switch (x[i]) { | |
case ".": i0 = i1 = i; break; | |
case "0": if (i0 === 0) i0 = i; i1 = i; break; | |
case "e": break out; | |
default: if (i0 > 0) i0 = 0; break; | |
} | |
} | |
return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; | |
}; | |
var prefixExponent; | |
var formatPrefixAuto = function(x, p) { | |
var d = formatDecimal(x, p); | |
if (!d) return x + ""; | |
var coefficient = d[0], | |
exponent = d[1], | |
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, | |
n = coefficient.length; | |
return i === n ? coefficient | |
: i > n ? coefficient + new Array(i - n + 1).join("0") | |
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) | |
: "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! | |
}; | |
var formatRounded = function(x, p) { | |
var d = formatDecimal(x, p); | |
if (!d) return x + ""; | |
var coefficient = d[0], | |
exponent = d[1]; | |
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient | |
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) | |
: coefficient + new Array(exponent - coefficient.length + 2).join("0"); | |
}; | |
var formatTypes = { | |
"": formatDefault, | |
"%": function(x, p) { return (x * 100).toFixed(p); }, | |
"b": function(x) { return Math.round(x).toString(2); }, | |
"c": function(x) { return x + ""; }, | |
"d": function(x) { return Math.round(x).toString(10); }, | |
"e": function(x, p) { return x.toExponential(p); }, | |
"f": function(x, p) { return x.toFixed(p); }, | |
"g": function(x, p) { return x.toPrecision(p); }, | |
"o": function(x) { return Math.round(x).toString(8); }, | |
"p": function(x, p) { return formatRounded(x * 100, p); }, | |
"r": formatRounded, | |
"s": formatPrefixAuto, | |
"X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, | |
"x": function(x) { return Math.round(x).toString(16); } | |
}; | |
// [[fill]align][sign][symbol][0][width][,][.precision][type] | |
var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; | |
function formatSpecifier(specifier) { | |
return new FormatSpecifier(specifier); | |
} | |
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof | |
function FormatSpecifier(specifier) { | |
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); | |
var match, | |
fill = match[1] || " ", | |
align = match[2] || ">", | |
sign = match[3] || "-", | |
symbol = match[4] || "", | |
zero = !!match[5], | |
width = match[6] && +match[6], | |
comma = !!match[7], | |
precision = match[8] && +match[8].slice(1), | |
type = match[9] || ""; | |
// The "n" type is an alias for ",g". | |
if (type === "n") comma = true, type = "g"; | |
// Map invalid types to the default format. | |
else if (!formatTypes[type]) type = ""; | |
// If zero fill is specified, padding goes after sign and before digits. | |
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; | |
this.fill = fill; | |
this.align = align; | |
this.sign = sign; | |
this.symbol = symbol; | |
this.zero = zero; | |
this.width = width; | |
this.comma = comma; | |
this.precision = precision; | |
this.type = type; | |
} | |
FormatSpecifier.prototype.toString = function() { | |
return this.fill | |
+ this.align | |
+ this.sign | |
+ this.symbol | |
+ (this.zero ? "0" : "") | |
+ (this.width == null ? "" : Math.max(1, this.width | 0)) | |
+ (this.comma ? "," : "") | |
+ (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) | |
+ this.type; | |
}; | |
var identity = function(x) { | |
return x; | |
}; | |
var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; | |
var formatLocale = function(locale) { | |
var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity, | |
currency = locale.currency, | |
decimal = locale.decimal, | |
numerals = locale.numerals ? formatNumerals(locale.numerals) : identity, | |
percent = locale.percent || "%"; | |
function newFormat(specifier) { | |
specifier = formatSpecifier(specifier); | |
var fill = specifier.fill, | |
align = specifier.align, | |
sign = specifier.sign, | |
symbol = specifier.symbol, | |
zero = specifier.zero, | |
width = specifier.width, | |
comma = specifier.comma, | |
precision = specifier.precision, | |
type = specifier.type; | |
// Compute the prefix and suffix. | |
// For SI-prefix, the suffix is lazily computed. | |
var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", | |
suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; | |
// What format function should we use? | |
// Is this an integer type? | |
// Can this type generate exponential notation? | |
var formatType = formatTypes[type], | |
maybeSuffix = !type || /[defgprs%]/.test(type); | |
// Set the default precision if not specified, | |
// or clamp the specified precision to the supported range. | |
// For significant precision, it must be in [1, 21]. | |
// For fixed precision, it must be in [0, 20]. | |
precision = precision == null ? (type ? 6 : 12) | |
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) | |
: Math.max(0, Math.min(20, precision)); | |
function format(value) { | |
var valuePrefix = prefix, | |
valueSuffix = suffix, | |
i, n, c; | |
if (type === "c") { | |
valueSuffix = formatType(value) + valueSuffix; | |
value = ""; | |
} else { | |
value = +value; | |
// Perform the initial formatting. | |
var valueNegative = value < 0; | |
value = formatType(Math.abs(value), precision); | |
// If a negative value rounds to zero during formatting, treat as positive. | |
if (valueNegative && +value === 0) valueNegative = false; | |
// Compute the prefix and suffix. | |
valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; | |
valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); | |
// Break the formatted value into the integer “value” part that can be | |
// grouped, and fractional or exponential “suffix” part that is not. | |
if (maybeSuffix) { | |
i = -1, n = value.length; | |
while (++i < n) { | |
if (c = value.charCodeAt(i), 48 > c || c > 57) { | |
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; | |
value = value.slice(0, i); | |
break; | |
} | |
} | |
} | |
} | |
// If the fill character is not "0", grouping is applied before padding. | |
if (comma && !zero) value = group(value, Infinity); | |
// Compute the padding. | |
var length = valuePrefix.length + value.length + valueSuffix.length, | |
padding = length < width ? new Array(width - length + 1).join(fill) : ""; | |
// If the fill character is "0", grouping is applied after padding. | |
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; | |
// Reconstruct the final output based on the desired alignment. | |
switch (align) { | |
case "<": value = valuePrefix + value + valueSuffix + padding; break; | |
case "=": value = valuePrefix + padding + value + valueSuffix; break; | |
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; | |
default: value = padding + valuePrefix + value + valueSuffix; break; | |
} | |
return numerals(value); | |
} | |
format.toString = function() { | |
return specifier + ""; | |
}; | |
return format; | |
} | |
function formatPrefix(specifier, value) { | |
var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), | |
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, | |
k = Math.pow(10, -e), | |
prefix = prefixes[8 + e / 3]; | |
return function(value) { | |
return f(k * value) + prefix; | |
}; | |
} | |
return { | |
format: newFormat, | |
formatPrefix: formatPrefix | |
}; | |
}; | |
var locale; | |
defaultLocale({ | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["$", ""] | |
}); | |
function defaultLocale(definition) { | |
locale = formatLocale(definition); | |
exports.format = locale.format; | |
exports.formatPrefix = locale.formatPrefix; | |
return locale; | |
} | |
var precisionFixed = function(step) { | |
return Math.max(0, -exponent(Math.abs(step))); | |
}; | |
var precisionPrefix = function(step, value) { | |
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); | |
}; | |
var precisionRound = function(step, max) { | |
step = Math.abs(step), max = Math.abs(max) - step; | |
return Math.max(0, exponent(max) - exponent(step)) + 1; | |
}; | |
exports.formatDefaultLocale = defaultLocale; | |
exports.formatLocale = formatLocale; | |
exports.formatSpecifier = formatSpecifier; | |
exports.precisionFixed = precisionFixed; | |
exports.precisionPrefix = precisionPrefix; | |
exports.precisionRound = precisionRound; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],27:[function(require,module,exports){ | |
// https://d3js.org/d3-geo/ Version 1.6.4. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3)); | |
}(this, (function (exports,d3Array) { 'use strict'; | |
// Adds floating point numbers with twice the normal precision. | |
// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and | |
// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) | |
// 305–363 (1997). | |
// Code adapted from GeographicLib by Charles F. F. Karney, | |
// http://geographiclib.sourceforge.net/ | |
var adder = function() { | |
return new Adder; | |
}; | |
function Adder() { | |
this.reset(); | |
} | |
Adder.prototype = { | |
constructor: Adder, | |
reset: function() { | |
this.s = // rounded value | |
this.t = 0; // exact error | |
}, | |
add: function(y) { | |
add(temp, y, this.t); | |
add(this, temp.s, this.s); | |
if (this.s) this.t += temp.t; | |
else this.s = temp.t; | |
}, | |
valueOf: function() { | |
return this.s; | |
} | |
}; | |
var temp = new Adder; | |
function add(adder, a, b) { | |
var x = adder.s = a + b, | |
bv = x - a, | |
av = x - bv; | |
adder.t = (a - av) + (b - bv); | |
} | |
var epsilon = 1e-6; | |
var epsilon2 = 1e-12; | |
var pi = Math.PI; | |
var halfPi = pi / 2; | |
var quarterPi = pi / 4; | |
var tau = pi * 2; | |
var degrees = 180 / pi; | |
var radians = pi / 180; | |
var abs = Math.abs; | |
var atan = Math.atan; | |
var atan2 = Math.atan2; | |
var cos = Math.cos; | |
var ceil = Math.ceil; | |
var exp = Math.exp; | |
var log = Math.log; | |
var pow = Math.pow; | |
var sin = Math.sin; | |
var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; | |
var sqrt = Math.sqrt; | |
var tan = Math.tan; | |
function acos(x) { | |
return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); | |
} | |
function asin(x) { | |
return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x); | |
} | |
function haversin(x) { | |
return (x = sin(x / 2)) * x; | |
} | |
function noop() {} | |
function streamGeometry(geometry, stream) { | |
if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { | |
streamGeometryType[geometry.type](geometry, stream); | |
} | |
} | |
var streamObjectType = { | |
Feature: function(object, stream) { | |
streamGeometry(object.geometry, stream); | |
}, | |
FeatureCollection: function(object, stream) { | |
var features = object.features, i = -1, n = features.length; | |
while (++i < n) streamGeometry(features[i].geometry, stream); | |
} | |
}; | |
var streamGeometryType = { | |
Sphere: function(object, stream) { | |
stream.sphere(); | |
}, | |
Point: function(object, stream) { | |
object = object.coordinates; | |
stream.point(object[0], object[1], object[2]); | |
}, | |
MultiPoint: function(object, stream) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); | |
}, | |
LineString: function(object, stream) { | |
streamLine(object.coordinates, stream, 0); | |
}, | |
MultiLineString: function(object, stream) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) streamLine(coordinates[i], stream, 0); | |
}, | |
Polygon: function(object, stream) { | |
streamPolygon(object.coordinates, stream); | |
}, | |
MultiPolygon: function(object, stream) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) streamPolygon(coordinates[i], stream); | |
}, | |
GeometryCollection: function(object, stream) { | |
var geometries = object.geometries, i = -1, n = geometries.length; | |
while (++i < n) streamGeometry(geometries[i], stream); | |
} | |
}; | |
function streamLine(coordinates, stream, closed) { | |
var i = -1, n = coordinates.length - closed, coordinate; | |
stream.lineStart(); | |
while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); | |
stream.lineEnd(); | |
} | |
function streamPolygon(coordinates, stream) { | |
var i = -1, n = coordinates.length; | |
stream.polygonStart(); | |
while (++i < n) streamLine(coordinates[i], stream, 1); | |
stream.polygonEnd(); | |
} | |
var geoStream = function(object, stream) { | |
if (object && streamObjectType.hasOwnProperty(object.type)) { | |
streamObjectType[object.type](object, stream); | |
} else { | |
streamGeometry(object, stream); | |
} | |
}; | |
var areaRingSum = adder(); | |
var areaSum = adder(); | |
var lambda00; | |
var phi00; | |
var lambda0; | |
var cosPhi0; | |
var sinPhi0; | |
var areaStream = { | |
point: noop, | |
lineStart: noop, | |
lineEnd: noop, | |
polygonStart: function() { | |
areaRingSum.reset(); | |
areaStream.lineStart = areaRingStart; | |
areaStream.lineEnd = areaRingEnd; | |
}, | |
polygonEnd: function() { | |
var areaRing = +areaRingSum; | |
areaSum.add(areaRing < 0 ? tau + areaRing : areaRing); | |
this.lineStart = this.lineEnd = this.point = noop; | |
}, | |
sphere: function() { | |
areaSum.add(tau); | |
} | |
}; | |
function areaRingStart() { | |
areaStream.point = areaPointFirst; | |
} | |
function areaRingEnd() { | |
areaPoint(lambda00, phi00); | |
} | |
function areaPointFirst(lambda, phi) { | |
areaStream.point = areaPoint; | |
lambda00 = lambda, phi00 = phi; | |
lambda *= radians, phi *= radians; | |
lambda0 = lambda, cosPhi0 = cos(phi = phi / 2 + quarterPi), sinPhi0 = sin(phi); | |
} | |
function areaPoint(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
phi = phi / 2 + quarterPi; // half the angular distance from south pole | |
// Spherical excess E for a spherical triangle with vertices: south pole, | |
// previous point, current point. Uses a formula derived from Cagnoli’s | |
// theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). | |
var dLambda = lambda - lambda0, | |
sdLambda = dLambda >= 0 ? 1 : -1, | |
adLambda = sdLambda * dLambda, | |
cosPhi = cos(phi), | |
sinPhi = sin(phi), | |
k = sinPhi0 * sinPhi, | |
u = cosPhi0 * cosPhi + k * cos(adLambda), | |
v = k * sdLambda * sin(adLambda); | |
areaRingSum.add(atan2(v, u)); | |
// Advance the previous points. | |
lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; | |
} | |
var area = function(object) { | |
areaSum.reset(); | |
geoStream(object, areaStream); | |
return areaSum * 2; | |
}; | |
function spherical(cartesian) { | |
return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; | |
} | |
function cartesian(spherical) { | |
var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi); | |
return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)]; | |
} | |
function cartesianDot(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
} | |
function cartesianCross(a, b) { | |
return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; | |
} | |
// TODO return a | |
function cartesianAddInPlace(a, b) { | |
a[0] += b[0], a[1] += b[1], a[2] += b[2]; | |
} | |
function cartesianScale(vector, k) { | |
return [vector[0] * k, vector[1] * k, vector[2] * k]; | |
} | |
// TODO return d | |
function cartesianNormalizeInPlace(d) { | |
var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); | |
d[0] /= l, d[1] /= l, d[2] /= l; | |
} | |
var lambda0$1; | |
var phi0; | |
var lambda1; | |
var phi1; | |
var lambda2; | |
var lambda00$1; | |
var phi00$1; | |
var p0; | |
var deltaSum = adder(); | |
var ranges; | |
var range$1; | |
var boundsStream = { | |
point: boundsPoint, | |
lineStart: boundsLineStart, | |
lineEnd: boundsLineEnd, | |
polygonStart: function() { | |
boundsStream.point = boundsRingPoint; | |
boundsStream.lineStart = boundsRingStart; | |
boundsStream.lineEnd = boundsRingEnd; | |
deltaSum.reset(); | |
areaStream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
areaStream.polygonEnd(); | |
boundsStream.point = boundsPoint; | |
boundsStream.lineStart = boundsLineStart; | |
boundsStream.lineEnd = boundsLineEnd; | |
if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); | |
else if (deltaSum > epsilon) phi1 = 90; | |
else if (deltaSum < -epsilon) phi0 = -90; | |
range$1[0] = lambda0$1, range$1[1] = lambda1; | |
} | |
}; | |
function boundsPoint(lambda, phi) { | |
ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); | |
if (phi < phi0) phi0 = phi; | |
if (phi > phi1) phi1 = phi; | |
} | |
function linePoint(lambda, phi) { | |
var p = cartesian([lambda * radians, phi * radians]); | |
if (p0) { | |
var normal = cartesianCross(p0, p), | |
equatorial = [normal[1], -normal[0], 0], | |
inflection = cartesianCross(equatorial, normal); | |
cartesianNormalizeInPlace(inflection); | |
inflection = spherical(inflection); | |
var delta = lambda - lambda2, | |
sign$$1 = delta > 0 ? 1 : -1, | |
lambdai = inflection[0] * degrees * sign$$1, | |
phii, | |
antimeridian = abs(delta) > 180; | |
if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { | |
phii = inflection[1] * degrees; | |
if (phii > phi1) phi1 = phii; | |
} else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { | |
phii = -inflection[1] * degrees; | |
if (phii < phi0) phi0 = phii; | |
} else { | |
if (phi < phi0) phi0 = phi; | |
if (phi > phi1) phi1 = phi; | |
} | |
if (antimeridian) { | |
if (lambda < lambda2) { | |
if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; | |
} else { | |
if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; | |
} | |
} else { | |
if (lambda1 >= lambda0$1) { | |
if (lambda < lambda0$1) lambda0$1 = lambda; | |
if (lambda > lambda1) lambda1 = lambda; | |
} else { | |
if (lambda > lambda2) { | |
if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; | |
} else { | |
if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; | |
} | |
} | |
} | |
} else { | |
ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); | |
} | |
if (phi < phi0) phi0 = phi; | |
if (phi > phi1) phi1 = phi; | |
p0 = p, lambda2 = lambda; | |
} | |
function boundsLineStart() { | |
boundsStream.point = linePoint; | |
} | |
function boundsLineEnd() { | |
range$1[0] = lambda0$1, range$1[1] = lambda1; | |
boundsStream.point = boundsPoint; | |
p0 = null; | |
} | |
function boundsRingPoint(lambda, phi) { | |
if (p0) { | |
var delta = lambda - lambda2; | |
deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); | |
} else { | |
lambda00$1 = lambda, phi00$1 = phi; | |
} | |
areaStream.point(lambda, phi); | |
linePoint(lambda, phi); | |
} | |
function boundsRingStart() { | |
areaStream.lineStart(); | |
} | |
function boundsRingEnd() { | |
boundsRingPoint(lambda00$1, phi00$1); | |
areaStream.lineEnd(); | |
if (abs(deltaSum) > epsilon) lambda0$1 = -(lambda1 = 180); | |
range$1[0] = lambda0$1, range$1[1] = lambda1; | |
p0 = null; | |
} | |
// Finds the left-right distance between two longitudes. | |
// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want | |
// the distance between ±180° to be 360°. | |
function angle(lambda0, lambda1) { | |
return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; | |
} | |
function rangeCompare(a, b) { | |
return a[0] - b[0]; | |
} | |
function rangeContains(range$$1, x) { | |
return range$$1[0] <= range$$1[1] ? range$$1[0] <= x && x <= range$$1[1] : x < range$$1[0] || range$$1[1] < x; | |
} | |
var bounds = function(feature) { | |
var i, n, a, b, merged, deltaMax, delta; | |
phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); | |
ranges = []; | |
geoStream(feature, boundsStream); | |
// First, sort ranges by their minimum longitudes. | |
if (n = ranges.length) { | |
ranges.sort(rangeCompare); | |
// Then, merge any ranges that overlap. | |
for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { | |
b = ranges[i]; | |
if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { | |
if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; | |
if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; | |
} else { | |
merged.push(a = b); | |
} | |
} | |
// Finally, find the largest gap between the merged ranges. | |
// The final bounding box will be the inverse of this gap. | |
for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { | |
b = merged[i]; | |
if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; | |
} | |
} | |
ranges = range$1 = null; | |
return lambda0$1 === Infinity || phi0 === Infinity | |
? [[NaN, NaN], [NaN, NaN]] | |
: [[lambda0$1, phi0], [lambda1, phi1]]; | |
}; | |
var W0; | |
var W1; | |
var X0; | |
var Y0; | |
var Z0; | |
var X1; | |
var Y1; | |
var Z1; | |
var X2; | |
var Y2; | |
var Z2; | |
var lambda00$2; | |
var phi00$2; | |
var x0; | |
var y0; | |
var z0; // previous point | |
var centroidStream = { | |
sphere: noop, | |
point: centroidPoint, | |
lineStart: centroidLineStart, | |
lineEnd: centroidLineEnd, | |
polygonStart: function() { | |
centroidStream.lineStart = centroidRingStart; | |
centroidStream.lineEnd = centroidRingEnd; | |
}, | |
polygonEnd: function() { | |
centroidStream.lineStart = centroidLineStart; | |
centroidStream.lineEnd = centroidLineEnd; | |
} | |
}; | |
// Arithmetic mean of Cartesian vectors. | |
function centroidPoint(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
var cosPhi = cos(phi); | |
centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)); | |
} | |
function centroidPointCartesian(x, y, z) { | |
++W0; | |
X0 += (x - X0) / W0; | |
Y0 += (y - Y0) / W0; | |
Z0 += (z - Z0) / W0; | |
} | |
function centroidLineStart() { | |
centroidStream.point = centroidLinePointFirst; | |
} | |
function centroidLinePointFirst(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
var cosPhi = cos(phi); | |
x0 = cosPhi * cos(lambda); | |
y0 = cosPhi * sin(lambda); | |
z0 = sin(phi); | |
centroidStream.point = centroidLinePoint; | |
centroidPointCartesian(x0, y0, z0); | |
} | |
function centroidLinePoint(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
var cosPhi = cos(phi), | |
x = cosPhi * cos(lambda), | |
y = cosPhi * sin(lambda), | |
z = sin(phi), | |
w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); | |
W1 += w; | |
X1 += w * (x0 + (x0 = x)); | |
Y1 += w * (y0 + (y0 = y)); | |
Z1 += w * (z0 + (z0 = z)); | |
centroidPointCartesian(x0, y0, z0); | |
} | |
function centroidLineEnd() { | |
centroidStream.point = centroidPoint; | |
} | |
// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, | |
// J. Applied Mechanics 42, 239 (1975). | |
function centroidRingStart() { | |
centroidStream.point = centroidRingPointFirst; | |
} | |
function centroidRingEnd() { | |
centroidRingPoint(lambda00$2, phi00$2); | |
centroidStream.point = centroidPoint; | |
} | |
function centroidRingPointFirst(lambda, phi) { | |
lambda00$2 = lambda, phi00$2 = phi; | |
lambda *= radians, phi *= radians; | |
centroidStream.point = centroidRingPoint; | |
var cosPhi = cos(phi); | |
x0 = cosPhi * cos(lambda); | |
y0 = cosPhi * sin(lambda); | |
z0 = sin(phi); | |
centroidPointCartesian(x0, y0, z0); | |
} | |
function centroidRingPoint(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
var cosPhi = cos(phi), | |
x = cosPhi * cos(lambda), | |
y = cosPhi * sin(lambda), | |
z = sin(phi), | |
cx = y0 * z - z0 * y, | |
cy = z0 * x - x0 * z, | |
cz = x0 * y - y0 * x, | |
m = sqrt(cx * cx + cy * cy + cz * cz), | |
w = asin(m), // line weight = angle | |
v = m && -w / m; // area weight multiplier | |
X2 += v * cx; | |
Y2 += v * cy; | |
Z2 += v * cz; | |
W1 += w; | |
X1 += w * (x0 + (x0 = x)); | |
Y1 += w * (y0 + (y0 = y)); | |
Z1 += w * (z0 + (z0 = z)); | |
centroidPointCartesian(x0, y0, z0); | |
} | |
var centroid = function(object) { | |
W0 = W1 = | |
X0 = Y0 = Z0 = | |
X1 = Y1 = Z1 = | |
X2 = Y2 = Z2 = 0; | |
geoStream(object, centroidStream); | |
var x = X2, | |
y = Y2, | |
z = Z2, | |
m = x * x + y * y + z * z; | |
// If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. | |
if (m < epsilon2) { | |
x = X1, y = Y1, z = Z1; | |
// If the feature has zero length, fall back to arithmetic mean of point vectors. | |
if (W1 < epsilon) x = X0, y = Y0, z = Z0; | |
m = x * x + y * y + z * z; | |
// If the feature still has an undefined ccentroid, then return. | |
if (m < epsilon2) return [NaN, NaN]; | |
} | |
return [atan2(y, x) * degrees, asin(z / sqrt(m)) * degrees]; | |
}; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var compose = function(a, b) { | |
function compose(x, y) { | |
return x = a(x, y), b(x[0], x[1]); | |
} | |
if (a.invert && b.invert) compose.invert = function(x, y) { | |
return x = b.invert(x, y), x && a.invert(x[0], x[1]); | |
}; | |
return compose; | |
}; | |
function rotationIdentity(lambda, phi) { | |
return [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; | |
} | |
rotationIdentity.invert = rotationIdentity; | |
function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { | |
return (deltaLambda %= tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) | |
: rotationLambda(deltaLambda)) | |
: (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) | |
: rotationIdentity); | |
} | |
function forwardRotationLambda(deltaLambda) { | |
return function(lambda, phi) { | |
return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; | |
}; | |
} | |
function rotationLambda(deltaLambda) { | |
var rotation = forwardRotationLambda(deltaLambda); | |
rotation.invert = forwardRotationLambda(-deltaLambda); | |
return rotation; | |
} | |
function rotationPhiGamma(deltaPhi, deltaGamma) { | |
var cosDeltaPhi = cos(deltaPhi), | |
sinDeltaPhi = sin(deltaPhi), | |
cosDeltaGamma = cos(deltaGamma), | |
sinDeltaGamma = sin(deltaGamma); | |
function rotation(lambda, phi) { | |
var cosPhi = cos(phi), | |
x = cos(lambda) * cosPhi, | |
y = sin(lambda) * cosPhi, | |
z = sin(phi), | |
k = z * cosDeltaPhi + x * sinDeltaPhi; | |
return [ | |
atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), | |
asin(k * cosDeltaGamma + y * sinDeltaGamma) | |
]; | |
} | |
rotation.invert = function(lambda, phi) { | |
var cosPhi = cos(phi), | |
x = cos(lambda) * cosPhi, | |
y = sin(lambda) * cosPhi, | |
z = sin(phi), | |
k = z * cosDeltaGamma - y * sinDeltaGamma; | |
return [ | |
atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), | |
asin(k * cosDeltaPhi - x * sinDeltaPhi) | |
]; | |
}; | |
return rotation; | |
} | |
var rotation = function(rotate) { | |
rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); | |
function forward(coordinates) { | |
coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); | |
return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates; | |
} | |
forward.invert = function(coordinates) { | |
coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); | |
return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates; | |
}; | |
return forward; | |
}; | |
// Generates a circle centered at [0°, 0°], with a given radius and precision. | |
function circleStream(stream, radius, delta, direction, t0, t1) { | |
if (!delta) return; | |
var cosRadius = cos(radius), | |
sinRadius = sin(radius), | |
step = direction * delta; | |
if (t0 == null) { | |
t0 = radius + direction * tau; | |
t1 = radius - step / 2; | |
} else { | |
t0 = circleRadius(cosRadius, t0); | |
t1 = circleRadius(cosRadius, t1); | |
if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau; | |
} | |
for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { | |
point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]); | |
stream.point(point[0], point[1]); | |
} | |
} | |
// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. | |
function circleRadius(cosRadius, point) { | |
point = cartesian(point), point[0] -= cosRadius; | |
cartesianNormalizeInPlace(point); | |
var radius = acos(-point[1]); | |
return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau; | |
} | |
var circle = function() { | |
var center = constant([0, 0]), | |
radius = constant(90), | |
precision = constant(6), | |
ring, | |
rotate, | |
stream = {point: point}; | |
function point(x, y) { | |
ring.push(x = rotate(x, y)); | |
x[0] *= degrees, x[1] *= degrees; | |
} | |
function circle() { | |
var c = center.apply(this, arguments), | |
r = radius.apply(this, arguments) * radians, | |
p = precision.apply(this, arguments) * radians; | |
ring = []; | |
rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; | |
circleStream(stream, r, p, 1); | |
c = {type: "Polygon", coordinates: [ring]}; | |
ring = rotate = null; | |
return c; | |
} | |
circle.center = function(_) { | |
return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center; | |
}; | |
circle.radius = function(_) { | |
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius; | |
}; | |
circle.precision = function(_) { | |
return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision; | |
}; | |
return circle; | |
}; | |
var clipBuffer = function() { | |
var lines = [], | |
line; | |
return { | |
point: function(x, y) { | |
line.push([x, y]); | |
}, | |
lineStart: function() { | |
lines.push(line = []); | |
}, | |
lineEnd: noop, | |
rejoin: function() { | |
if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); | |
}, | |
result: function() { | |
var result = lines; | |
lines = []; | |
line = null; | |
return result; | |
} | |
}; | |
}; | |
var clipLine = function(a, b, x0, y0, x1, y1) { | |
var ax = a[0], | |
ay = a[1], | |
bx = b[0], | |
by = b[1], | |
t0 = 0, | |
t1 = 1, | |
dx = bx - ax, | |
dy = by - ay, | |
r; | |
r = x0 - ax; | |
if (!dx && r > 0) return; | |
r /= dx; | |
if (dx < 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} else if (dx > 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} | |
r = x1 - ax; | |
if (!dx && r < 0) return; | |
r /= dx; | |
if (dx < 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} else if (dx > 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} | |
r = y0 - ay; | |
if (!dy && r > 0) return; | |
r /= dy; | |
if (dy < 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} else if (dy > 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} | |
r = y1 - ay; | |
if (!dy && r < 0) return; | |
r /= dy; | |
if (dy < 0) { | |
if (r > t1) return; | |
if (r > t0) t0 = r; | |
} else if (dy > 0) { | |
if (r < t0) return; | |
if (r < t1) t1 = r; | |
} | |
if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; | |
if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; | |
return true; | |
}; | |
var pointEqual = function(a, b) { | |
return abs(a[0] - b[0]) < epsilon && abs(a[1] - b[1]) < epsilon; | |
}; | |
function Intersection(point, points, other, entry) { | |
this.x = point; | |
this.z = points; | |
this.o = other; // another intersection | |
this.e = entry; // is an entry? | |
this.v = false; // visited | |
this.n = this.p = null; // next & previous | |
} | |
// A generalized polygon clipping algorithm: given a polygon that has been cut | |
// into its visible line segments, and rejoins the segments by interpolating | |
// along the clip edge. | |
var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) { | |
var subject = [], | |
clip = [], | |
i, | |
n; | |
segments.forEach(function(segment) { | |
if ((n = segment.length - 1) <= 0) return; | |
var n, p0 = segment[0], p1 = segment[n], x; | |
// If the first and last points of a segment are coincident, then treat as a | |
// closed ring. TODO if all rings are closed, then the winding order of the | |
// exterior ring should be checked. | |
if (pointEqual(p0, p1)) { | |
stream.lineStart(); | |
for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); | |
stream.lineEnd(); | |
return; | |
} | |
subject.push(x = new Intersection(p0, segment, null, true)); | |
clip.push(x.o = new Intersection(p0, null, x, false)); | |
subject.push(x = new Intersection(p1, segment, null, false)); | |
clip.push(x.o = new Intersection(p1, null, x, true)); | |
}); | |
if (!subject.length) return; | |
clip.sort(compareIntersection); | |
link(subject); | |
link(clip); | |
for (i = 0, n = clip.length; i < n; ++i) { | |
clip[i].e = startInside = !startInside; | |
} | |
var start = subject[0], | |
points, | |
point; | |
while (1) { | |
// Find first unvisited intersection. | |
var current = start, | |
isSubject = true; | |
while (current.v) if ((current = current.n) === start) return; | |
points = current.z; | |
stream.lineStart(); | |
do { | |
current.v = current.o.v = true; | |
if (current.e) { | |
if (isSubject) { | |
for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.x, current.n.x, 1, stream); | |
} | |
current = current.n; | |
} else { | |
if (isSubject) { | |
points = current.p.z; | |
for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.x, current.p.x, -1, stream); | |
} | |
current = current.p; | |
} | |
current = current.o; | |
points = current.z; | |
isSubject = !isSubject; | |
} while (!current.v); | |
stream.lineEnd(); | |
} | |
}; | |
function link(array) { | |
if (!(n = array.length)) return; | |
var n, | |
i = 0, | |
a = array[0], | |
b; | |
while (++i < n) { | |
a.n = b = array[i]; | |
b.p = a; | |
a = b; | |
} | |
a.n = b = array[0]; | |
b.p = a; | |
} | |
var clipMax = 1e9; | |
var clipMin = -clipMax; | |
// TODO Use d3-polygon’s polygonContains here for the ring check? | |
// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? | |
function clipExtent(x0, y0, x1, y1) { | |
function visible(x, y) { | |
return x0 <= x && x <= x1 && y0 <= y && y <= y1; | |
} | |
function interpolate(from, to, direction, stream) { | |
var a = 0, a1 = 0; | |
if (from == null | |
|| (a = corner(from, direction)) !== (a1 = corner(to, direction)) | |
|| comparePoint(from, to) < 0 ^ direction > 0) { | |
do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); | |
while ((a = (a + direction + 4) % 4) !== a1); | |
} else { | |
stream.point(to[0], to[1]); | |
} | |
} | |
function corner(p, direction) { | |
return abs(p[0] - x0) < epsilon ? direction > 0 ? 0 : 3 | |
: abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1 | |
: abs(p[1] - y0) < epsilon ? direction > 0 ? 1 : 0 | |
: direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon | |
} | |
function compareIntersection(a, b) { | |
return comparePoint(a.x, b.x); | |
} | |
function comparePoint(a, b) { | |
var ca = corner(a, 1), | |
cb = corner(b, 1); | |
return ca !== cb ? ca - cb | |
: ca === 0 ? b[1] - a[1] | |
: ca === 1 ? a[0] - b[0] | |
: ca === 2 ? a[1] - b[1] | |
: b[0] - a[0]; | |
} | |
return function(stream) { | |
var activeStream = stream, | |
bufferStream = clipBuffer(), | |
segments, | |
polygon, | |
ring, | |
x__, y__, v__, // first point | |
x_, y_, v_, // previous point | |
first, | |
clean; | |
var clipStream = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: polygonStart, | |
polygonEnd: polygonEnd | |
}; | |
function point(x, y) { | |
if (visible(x, y)) activeStream.point(x, y); | |
} | |
function polygonInside() { | |
var winding = 0; | |
for (var i = 0, n = polygon.length; i < n; ++i) { | |
for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { | |
a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; | |
if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } | |
else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } | |
} | |
} | |
return winding; | |
} | |
// Buffer geometry within a polygon and then clip it en masse. | |
function polygonStart() { | |
activeStream = bufferStream, segments = [], polygon = [], clean = true; | |
} | |
function polygonEnd() { | |
var startInside = polygonInside(), | |
cleanInside = clean && startInside, | |
visible = (segments = d3Array.merge(segments)).length; | |
if (cleanInside || visible) { | |
stream.polygonStart(); | |
if (cleanInside) { | |
stream.lineStart(); | |
interpolate(null, null, 1, stream); | |
stream.lineEnd(); | |
} | |
if (visible) { | |
clipPolygon(segments, compareIntersection, startInside, interpolate, stream); | |
} | |
stream.polygonEnd(); | |
} | |
activeStream = stream, segments = polygon = ring = null; | |
} | |
function lineStart() { | |
clipStream.point = linePoint; | |
if (polygon) polygon.push(ring = []); | |
first = true; | |
v_ = false; | |
x_ = y_ = NaN; | |
} | |
// TODO rather than special-case polygons, simply handle them separately. | |
// Ideally, coincident intersection points should be jittered to avoid | |
// clipping issues. | |
function lineEnd() { | |
if (segments) { | |
linePoint(x__, y__); | |
if (v__ && v_) bufferStream.rejoin(); | |
segments.push(bufferStream.result()); | |
} | |
clipStream.point = point; | |
if (v_) activeStream.lineEnd(); | |
} | |
function linePoint(x, y) { | |
var v = visible(x, y); | |
if (polygon) ring.push([x, y]); | |
if (first) { | |
x__ = x, y__ = y, v__ = v; | |
first = false; | |
if (v) { | |
activeStream.lineStart(); | |
activeStream.point(x, y); | |
} | |
} else { | |
if (v && v_) activeStream.point(x, y); | |
else { | |
var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], | |
b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; | |
if (clipLine(a, b, x0, y0, x1, y1)) { | |
if (!v_) { | |
activeStream.lineStart(); | |
activeStream.point(a[0], a[1]); | |
} | |
activeStream.point(b[0], b[1]); | |
if (!v) activeStream.lineEnd(); | |
clean = false; | |
} else if (v) { | |
activeStream.lineStart(); | |
activeStream.point(x, y); | |
clean = false; | |
} | |
} | |
} | |
x_ = x, y_ = y, v_ = v; | |
} | |
return clipStream; | |
}; | |
} | |
var extent = function() { | |
var x0 = 0, | |
y0 = 0, | |
x1 = 960, | |
y1 = 500, | |
cache, | |
cacheStream, | |
clip; | |
return clip = { | |
stream: function(stream) { | |
return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream); | |
}, | |
extent: function(_) { | |
return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; | |
} | |
}; | |
}; | |
var sum = adder(); | |
var polygonContains = function(polygon, point) { | |
var lambda = point[0], | |
phi = point[1], | |
normal = [sin(lambda), -cos(lambda), 0], | |
angle = 0, | |
winding = 0; | |
sum.reset(); | |
for (var i = 0, n = polygon.length; i < n; ++i) { | |
if (!(m = (ring = polygon[i]).length)) continue; | |
var ring, | |
m, | |
point0 = ring[m - 1], | |
lambda0 = point0[0], | |
phi0 = point0[1] / 2 + quarterPi, | |
sinPhi0 = sin(phi0), | |
cosPhi0 = cos(phi0); | |
for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { | |
var point1 = ring[j], | |
lambda1 = point1[0], | |
phi1 = point1[1] / 2 + quarterPi, | |
sinPhi1 = sin(phi1), | |
cosPhi1 = cos(phi1), | |
delta = lambda1 - lambda0, | |
sign$$1 = delta >= 0 ? 1 : -1, | |
absDelta = sign$$1 * delta, | |
antimeridian = absDelta > pi, | |
k = sinPhi0 * sinPhi1; | |
sum.add(atan2(k * sign$$1 * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta))); | |
angle += antimeridian ? delta + sign$$1 * tau : delta; | |
// Are the longitudes either side of the point’s meridian (lambda), | |
// and are the latitudes smaller than the parallel (phi)? | |
if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { | |
var arc = cartesianCross(cartesian(point0), cartesian(point1)); | |
cartesianNormalizeInPlace(arc); | |
var intersection = cartesianCross(normal, arc); | |
cartesianNormalizeInPlace(intersection); | |
var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); | |
if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { | |
winding += antimeridian ^ delta >= 0 ? 1 : -1; | |
} | |
} | |
} | |
} | |
// First, determine whether the South pole is inside or outside: | |
// | |
// It is inside if: | |
// * the polygon winds around it in a clockwise direction. | |
// * the polygon does not (cumulatively) wind around it, but has a negative | |
// (counter-clockwise) area. | |
// | |
// Second, count the (signed) number of times a segment crosses a lambda | |
// from the point to the South pole. If it is zero, then the point is the | |
// same side as the South pole. | |
return (angle < -epsilon || angle < epsilon && sum < -epsilon) ^ (winding & 1); | |
}; | |
var lengthSum = adder(); | |
var lambda0$2; | |
var sinPhi0$1; | |
var cosPhi0$1; | |
var lengthStream = { | |
sphere: noop, | |
point: noop, | |
lineStart: lengthLineStart, | |
lineEnd: noop, | |
polygonStart: noop, | |
polygonEnd: noop | |
}; | |
function lengthLineStart() { | |
lengthStream.point = lengthPointFirst; | |
lengthStream.lineEnd = lengthLineEnd; | |
} | |
function lengthLineEnd() { | |
lengthStream.point = lengthStream.lineEnd = noop; | |
} | |
function lengthPointFirst(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
lambda0$2 = lambda, sinPhi0$1 = sin(phi), cosPhi0$1 = cos(phi); | |
lengthStream.point = lengthPoint; | |
} | |
function lengthPoint(lambda, phi) { | |
lambda *= radians, phi *= radians; | |
var sinPhi = sin(phi), | |
cosPhi = cos(phi), | |
delta = abs(lambda - lambda0$2), | |
cosDelta = cos(delta), | |
sinDelta = sin(delta), | |
x = cosPhi * sinDelta, | |
y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, | |
z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; | |
lengthSum.add(atan2(sqrt(x * x + y * y), z)); | |
lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; | |
} | |
var length = function(object) { | |
lengthSum.reset(); | |
geoStream(object, lengthStream); | |
return +lengthSum; | |
}; | |
var coordinates = [null, null]; | |
var object = {type: "LineString", coordinates: coordinates}; | |
var distance = function(a, b) { | |
coordinates[0] = a; | |
coordinates[1] = b; | |
return length(object); | |
}; | |
var containsObjectType = { | |
Feature: function(object, point) { | |
return containsGeometry(object.geometry, point); | |
}, | |
FeatureCollection: function(object, point) { | |
var features = object.features, i = -1, n = features.length; | |
while (++i < n) if (containsGeometry(features[i].geometry, point)) return true; | |
return false; | |
} | |
}; | |
var containsGeometryType = { | |
Sphere: function() { | |
return true; | |
}, | |
Point: function(object, point) { | |
return containsPoint(object.coordinates, point); | |
}, | |
MultiPoint: function(object, point) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) if (containsPoint(coordinates[i], point)) return true; | |
return false; | |
}, | |
LineString: function(object, point) { | |
return containsLine(object.coordinates, point); | |
}, | |
MultiLineString: function(object, point) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) if (containsLine(coordinates[i], point)) return true; | |
return false; | |
}, | |
Polygon: function(object, point) { | |
return containsPolygon(object.coordinates, point); | |
}, | |
MultiPolygon: function(object, point) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) if (containsPolygon(coordinates[i], point)) return true; | |
return false; | |
}, | |
GeometryCollection: function(object, point) { | |
var geometries = object.geometries, i = -1, n = geometries.length; | |
while (++i < n) if (containsGeometry(geometries[i], point)) return true; | |
return false; | |
} | |
}; | |
function containsGeometry(geometry, point) { | |
return geometry && containsGeometryType.hasOwnProperty(geometry.type) | |
? containsGeometryType[geometry.type](geometry, point) | |
: false; | |
} | |
function containsPoint(coordinates, point) { | |
return distance(coordinates, point) === 0; | |
} | |
function containsLine(coordinates, point) { | |
var ab = distance(coordinates[0], coordinates[1]), | |
ao = distance(coordinates[0], point), | |
ob = distance(point, coordinates[1]); | |
return ao + ob <= ab + epsilon; | |
} | |
function containsPolygon(coordinates, point) { | |
return !!polygonContains(coordinates.map(ringRadians), pointRadians(point)); | |
} | |
function ringRadians(ring) { | |
return ring = ring.map(pointRadians), ring.pop(), ring; | |
} | |
function pointRadians(point) { | |
return [point[0] * radians, point[1] * radians]; | |
} | |
var contains = function(object, point) { | |
return (object && containsObjectType.hasOwnProperty(object.type) | |
? containsObjectType[object.type] | |
: containsGeometry)(object, point); | |
}; | |
function graticuleX(y0, y1, dy) { | |
var y = d3Array.range(y0, y1 - epsilon, dy).concat(y1); | |
return function(x) { return y.map(function(y) { return [x, y]; }); }; | |
} | |
function graticuleY(x0, x1, dx) { | |
var x = d3Array.range(x0, x1 - epsilon, dx).concat(x1); | |
return function(y) { return x.map(function(x) { return [x, y]; }); }; | |
} | |
function graticule() { | |
var x1, x0, X1, X0, | |
y1, y0, Y1, Y0, | |
dx = 10, dy = dx, DX = 90, DY = 360, | |
x, y, X, Y, | |
precision = 2.5; | |
function graticule() { | |
return {type: "MultiLineString", coordinates: lines()}; | |
} | |
function lines() { | |
return d3Array.range(ceil(X0 / DX) * DX, X1, DX).map(X) | |
.concat(d3Array.range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) | |
.concat(d3Array.range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x)) | |
.concat(d3Array.range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).map(y)); | |
} | |
graticule.lines = function() { | |
return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; }); | |
}; | |
graticule.outline = function() { | |
return { | |
type: "Polygon", | |
coordinates: [ | |
X(X0).concat( | |
Y(Y1).slice(1), | |
X(X1).reverse().slice(1), | |
Y(Y0).reverse().slice(1)) | |
] | |
}; | |
}; | |
graticule.extent = function(_) { | |
if (!arguments.length) return graticule.extentMinor(); | |
return graticule.extentMajor(_).extentMinor(_); | |
}; | |
graticule.extentMajor = function(_) { | |
if (!arguments.length) return [[X0, Y0], [X1, Y1]]; | |
X0 = +_[0][0], X1 = +_[1][0]; | |
Y0 = +_[0][1], Y1 = +_[1][1]; | |
if (X0 > X1) _ = X0, X0 = X1, X1 = _; | |
if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; | |
return graticule.precision(precision); | |
}; | |
graticule.extentMinor = function(_) { | |
if (!arguments.length) return [[x0, y0], [x1, y1]]; | |
x0 = +_[0][0], x1 = +_[1][0]; | |
y0 = +_[0][1], y1 = +_[1][1]; | |
if (x0 > x1) _ = x0, x0 = x1, x1 = _; | |
if (y0 > y1) _ = y0, y0 = y1, y1 = _; | |
return graticule.precision(precision); | |
}; | |
graticule.step = function(_) { | |
if (!arguments.length) return graticule.stepMinor(); | |
return graticule.stepMajor(_).stepMinor(_); | |
}; | |
graticule.stepMajor = function(_) { | |
if (!arguments.length) return [DX, DY]; | |
DX = +_[0], DY = +_[1]; | |
return graticule; | |
}; | |
graticule.stepMinor = function(_) { | |
if (!arguments.length) return [dx, dy]; | |
dx = +_[0], dy = +_[1]; | |
return graticule; | |
}; | |
graticule.precision = function(_) { | |
if (!arguments.length) return precision; | |
precision = +_; | |
x = graticuleX(y0, y1, 90); | |
y = graticuleY(x0, x1, precision); | |
X = graticuleX(Y0, Y1, 90); | |
Y = graticuleY(X0, X1, precision); | |
return graticule; | |
}; | |
return graticule | |
.extentMajor([[-180, -90 + epsilon], [180, 90 - epsilon]]) | |
.extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]); | |
} | |
function graticule10() { | |
return graticule()(); | |
} | |
var interpolate = function(a, b) { | |
var x0 = a[0] * radians, | |
y0 = a[1] * radians, | |
x1 = b[0] * radians, | |
y1 = b[1] * radians, | |
cy0 = cos(y0), | |
sy0 = sin(y0), | |
cy1 = cos(y1), | |
sy1 = sin(y1), | |
kx0 = cy0 * cos(x0), | |
ky0 = cy0 * sin(x0), | |
kx1 = cy1 * cos(x1), | |
ky1 = cy1 * sin(x1), | |
d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), | |
k = sin(d); | |
var interpolate = d ? function(t) { | |
var B = sin(t *= d) / k, | |
A = sin(d - t) / k, | |
x = A * kx0 + B * kx1, | |
y = A * ky0 + B * ky1, | |
z = A * sy0 + B * sy1; | |
return [ | |
atan2(y, x) * degrees, | |
atan2(z, sqrt(x * x + y * y)) * degrees | |
]; | |
} : function() { | |
return [x0 * degrees, y0 * degrees]; | |
}; | |
interpolate.distance = d; | |
return interpolate; | |
}; | |
var identity = function(x) { | |
return x; | |
}; | |
var areaSum$1 = adder(); | |
var areaRingSum$1 = adder(); | |
var x00; | |
var y00; | |
var x0$1; | |
var y0$1; | |
var areaStream$1 = { | |
point: noop, | |
lineStart: noop, | |
lineEnd: noop, | |
polygonStart: function() { | |
areaStream$1.lineStart = areaRingStart$1; | |
areaStream$1.lineEnd = areaRingEnd$1; | |
}, | |
polygonEnd: function() { | |
areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop; | |
areaSum$1.add(abs(areaRingSum$1)); | |
areaRingSum$1.reset(); | |
}, | |
result: function() { | |
var area = areaSum$1 / 2; | |
areaSum$1.reset(); | |
return area; | |
} | |
}; | |
function areaRingStart$1() { | |
areaStream$1.point = areaPointFirst$1; | |
} | |
function areaPointFirst$1(x, y) { | |
areaStream$1.point = areaPoint$1; | |
x00 = x0$1 = x, y00 = y0$1 = y; | |
} | |
function areaPoint$1(x, y) { | |
areaRingSum$1.add(y0$1 * x - x0$1 * y); | |
x0$1 = x, y0$1 = y; | |
} | |
function areaRingEnd$1() { | |
areaPoint$1(x00, y00); | |
} | |
var x0$2 = Infinity; | |
var y0$2 = x0$2; | |
var x1 = -x0$2; | |
var y1 = x1; | |
var boundsStream$1 = { | |
point: boundsPoint$1, | |
lineStart: noop, | |
lineEnd: noop, | |
polygonStart: noop, | |
polygonEnd: noop, | |
result: function() { | |
var bounds = [[x0$2, y0$2], [x1, y1]]; | |
x1 = y1 = -(y0$2 = x0$2 = Infinity); | |
return bounds; | |
} | |
}; | |
function boundsPoint$1(x, y) { | |
if (x < x0$2) x0$2 = x; | |
if (x > x1) x1 = x; | |
if (y < y0$2) y0$2 = y; | |
if (y > y1) y1 = y; | |
} | |
// TODO Enforce positive area for exterior, negative area for interior? | |
var X0$1 = 0; | |
var Y0$1 = 0; | |
var Z0$1 = 0; | |
var X1$1 = 0; | |
var Y1$1 = 0; | |
var Z1$1 = 0; | |
var X2$1 = 0; | |
var Y2$1 = 0; | |
var Z2$1 = 0; | |
var x00$1; | |
var y00$1; | |
var x0$3; | |
var y0$3; | |
var centroidStream$1 = { | |
point: centroidPoint$1, | |
lineStart: centroidLineStart$1, | |
lineEnd: centroidLineEnd$1, | |
polygonStart: function() { | |
centroidStream$1.lineStart = centroidRingStart$1; | |
centroidStream$1.lineEnd = centroidRingEnd$1; | |
}, | |
polygonEnd: function() { | |
centroidStream$1.point = centroidPoint$1; | |
centroidStream$1.lineStart = centroidLineStart$1; | |
centroidStream$1.lineEnd = centroidLineEnd$1; | |
}, | |
result: function() { | |
var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] | |
: Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] | |
: Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] | |
: [NaN, NaN]; | |
X0$1 = Y0$1 = Z0$1 = | |
X1$1 = Y1$1 = Z1$1 = | |
X2$1 = Y2$1 = Z2$1 = 0; | |
return centroid; | |
} | |
}; | |
function centroidPoint$1(x, y) { | |
X0$1 += x; | |
Y0$1 += y; | |
++Z0$1; | |
} | |
function centroidLineStart$1() { | |
centroidStream$1.point = centroidPointFirstLine; | |
} | |
function centroidPointFirstLine(x, y) { | |
centroidStream$1.point = centroidPointLine; | |
centroidPoint$1(x0$3 = x, y0$3 = y); | |
} | |
function centroidPointLine(x, y) { | |
var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); | |
X1$1 += z * (x0$3 + x) / 2; | |
Y1$1 += z * (y0$3 + y) / 2; | |
Z1$1 += z; | |
centroidPoint$1(x0$3 = x, y0$3 = y); | |
} | |
function centroidLineEnd$1() { | |
centroidStream$1.point = centroidPoint$1; | |
} | |
function centroidRingStart$1() { | |
centroidStream$1.point = centroidPointFirstRing; | |
} | |
function centroidRingEnd$1() { | |
centroidPointRing(x00$1, y00$1); | |
} | |
function centroidPointFirstRing(x, y) { | |
centroidStream$1.point = centroidPointRing; | |
centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); | |
} | |
function centroidPointRing(x, y) { | |
var dx = x - x0$3, | |
dy = y - y0$3, | |
z = sqrt(dx * dx + dy * dy); | |
X1$1 += z * (x0$3 + x) / 2; | |
Y1$1 += z * (y0$3 + y) / 2; | |
Z1$1 += z; | |
z = y0$3 * x - x0$3 * y; | |
X2$1 += z * (x0$3 + x); | |
Y2$1 += z * (y0$3 + y); | |
Z2$1 += z * 3; | |
centroidPoint$1(x0$3 = x, y0$3 = y); | |
} | |
function PathContext(context) { | |
this._context = context; | |
} | |
PathContext.prototype = { | |
_radius: 4.5, | |
pointRadius: function(_) { | |
return this._radius = _, this; | |
}, | |
polygonStart: function() { | |
this._line = 0; | |
}, | |
polygonEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line === 0) this._context.closePath(); | |
this._point = NaN; | |
}, | |
point: function(x, y) { | |
switch (this._point) { | |
case 0: { | |
this._context.moveTo(x, y); | |
this._point = 1; | |
break; | |
} | |
case 1: { | |
this._context.lineTo(x, y); | |
break; | |
} | |
default: { | |
this._context.moveTo(x + this._radius, y); | |
this._context.arc(x, y, this._radius, 0, tau); | |
break; | |
} | |
} | |
}, | |
result: noop | |
}; | |
var lengthSum$1 = adder(); | |
var lengthRing; | |
var x00$2; | |
var y00$2; | |
var x0$4; | |
var y0$4; | |
var lengthStream$1 = { | |
point: noop, | |
lineStart: function() { | |
lengthStream$1.point = lengthPointFirst$1; | |
}, | |
lineEnd: function() { | |
if (lengthRing) lengthPoint$1(x00$2, y00$2); | |
lengthStream$1.point = noop; | |
}, | |
polygonStart: function() { | |
lengthRing = true; | |
}, | |
polygonEnd: function() { | |
lengthRing = null; | |
}, | |
result: function() { | |
var length = +lengthSum$1; | |
lengthSum$1.reset(); | |
return length; | |
} | |
}; | |
function lengthPointFirst$1(x, y) { | |
lengthStream$1.point = lengthPoint$1; | |
x00$2 = x0$4 = x, y00$2 = y0$4 = y; | |
} | |
function lengthPoint$1(x, y) { | |
x0$4 -= x, y0$4 -= y; | |
lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4)); | |
x0$4 = x, y0$4 = y; | |
} | |
function PathString() { | |
this._string = []; | |
} | |
PathString.prototype = { | |
_radius: 4.5, | |
_circle: circle$1(4.5), | |
pointRadius: function(_) { | |
if ((_ = +_) !== this._radius) this._radius = _, this._circle = null; | |
return this; | |
}, | |
polygonStart: function() { | |
this._line = 0; | |
}, | |
polygonEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line === 0) this._string.push("Z"); | |
this._point = NaN; | |
}, | |
point: function(x, y) { | |
switch (this._point) { | |
case 0: { | |
this._string.push("M", x, ",", y); | |
this._point = 1; | |
break; | |
} | |
case 1: { | |
this._string.push("L", x, ",", y); | |
break; | |
} | |
default: { | |
if (this._circle == null) this._circle = circle$1(this._radius); | |
this._string.push("M", x, ",", y, this._circle); | |
break; | |
} | |
} | |
}, | |
result: function() { | |
if (this._string.length) { | |
var result = this._string.join(""); | |
this._string = []; | |
return result; | |
} else { | |
return null; | |
} | |
} | |
}; | |
function circle$1(radius) { | |
return "m0," + radius | |
+ "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius | |
+ "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius | |
+ "z"; | |
} | |
var index = function(projection, context) { | |
var pointRadius = 4.5, | |
projectionStream, | |
contextStream; | |
function path(object) { | |
if (object) { | |
if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); | |
geoStream(object, projectionStream(contextStream)); | |
} | |
return contextStream.result(); | |
} | |
path.area = function(object) { | |
geoStream(object, projectionStream(areaStream$1)); | |
return areaStream$1.result(); | |
}; | |
path.measure = function(object) { | |
geoStream(object, projectionStream(lengthStream$1)); | |
return lengthStream$1.result(); | |
}; | |
path.bounds = function(object) { | |
geoStream(object, projectionStream(boundsStream$1)); | |
return boundsStream$1.result(); | |
}; | |
path.centroid = function(object) { | |
geoStream(object, projectionStream(centroidStream$1)); | |
return centroidStream$1.result(); | |
}; | |
path.projection = function(_) { | |
return arguments.length ? (projectionStream = _ == null ? (projection = null, identity) : (projection = _).stream, path) : projection; | |
}; | |
path.context = function(_) { | |
if (!arguments.length) return context; | |
contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); | |
if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); | |
return path; | |
}; | |
path.pointRadius = function(_) { | |
if (!arguments.length) return pointRadius; | |
pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); | |
return path; | |
}; | |
return path.projection(projection).context(context); | |
}; | |
var clip = function(pointVisible, clipLine, interpolate, start) { | |
return function(rotate, sink) { | |
var line = clipLine(sink), | |
rotatedStart = rotate.invert(start[0], start[1]), | |
ringBuffer = clipBuffer(), | |
ringSink = clipLine(ringBuffer), | |
polygonStarted = false, | |
polygon, | |
segments, | |
ring; | |
var clip = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
clip.point = pointRing; | |
clip.lineStart = ringStart; | |
clip.lineEnd = ringEnd; | |
segments = []; | |
polygon = []; | |
}, | |
polygonEnd: function() { | |
clip.point = point; | |
clip.lineStart = lineStart; | |
clip.lineEnd = lineEnd; | |
segments = d3Array.merge(segments); | |
var startInside = polygonContains(polygon, rotatedStart); | |
if (segments.length) { | |
if (!polygonStarted) sink.polygonStart(), polygonStarted = true; | |
clipPolygon(segments, compareIntersection, startInside, interpolate, sink); | |
} else if (startInside) { | |
if (!polygonStarted) sink.polygonStart(), polygonStarted = true; | |
sink.lineStart(); | |
interpolate(null, null, 1, sink); | |
sink.lineEnd(); | |
} | |
if (polygonStarted) sink.polygonEnd(), polygonStarted = false; | |
segments = polygon = null; | |
}, | |
sphere: function() { | |
sink.polygonStart(); | |
sink.lineStart(); | |
interpolate(null, null, 1, sink); | |
sink.lineEnd(); | |
sink.polygonEnd(); | |
} | |
}; | |
function point(lambda, phi) { | |
var point = rotate(lambda, phi); | |
if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi); | |
} | |
function pointLine(lambda, phi) { | |
var point = rotate(lambda, phi); | |
line.point(point[0], point[1]); | |
} | |
function lineStart() { | |
clip.point = pointLine; | |
line.lineStart(); | |
} | |
function lineEnd() { | |
clip.point = point; | |
line.lineEnd(); | |
} | |
function pointRing(lambda, phi) { | |
ring.push([lambda, phi]); | |
var point = rotate(lambda, phi); | |
ringSink.point(point[0], point[1]); | |
} | |
function ringStart() { | |
ringSink.lineStart(); | |
ring = []; | |
} | |
function ringEnd() { | |
pointRing(ring[0][0], ring[0][1]); | |
ringSink.lineEnd(); | |
var clean = ringSink.clean(), | |
ringSegments = ringBuffer.result(), | |
i, n = ringSegments.length, m, | |
segment, | |
point; | |
ring.pop(); | |
polygon.push(ring); | |
ring = null; | |
if (!n) return; | |
// No intersections. | |
if (clean & 1) { | |
segment = ringSegments[0]; | |
if ((m = segment.length - 1) > 0) { | |
if (!polygonStarted) sink.polygonStart(), polygonStarted = true; | |
sink.lineStart(); | |
for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); | |
sink.lineEnd(); | |
} | |
return; | |
} | |
// Rejoin connected segments. | |
// TODO reuse ringBuffer.rejoin()? | |
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); | |
segments.push(ringSegments.filter(validSegment)); | |
} | |
return clip; | |
}; | |
}; | |
function validSegment(segment) { | |
return segment.length > 1; | |
} | |
// Intersections are sorted along the clip edge. For both antimeridian cutting | |
// and circle clipping, the same comparison is used. | |
function compareIntersection(a, b) { | |
return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon : halfPi - a[1]) | |
- ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]); | |
} | |
var clipAntimeridian = clip( | |
function() { return true; }, | |
clipAntimeridianLine, | |
clipAntimeridianInterpolate, | |
[-pi, -halfPi] | |
); | |
// Takes a line and cuts into visible segments. Return values: 0 - there were | |
// intersections or the line was empty; 1 - no intersections; 2 - there were | |
// intersections, and the first and last segments should be rejoined. | |
function clipAntimeridianLine(stream) { | |
var lambda0 = NaN, | |
phi0 = NaN, | |
sign0 = NaN, | |
clean; // no intersections | |
return { | |
lineStart: function() { | |
stream.lineStart(); | |
clean = 1; | |
}, | |
point: function(lambda1, phi1) { | |
var sign1 = lambda1 > 0 ? pi : -pi, | |
delta = abs(lambda1 - lambda0); | |
if (abs(delta - pi) < epsilon) { // line crosses a pole | |
stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi); | |
stream.point(sign0, phi0); | |
stream.lineEnd(); | |
stream.lineStart(); | |
stream.point(sign1, phi0); | |
stream.point(lambda1, phi0); | |
clean = 0; | |
} else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian | |
if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon; // handle degeneracies | |
if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon; | |
phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); | |
stream.point(sign0, phi0); | |
stream.lineEnd(); | |
stream.lineStart(); | |
stream.point(sign1, phi0); | |
clean = 0; | |
} | |
stream.point(lambda0 = lambda1, phi0 = phi1); | |
sign0 = sign1; | |
}, | |
lineEnd: function() { | |
stream.lineEnd(); | |
lambda0 = phi0 = NaN; | |
}, | |
clean: function() { | |
return 2 - clean; // if intersections, rejoin first and last segments | |
} | |
}; | |
} | |
function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { | |
var cosPhi0, | |
cosPhi1, | |
sinLambda0Lambda1 = sin(lambda0 - lambda1); | |
return abs(sinLambda0Lambda1) > epsilon | |
? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) | |
- sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) | |
/ (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) | |
: (phi0 + phi1) / 2; | |
} | |
function clipAntimeridianInterpolate(from, to, direction, stream) { | |
var phi; | |
if (from == null) { | |
phi = direction * halfPi; | |
stream.point(-pi, phi); | |
stream.point(0, phi); | |
stream.point(pi, phi); | |
stream.point(pi, 0); | |
stream.point(pi, -phi); | |
stream.point(0, -phi); | |
stream.point(-pi, -phi); | |
stream.point(-pi, 0); | |
stream.point(-pi, phi); | |
} else if (abs(from[0] - to[0]) > epsilon) { | |
var lambda = from[0] < to[0] ? pi : -pi; | |
phi = direction * lambda / 2; | |
stream.point(-lambda, phi); | |
stream.point(0, phi); | |
stream.point(lambda, phi); | |
} else { | |
stream.point(to[0], to[1]); | |
} | |
} | |
var clipCircle = function(radius, delta) { | |
var cr = cos(radius), | |
smallRadius = cr > 0, | |
notHemisphere = abs(cr) > epsilon; // TODO optimise for this common case | |
function interpolate(from, to, direction, stream) { | |
circleStream(stream, radius, delta, direction, from, to); | |
} | |
function visible(lambda, phi) { | |
return cos(lambda) * cos(phi) > cr; | |
} | |
// Takes a line and cuts into visible segments. Return values used for polygon | |
// clipping: 0 - there were intersections or the line was empty; 1 - no | |
// intersections 2 - there were intersections, and the first and last segments | |
// should be rejoined. | |
function clipLine(stream) { | |
var point0, // previous point | |
c0, // code for previous point | |
v0, // visibility of previous point | |
v00, // visibility of first point | |
clean; // no intersections | |
return { | |
lineStart: function() { | |
v00 = v0 = false; | |
clean = 1; | |
}, | |
point: function(lambda, phi) { | |
var point1 = [lambda, phi], | |
point2, | |
v = visible(lambda, phi), | |
c = smallRadius | |
? v ? 0 : code(lambda, phi) | |
: v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0; | |
if (!point0 && (v00 = v0 = v)) stream.lineStart(); | |
// Handle degeneracies. | |
// TODO ignore if not clipping polygons. | |
if (v !== v0) { | |
point2 = intersect(point0, point1); | |
if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { | |
point1[0] += epsilon; | |
point1[1] += epsilon; | |
v = visible(point1[0], point1[1]); | |
} | |
} | |
if (v !== v0) { | |
clean = 0; | |
if (v) { | |
// outside going in | |
stream.lineStart(); | |
point2 = intersect(point1, point0); | |
stream.point(point2[0], point2[1]); | |
} else { | |
// inside going out | |
point2 = intersect(point0, point1); | |
stream.point(point2[0], point2[1]); | |
stream.lineEnd(); | |
} | |
point0 = point2; | |
} else if (notHemisphere && point0 && smallRadius ^ v) { | |
var t; | |
// If the codes for two points are different, or are both zero, | |
// and there this segment intersects with the small circle. | |
if (!(c & c0) && (t = intersect(point1, point0, true))) { | |
clean = 0; | |
if (smallRadius) { | |
stream.lineStart(); | |
stream.point(t[0][0], t[0][1]); | |
stream.point(t[1][0], t[1][1]); | |
stream.lineEnd(); | |
} else { | |
stream.point(t[1][0], t[1][1]); | |
stream.lineEnd(); | |
stream.lineStart(); | |
stream.point(t[0][0], t[0][1]); | |
} | |
} | |
} | |
if (v && (!point0 || !pointEqual(point0, point1))) { | |
stream.point(point1[0], point1[1]); | |
} | |
point0 = point1, v0 = v, c0 = c; | |
}, | |
lineEnd: function() { | |
if (v0) stream.lineEnd(); | |
point0 = null; | |
}, | |
// Rejoin first and last segments if there were intersections and the first | |
// and last points were visible. | |
clean: function() { | |
return clean | ((v00 && v0) << 1); | |
} | |
}; | |
} | |
// Intersects the great circle between a and b with the clip circle. | |
function intersect(a, b, two) { | |
var pa = cartesian(a), | |
pb = cartesian(b); | |
// We have two planes, n1.p = d1 and n2.p = d2. | |
// Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). | |
var n1 = [1, 0, 0], // normal | |
n2 = cartesianCross(pa, pb), | |
n2n2 = cartesianDot(n2, n2), | |
n1n2 = n2[0], // cartesianDot(n1, n2), | |
determinant = n2n2 - n1n2 * n1n2; | |
// Two polar points. | |
if (!determinant) return !two && a; | |
var c1 = cr * n2n2 / determinant, | |
c2 = -cr * n1n2 / determinant, | |
n1xn2 = cartesianCross(n1, n2), | |
A = cartesianScale(n1, c1), | |
B = cartesianScale(n2, c2); | |
cartesianAddInPlace(A, B); | |
// Solve |p(t)|^2 = 1. | |
var u = n1xn2, | |
w = cartesianDot(A, u), | |
uu = cartesianDot(u, u), | |
t2 = w * w - uu * (cartesianDot(A, A) - 1); | |
if (t2 < 0) return; | |
var t = sqrt(t2), | |
q = cartesianScale(u, (-w - t) / uu); | |
cartesianAddInPlace(q, A); | |
q = spherical(q); | |
if (!two) return q; | |
// Two intersection points. | |
var lambda0 = a[0], | |
lambda1 = b[0], | |
phi0 = a[1], | |
phi1 = b[1], | |
z; | |
if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; | |
var delta = lambda1 - lambda0, | |
polar = abs(delta - pi) < epsilon, | |
meridian = polar || delta < epsilon; | |
if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; | |
// Check that the first point is between a and b. | |
if (meridian | |
? polar | |
? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon ? phi0 : phi1) | |
: phi0 <= q[1] && q[1] <= phi1 | |
: delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) { | |
var q1 = cartesianScale(u, (-w + t) / uu); | |
cartesianAddInPlace(q1, A); | |
return [q, spherical(q1)]; | |
} | |
} | |
// Generates a 4-bit vector representing the location of a point relative to | |
// the small circle's bounding box. | |
function code(lambda, phi) { | |
var r = smallRadius ? radius : pi - radius, | |
code = 0; | |
if (lambda < -r) code |= 1; // left | |
else if (lambda > r) code |= 2; // right | |
if (phi < -r) code |= 4; // below | |
else if (phi > r) code |= 8; // above | |
return code; | |
} | |
return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]); | |
}; | |
var transform = function(methods) { | |
return { | |
stream: transformer(methods) | |
}; | |
}; | |
function transformer(methods) { | |
return function(stream) { | |
var s = new TransformStream; | |
for (var key in methods) s[key] = methods[key]; | |
s.stream = stream; | |
return s; | |
}; | |
} | |
function TransformStream() {} | |
TransformStream.prototype = { | |
constructor: TransformStream, | |
point: function(x, y) { this.stream.point(x, y); }, | |
sphere: function() { this.stream.sphere(); }, | |
lineStart: function() { this.stream.lineStart(); }, | |
lineEnd: function() { this.stream.lineEnd(); }, | |
polygonStart: function() { this.stream.polygonStart(); }, | |
polygonEnd: function() { this.stream.polygonEnd(); } | |
}; | |
function fitExtent(projection, extent, object) { | |
var w = extent[1][0] - extent[0][0], | |
h = extent[1][1] - extent[0][1], | |
clip = projection.clipExtent && projection.clipExtent(); | |
projection | |
.scale(150) | |
.translate([0, 0]); | |
if (clip != null) projection.clipExtent(null); | |
geoStream(object, projection.stream(boundsStream$1)); | |
var b = boundsStream$1.result(), | |
k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), | |
x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, | |
y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; | |
if (clip != null) projection.clipExtent(clip); | |
return projection | |
.scale(k * 150) | |
.translate([x, y]); | |
} | |
function fitSize(projection, size, object) { | |
return fitExtent(projection, [[0, 0], size], object); | |
} | |
var maxDepth = 16; | |
var cosMinDistance = cos(30 * radians); // cos(minimum angular distance) | |
var resample = function(project, delta2) { | |
return +delta2 ? resample$1(project, delta2) : resampleNone(project); | |
}; | |
function resampleNone(project) { | |
return transformer({ | |
point: function(x, y) { | |
x = project(x, y); | |
this.stream.point(x[0], x[1]); | |
} | |
}); | |
} | |
function resample$1(project, delta2) { | |
function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { | |
var dx = x1 - x0, | |
dy = y1 - y0, | |
d2 = dx * dx + dy * dy; | |
if (d2 > 4 * delta2 && depth--) { | |
var a = a0 + a1, | |
b = b0 + b1, | |
c = c0 + c1, | |
m = sqrt(a * a + b * b + c * c), | |
phi2 = asin(c /= m), | |
lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (lambda0 + lambda1) / 2 : atan2(b, a), | |
p = project(lambda2, phi2), | |
x2 = p[0], | |
y2 = p[1], | |
dx2 = x2 - x0, | |
dy2 = y2 - y0, | |
dz = dy * dx2 - dx * dy2; | |
if (dz * dz / d2 > delta2 // perpendicular projected distance | |
|| abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end | |
|| a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance | |
resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); | |
stream.point(x2, y2); | |
resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); | |
} | |
} | |
} | |
return function(stream) { | |
var lambda00, x00, y00, a00, b00, c00, // first point | |
lambda0, x0, y0, a0, b0, c0; // previous point | |
var resampleStream = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, | |
polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } | |
}; | |
function point(x, y) { | |
x = project(x, y); | |
stream.point(x[0], x[1]); | |
} | |
function lineStart() { | |
x0 = NaN; | |
resampleStream.point = linePoint; | |
stream.lineStart(); | |
} | |
function linePoint(lambda, phi) { | |
var c = cartesian([lambda, phi]), p = project(lambda, phi); | |
resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); | |
stream.point(x0, y0); | |
} | |
function lineEnd() { | |
resampleStream.point = point; | |
stream.lineEnd(); | |
} | |
function ringStart() { | |
lineStart(); | |
resampleStream.point = ringPoint; | |
resampleStream.lineEnd = ringEnd; | |
} | |
function ringPoint(lambda, phi) { | |
linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; | |
resampleStream.point = linePoint; | |
} | |
function ringEnd() { | |
resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); | |
resampleStream.lineEnd = lineEnd; | |
lineEnd(); | |
} | |
return resampleStream; | |
}; | |
} | |
var transformRadians = transformer({ | |
point: function(x, y) { | |
this.stream.point(x * radians, y * radians); | |
} | |
}); | |
function projection(project) { | |
return projectionMutator(function() { return project; })(); | |
} | |
function projectionMutator(projectAt) { | |
var project, | |
k = 150, // scale | |
x = 480, y = 250, // translate | |
dx, dy, lambda = 0, phi = 0, // center | |
deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate | |
theta = null, preclip = clipAntimeridian, // clip angle | |
x0 = null, y0, x1, y1, postclip = identity, // clip extent | |
delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision | |
cache, | |
cacheStream; | |
function projection(point) { | |
point = projectRotate(point[0] * radians, point[1] * radians); | |
return [point[0] * k + dx, dy - point[1] * k]; | |
} | |
function invert(point) { | |
point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); | |
return point && [point[0] * degrees, point[1] * degrees]; | |
} | |
function projectTransform(x, y) { | |
return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; | |
} | |
projection.stream = function(stream) { | |
return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))); | |
}; | |
projection.clipAngle = function(_) { | |
return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees; | |
}; | |
projection.clipExtent = function(_) { | |
return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; | |
}; | |
projection.scale = function(_) { | |
return arguments.length ? (k = +_, recenter()) : k; | |
}; | |
projection.translate = function(_) { | |
return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; | |
}; | |
projection.center = function(_) { | |
return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees, phi * degrees]; | |
}; | |
projection.rotate = function(_) { | |
return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees]; | |
}; | |
projection.precision = function(_) { | |
return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); | |
}; | |
projection.fitExtent = function(extent, object) { | |
return fitExtent(projection, extent, object); | |
}; | |
projection.fitSize = function(size, object) { | |
return fitSize(projection, size, object); | |
}; | |
function recenter() { | |
projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); | |
var center = project(lambda, phi); | |
dx = x - center[0] * k; | |
dy = y + center[1] * k; | |
return reset(); | |
} | |
function reset() { | |
cache = cacheStream = null; | |
return projection; | |
} | |
return function() { | |
project = projectAt.apply(this, arguments); | |
projection.invert = project.invert && invert; | |
return recenter(); | |
}; | |
} | |
function conicProjection(projectAt) { | |
var phi0 = 0, | |
phi1 = pi / 3, | |
m = projectionMutator(projectAt), | |
p = m(phi0, phi1); | |
p.parallels = function(_) { | |
return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees, phi1 * degrees]; | |
}; | |
return p; | |
} | |
function cylindricalEqualAreaRaw(phi0) { | |
var cosPhi0 = cos(phi0); | |
function forward(lambda, phi) { | |
return [lambda * cosPhi0, sin(phi) / cosPhi0]; | |
} | |
forward.invert = function(x, y) { | |
return [x / cosPhi0, asin(y * cosPhi0)]; | |
}; | |
return forward; | |
} | |
function conicEqualAreaRaw(y0, y1) { | |
var sy0 = sin(y0), n = (sy0 + sin(y1)) / 2; | |
// Are the parallels symmetrical around the Equator? | |
if (abs(n) < epsilon) return cylindricalEqualAreaRaw(y0); | |
var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; | |
function project(x, y) { | |
var r = sqrt(c - 2 * n * sin(y)) / n; | |
return [r * sin(x *= n), r0 - r * cos(x)]; | |
} | |
project.invert = function(x, y) { | |
var r0y = r0 - y; | |
return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; | |
}; | |
return project; | |
} | |
var conicEqualArea = function() { | |
return conicProjection(conicEqualAreaRaw) | |
.scale(155.424) | |
.center([0, 33.6442]); | |
}; | |
var albers = function() { | |
return conicEqualArea() | |
.parallels([29.5, 45.5]) | |
.scale(1070) | |
.translate([480, 250]) | |
.rotate([96, 0]) | |
.center([-0.6, 38.7]); | |
}; | |
// The projections must have mutually exclusive clip regions on the sphere, | |
// as this will avoid emitting interleaving lines and polygons. | |
function multiplex(streams) { | |
var n = streams.length; | |
return { | |
point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, | |
sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, | |
lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, | |
lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, | |
polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, | |
polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } | |
}; | |
} | |
// A composite projection for the United States, configured by default for | |
// 960×500. The projection also works quite well at 960×600 if you change the | |
// scale to 1285 and adjust the translate accordingly. The set of standard | |
// parallels for each region comes from USGS, which is published here: | |
// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers | |
var albersUsa = function() { | |
var cache, | |
cacheStream, | |
lower48 = albers(), lower48Point, | |
alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 | |
hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 | |
point, pointStream = {point: function(x, y) { point = [x, y]; }}; | |
function albersUsa(coordinates) { | |
var x = coordinates[0], y = coordinates[1]; | |
return point = null, | |
(lower48Point.point(x, y), point) | |
|| (alaskaPoint.point(x, y), point) | |
|| (hawaiiPoint.point(x, y), point); | |
} | |
albersUsa.invert = function(coordinates) { | |
var k = lower48.scale(), | |
t = lower48.translate(), | |
x = (coordinates[0] - t[0]) / k, | |
y = (coordinates[1] - t[1]) / k; | |
return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska | |
: y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii | |
: lower48).invert(coordinates); | |
}; | |
albersUsa.stream = function(stream) { | |
return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); | |
}; | |
albersUsa.precision = function(_) { | |
if (!arguments.length) return lower48.precision(); | |
lower48.precision(_), alaska.precision(_), hawaii.precision(_); | |
return reset(); | |
}; | |
albersUsa.scale = function(_) { | |
if (!arguments.length) return lower48.scale(); | |
lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); | |
return albersUsa.translate(lower48.translate()); | |
}; | |
albersUsa.translate = function(_) { | |
if (!arguments.length) return lower48.translate(); | |
var k = lower48.scale(), x = +_[0], y = +_[1]; | |
lower48Point = lower48 | |
.translate(_) | |
.clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) | |
.stream(pointStream); | |
alaskaPoint = alaska | |
.translate([x - 0.307 * k, y + 0.201 * k]) | |
.clipExtent([[x - 0.425 * k + epsilon, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]]) | |
.stream(pointStream); | |
hawaiiPoint = hawaii | |
.translate([x - 0.205 * k, y + 0.212 * k]) | |
.clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]]) | |
.stream(pointStream); | |
return reset(); | |
}; | |
albersUsa.fitExtent = function(extent, object) { | |
return fitExtent(albersUsa, extent, object); | |
}; | |
albersUsa.fitSize = function(size, object) { | |
return fitSize(albersUsa, size, object); | |
}; | |
function reset() { | |
cache = cacheStream = null; | |
return albersUsa; | |
} | |
return albersUsa.scale(1070); | |
}; | |
function azimuthalRaw(scale) { | |
return function(x, y) { | |
var cx = cos(x), | |
cy = cos(y), | |
k = scale(cx * cy); | |
return [ | |
k * cy * sin(x), | |
k * sin(y) | |
]; | |
} | |
} | |
function azimuthalInvert(angle) { | |
return function(x, y) { | |
var z = sqrt(x * x + y * y), | |
c = angle(z), | |
sc = sin(c), | |
cc = cos(c); | |
return [ | |
atan2(x * sc, z * cc), | |
asin(z && y * sc / z) | |
]; | |
} | |
} | |
var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { | |
return sqrt(2 / (1 + cxcy)); | |
}); | |
azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { | |
return 2 * asin(z / 2); | |
}); | |
var azimuthalEqualArea = function() { | |
return projection(azimuthalEqualAreaRaw) | |
.scale(124.75) | |
.clipAngle(180 - 1e-3); | |
}; | |
var azimuthalEquidistantRaw = azimuthalRaw(function(c) { | |
return (c = acos(c)) && c / sin(c); | |
}); | |
azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { | |
return z; | |
}); | |
var azimuthalEquidistant = function() { | |
return projection(azimuthalEquidistantRaw) | |
.scale(79.4188) | |
.clipAngle(180 - 1e-3); | |
}; | |
function mercatorRaw(lambda, phi) { | |
return [lambda, log(tan((halfPi + phi) / 2))]; | |
} | |
mercatorRaw.invert = function(x, y) { | |
return [x, 2 * atan(exp(y)) - halfPi]; | |
}; | |
var mercator = function() { | |
return mercatorProjection(mercatorRaw) | |
.scale(961 / tau); | |
}; | |
function mercatorProjection(project) { | |
var m = projection(project), | |
center = m.center, | |
scale = m.scale, | |
translate = m.translate, | |
clipExtent = m.clipExtent, | |
x0 = null, y0, x1, y1; // clip extent | |
m.scale = function(_) { | |
return arguments.length ? (scale(_), reclip()) : scale(); | |
}; | |
m.translate = function(_) { | |
return arguments.length ? (translate(_), reclip()) : translate(); | |
}; | |
m.center = function(_) { | |
return arguments.length ? (center(_), reclip()) : center(); | |
}; | |
m.clipExtent = function(_) { | |
return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; | |
}; | |
function reclip() { | |
var k = pi * scale(), | |
t = m(rotation(m.rotate()).invert([0, 0])); | |
return clipExtent(x0 == null | |
? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw | |
? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] | |
: [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); | |
} | |
return reclip(); | |
} | |
function tany(y) { | |
return tan((halfPi + y) / 2); | |
} | |
function conicConformalRaw(y0, y1) { | |
var cy0 = cos(y0), | |
n = y0 === y1 ? sin(y0) : log(cy0 / cos(y1)) / log(tany(y1) / tany(y0)), | |
f = cy0 * pow(tany(y0), n) / n; | |
if (!n) return mercatorRaw; | |
function project(x, y) { | |
if (f > 0) { if (y < -halfPi + epsilon) y = -halfPi + epsilon; } | |
else { if (y > halfPi - epsilon) y = halfPi - epsilon; } | |
var r = f / pow(tany(y), n); | |
return [r * sin(n * x), f - r * cos(n * x)]; | |
} | |
project.invert = function(x, y) { | |
var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); | |
return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi]; | |
}; | |
return project; | |
} | |
var conicConformal = function() { | |
return conicProjection(conicConformalRaw) | |
.scale(109.5) | |
.parallels([30, 30]); | |
}; | |
function equirectangularRaw(lambda, phi) { | |
return [lambda, phi]; | |
} | |
equirectangularRaw.invert = equirectangularRaw; | |
var equirectangular = function() { | |
return projection(equirectangularRaw) | |
.scale(152.63); | |
}; | |
function conicEquidistantRaw(y0, y1) { | |
var cy0 = cos(y0), | |
n = y0 === y1 ? sin(y0) : (cy0 - cos(y1)) / (y1 - y0), | |
g = cy0 / n + y0; | |
if (abs(n) < epsilon) return equirectangularRaw; | |
function project(x, y) { | |
var gy = g - y, nx = n * x; | |
return [gy * sin(nx), g - gy * cos(nx)]; | |
} | |
project.invert = function(x, y) { | |
var gy = g - y; | |
return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)]; | |
}; | |
return project; | |
} | |
var conicEquidistant = function() { | |
return conicProjection(conicEquidistantRaw) | |
.scale(131.154) | |
.center([0, 13.9389]); | |
}; | |
function gnomonicRaw(x, y) { | |
var cy = cos(y), k = cos(x) * cy; | |
return [cy * sin(x) / k, sin(y) / k]; | |
} | |
gnomonicRaw.invert = azimuthalInvert(atan); | |
var gnomonic = function() { | |
return projection(gnomonicRaw) | |
.scale(144.049) | |
.clipAngle(60); | |
}; | |
function scaleTranslate(kx, ky, tx, ty) { | |
return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity : transformer({ | |
point: function(x, y) { | |
this.stream.point(x * kx + tx, y * ky + ty); | |
} | |
}); | |
} | |
var identity$1 = function() { | |
var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity, // scale, translate and reflect | |
x0 = null, y0, x1, y1, clip = identity, // clip extent | |
cache, | |
cacheStream, | |
projection; | |
function reset() { | |
cache = cacheStream = null; | |
return projection; | |
} | |
return projection = { | |
stream: function(stream) { | |
return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream)); | |
}, | |
clipExtent: function(_) { | |
return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; | |
}, | |
scale: function(_) { | |
return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k; | |
}, | |
translate: function(_) { | |
return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; | |
}, | |
reflectX: function(_) { | |
return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0; | |
}, | |
reflectY: function(_) { | |
return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0; | |
}, | |
fitExtent: function(extent, object) { | |
return fitExtent(projection, extent, object); | |
}, | |
fitSize: function(size, object) { | |
return fitSize(projection, size, object); | |
} | |
}; | |
}; | |
function orthographicRaw(x, y) { | |
return [cos(y) * sin(x), sin(y)]; | |
} | |
orthographicRaw.invert = azimuthalInvert(asin); | |
var orthographic = function() { | |
return projection(orthographicRaw) | |
.scale(249.5) | |
.clipAngle(90 + epsilon); | |
}; | |
function stereographicRaw(x, y) { | |
var cy = cos(y), k = 1 + cos(x) * cy; | |
return [cy * sin(x) / k, sin(y) / k]; | |
} | |
stereographicRaw.invert = azimuthalInvert(function(z) { | |
return 2 * atan(z); | |
}); | |
var stereographic = function() { | |
return projection(stereographicRaw) | |
.scale(250) | |
.clipAngle(142); | |
}; | |
function transverseMercatorRaw(lambda, phi) { | |
return [log(tan((halfPi + phi) / 2)), -lambda]; | |
} | |
transverseMercatorRaw.invert = function(x, y) { | |
return [-y, 2 * atan(exp(x)) - halfPi]; | |
}; | |
var transverseMercator = function() { | |
var m = mercatorProjection(transverseMercatorRaw), | |
center = m.center, | |
rotate = m.rotate; | |
m.center = function(_) { | |
return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); | |
}; | |
m.rotate = function(_) { | |
return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); | |
}; | |
return rotate([0, 0, 90]) | |
.scale(159.155); | |
}; | |
exports.geoArea = area; | |
exports.geoBounds = bounds; | |
exports.geoCentroid = centroid; | |
exports.geoCircle = circle; | |
exports.geoClipExtent = extent; | |
exports.geoContains = contains; | |
exports.geoDistance = distance; | |
exports.geoGraticule = graticule; | |
exports.geoGraticule10 = graticule10; | |
exports.geoInterpolate = interpolate; | |
exports.geoLength = length; | |
exports.geoPath = index; | |
exports.geoAlbers = albers; | |
exports.geoAlbersUsa = albersUsa; | |
exports.geoAzimuthalEqualArea = azimuthalEqualArea; | |
exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; | |
exports.geoAzimuthalEquidistant = azimuthalEquidistant; | |
exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; | |
exports.geoConicConformal = conicConformal; | |
exports.geoConicConformalRaw = conicConformalRaw; | |
exports.geoConicEqualArea = conicEqualArea; | |
exports.geoConicEqualAreaRaw = conicEqualAreaRaw; | |
exports.geoConicEquidistant = conicEquidistant; | |
exports.geoConicEquidistantRaw = conicEquidistantRaw; | |
exports.geoEquirectangular = equirectangular; | |
exports.geoEquirectangularRaw = equirectangularRaw; | |
exports.geoGnomonic = gnomonic; | |
exports.geoGnomonicRaw = gnomonicRaw; | |
exports.geoIdentity = identity$1; | |
exports.geoProjection = projection; | |
exports.geoProjectionMutator = projectionMutator; | |
exports.geoMercator = mercator; | |
exports.geoMercatorRaw = mercatorRaw; | |
exports.geoOrthographic = orthographic; | |
exports.geoOrthographicRaw = orthographicRaw; | |
exports.geoStereographic = stereographic; | |
exports.geoStereographicRaw = stereographicRaw; | |
exports.geoTransverseMercator = transverseMercator; | |
exports.geoTransverseMercatorRaw = transverseMercatorRaw; | |
exports.geoRotation = rotation; | |
exports.geoStream = geoStream; | |
exports.geoTransform = transform; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-array":15}],28:[function(require,module,exports){ | |
// https://d3js.org/d3-hierarchy/ Version 1.1.5. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
function defaultSeparation(a, b) { | |
return a.parent === b.parent ? 1 : 2; | |
} | |
function meanX(children) { | |
return children.reduce(meanXReduce, 0) / children.length; | |
} | |
function meanXReduce(x, c) { | |
return x + c.x; | |
} | |
function maxY(children) { | |
return 1 + children.reduce(maxYReduce, 0); | |
} | |
function maxYReduce(y, c) { | |
return Math.max(y, c.y); | |
} | |
function leafLeft(node) { | |
var children; | |
while (children = node.children) node = children[0]; | |
return node; | |
} | |
function leafRight(node) { | |
var children; | |
while (children = node.children) node = children[children.length - 1]; | |
return node; | |
} | |
var cluster = function() { | |
var separation = defaultSeparation, | |
dx = 1, | |
dy = 1, | |
nodeSize = false; | |
function cluster(root) { | |
var previousNode, | |
x = 0; | |
// First walk, computing the initial x & y values. | |
root.eachAfter(function(node) { | |
var children = node.children; | |
if (children) { | |
node.x = meanX(children); | |
node.y = maxY(children); | |
} else { | |
node.x = previousNode ? x += separation(node, previousNode) : 0; | |
node.y = 0; | |
previousNode = node; | |
} | |
}); | |
var left = leafLeft(root), | |
right = leafRight(root), | |
x0 = left.x - separation(left, right) / 2, | |
x1 = right.x + separation(right, left) / 2; | |
// Second walk, normalizing x & y to the desired size. | |
return root.eachAfter(nodeSize ? function(node) { | |
node.x = (node.x - root.x) * dx; | |
node.y = (root.y - node.y) * dy; | |
} : function(node) { | |
node.x = (node.x - x0) / (x1 - x0) * dx; | |
node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; | |
}); | |
} | |
cluster.separation = function(x) { | |
return arguments.length ? (separation = x, cluster) : separation; | |
}; | |
cluster.size = function(x) { | |
return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); | |
}; | |
cluster.nodeSize = function(x) { | |
return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); | |
}; | |
return cluster; | |
}; | |
function count(node) { | |
var sum = 0, | |
children = node.children, | |
i = children && children.length; | |
if (!i) sum = 1; | |
else while (--i >= 0) sum += children[i].value; | |
node.value = sum; | |
} | |
var node_count = function() { | |
return this.eachAfter(count); | |
}; | |
var node_each = function(callback) { | |
var node = this, current, next = [node], children, i, n; | |
do { | |
current = next.reverse(), next = []; | |
while (node = current.pop()) { | |
callback(node), children = node.children; | |
if (children) for (i = 0, n = children.length; i < n; ++i) { | |
next.push(children[i]); | |
} | |
} | |
} while (next.length); | |
return this; | |
}; | |
var node_eachBefore = function(callback) { | |
var node = this, nodes = [node], children, i; | |
while (node = nodes.pop()) { | |
callback(node), children = node.children; | |
if (children) for (i = children.length - 1; i >= 0; --i) { | |
nodes.push(children[i]); | |
} | |
} | |
return this; | |
}; | |
var node_eachAfter = function(callback) { | |
var node = this, nodes = [node], next = [], children, i, n; | |
while (node = nodes.pop()) { | |
next.push(node), children = node.children; | |
if (children) for (i = 0, n = children.length; i < n; ++i) { | |
nodes.push(children[i]); | |
} | |
} | |
while (node = next.pop()) { | |
callback(node); | |
} | |
return this; | |
}; | |
var node_sum = function(value) { | |
return this.eachAfter(function(node) { | |
var sum = +value(node.data) || 0, | |
children = node.children, | |
i = children && children.length; | |
while (--i >= 0) sum += children[i].value; | |
node.value = sum; | |
}); | |
}; | |
var node_sort = function(compare) { | |
return this.eachBefore(function(node) { | |
if (node.children) { | |
node.children.sort(compare); | |
} | |
}); | |
}; | |
var node_path = function(end) { | |
var start = this, | |
ancestor = leastCommonAncestor(start, end), | |
nodes = [start]; | |
while (start !== ancestor) { | |
start = start.parent; | |
nodes.push(start); | |
} | |
var k = nodes.length; | |
while (end !== ancestor) { | |
nodes.splice(k, 0, end); | |
end = end.parent; | |
} | |
return nodes; | |
}; | |
function leastCommonAncestor(a, b) { | |
if (a === b) return a; | |
var aNodes = a.ancestors(), | |
bNodes = b.ancestors(), | |
c = null; | |
a = aNodes.pop(); | |
b = bNodes.pop(); | |
while (a === b) { | |
c = a; | |
a = aNodes.pop(); | |
b = bNodes.pop(); | |
} | |
return c; | |
} | |
var node_ancestors = function() { | |
var node = this, nodes = [node]; | |
while (node = node.parent) { | |
nodes.push(node); | |
} | |
return nodes; | |
}; | |
var node_descendants = function() { | |
var nodes = []; | |
this.each(function(node) { | |
nodes.push(node); | |
}); | |
return nodes; | |
}; | |
var node_leaves = function() { | |
var leaves = []; | |
this.eachBefore(function(node) { | |
if (!node.children) { | |
leaves.push(node); | |
} | |
}); | |
return leaves; | |
}; | |
var node_links = function() { | |
var root = this, links = []; | |
root.each(function(node) { | |
if (node !== root) { // Don’t include the root’s parent, if any. | |
links.push({source: node.parent, target: node}); | |
} | |
}); | |
return links; | |
}; | |
function hierarchy(data, children) { | |
var root = new Node(data), | |
valued = +data.value && (root.value = data.value), | |
node, | |
nodes = [root], | |
child, | |
childs, | |
i, | |
n; | |
if (children == null) children = defaultChildren; | |
while (node = nodes.pop()) { | |
if (valued) node.value = +node.data.value; | |
if ((childs = children(node.data)) && (n = childs.length)) { | |
node.children = new Array(n); | |
for (i = n - 1; i >= 0; --i) { | |
nodes.push(child = node.children[i] = new Node(childs[i])); | |
child.parent = node; | |
child.depth = node.depth + 1; | |
} | |
} | |
} | |
return root.eachBefore(computeHeight); | |
} | |
function node_copy() { | |
return hierarchy(this).eachBefore(copyData); | |
} | |
function defaultChildren(d) { | |
return d.children; | |
} | |
function copyData(node) { | |
node.data = node.data.data; | |
} | |
function computeHeight(node) { | |
var height = 0; | |
do node.height = height; | |
while ((node = node.parent) && (node.height < ++height)); | |
} | |
function Node(data) { | |
this.data = data; | |
this.depth = | |
this.height = 0; | |
this.parent = null; | |
} | |
Node.prototype = hierarchy.prototype = { | |
constructor: Node, | |
count: node_count, | |
each: node_each, | |
eachAfter: node_eachAfter, | |
eachBefore: node_eachBefore, | |
sum: node_sum, | |
sort: node_sort, | |
path: node_path, | |
ancestors: node_ancestors, | |
descendants: node_descendants, | |
leaves: node_leaves, | |
links: node_links, | |
copy: node_copy | |
}; | |
var slice = Array.prototype.slice; | |
function shuffle(array) { | |
var m = array.length, | |
t, | |
i; | |
while (m) { | |
i = Math.random() * m-- | 0; | |
t = array[m]; | |
array[m] = array[i]; | |
array[i] = t; | |
} | |
return array; | |
} | |
var enclose = function(circles) { | |
var i = 0, n = (circles = shuffle(slice.call(circles))).length, B = [], p, e; | |
while (i < n) { | |
p = circles[i]; | |
if (e && enclosesWeak(e, p)) ++i; | |
else e = encloseBasis(B = extendBasis(B, p)), i = 0; | |
} | |
return e; | |
}; | |
function extendBasis(B, p) { | |
var i, j; | |
if (enclosesWeakAll(p, B)) return [p]; | |
// If we get here then B must have at least one element. | |
for (i = 0; i < B.length; ++i) { | |
if (enclosesNot(p, B[i]) | |
&& enclosesWeakAll(encloseBasis2(B[i], p), B)) { | |
return [B[i], p]; | |
} | |
} | |
// If we get here then B must have at least two elements. | |
for (i = 0; i < B.length - 1; ++i) { | |
for (j = i + 1; j < B.length; ++j) { | |
if (enclosesNot(encloseBasis2(B[i], B[j]), p) | |
&& enclosesNot(encloseBasis2(B[i], p), B[j]) | |
&& enclosesNot(encloseBasis2(B[j], p), B[i]) | |
&& enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { | |
return [B[i], B[j], p]; | |
} | |
} | |
} | |
// If we get here then something is very wrong. | |
throw new Error; | |
} | |
function enclosesNot(a, b) { | |
var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; | |
return dr < 0 || dr * dr < dx * dx + dy * dy; | |
} | |
function enclosesWeak(a, b) { | |
var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; | |
return dr > 0 && dr * dr > dx * dx + dy * dy; | |
} | |
function enclosesWeakAll(a, B) { | |
for (var i = 0; i < B.length; ++i) { | |
if (!enclosesWeak(a, B[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function encloseBasis(B) { | |
switch (B.length) { | |
case 1: return encloseBasis1(B[0]); | |
case 2: return encloseBasis2(B[0], B[1]); | |
case 3: return encloseBasis3(B[0], B[1], B[2]); | |
} | |
} | |
function encloseBasis1(a) { | |
return { | |
x: a.x, | |
y: a.y, | |
r: a.r | |
}; | |
} | |
function encloseBasis2(a, b) { | |
var x1 = a.x, y1 = a.y, r1 = a.r, | |
x2 = b.x, y2 = b.y, r2 = b.r, | |
x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, | |
l = Math.sqrt(x21 * x21 + y21 * y21); | |
return { | |
x: (x1 + x2 + x21 / l * r21) / 2, | |
y: (y1 + y2 + y21 / l * r21) / 2, | |
r: (l + r1 + r2) / 2 | |
}; | |
} | |
function encloseBasis3(a, b, c) { | |
var x1 = a.x, y1 = a.y, r1 = a.r, | |
x2 = b.x, y2 = b.y, r2 = b.r, | |
x3 = c.x, y3 = c.y, r3 = c.r, | |
a2 = x1 - x2, | |
a3 = x1 - x3, | |
b2 = y1 - y2, | |
b3 = y1 - y3, | |
c2 = r2 - r1, | |
c3 = r3 - r1, | |
d1 = x1 * x1 + y1 * y1 - r1 * r1, | |
d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, | |
d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, | |
ab = a3 * b2 - a2 * b3, | |
xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, | |
xb = (b3 * c2 - b2 * c3) / ab, | |
ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, | |
yb = (a2 * c3 - a3 * c2) / ab, | |
A = xb * xb + yb * yb - 1, | |
B = 2 * (r1 + xa * xb + ya * yb), | |
C = xa * xa + ya * ya - r1 * r1, | |
r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); | |
return { | |
x: x1 + xa + xb * r, | |
y: y1 + ya + yb * r, | |
r: r | |
}; | |
} | |
function place(a, b, c) { | |
var ax = a.x, | |
ay = a.y, | |
da = b.r + c.r, | |
db = a.r + c.r, | |
dx = b.x - ax, | |
dy = b.y - ay, | |
dc = dx * dx + dy * dy; | |
if (dc) { | |
var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), | |
y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); | |
c.x = ax + x * dx + y * dy; | |
c.y = ay + x * dy - y * dx; | |
} else { | |
c.x = ax + db; | |
c.y = ay; | |
} | |
} | |
function intersects(a, b) { | |
var dx = b.x - a.x, | |
dy = b.y - a.y, | |
dr = a.r + b.r; | |
return dr * dr - 1e-6 > dx * dx + dy * dy; | |
} | |
function score(node) { | |
var a = node._, | |
b = node.next._, | |
ab = a.r + b.r, | |
dx = (a.x * b.r + b.x * a.r) / ab, | |
dy = (a.y * b.r + b.y * a.r) / ab; | |
return dx * dx + dy * dy; | |
} | |
function Node$1(circle) { | |
this._ = circle; | |
this.next = null; | |
this.previous = null; | |
} | |
function packEnclose(circles) { | |
if (!(n = circles.length)) return 0; | |
var a, b, c, n, aa, ca, i, j, k, sj, sk; | |
// Place the first circle. | |
a = circles[0], a.x = 0, a.y = 0; | |
if (!(n > 1)) return a.r; | |
// Place the second circle. | |
b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; | |
if (!(n > 2)) return a.r + b.r; | |
// Place the third circle. | |
place(b, a, c = circles[2]); | |
// Initialize the front-chain using the first three circles a, b and c. | |
a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); | |
a.next = c.previous = b; | |
b.next = a.previous = c; | |
c.next = b.previous = a; | |
// Attempt to place each remaining circle… | |
pack: for (i = 3; i < n; ++i) { | |
place(a._, b._, c = circles[i]), c = new Node$1(c); | |
// Find the closest intersecting circle on the front-chain, if any. | |
// “Closeness” is determined by linear distance along the front-chain. | |
// “Ahead” or “behind” is likewise determined by linear distance. | |
j = b.next, k = a.previous, sj = b._.r, sk = a._.r; | |
do { | |
if (sj <= sk) { | |
if (intersects(j._, c._)) { | |
b = j, a.next = b, b.previous = a, --i; | |
continue pack; | |
} | |
sj += j._.r, j = j.next; | |
} else { | |
if (intersects(k._, c._)) { | |
a = k, a.next = b, b.previous = a, --i; | |
continue pack; | |
} | |
sk += k._.r, k = k.previous; | |
} | |
} while (j !== k.next); | |
// Success! Insert the new circle c between a and b. | |
c.previous = a, c.next = b, a.next = b.previous = b = c; | |
// Compute the new closest circle pair to the centroid. | |
aa = score(a); | |
while ((c = c.next) !== b) { | |
if ((ca = score(c)) < aa) { | |
a = c, aa = ca; | |
} | |
} | |
b = a.next; | |
} | |
// Compute the enclosing circle of the front chain. | |
a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); | |
// Translate the circles to put the enclosing circle around the origin. | |
for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; | |
return c.r; | |
} | |
var siblings = function(circles) { | |
packEnclose(circles); | |
return circles; | |
}; | |
function optional(f) { | |
return f == null ? null : required(f); | |
} | |
function required(f) { | |
if (typeof f !== "function") throw new Error; | |
return f; | |
} | |
function constantZero() { | |
return 0; | |
} | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
function defaultRadius(d) { | |
return Math.sqrt(d.value); | |
} | |
var index = function() { | |
var radius = null, | |
dx = 1, | |
dy = 1, | |
padding = constantZero; | |
function pack(root) { | |
root.x = dx / 2, root.y = dy / 2; | |
if (radius) { | |
root.eachBefore(radiusLeaf(radius)) | |
.eachAfter(packChildren(padding, 0.5)) | |
.eachBefore(translateChild(1)); | |
} else { | |
root.eachBefore(radiusLeaf(defaultRadius)) | |
.eachAfter(packChildren(constantZero, 1)) | |
.eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) | |
.eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); | |
} | |
return root; | |
} | |
pack.radius = function(x) { | |
return arguments.length ? (radius = optional(x), pack) : radius; | |
}; | |
pack.size = function(x) { | |
return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; | |
}; | |
pack.padding = function(x) { | |
return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding; | |
}; | |
return pack; | |
}; | |
function radiusLeaf(radius) { | |
return function(node) { | |
if (!node.children) { | |
node.r = Math.max(0, +radius(node) || 0); | |
} | |
}; | |
} | |
function packChildren(padding, k) { | |
return function(node) { | |
if (children = node.children) { | |
var children, | |
i, | |
n = children.length, | |
r = padding(node) * k || 0, | |
e; | |
if (r) for (i = 0; i < n; ++i) children[i].r += r; | |
e = packEnclose(children); | |
if (r) for (i = 0; i < n; ++i) children[i].r -= r; | |
node.r = e + r; | |
} | |
}; | |
} | |
function translateChild(k) { | |
return function(node) { | |
var parent = node.parent; | |
node.r *= k; | |
if (parent) { | |
node.x = parent.x + k * node.x; | |
node.y = parent.y + k * node.y; | |
} | |
}; | |
} | |
var roundNode = function(node) { | |
node.x0 = Math.round(node.x0); | |
node.y0 = Math.round(node.y0); | |
node.x1 = Math.round(node.x1); | |
node.y1 = Math.round(node.y1); | |
}; | |
var treemapDice = function(parent, x0, y0, x1, y1) { | |
var nodes = parent.children, | |
node, | |
i = -1, | |
n = nodes.length, | |
k = parent.value && (x1 - x0) / parent.value; | |
while (++i < n) { | |
node = nodes[i], node.y0 = y0, node.y1 = y1; | |
node.x0 = x0, node.x1 = x0 += node.value * k; | |
} | |
}; | |
var partition = function() { | |
var dx = 1, | |
dy = 1, | |
padding = 0, | |
round = false; | |
function partition(root) { | |
var n = root.height + 1; | |
root.x0 = | |
root.y0 = padding; | |
root.x1 = dx; | |
root.y1 = dy / n; | |
root.eachBefore(positionNode(dy, n)); | |
if (round) root.eachBefore(roundNode); | |
return root; | |
} | |
function positionNode(dy, n) { | |
return function(node) { | |
if (node.children) { | |
treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); | |
} | |
var x0 = node.x0, | |
y0 = node.y0, | |
x1 = node.x1 - padding, | |
y1 = node.y1 - padding; | |
if (x1 < x0) x0 = x1 = (x0 + x1) / 2; | |
if (y1 < y0) y0 = y1 = (y0 + y1) / 2; | |
node.x0 = x0; | |
node.y0 = y0; | |
node.x1 = x1; | |
node.y1 = y1; | |
}; | |
} | |
partition.round = function(x) { | |
return arguments.length ? (round = !!x, partition) : round; | |
}; | |
partition.size = function(x) { | |
return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; | |
}; | |
partition.padding = function(x) { | |
return arguments.length ? (padding = +x, partition) : padding; | |
}; | |
return partition; | |
}; | |
var keyPrefix = "$"; | |
var preroot = {depth: -1}; | |
var ambiguous = {}; | |
function defaultId(d) { | |
return d.id; | |
} | |
function defaultParentId(d) { | |
return d.parentId; | |
} | |
var stratify = function() { | |
var id = defaultId, | |
parentId = defaultParentId; | |
function stratify(data) { | |
var d, | |
i, | |
n = data.length, | |
root, | |
parent, | |
node, | |
nodes = new Array(n), | |
nodeId, | |
nodeKey, | |
nodeByKey = {}; | |
for (i = 0; i < n; ++i) { | |
d = data[i], node = nodes[i] = new Node(d); | |
if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { | |
nodeKey = keyPrefix + (node.id = nodeId); | |
nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; | |
} | |
} | |
for (i = 0; i < n; ++i) { | |
node = nodes[i], nodeId = parentId(data[i], i, data); | |
if (nodeId == null || !(nodeId += "")) { | |
if (root) throw new Error("multiple roots"); | |
root = node; | |
} else { | |
parent = nodeByKey[keyPrefix + nodeId]; | |
if (!parent) throw new Error("missing: " + nodeId); | |
if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); | |
if (parent.children) parent.children.push(node); | |
else parent.children = [node]; | |
node.parent = parent; | |
} | |
} | |
if (!root) throw new Error("no root"); | |
root.parent = preroot; | |
root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); | |
root.parent = null; | |
if (n > 0) throw new Error("cycle"); | |
return root; | |
} | |
stratify.id = function(x) { | |
return arguments.length ? (id = required(x), stratify) : id; | |
}; | |
stratify.parentId = function(x) { | |
return arguments.length ? (parentId = required(x), stratify) : parentId; | |
}; | |
return stratify; | |
}; | |
function defaultSeparation$1(a, b) { | |
return a.parent === b.parent ? 1 : 2; | |
} | |
// function radialSeparation(a, b) { | |
// return (a.parent === b.parent ? 1 : 2) / a.depth; | |
// } | |
// This function is used to traverse the left contour of a subtree (or | |
// subforest). It returns the successor of v on this contour. This successor is | |
// either given by the leftmost child of v or by the thread of v. The function | |
// returns null if and only if v is on the highest level of its subtree. | |
function nextLeft(v) { | |
var children = v.children; | |
return children ? children[0] : v.t; | |
} | |
// This function works analogously to nextLeft. | |
function nextRight(v) { | |
var children = v.children; | |
return children ? children[children.length - 1] : v.t; | |
} | |
// Shifts the current subtree rooted at w+. This is done by increasing | |
// prelim(w+) and mod(w+) by shift. | |
function moveSubtree(wm, wp, shift) { | |
var change = shift / (wp.i - wm.i); | |
wp.c -= change; | |
wp.s += shift; | |
wm.c += change; | |
wp.z += shift; | |
wp.m += shift; | |
} | |
// All other shifts, applied to the smaller subtrees between w- and w+, are | |
// performed by this function. To prepare the shifts, we have to adjust | |
// change(w+), shift(w+), and change(w-). | |
function executeShifts(v) { | |
var shift = 0, | |
change = 0, | |
children = v.children, | |
i = children.length, | |
w; | |
while (--i >= 0) { | |
w = children[i]; | |
w.z += shift; | |
w.m += shift; | |
shift += w.s + (change += w.c); | |
} | |
} | |
// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, | |
// returns the specified (default) ancestor. | |
function nextAncestor(vim, v, ancestor) { | |
return vim.a.parent === v.parent ? vim.a : ancestor; | |
} | |
function TreeNode(node, i) { | |
this._ = node; | |
this.parent = null; | |
this.children = null; | |
this.A = null; // default ancestor | |
this.a = this; // ancestor | |
this.z = 0; // prelim | |
this.m = 0; // mod | |
this.c = 0; // change | |
this.s = 0; // shift | |
this.t = null; // thread | |
this.i = i; // number | |
} | |
TreeNode.prototype = Object.create(Node.prototype); | |
function treeRoot(root) { | |
var tree = new TreeNode(root, 0), | |
node, | |
nodes = [tree], | |
child, | |
children, | |
i, | |
n; | |
while (node = nodes.pop()) { | |
if (children = node._.children) { | |
node.children = new Array(n = children.length); | |
for (i = n - 1; i >= 0; --i) { | |
nodes.push(child = node.children[i] = new TreeNode(children[i], i)); | |
child.parent = node; | |
} | |
} | |
} | |
(tree.parent = new TreeNode(null, 0)).children = [tree]; | |
return tree; | |
} | |
// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm | |
var tree = function() { | |
var separation = defaultSeparation$1, | |
dx = 1, | |
dy = 1, | |
nodeSize = null; | |
function tree(root) { | |
var t = treeRoot(root); | |
// Compute the layout using Buchheim et al.’s algorithm. | |
t.eachAfter(firstWalk), t.parent.m = -t.z; | |
t.eachBefore(secondWalk); | |
// If a fixed node size is specified, scale x and y. | |
if (nodeSize) root.eachBefore(sizeNode); | |
// If a fixed tree size is specified, scale x and y based on the extent. | |
// Compute the left-most, right-most, and depth-most nodes for extents. | |
else { | |
var left = root, | |
right = root, | |
bottom = root; | |
root.eachBefore(function(node) { | |
if (node.x < left.x) left = node; | |
if (node.x > right.x) right = node; | |
if (node.depth > bottom.depth) bottom = node; | |
}); | |
var s = left === right ? 1 : separation(left, right) / 2, | |
tx = s - left.x, | |
kx = dx / (right.x + s + tx), | |
ky = dy / (bottom.depth || 1); | |
root.eachBefore(function(node) { | |
node.x = (node.x + tx) * kx; | |
node.y = node.depth * ky; | |
}); | |
} | |
return root; | |
} | |
// Computes a preliminary x-coordinate for v. Before that, FIRST WALK is | |
// applied recursively to the children of v, as well as the function | |
// APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the | |
// node v is placed to the midpoint of its outermost children. | |
function firstWalk(v) { | |
var children = v.children, | |
siblings = v.parent.children, | |
w = v.i ? siblings[v.i - 1] : null; | |
if (children) { | |
executeShifts(v); | |
var midpoint = (children[0].z + children[children.length - 1].z) / 2; | |
if (w) { | |
v.z = w.z + separation(v._, w._); | |
v.m = v.z - midpoint; | |
} else { | |
v.z = midpoint; | |
} | |
} else if (w) { | |
v.z = w.z + separation(v._, w._); | |
} | |
v.parent.A = apportion(v, w, v.parent.A || siblings[0]); | |
} | |
// Computes all real x-coordinates by summing up the modifiers recursively. | |
function secondWalk(v) { | |
v._.x = v.z + v.parent.m; | |
v.m += v.parent.m; | |
} | |
// The core of the algorithm. Here, a new subtree is combined with the | |
// previous subtrees. Threads are used to traverse the inside and outside | |
// contours of the left and right subtree up to the highest common level. The | |
// vertices used for the traversals are vi+, vi-, vo-, and vo+, where the | |
// superscript o means outside and i means inside, the subscript - means left | |
// subtree and + means right subtree. For summing up the modifiers along the | |
// contour, we use respective variables si+, si-, so-, and so+. Whenever two | |
// nodes of the inside contours conflict, we compute the left one of the | |
// greatest uncommon ancestors using the function ANCESTOR and call MOVE | |
// SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. | |
// Finally, we add a new thread (if necessary). | |
function apportion(v, w, ancestor) { | |
if (w) { | |
var vip = v, | |
vop = v, | |
vim = w, | |
vom = vip.parent.children[0], | |
sip = vip.m, | |
sop = vop.m, | |
sim = vim.m, | |
som = vom.m, | |
shift; | |
while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { | |
vom = nextLeft(vom); | |
vop = nextRight(vop); | |
vop.a = v; | |
shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); | |
if (shift > 0) { | |
moveSubtree(nextAncestor(vim, v, ancestor), v, shift); | |
sip += shift; | |
sop += shift; | |
} | |
sim += vim.m; | |
sip += vip.m; | |
som += vom.m; | |
sop += vop.m; | |
} | |
if (vim && !nextRight(vop)) { | |
vop.t = vim; | |
vop.m += sim - sop; | |
} | |
if (vip && !nextLeft(vom)) { | |
vom.t = vip; | |
vom.m += sip - som; | |
ancestor = v; | |
} | |
} | |
return ancestor; | |
} | |
function sizeNode(node) { | |
node.x *= dx; | |
node.y = node.depth * dy; | |
} | |
tree.separation = function(x) { | |
return arguments.length ? (separation = x, tree) : separation; | |
}; | |
tree.size = function(x) { | |
return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); | |
}; | |
tree.nodeSize = function(x) { | |
return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); | |
}; | |
return tree; | |
}; | |
var treemapSlice = function(parent, x0, y0, x1, y1) { | |
var nodes = parent.children, | |
node, | |
i = -1, | |
n = nodes.length, | |
k = parent.value && (y1 - y0) / parent.value; | |
while (++i < n) { | |
node = nodes[i], node.x0 = x0, node.x1 = x1; | |
node.y0 = y0, node.y1 = y0 += node.value * k; | |
} | |
}; | |
var phi = (1 + Math.sqrt(5)) / 2; | |
function squarifyRatio(ratio, parent, x0, y0, x1, y1) { | |
var rows = [], | |
nodes = parent.children, | |
row, | |
nodeValue, | |
i0 = 0, | |
i1 = 0, | |
n = nodes.length, | |
dx, dy, | |
value = parent.value, | |
sumValue, | |
minValue, | |
maxValue, | |
newRatio, | |
minRatio, | |
alpha, | |
beta; | |
while (i0 < n) { | |
dx = x1 - x0, dy = y1 - y0; | |
// Find the next non-empty node. | |
do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); | |
minValue = maxValue = sumValue; | |
alpha = Math.max(dy / dx, dx / dy) / (value * ratio); | |
beta = sumValue * sumValue * alpha; | |
minRatio = Math.max(maxValue / beta, beta / minValue); | |
// Keep adding nodes while the aspect ratio maintains or improves. | |
for (; i1 < n; ++i1) { | |
sumValue += nodeValue = nodes[i1].value; | |
if (nodeValue < minValue) minValue = nodeValue; | |
if (nodeValue > maxValue) maxValue = nodeValue; | |
beta = sumValue * sumValue * alpha; | |
newRatio = Math.max(maxValue / beta, beta / minValue); | |
if (newRatio > minRatio) { sumValue -= nodeValue; break; } | |
minRatio = newRatio; | |
} | |
// Position and record the row orientation. | |
rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); | |
if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); | |
else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); | |
value -= sumValue, i0 = i1; | |
} | |
return rows; | |
} | |
var squarify = ((function custom(ratio) { | |
function squarify(parent, x0, y0, x1, y1) { | |
squarifyRatio(ratio, parent, x0, y0, x1, y1); | |
} | |
squarify.ratio = function(x) { | |
return custom((x = +x) > 1 ? x : 1); | |
}; | |
return squarify; | |
}))(phi); | |
var index$1 = function() { | |
var tile = squarify, | |
round = false, | |
dx = 1, | |
dy = 1, | |
paddingStack = [0], | |
paddingInner = constantZero, | |
paddingTop = constantZero, | |
paddingRight = constantZero, | |
paddingBottom = constantZero, | |
paddingLeft = constantZero; | |
function treemap(root) { | |
root.x0 = | |
root.y0 = 0; | |
root.x1 = dx; | |
root.y1 = dy; | |
root.eachBefore(positionNode); | |
paddingStack = [0]; | |
if (round) root.eachBefore(roundNode); | |
return root; | |
} | |
function positionNode(node) { | |
var p = paddingStack[node.depth], | |
x0 = node.x0 + p, | |
y0 = node.y0 + p, | |
x1 = node.x1 - p, | |
y1 = node.y1 - p; | |
if (x1 < x0) x0 = x1 = (x0 + x1) / 2; | |
if (y1 < y0) y0 = y1 = (y0 + y1) / 2; | |
node.x0 = x0; | |
node.y0 = y0; | |
node.x1 = x1; | |
node.y1 = y1; | |
if (node.children) { | |
p = paddingStack[node.depth + 1] = paddingInner(node) / 2; | |
x0 += paddingLeft(node) - p; | |
y0 += paddingTop(node) - p; | |
x1 -= paddingRight(node) - p; | |
y1 -= paddingBottom(node) - p; | |
if (x1 < x0) x0 = x1 = (x0 + x1) / 2; | |
if (y1 < y0) y0 = y1 = (y0 + y1) / 2; | |
tile(node, x0, y0, x1, y1); | |
} | |
} | |
treemap.round = function(x) { | |
return arguments.length ? (round = !!x, treemap) : round; | |
}; | |
treemap.size = function(x) { | |
return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; | |
}; | |
treemap.tile = function(x) { | |
return arguments.length ? (tile = required(x), treemap) : tile; | |
}; | |
treemap.padding = function(x) { | |
return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); | |
}; | |
treemap.paddingInner = function(x) { | |
return arguments.length ? (paddingInner = typeof x === "function" ? x : constant(+x), treemap) : paddingInner; | |
}; | |
treemap.paddingOuter = function(x) { | |
return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); | |
}; | |
treemap.paddingTop = function(x) { | |
return arguments.length ? (paddingTop = typeof x === "function" ? x : constant(+x), treemap) : paddingTop; | |
}; | |
treemap.paddingRight = function(x) { | |
return arguments.length ? (paddingRight = typeof x === "function" ? x : constant(+x), treemap) : paddingRight; | |
}; | |
treemap.paddingBottom = function(x) { | |
return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant(+x), treemap) : paddingBottom; | |
}; | |
treemap.paddingLeft = function(x) { | |
return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant(+x), treemap) : paddingLeft; | |
}; | |
return treemap; | |
}; | |
var binary = function(parent, x0, y0, x1, y1) { | |
var nodes = parent.children, | |
i, n = nodes.length, | |
sum, sums = new Array(n + 1); | |
for (sums[0] = sum = i = 0; i < n; ++i) { | |
sums[i + 1] = sum += nodes[i].value; | |
} | |
partition(0, n, parent.value, x0, y0, x1, y1); | |
function partition(i, j, value, x0, y0, x1, y1) { | |
if (i >= j - 1) { | |
var node = nodes[i]; | |
node.x0 = x0, node.y0 = y0; | |
node.x1 = x1, node.y1 = y1; | |
return; | |
} | |
var valueOffset = sums[i], | |
valueTarget = (value / 2) + valueOffset, | |
k = i + 1, | |
hi = j - 1; | |
while (k < hi) { | |
var mid = k + hi >>> 1; | |
if (sums[mid] < valueTarget) k = mid + 1; | |
else hi = mid; | |
} | |
if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k; | |
var valueLeft = sums[k] - valueOffset, | |
valueRight = value - valueLeft; | |
if ((x1 - x0) > (y1 - y0)) { | |
var xk = (x0 * valueRight + x1 * valueLeft) / value; | |
partition(i, k, valueLeft, x0, y0, xk, y1); | |
partition(k, j, valueRight, xk, y0, x1, y1); | |
} else { | |
var yk = (y0 * valueRight + y1 * valueLeft) / value; | |
partition(i, k, valueLeft, x0, y0, x1, yk); | |
partition(k, j, valueRight, x0, yk, x1, y1); | |
} | |
} | |
}; | |
var sliceDice = function(parent, x0, y0, x1, y1) { | |
(parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); | |
}; | |
var resquarify = ((function custom(ratio) { | |
function resquarify(parent, x0, y0, x1, y1) { | |
if ((rows = parent._squarify) && (rows.ratio === ratio)) { | |
var rows, | |
row, | |
nodes, | |
i, | |
j = -1, | |
n, | |
m = rows.length, | |
value = parent.value; | |
while (++j < m) { | |
row = rows[j], nodes = row.children; | |
for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; | |
if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); | |
else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); | |
value -= row.value; | |
} | |
} else { | |
parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); | |
rows.ratio = ratio; | |
} | |
} | |
resquarify.ratio = function(x) { | |
return custom((x = +x) > 1 ? x : 1); | |
}; | |
return resquarify; | |
}))(phi); | |
exports.cluster = cluster; | |
exports.hierarchy = hierarchy; | |
exports.pack = index; | |
exports.packSiblings = siblings; | |
exports.packEnclose = enclose; | |
exports.partition = partition; | |
exports.stratify = stratify; | |
exports.tree = tree; | |
exports.treemap = index$1; | |
exports.treemapBinary = binary; | |
exports.treemapDice = treemapDice; | |
exports.treemapSlice = treemapSlice; | |
exports.treemapSliceDice = sliceDice; | |
exports.treemapSquarify = squarify; | |
exports.treemapResquarify = resquarify; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],29:[function(require,module,exports){ | |
// https://d3js.org/d3-interpolate/ Version 1.1.5. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-color')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3)); | |
}(this, (function (exports,d3Color) { 'use strict'; | |
function basis(t1, v0, v1, v2, v3) { | |
var t2 = t1 * t1, t3 = t2 * t1; | |
return ((1 - 3 * t1 + 3 * t2 - t3) * v0 | |
+ (4 - 6 * t2 + 3 * t3) * v1 | |
+ (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 | |
+ t3 * v3) / 6; | |
} | |
var basis$1 = function(values) { | |
var n = values.length - 1; | |
return function(t) { | |
var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), | |
v1 = values[i], | |
v2 = values[i + 1], | |
v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, | |
v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; | |
return basis((t - i / n) * n, v0, v1, v2, v3); | |
}; | |
}; | |
var basisClosed = function(values) { | |
var n = values.length; | |
return function(t) { | |
var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), | |
v0 = values[(i + n - 1) % n], | |
v1 = values[i % n], | |
v2 = values[(i + 1) % n], | |
v3 = values[(i + 2) % n]; | |
return basis((t - i / n) * n, v0, v1, v2, v3); | |
}; | |
}; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
function linear(a, d) { | |
return function(t) { | |
return a + t * d; | |
}; | |
} | |
function exponential(a, b, y) { | |
return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { | |
return Math.pow(a + t * b, y); | |
}; | |
} | |
function hue(a, b) { | |
var d = b - a; | |
return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); | |
} | |
function gamma(y) { | |
return (y = +y) === 1 ? nogamma : function(a, b) { | |
return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); | |
}; | |
} | |
function nogamma(a, b) { | |
var d = b - a; | |
return d ? linear(a, d) : constant(isNaN(a) ? b : a); | |
} | |
var rgb$1 = ((function rgbGamma(y) { | |
var color$$1 = gamma(y); | |
function rgb$$1(start, end) { | |
var r = color$$1((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), | |
g = color$$1(start.g, end.g), | |
b = color$$1(start.b, end.b), | |
opacity = nogamma(start.opacity, end.opacity); | |
return function(t) { | |
start.r = r(t); | |
start.g = g(t); | |
start.b = b(t); | |
start.opacity = opacity(t); | |
return start + ""; | |
}; | |
} | |
rgb$$1.gamma = rgbGamma; | |
return rgb$$1; | |
}))(1); | |
function rgbSpline(spline) { | |
return function(colors) { | |
var n = colors.length, | |
r = new Array(n), | |
g = new Array(n), | |
b = new Array(n), | |
i, color$$1; | |
for (i = 0; i < n; ++i) { | |
color$$1 = d3Color.rgb(colors[i]); | |
r[i] = color$$1.r || 0; | |
g[i] = color$$1.g || 0; | |
b[i] = color$$1.b || 0; | |
} | |
r = spline(r); | |
g = spline(g); | |
b = spline(b); | |
color$$1.opacity = 1; | |
return function(t) { | |
color$$1.r = r(t); | |
color$$1.g = g(t); | |
color$$1.b = b(t); | |
return color$$1 + ""; | |
}; | |
}; | |
} | |
var rgbBasis = rgbSpline(basis$1); | |
var rgbBasisClosed = rgbSpline(basisClosed); | |
var array = function(a, b) { | |
var nb = b ? b.length : 0, | |
na = a ? Math.min(nb, a.length) : 0, | |
x = new Array(nb), | |
c = new Array(nb), | |
i; | |
for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]); | |
for (; i < nb; ++i) c[i] = b[i]; | |
return function(t) { | |
for (i = 0; i < na; ++i) c[i] = x[i](t); | |
return c; | |
}; | |
}; | |
var date = function(a, b) { | |
var d = new Date; | |
return a = +a, b -= a, function(t) { | |
return d.setTime(a + b * t), d; | |
}; | |
}; | |
var number = function(a, b) { | |
return a = +a, b -= a, function(t) { | |
return a + b * t; | |
}; | |
}; | |
var object = function(a, b) { | |
var i = {}, | |
c = {}, | |
k; | |
if (a === null || typeof a !== "object") a = {}; | |
if (b === null || typeof b !== "object") b = {}; | |
for (k in b) { | |
if (k in a) { | |
i[k] = value(a[k], b[k]); | |
} else { | |
c[k] = b[k]; | |
} | |
} | |
return function(t) { | |
for (k in i) c[k] = i[k](t); | |
return c; | |
}; | |
}; | |
var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; | |
var reB = new RegExp(reA.source, "g"); | |
function zero(b) { | |
return function() { | |
return b; | |
}; | |
} | |
function one(b) { | |
return function(t) { | |
return b(t) + ""; | |
}; | |
} | |
var string = function(a, b) { | |
var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b | |
am, // current match in a | |
bm, // current match in b | |
bs, // string preceding current number in b, if any | |
i = -1, // index in s | |
s = [], // string constants and placeholders | |
q = []; // number interpolators | |
// Coerce inputs to strings. | |
a = a + "", b = b + ""; | |
// Interpolate pairs of numbers in a & b. | |
while ((am = reA.exec(a)) | |
&& (bm = reB.exec(b))) { | |
if ((bs = bm.index) > bi) { // a string precedes the next number in b | |
bs = b.slice(bi, bs); | |
if (s[i]) s[i] += bs; // coalesce with previous string | |
else s[++i] = bs; | |
} | |
if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match | |
if (s[i]) s[i] += bm; // coalesce with previous string | |
else s[++i] = bm; | |
} else { // interpolate non-matching numbers | |
s[++i] = null; | |
q.push({i: i, x: number(am, bm)}); | |
} | |
bi = reB.lastIndex; | |
} | |
// Add remains of b. | |
if (bi < b.length) { | |
bs = b.slice(bi); | |
if (s[i]) s[i] += bs; // coalesce with previous string | |
else s[++i] = bs; | |
} | |
// Special optimization for only a single match. | |
// Otherwise, interpolate each of the numbers and rejoin the string. | |
return s.length < 2 ? (q[0] | |
? one(q[0].x) | |
: zero(b)) | |
: (b = q.length, function(t) { | |
for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}); | |
}; | |
var value = function(a, b) { | |
var t = typeof b, c; | |
return b == null || t === "boolean" ? constant(b) | |
: (t === "number" ? number | |
: t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb$1) : string) | |
: b instanceof d3Color.color ? rgb$1 | |
: b instanceof Date ? date | |
: Array.isArray(b) ? array | |
: typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object | |
: number)(a, b); | |
}; | |
var round = function(a, b) { | |
return a = +a, b -= a, function(t) { | |
return Math.round(a + b * t); | |
}; | |
}; | |
var degrees = 180 / Math.PI; | |
var identity = { | |
translateX: 0, | |
translateY: 0, | |
rotate: 0, | |
skewX: 0, | |
scaleX: 1, | |
scaleY: 1 | |
}; | |
var decompose = function(a, b, c, d, e, f) { | |
var scaleX, scaleY, skewX; | |
if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; | |
if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; | |
if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; | |
if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; | |
return { | |
translateX: e, | |
translateY: f, | |
rotate: Math.atan2(b, a) * degrees, | |
skewX: Math.atan(skewX) * degrees, | |
scaleX: scaleX, | |
scaleY: scaleY | |
}; | |
}; | |
var cssNode; | |
var cssRoot; | |
var cssView; | |
var svgNode; | |
function parseCss(value) { | |
if (value === "none") return identity; | |
if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; | |
cssNode.style.transform = value; | |
value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); | |
cssRoot.removeChild(cssNode); | |
value = value.slice(7, -1).split(","); | |
return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); | |
} | |
function parseSvg(value) { | |
if (value == null) return identity; | |
if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); | |
svgNode.setAttribute("transform", value); | |
if (!(value = svgNode.transform.baseVal.consolidate())) return identity; | |
value = value.matrix; | |
return decompose(value.a, value.b, value.c, value.d, value.e, value.f); | |
} | |
function interpolateTransform(parse, pxComma, pxParen, degParen) { | |
function pop(s) { | |
return s.length ? s.pop() + " " : ""; | |
} | |
function translate(xa, ya, xb, yb, s, q) { | |
if (xa !== xb || ya !== yb) { | |
var i = s.push("translate(", null, pxComma, null, pxParen); | |
q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); | |
} else if (xb || yb) { | |
s.push("translate(" + xb + pxComma + yb + pxParen); | |
} | |
} | |
function rotate(a, b, s, q) { | |
if (a !== b) { | |
if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path | |
q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); | |
} else if (b) { | |
s.push(pop(s) + "rotate(" + b + degParen); | |
} | |
} | |
function skewX(a, b, s, q) { | |
if (a !== b) { | |
q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); | |
} else if (b) { | |
s.push(pop(s) + "skewX(" + b + degParen); | |
} | |
} | |
function scale(xa, ya, xb, yb, s, q) { | |
if (xa !== xb || ya !== yb) { | |
var i = s.push(pop(s) + "scale(", null, ",", null, ")"); | |
q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); | |
} else if (xb !== 1 || yb !== 1) { | |
s.push(pop(s) + "scale(" + xb + "," + yb + ")"); | |
} | |
} | |
return function(a, b) { | |
var s = [], // string constants and placeholders | |
q = []; // number interpolators | |
a = parse(a), b = parse(b); | |
translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); | |
rotate(a.rotate, b.rotate, s, q); | |
skewX(a.skewX, b.skewX, s, q); | |
scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); | |
a = b = null; // gc | |
return function(t) { | |
var i = -1, n = q.length, o; | |
while (++i < n) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}; | |
}; | |
} | |
var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); | |
var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); | |
var rho = Math.SQRT2; | |
var rho2 = 2; | |
var rho4 = 4; | |
var epsilon2 = 1e-12; | |
function cosh(x) { | |
return ((x = Math.exp(x)) + 1 / x) / 2; | |
} | |
function sinh(x) { | |
return ((x = Math.exp(x)) - 1 / x) / 2; | |
} | |
function tanh(x) { | |
return ((x = Math.exp(2 * x)) - 1) / (x + 1); | |
} | |
// p0 = [ux0, uy0, w0] | |
// p1 = [ux1, uy1, w1] | |
var zoom = function(p0, p1) { | |
var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], | |
ux1 = p1[0], uy1 = p1[1], w1 = p1[2], | |
dx = ux1 - ux0, | |
dy = uy1 - uy0, | |
d2 = dx * dx + dy * dy, | |
i, | |
S; | |
// Special case for u0 ≅ u1. | |
if (d2 < epsilon2) { | |
S = Math.log(w1 / w0) / rho; | |
i = function(t) { | |
return [ | |
ux0 + t * dx, | |
uy0 + t * dy, | |
w0 * Math.exp(rho * t * S) | |
]; | |
}; | |
} | |
// General case. | |
else { | |
var d1 = Math.sqrt(d2), | |
b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), | |
b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), | |
r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), | |
r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); | |
S = (r1 - r0) / rho; | |
i = function(t) { | |
var s = t * S, | |
coshr0 = cosh(r0), | |
u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); | |
return [ | |
ux0 + u * dx, | |
uy0 + u * dy, | |
w0 * coshr0 / cosh(rho * s + r0) | |
]; | |
}; | |
} | |
i.duration = S * 1000; | |
return i; | |
}; | |
function hsl$1(hue$$1) { | |
return function(start, end) { | |
var h = hue$$1((start = d3Color.hsl(start)).h, (end = d3Color.hsl(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(t); | |
start.opacity = opacity(t); | |
return start + ""; | |
}; | |
} | |
} | |
var hsl$2 = hsl$1(hue); | |
var hslLong = hsl$1(nogamma); | |
function lab$1(start, end) { | |
var l = nogamma((start = d3Color.lab(start)).l, (end = d3Color.lab(end)).l), | |
a = nogamma(start.a, end.a), | |
b = nogamma(start.b, end.b), | |
opacity = nogamma(start.opacity, end.opacity); | |
return function(t) { | |
start.l = l(t); | |
start.a = a(t); | |
start.b = b(t); | |
start.opacity = opacity(t); | |
return start + ""; | |
}; | |
} | |
function hcl$1(hue$$1) { | |
return function(start, end) { | |
var h = hue$$1((start = d3Color.hcl(start)).h, (end = d3Color.hcl(end)).h), | |
c = nogamma(start.c, end.c), | |
l = nogamma(start.l, end.l), | |
opacity = nogamma(start.opacity, end.opacity); | |
return function(t) { | |
start.h = h(t); | |
start.c = c(t); | |
start.l = l(t); | |
start.opacity = opacity(t); | |
return start + ""; | |
}; | |
} | |
} | |
var hcl$2 = hcl$1(hue); | |
var hclLong = hcl$1(nogamma); | |
function cubehelix$1(hue$$1) { | |
return (function cubehelixGamma(y) { | |
y = +y; | |
function cubehelix$$1(start, end) { | |
var h = hue$$1((start = d3Color.cubehelix(start)).h, (end = d3Color.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); | |
} | |
var cubehelix$2 = cubehelix$1(hue); | |
var cubehelixLong = cubehelix$1(nogamma); | |
var quantize = function(interpolator, n) { | |
var samples = new Array(n); | |
for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); | |
return samples; | |
}; | |
exports.interpolate = value; | |
exports.interpolateArray = array; | |
exports.interpolateBasis = basis$1; | |
exports.interpolateBasisClosed = basisClosed; | |
exports.interpolateDate = date; | |
exports.interpolateNumber = number; | |
exports.interpolateObject = object; | |
exports.interpolateRound = round; | |
exports.interpolateString = string; | |
exports.interpolateTransformCss = interpolateTransformCss; | |
exports.interpolateTransformSvg = interpolateTransformSvg; | |
exports.interpolateZoom = zoom; | |
exports.interpolateRgb = rgb$1; | |
exports.interpolateRgbBasis = rgbBasis; | |
exports.interpolateRgbBasisClosed = rgbBasisClosed; | |
exports.interpolateHsl = hsl$2; | |
exports.interpolateHslLong = hslLong; | |
exports.interpolateLab = lab$1; | |
exports.interpolateHcl = hcl$2; | |
exports.interpolateHclLong = hclLong; | |
exports.interpolateCubehelix = cubehelix$2; | |
exports.interpolateCubehelixLong = cubehelixLong; | |
exports.quantize = quantize; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-color":20}],30:[function(require,module,exports){ | |
// https://d3js.org/d3-path/ Version 1.0.5. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var pi = Math.PI; | |
var tau = 2 * pi; | |
var epsilon = 1e-6; | |
var tauEpsilon = tau - epsilon; | |
function Path() { | |
this._x0 = this._y0 = // start of current subpath | |
this._x1 = this._y1 = null; // end of current subpath | |
this._ = ""; | |
} | |
function path() { | |
return new Path; | |
} | |
Path.prototype = path.prototype = { | |
constructor: Path, | |
moveTo: function(x, y) { | |
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); | |
}, | |
closePath: function() { | |
if (this._x1 !== null) { | |
this._x1 = this._x0, this._y1 = this._y0; | |
this._ += "Z"; | |
} | |
}, | |
lineTo: function(x, y) { | |
this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); | |
}, | |
quadraticCurveTo: function(x1, y1, x, y) { | |
this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); | |
}, | |
bezierCurveTo: function(x1, y1, x2, y2, x, y) { | |
this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); | |
}, | |
arcTo: function(x1, y1, x2, y2, r) { | |
x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; | |
var x0 = this._x1, | |
y0 = this._y1, | |
x21 = x2 - x1, | |
y21 = y2 - y1, | |
x01 = x0 - x1, | |
y01 = y0 - y1, | |
l01_2 = x01 * x01 + y01 * y01; | |
// Is the radius negative? Error. | |
if (r < 0) throw new Error("negative radius: " + r); | |
// Is this path empty? Move to (x1,y1). | |
if (this._x1 === null) { | |
this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); | |
} | |
// Or, is (x1,y1) coincident with (x0,y0)? Do nothing. | |
else if (!(l01_2 > epsilon)) {} | |
// Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? | |
// Equivalently, is (x1,y1) coincident with (x2,y2)? | |
// Or, is the radius zero? Line to (x1,y1). | |
else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { | |
this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); | |
} | |
// Otherwise, draw an arc! | |
else { | |
var x20 = x2 - x0, | |
y20 = y2 - y0, | |
l21_2 = x21 * x21 + y21 * y21, | |
l20_2 = x20 * x20 + y20 * y20, | |
l21 = Math.sqrt(l21_2), | |
l01 = Math.sqrt(l01_2), | |
l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), | |
t01 = l / l01, | |
t21 = l / l21; | |
// If the start tangent is not coincident with (x0,y0), line to. | |
if (Math.abs(t01 - 1) > epsilon) { | |
this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); | |
} | |
this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); | |
} | |
}, | |
arc: function(x, y, r, a0, a1, ccw) { | |
x = +x, y = +y, r = +r; | |
var dx = r * Math.cos(a0), | |
dy = r * Math.sin(a0), | |
x0 = x + dx, | |
y0 = y + dy, | |
cw = 1 ^ ccw, | |
da = ccw ? a0 - a1 : a1 - a0; | |
// Is the radius negative? Error. | |
if (r < 0) throw new Error("negative radius: " + r); | |
// Is this path empty? Move to (x0,y0). | |
if (this._x1 === null) { | |
this._ += "M" + x0 + "," + y0; | |
} | |
// Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). | |
else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { | |
this._ += "L" + x0 + "," + y0; | |
} | |
// Is this arc empty? We’re done. | |
if (!r) return; | |
// Does the angle go the wrong way? Flip the direction. | |
if (da < 0) da = da % tau + tau; | |
// Is this a complete circle? Draw two arcs to complete the circle. | |
if (da > tauEpsilon) { | |
this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); | |
} | |
// Is this arc non-empty? Draw an arc! | |
else if (da > epsilon) { | |
this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); | |
} | |
}, | |
rect: function(x, y, w, h) { | |
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; | |
}, | |
toString: function() { | |
return this._; | |
} | |
}; | |
exports.path = path; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],31:[function(require,module,exports){ | |
// https://d3js.org/d3-polygon/ Version 1.0.3. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var area = function(polygon) { | |
var i = -1, | |
n = polygon.length, | |
a, | |
b = polygon[n - 1], | |
area = 0; | |
while (++i < n) { | |
a = b; | |
b = polygon[i]; | |
area += a[1] * b[0] - a[0] * b[1]; | |
} | |
return area / 2; | |
}; | |
var centroid = function(polygon) { | |
var i = -1, | |
n = polygon.length, | |
x = 0, | |
y = 0, | |
a, | |
b = polygon[n - 1], | |
c, | |
k = 0; | |
while (++i < n) { | |
a = b; | |
b = polygon[i]; | |
k += c = a[0] * b[1] - b[0] * a[1]; | |
x += (a[0] + b[0]) * c; | |
y += (a[1] + b[1]) * c; | |
} | |
return k *= 3, [x / k, y / k]; | |
}; | |
// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of | |
// the 3D cross product in a quadrant I Cartesian coordinate system (+x is | |
// right, +y is up). Returns a positive value if ABC is counter-clockwise, | |
// negative if clockwise, and zero if the points are collinear. | |
var cross = function(a, b, c) { | |
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); | |
}; | |
function lexicographicOrder(a, b) { | |
return a[0] - b[0] || a[1] - b[1]; | |
} | |
// Computes the upper convex hull per the monotone chain algorithm. | |
// Assumes points.length >= 3, is sorted by x, unique in y. | |
// Returns an array of indices into points in left-to-right order. | |
function computeUpperHullIndexes(points) { | |
var n = points.length, | |
indexes = [0, 1], | |
size = 2; | |
for (var i = 2; i < n; ++i) { | |
while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; | |
indexes[size++] = i; | |
} | |
return indexes.slice(0, size); // remove popped points | |
} | |
var hull = function(points) { | |
if ((n = points.length) < 3) return null; | |
var i, | |
n, | |
sortedPoints = new Array(n), | |
flippedPoints = new Array(n); | |
for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; | |
sortedPoints.sort(lexicographicOrder); | |
for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; | |
var upperIndexes = computeUpperHullIndexes(sortedPoints), | |
lowerIndexes = computeUpperHullIndexes(flippedPoints); | |
// Construct the hull polygon, removing possible duplicate endpoints. | |
var skipLeft = lowerIndexes[0] === upperIndexes[0], | |
skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], | |
hull = []; | |
// Add upper hull in right-to-l order. | |
// Then add lower hull in left-to-right order. | |
for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); | |
for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); | |
return hull; | |
}; | |
var contains = function(polygon, point) { | |
var n = polygon.length, | |
p = polygon[n - 1], | |
x = point[0], y = point[1], | |
x0 = p[0], y0 = p[1], | |
x1, y1, | |
inside = false; | |
for (var i = 0; i < n; ++i) { | |
p = polygon[i], x1 = p[0], y1 = p[1]; | |
if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; | |
x0 = x1, y0 = y1; | |
} | |
return inside; | |
}; | |
var length = function(polygon) { | |
var i = -1, | |
n = polygon.length, | |
b = polygon[n - 1], | |
xa, | |
ya, | |
xb = b[0], | |
yb = b[1], | |
perimeter = 0; | |
while (++i < n) { | |
xa = xb; | |
ya = yb; | |
b = polygon[i]; | |
xb = b[0]; | |
yb = b[1]; | |
xa -= xb; | |
ya -= yb; | |
perimeter += Math.sqrt(xa * xa + ya * ya); | |
} | |
return perimeter; | |
}; | |
exports.polygonArea = area; | |
exports.polygonCentroid = centroid; | |
exports.polygonHull = hull; | |
exports.polygonContains = contains; | |
exports.polygonLength = length; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],32:[function(require,module,exports){ | |
// https://d3js.org/d3-quadtree/ Version 1.0.3. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
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; | |
} | |
// Otherwise, double repeatedly to cover. | |
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; | |
} | |
// If the quadtree covers the point already, just return. | |
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; | |
} | |
} | |
// Visit this point. (Visiting coincident points isn’t necessary!) | |
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; | |
exports.quadtree = quadtree; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],33:[function(require,module,exports){ | |
// https://d3js.org/d3-queue/ Version 3.0.7. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var slice = [].slice; | |
var noabort = {}; | |
function Queue(size) { | |
this._size = size; | |
this._call = | |
this._error = null; | |
this._tasks = []; | |
this._data = []; | |
this._waiting = | |
this._active = | |
this._ended = | |
this._start = 0; // inside a synchronous task callback? | |
} | |
Queue.prototype = queue.prototype = { | |
constructor: Queue, | |
defer: function(callback) { | |
if (typeof callback !== "function") throw new Error("invalid callback"); | |
if (this._call) throw new Error("defer after await"); | |
if (this._error != null) return this; | |
var t = slice.call(arguments, 1); | |
t.push(callback); | |
++this._waiting, this._tasks.push(t); | |
poke(this); | |
return this; | |
}, | |
abort: function() { | |
if (this._error == null) abort(this, new Error("abort")); | |
return this; | |
}, | |
await: function(callback) { | |
if (typeof callback !== "function") throw new Error("invalid callback"); | |
if (this._call) throw new Error("multiple await"); | |
this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; | |
maybeNotify(this); | |
return this; | |
}, | |
awaitAll: function(callback) { | |
if (typeof callback !== "function") throw new Error("invalid callback"); | |
if (this._call) throw new Error("multiple await"); | |
this._call = callback; | |
maybeNotify(this); | |
return this; | |
} | |
}; | |
function poke(q) { | |
if (!q._start) { | |
try { start(q); } // let the current task complete | |
catch (e) { | |
if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously | |
else if (!q._data) throw e; // await callback errored synchronously | |
} | |
} | |
} | |
function start(q) { | |
while (q._start = q._waiting && q._active < q._size) { | |
var i = q._ended + q._active, | |
t = q._tasks[i], | |
j = t.length - 1, | |
c = t[j]; | |
t[j] = end(q, i); | |
--q._waiting, ++q._active; | |
t = c.apply(null, t); | |
if (!q._tasks[i]) continue; // task finished synchronously | |
q._tasks[i] = t || noabort; | |
} | |
} | |
function end(q, i) { | |
return function(e, r) { | |
if (!q._tasks[i]) return; // ignore multiple callbacks | |
--q._active, ++q._ended; | |
q._tasks[i] = null; | |
if (q._error != null) return; // ignore secondary errors | |
if (e != null) { | |
abort(q, e); | |
} else { | |
q._data[i] = r; | |
if (q._waiting) poke(q); | |
else maybeNotify(q); | |
} | |
}; | |
} | |
function abort(q, e) { | |
var i = q._tasks.length, t; | |
q._error = e; // ignore active callbacks | |
q._data = undefined; // allow gc | |
q._waiting = NaN; // prevent starting | |
while (--i >= 0) { | |
if (t = q._tasks[i]) { | |
q._tasks[i] = null; | |
if (t.abort) { | |
try { t.abort(); } | |
catch (e) { /* ignore */ } | |
} | |
} | |
} | |
q._active = NaN; // allow notification | |
maybeNotify(q); | |
} | |
function maybeNotify(q) { | |
if (!q._active && q._call) { | |
var d = q._data; | |
q._data = undefined; // allow gc | |
q._call(q._error, d); | |
} | |
} | |
function queue(concurrency) { | |
if (concurrency == null) concurrency = Infinity; | |
else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency"); | |
return new Queue(concurrency); | |
} | |
exports.queue = queue; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],34:[function(require,module,exports){ | |
// https://d3js.org/d3-random/ Version 1.1.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var defaultSource = function() { | |
return Math.random(); | |
}; | |
var uniform = ((function sourceRandomUniform(source) { | |
function randomUniform(min, max) { | |
min = min == null ? 0 : +min; | |
max = max == null ? 1 : +max; | |
if (arguments.length === 1) max = min, min = 0; | |
else max -= min; | |
return function() { | |
return source() * max + min; | |
}; | |
} | |
randomUniform.source = sourceRandomUniform; | |
return randomUniform; | |
}))(defaultSource); | |
var normal = ((function sourceRandomNormal(source) { | |
function randomNormal(mu, sigma) { | |
var x, r; | |
mu = mu == null ? 0 : +mu; | |
sigma = sigma == null ? 1 : +sigma; | |
return function() { | |
var y; | |
// If available, use the second previously-generated uniform random. | |
if (x != null) y = x, x = null; | |
// Otherwise, generate a new x and y. | |
else do { | |
x = source() * 2 - 1; | |
y = source() * 2 - 1; | |
r = x * x + y * y; | |
} while (!r || r > 1); | |
return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); | |
}; | |
} | |
randomNormal.source = sourceRandomNormal; | |
return randomNormal; | |
}))(defaultSource); | |
var logNormal = ((function sourceRandomLogNormal(source) { | |
function randomLogNormal() { | |
var randomNormal = normal.source(source).apply(this, arguments); | |
return function() { | |
return Math.exp(randomNormal()); | |
}; | |
} | |
randomLogNormal.source = sourceRandomLogNormal; | |
return randomLogNormal; | |
}))(defaultSource); | |
var irwinHall = ((function sourceRandomIrwinHall(source) { | |
function randomIrwinHall(n) { | |
return function() { | |
for (var sum = 0, i = 0; i < n; ++i) sum += source(); | |
return sum; | |
}; | |
} | |
randomIrwinHall.source = sourceRandomIrwinHall; | |
return randomIrwinHall; | |
}))(defaultSource); | |
var bates = ((function sourceRandomBates(source) { | |
function randomBates(n) { | |
var randomIrwinHall = irwinHall.source(source)(n); | |
return function() { | |
return randomIrwinHall() / n; | |
}; | |
} | |
randomBates.source = sourceRandomBates; | |
return randomBates; | |
}))(defaultSource); | |
var exponential = ((function sourceRandomExponential(source) { | |
function randomExponential(lambda) { | |
return function() { | |
return -Math.log(1 - source()) / lambda; | |
}; | |
} | |
randomExponential.source = sourceRandomExponential; | |
return randomExponential; | |
}))(defaultSource); | |
exports.randomUniform = uniform; | |
exports.randomNormal = normal; | |
exports.randomLogNormal = logNormal; | |
exports.randomBates = bates; | |
exports.randomIrwinHall = irwinHall; | |
exports.randomExponential = exponential; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],35:[function(require,module,exports){ | |
'use strict'; | |
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
var d3Collection = require('d3-collection'); | |
var d3Dispatch = require('d3-dispatch'); | |
var d3Dsv = require('d3-dsv'); | |
var request = function(url, callback) { | |
var request, | |
event = d3Dispatch.dispatch("beforesend", "progress", "load", "error"), | |
mimeType, | |
headers = d3Collection.map(), | |
xhr = new XMLHttpRequest, | |
user = null, | |
password = null, | |
response, | |
responseType, | |
timeout = 0; | |
// If IE does not support CORS, use XDomainRequest. | |
if (typeof XDomainRequest !== "undefined" | |
&& !("withCredentials" in xhr) | |
&& /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; | |
"onload" in xhr | |
? xhr.onload = xhr.onerror = xhr.ontimeout = respond | |
: xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; | |
function respond(o) { | |
var status = xhr.status, result; | |
if (!status && hasResponse(xhr) | |
|| status >= 200 && status < 300 | |
|| status === 304) { | |
if (response) { | |
try { | |
result = response.call(request, xhr); | |
} catch (e) { | |
event.call("error", request, e); | |
return; | |
} | |
} else { | |
result = xhr; | |
} | |
event.call("load", request, result); | |
} else { | |
event.call("error", request, o); | |
} | |
} | |
xhr.onprogress = function(e) { | |
event.call("progress", request, e); | |
}; | |
request = { | |
header: function(name, value) { | |
name = (name + "").toLowerCase(); | |
if (arguments.length < 2) return headers.get(name); | |
if (value == null) headers.remove(name); | |
else headers.set(name, value + ""); | |
return request; | |
}, | |
// If mimeType is non-null and no Accept header is set, a default is used. | |
mimeType: function(value) { | |
if (!arguments.length) return mimeType; | |
mimeType = value == null ? null : value + ""; | |
return request; | |
}, | |
// Specifies what type the response value should take; | |
// for instance, arraybuffer, blob, document, or text. | |
responseType: function(value) { | |
if (!arguments.length) return responseType; | |
responseType = value; | |
return request; | |
}, | |
timeout: function(value) { | |
if (!arguments.length) return timeout; | |
timeout = +value; | |
return request; | |
}, | |
user: function(value) { | |
return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); | |
}, | |
password: function(value) { | |
return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); | |
}, | |
// Specify how to convert the response content to a specific type; | |
// changes the callback value on "load" events. | |
response: function(value) { | |
response = value; | |
return request; | |
}, | |
// Alias for send("GET", …). | |
get: function(data, callback) { | |
return request.send("GET", data, callback); | |
}, | |
// Alias for send("POST", …). | |
post: function(data, callback) { | |
return request.send("POST", data, callback); | |
}, | |
// If callback is non-null, it will be used for error and load events. | |
send: function(method, data, callback) { | |
xhr.open(method, url, true, user, password); | |
if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); | |
if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); | |
if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); | |
if (responseType != null) xhr.responseType = responseType; | |
if (timeout > 0) xhr.timeout = timeout; | |
if (callback == null && typeof data === "function") callback = data, data = null; | |
if (callback != null && callback.length === 1) callback = fixCallback(callback); | |
if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); | |
event.call("beforesend", request, xhr); | |
xhr.send(data == null ? null : data); | |
return request; | |
}, | |
abort: function() { | |
xhr.abort(); | |
return request; | |
}, | |
on: function() { | |
var value = event.on.apply(event, arguments); | |
return value === event ? request : value; | |
} | |
}; | |
if (callback != null) { | |
if (typeof callback !== "function") throw new Error("invalid callback: " + callback); | |
return request.get(callback); | |
} | |
return request; | |
}; | |
function fixCallback(callback) { | |
return function(error, xhr) { | |
callback(error == null ? xhr : null); | |
}; | |
} | |
function hasResponse(xhr) { | |
var type = xhr.responseType; | |
return type && type !== "text" | |
? xhr.response // null on error | |
: xhr.responseText; // "" on error | |
} | |
var type = function(defaultMimeType, response) { | |
return function(url, callback) { | |
var r = request(url).mimeType(defaultMimeType).response(response); | |
if (callback != null) { | |
if (typeof callback !== "function") throw new Error("invalid callback: " + callback); | |
return r.get(callback); | |
} | |
return r; | |
}; | |
}; | |
var html = type("text/html", function(xhr) { | |
return document.createRange().createContextualFragment(xhr.responseText); | |
}); | |
var json = type("application/json", function(xhr) { | |
return JSON.parse(xhr.responseText); | |
}); | |
var text = type("text/plain", function(xhr) { | |
return xhr.responseText; | |
}); | |
var xml = type("application/xml", function(xhr) { | |
var xml = xhr.responseXML; | |
if (!xml) throw new Error("parse error"); | |
return xml; | |
}); | |
var dsv = function(defaultMimeType, parse) { | |
return function(url, row, callback) { | |
if (arguments.length < 3) callback = row, row = null; | |
var r = request(url).mimeType(defaultMimeType); | |
r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; | |
r.row(row); | |
return callback ? r.get(callback) : r; | |
}; | |
}; | |
function responseOf(parse, row) { | |
return function(request$$1) { | |
return parse(request$$1.responseText, row); | |
}; | |
} | |
var csv = dsv("text/csv", d3Dsv.csvParse); | |
var tsv = dsv("text/tab-separated-values", d3Dsv.tsvParse); | |
exports.request = request; | |
exports.html = html; | |
exports.json = json; | |
exports.text = text; | |
exports.xml = xml; | |
exports.csv = csv; | |
exports.tsv = tsv; | |
},{"d3-collection":19,"d3-dispatch":21,"d3-dsv":23,"xmlhttprequest":90}],36:[function(require,module,exports){ | |
// https://d3js.org/d3-scale/ Version 1.0.6. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-collection'), require('d3-interpolate'), require('d3-format'), require('d3-time'), require('d3-time-format'), require('d3-color')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-collection', 'd3-interpolate', 'd3-format', 'd3-time', 'd3-time-format', 'd3-color'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); | |
}(this, (function (exports,d3Array,d3Collection,d3Interpolate,d3Format,d3Time,d3TimeFormat,d3Color) { 'use strict'; | |
var array = Array.prototype; | |
var map$1 = array.map; | |
var slice = array.slice; | |
var implicit = {name: "implicit"}; | |
function ordinal(range$$1) { | |
var index = d3Collection.map(), | |
domain = [], | |
unknown = implicit; | |
range$$1 = range$$1 == null ? [] : slice.call(range$$1); | |
function scale(d) { | |
var key = d + "", i = index.get(key); | |
if (!i) { | |
if (unknown !== implicit) return unknown; | |
index.set(key, i = domain.push(d)); | |
} | |
return range$$1[(i - 1) % range$$1.length]; | |
} | |
scale.domain = function(_) { | |
if (!arguments.length) return domain.slice(); | |
domain = [], index = d3Collection.map(); | |
var i = -1, n = _.length, d, key; | |
while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); | |
return scale; | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (range$$1 = slice.call(_), scale) : range$$1.slice(); | |
}; | |
scale.unknown = function(_) { | |
return arguments.length ? (unknown = _, scale) : unknown; | |
}; | |
scale.copy = function() { | |
return ordinal() | |
.domain(domain) | |
.range(range$$1) | |
.unknown(unknown); | |
}; | |
return scale; | |
} | |
function band() { | |
var scale = ordinal().unknown(undefined), | |
domain = scale.domain, | |
ordinalRange = scale.range, | |
range$$1 = [0, 1], | |
step, | |
bandwidth, | |
round = false, | |
paddingInner = 0, | |
paddingOuter = 0, | |
align = 0.5; | |
delete scale.unknown; | |
function rescale() { | |
var n = domain().length, | |
reverse = range$$1[1] < range$$1[0], | |
start = range$$1[reverse - 0], | |
stop = range$$1[1 - reverse]; | |
step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); | |
if (round) step = Math.floor(step); | |
start += (stop - start - step * (n - paddingInner)) * align; | |
bandwidth = step * (1 - paddingInner); | |
if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); | |
var values = d3Array.range(n).map(function(i) { return start + step * i; }); | |
return ordinalRange(reverse ? values.reverse() : values); | |
} | |
scale.domain = function(_) { | |
return arguments.length ? (domain(_), rescale()) : domain(); | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); | |
}; | |
scale.rangeRound = function(_) { | |
return range$$1 = [+_[0], +_[1]], round = true, rescale(); | |
}; | |
scale.bandwidth = function() { | |
return bandwidth; | |
}; | |
scale.step = function() { | |
return step; | |
}; | |
scale.round = function(_) { | |
return arguments.length ? (round = !!_, rescale()) : round; | |
}; | |
scale.padding = function(_) { | |
return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; | |
}; | |
scale.paddingInner = function(_) { | |
return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; | |
}; | |
scale.paddingOuter = function(_) { | |
return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; | |
}; | |
scale.align = function(_) { | |
return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; | |
}; | |
scale.copy = function() { | |
return band() | |
.domain(domain()) | |
.range(range$$1) | |
.round(round) | |
.paddingInner(paddingInner) | |
.paddingOuter(paddingOuter) | |
.align(align); | |
}; | |
return rescale(); | |
} | |
function pointish(scale) { | |
var copy = scale.copy; | |
scale.padding = scale.paddingOuter; | |
delete scale.paddingInner; | |
delete scale.paddingOuter; | |
scale.copy = function() { | |
return pointish(copy()); | |
}; | |
return scale; | |
} | |
function point() { | |
return pointish(band().paddingInner(1)); | |
} | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var number = function(x) { | |
return +x; | |
}; | |
var unit = [0, 1]; | |
function deinterpolateLinear(a, b) { | |
return (b -= (a = +a)) | |
? function(x) { return (x - a) / b; } | |
: constant(b); | |
} | |
function deinterpolateClamp(deinterpolate) { | |
return function(a, b) { | |
var d = deinterpolate(a = +a, b = +b); | |
return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; | |
}; | |
} | |
function reinterpolateClamp(reinterpolate) { | |
return function(a, b) { | |
var r = reinterpolate(a = +a, b = +b); | |
return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; | |
}; | |
} | |
function bimap(domain, range$$1, deinterpolate, reinterpolate) { | |
var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; | |
if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); | |
else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); | |
return function(x) { return r0(d0(x)); }; | |
} | |
function polymap(domain, range$$1, deinterpolate, reinterpolate) { | |
var j = Math.min(domain.length, range$$1.length) - 1, | |
d = new Array(j), | |
r = new Array(j), | |
i = -1; | |
// Reverse descending domains. | |
if (domain[j] < domain[0]) { | |
domain = domain.slice().reverse(); | |
range$$1 = range$$1.slice().reverse(); | |
} | |
while (++i < j) { | |
d[i] = deinterpolate(domain[i], domain[i + 1]); | |
r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); | |
} | |
return function(x) { | |
var i = d3Array.bisect(domain, x, 1, j) - 1; | |
return r[i](d[i](x)); | |
}; | |
} | |
function copy(source, target) { | |
return target | |
.domain(source.domain()) | |
.range(source.range()) | |
.interpolate(source.interpolate()) | |
.clamp(source.clamp()); | |
} | |
// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. | |
// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. | |
function continuous(deinterpolate, reinterpolate) { | |
var domain = unit, | |
range$$1 = unit, | |
interpolate$$1 = d3Interpolate.interpolate, | |
clamp = false, | |
piecewise, | |
output, | |
input; | |
function rescale() { | |
piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; | |
output = input = null; | |
return scale; | |
} | |
function scale(x) { | |
return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); | |
} | |
scale.invert = function(y) { | |
return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); | |
}; | |
scale.domain = function(_) { | |
return arguments.length ? (domain = map$1.call(_, number), rescale()) : domain.slice(); | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (range$$1 = slice.call(_), rescale()) : range$$1.slice(); | |
}; | |
scale.rangeRound = function(_) { | |
return range$$1 = slice.call(_), interpolate$$1 = d3Interpolate.interpolateRound, rescale(); | |
}; | |
scale.clamp = function(_) { | |
return arguments.length ? (clamp = !!_, rescale()) : clamp; | |
}; | |
scale.interpolate = function(_) { | |
return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; | |
}; | |
return rescale(); | |
} | |
var tickFormat = function(domain, count, specifier) { | |
var start = domain[0], | |
stop = domain[domain.length - 1], | |
step = d3Array.tickStep(start, stop, count == null ? 10 : count), | |
precision; | |
specifier = d3Format.formatSpecifier(specifier == null ? ",f" : specifier); | |
switch (specifier.type) { | |
case "s": { | |
var value = Math.max(Math.abs(start), Math.abs(stop)); | |
if (specifier.precision == null && !isNaN(precision = d3Format.precisionPrefix(step, value))) specifier.precision = precision; | |
return d3Format.formatPrefix(specifier, value); | |
} | |
case "": | |
case "e": | |
case "g": | |
case "p": | |
case "r": { | |
if (specifier.precision == null && !isNaN(precision = d3Format.precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); | |
break; | |
} | |
case "f": | |
case "%": { | |
if (specifier.precision == null && !isNaN(precision = d3Format.precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; | |
break; | |
} | |
} | |
return d3Format.format(specifier); | |
}; | |
function linearish(scale) { | |
var domain = scale.domain; | |
scale.ticks = function(count) { | |
var d = domain(); | |
return d3Array.ticks(d[0], d[d.length - 1], count == null ? 10 : count); | |
}; | |
scale.tickFormat = function(count, specifier) { | |
return tickFormat(domain(), count, specifier); | |
}; | |
scale.nice = function(count) { | |
if (count == null) count = 10; | |
var d = domain(), | |
i0 = 0, | |
i1 = d.length - 1, | |
start = d[i0], | |
stop = d[i1], | |
step; | |
if (stop < start) { | |
step = start, start = stop, stop = step; | |
step = i0, i0 = i1, i1 = step; | |
} | |
step = d3Array.tickIncrement(start, stop, count); | |
if (step > 0) { | |
start = Math.floor(start / step) * step; | |
stop = Math.ceil(stop / step) * step; | |
step = d3Array.tickIncrement(start, stop, count); | |
} else if (step < 0) { | |
start = Math.ceil(start * step) / step; | |
stop = Math.floor(stop * step) / step; | |
step = d3Array.tickIncrement(start, stop, count); | |
} | |
if (step > 0) { | |
d[i0] = Math.floor(start / step) * step; | |
d[i1] = Math.ceil(stop / step) * step; | |
domain(d); | |
} else if (step < 0) { | |
d[i0] = Math.ceil(start * step) / step; | |
d[i1] = Math.floor(stop * step) / step; | |
domain(d); | |
} | |
return scale; | |
}; | |
return scale; | |
} | |
function linear() { | |
var scale = continuous(deinterpolateLinear, d3Interpolate.interpolateNumber); | |
scale.copy = function() { | |
return copy(scale, linear()); | |
}; | |
return linearish(scale); | |
} | |
function identity() { | |
var domain = [0, 1]; | |
function scale(x) { | |
return +x; | |
} | |
scale.invert = scale; | |
scale.domain = scale.range = function(_) { | |
return arguments.length ? (domain = map$1.call(_, number), scale) : domain.slice(); | |
}; | |
scale.copy = function() { | |
return identity().domain(domain); | |
}; | |
return linearish(scale); | |
} | |
var nice = function(domain, interval) { | |
domain = domain.slice(); | |
var i0 = 0, | |
i1 = domain.length - 1, | |
x0 = domain[i0], | |
x1 = domain[i1], | |
t; | |
if (x1 < x0) { | |
t = i0, i0 = i1, i1 = t; | |
t = x0, x0 = x1, x1 = t; | |
} | |
domain[i0] = interval.floor(x0); | |
domain[i1] = interval.ceil(x1); | |
return domain; | |
}; | |
function deinterpolate(a, b) { | |
return (b = Math.log(b / a)) | |
? function(x) { return Math.log(x / a) / b; } | |
: constant(b); | |
} | |
function reinterpolate(a, b) { | |
return a < 0 | |
? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } | |
: function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; | |
} | |
function pow10(x) { | |
return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; | |
} | |
function powp(base) { | |
return base === 10 ? pow10 | |
: base === Math.E ? Math.exp | |
: function(x) { return Math.pow(base, x); }; | |
} | |
function logp(base) { | |
return base === Math.E ? Math.log | |
: base === 10 && Math.log10 | |
|| base === 2 && Math.log2 | |
|| (base = Math.log(base), function(x) { return Math.log(x) / base; }); | |
} | |
function reflect(f) { | |
return function(x) { | |
return -f(-x); | |
}; | |
} | |
function log() { | |
var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]), | |
domain = scale.domain, | |
base = 10, | |
logs = logp(10), | |
pows = powp(10); | |
function rescale() { | |
logs = logp(base), pows = powp(base); | |
if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); | |
return scale; | |
} | |
scale.base = function(_) { | |
return arguments.length ? (base = +_, rescale()) : base; | |
}; | |
scale.domain = function(_) { | |
return arguments.length ? (domain(_), rescale()) : domain(); | |
}; | |
scale.ticks = function(count) { | |
var d = domain(), | |
u = d[0], | |
v = d[d.length - 1], | |
r; | |
if (r = v < u) i = u, u = v, v = i; | |
var i = logs(u), | |
j = logs(v), | |
p, | |
k, | |
t, | |
n = count == null ? 10 : +count, | |
z = []; | |
if (!(base % 1) && j - i < n) { | |
i = Math.round(i) - 1, j = Math.round(j) + 1; | |
if (u > 0) for (; i < j; ++i) { | |
for (k = 1, p = pows(i); k < base; ++k) { | |
t = p * k; | |
if (t < u) continue; | |
if (t > v) break; | |
z.push(t); | |
} | |
} else for (; i < j; ++i) { | |
for (k = base - 1, p = pows(i); k >= 1; --k) { | |
t = p * k; | |
if (t < u) continue; | |
if (t > v) break; | |
z.push(t); | |
} | |
} | |
} else { | |
z = d3Array.ticks(i, j, Math.min(j - i, n)).map(pows); | |
} | |
return r ? z.reverse() : z; | |
}; | |
scale.tickFormat = function(count, specifier) { | |
if (specifier == null) specifier = base === 10 ? ".0e" : ","; | |
if (typeof specifier !== "function") specifier = d3Format.format(specifier); | |
if (count === Infinity) return specifier; | |
if (count == null) count = 10; | |
var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? | |
return function(d) { | |
var i = d / pows(Math.round(logs(d))); | |
if (i * base < base - 0.5) i *= base; | |
return i <= k ? specifier(d) : ""; | |
}; | |
}; | |
scale.nice = function() { | |
return domain(nice(domain(), { | |
floor: function(x) { return pows(Math.floor(logs(x))); }, | |
ceil: function(x) { return pows(Math.ceil(logs(x))); } | |
})); | |
}; | |
scale.copy = function() { | |
return copy(scale, log().base(base)); | |
}; | |
return scale; | |
} | |
function raise(x, exponent) { | |
return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); | |
} | |
function pow() { | |
var exponent = 1, | |
scale = continuous(deinterpolate, reinterpolate), | |
domain = scale.domain; | |
function deinterpolate(a, b) { | |
return (b = raise(b, exponent) - (a = raise(a, exponent))) | |
? function(x) { return (raise(x, exponent) - a) / b; } | |
: constant(b); | |
} | |
function reinterpolate(a, b) { | |
b = raise(b, exponent) - (a = raise(a, exponent)); | |
return function(t) { return raise(a + b * t, 1 / exponent); }; | |
} | |
scale.exponent = function(_) { | |
return arguments.length ? (exponent = +_, domain(domain())) : exponent; | |
}; | |
scale.copy = function() { | |
return copy(scale, pow().exponent(exponent)); | |
}; | |
return linearish(scale); | |
} | |
function sqrt() { | |
return pow().exponent(0.5); | |
} | |
function quantile$1() { | |
var domain = [], | |
range$$1 = [], | |
thresholds = []; | |
function rescale() { | |
var i = 0, n = Math.max(1, range$$1.length); | |
thresholds = new Array(n - 1); | |
while (++i < n) thresholds[i - 1] = d3Array.quantile(domain, i / n); | |
return scale; | |
} | |
function scale(x) { | |
if (!isNaN(x = +x)) return range$$1[d3Array.bisect(thresholds, x)]; | |
} | |
scale.invertExtent = function(y) { | |
var i = range$$1.indexOf(y); | |
return i < 0 ? [NaN, NaN] : [ | |
i > 0 ? thresholds[i - 1] : domain[0], | |
i < thresholds.length ? thresholds[i] : domain[domain.length - 1] | |
]; | |
}; | |
scale.domain = function(_) { | |
if (!arguments.length) return domain.slice(); | |
domain = []; | |
for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); | |
domain.sort(d3Array.ascending); | |
return rescale(); | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (range$$1 = slice.call(_), rescale()) : range$$1.slice(); | |
}; | |
scale.quantiles = function() { | |
return thresholds.slice(); | |
}; | |
scale.copy = function() { | |
return quantile$1() | |
.domain(domain) | |
.range(range$$1); | |
}; | |
return scale; | |
} | |
function quantize() { | |
var x0 = 0, | |
x1 = 1, | |
n = 1, | |
domain = [0.5], | |
range$$1 = [0, 1]; | |
function scale(x) { | |
if (x <= x) return range$$1[d3Array.bisect(domain, x, 0, n)]; | |
} | |
function rescale() { | |
var i = -1; | |
domain = new Array(n); | |
while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); | |
return scale; | |
} | |
scale.domain = function(_) { | |
return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (n = (range$$1 = slice.call(_)).length - 1, rescale()) : range$$1.slice(); | |
}; | |
scale.invertExtent = function(y) { | |
var i = range$$1.indexOf(y); | |
return i < 0 ? [NaN, NaN] | |
: i < 1 ? [x0, domain[0]] | |
: i >= n ? [domain[n - 1], x1] | |
: [domain[i - 1], domain[i]]; | |
}; | |
scale.copy = function() { | |
return quantize() | |
.domain([x0, x1]) | |
.range(range$$1); | |
}; | |
return linearish(scale); | |
} | |
function threshold() { | |
var domain = [0.5], | |
range$$1 = [0, 1], | |
n = 1; | |
function scale(x) { | |
if (x <= x) return range$$1[d3Array.bisect(domain, x, 0, n)]; | |
} | |
scale.domain = function(_) { | |
return arguments.length ? (domain = slice.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); | |
}; | |
scale.range = function(_) { | |
return arguments.length ? (range$$1 = slice.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); | |
}; | |
scale.invertExtent = function(y) { | |
var i = range$$1.indexOf(y); | |
return [domain[i - 1], domain[i]]; | |
}; | |
scale.copy = function() { | |
return threshold() | |
.domain(domain) | |
.range(range$$1); | |
}; | |
return scale; | |
} | |
var durationSecond = 1000; | |
var durationMinute = durationSecond * 60; | |
var durationHour = durationMinute * 60; | |
var durationDay = durationHour * 24; | |
var durationWeek = durationDay * 7; | |
var durationMonth = durationDay * 30; | |
var durationYear = durationDay * 365; | |
function date(t) { | |
return new Date(t); | |
} | |
function number$1(t) { | |
return t instanceof Date ? +t : +new Date(+t); | |
} | |
function calendar(year, month, week, day, hour, minute, second, millisecond, format$$1) { | |
var scale = continuous(deinterpolateLinear, d3Interpolate.interpolateNumber), | |
invert = scale.invert, | |
domain = scale.domain; | |
var formatMillisecond = format$$1(".%L"), | |
formatSecond = format$$1(":%S"), | |
formatMinute = format$$1("%I:%M"), | |
formatHour = format$$1("%I %p"), | |
formatDay = format$$1("%a %d"), | |
formatWeek = format$$1("%b %d"), | |
formatMonth = format$$1("%B"), | |
formatYear = format$$1("%Y"); | |
var tickIntervals = [ | |
[second, 1, durationSecond], | |
[second, 5, 5 * durationSecond], | |
[second, 15, 15 * durationSecond], | |
[second, 30, 30 * durationSecond], | |
[minute, 1, durationMinute], | |
[minute, 5, 5 * durationMinute], | |
[minute, 15, 15 * durationMinute], | |
[minute, 30, 30 * durationMinute], | |
[ hour, 1, durationHour ], | |
[ hour, 3, 3 * durationHour ], | |
[ hour, 6, 6 * durationHour ], | |
[ hour, 12, 12 * durationHour ], | |
[ day, 1, durationDay ], | |
[ day, 2, 2 * durationDay ], | |
[ week, 1, durationWeek ], | |
[ month, 1, durationMonth ], | |
[ month, 3, 3 * durationMonth ], | |
[ year, 1, durationYear ] | |
]; | |
function tickFormat(date) { | |
return (second(date) < date ? formatMillisecond | |
: minute(date) < date ? formatSecond | |
: hour(date) < date ? formatMinute | |
: day(date) < date ? formatHour | |
: month(date) < date ? (week(date) < date ? formatDay : formatWeek) | |
: year(date) < date ? formatMonth | |
: formatYear)(date); | |
} | |
function tickInterval(interval, start, stop, step) { | |
if (interval == null) interval = 10; | |
// If a desired tick count is specified, pick a reasonable tick interval | |
// based on the extent of the domain and a rough estimate of tick size. | |
// Otherwise, assume interval is already a time interval and use it. | |
if (typeof interval === "number") { | |
var target = Math.abs(stop - start) / interval, | |
i = d3Array.bisector(function(i) { return i[2]; }).right(tickIntervals, target); | |
if (i === tickIntervals.length) { | |
step = d3Array.tickStep(start / durationYear, stop / durationYear, interval); | |
interval = year; | |
} else if (i) { | |
i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; | |
step = i[1]; | |
interval = i[0]; | |
} else { | |
step = d3Array.tickStep(start, stop, interval); | |
interval = millisecond; | |
} | |
} | |
return step == null ? interval : interval.every(step); | |
} | |
scale.invert = function(y) { | |
return new Date(invert(y)); | |
}; | |
scale.domain = function(_) { | |
return arguments.length ? domain(map$1.call(_, number$1)) : domain().map(date); | |
}; | |
scale.ticks = function(interval, step) { | |
var d = domain(), | |
t0 = d[0], | |
t1 = d[d.length - 1], | |
r = t1 < t0, | |
t; | |
if (r) t = t0, t0 = t1, t1 = t; | |
t = tickInterval(interval, t0, t1, step); | |
t = t ? t.range(t0, t1 + 1) : []; // inclusive stop | |
return r ? t.reverse() : t; | |
}; | |
scale.tickFormat = function(count, specifier) { | |
return specifier == null ? tickFormat : format$$1(specifier); | |
}; | |
scale.nice = function(interval, step) { | |
var d = domain(); | |
return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) | |
? domain(nice(d, interval)) | |
: scale; | |
}; | |
scale.copy = function() { | |
return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format$$1)); | |
}; | |
return scale; | |
} | |
var time = function() { | |
return calendar(d3Time.timeYear, d3Time.timeMonth, d3Time.timeWeek, d3Time.timeDay, d3Time.timeHour, d3Time.timeMinute, d3Time.timeSecond, d3Time.timeMillisecond, d3TimeFormat.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); | |
}; | |
var utcTime = function() { | |
return calendar(d3Time.utcYear, d3Time.utcMonth, d3Time.utcWeek, d3Time.utcDay, d3Time.utcHour, d3Time.utcMinute, d3Time.utcSecond, d3Time.utcMillisecond, d3TimeFormat.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); | |
}; | |
var colors = function(s) { | |
return s.match(/.{6}/g).map(function(x) { | |
return "#" + x; | |
}); | |
}; | |
var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); | |
var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); | |
var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); | |
var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); | |
var cubehelix$1 = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(300, 0.5, 0.0), d3Color.cubehelix(-240, 0.5, 1.0)); | |
var warm = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(-100, 0.75, 0.35), d3Color.cubehelix(80, 1.50, 0.8)); | |
var cool = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(260, 0.75, 0.35), d3Color.cubehelix(80, 1.50, 0.8)); | |
var rainbow = d3Color.cubehelix(); | |
var rainbow$1 = function(t) { | |
if (t < 0 || t > 1) t -= Math.floor(t); | |
var ts = Math.abs(t - 0.5); | |
rainbow.h = 360 * t - 100; | |
rainbow.s = 1.5 - 1.5 * ts; | |
rainbow.l = 0.8 - 0.9 * ts; | |
return rainbow + ""; | |
}; | |
function ramp(range$$1) { | |
var n = range$$1.length; | |
return function(t) { | |
return range$$1[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; | |
}; | |
} | |
var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); | |
var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); | |
var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); | |
var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); | |
function sequential(interpolator) { | |
var x0 = 0, | |
x1 = 1, | |
clamp = false; | |
function scale(x) { | |
var t = (x - x0) / (x1 - x0); | |
return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); | |
} | |
scale.domain = function(_) { | |
return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; | |
}; | |
scale.clamp = function(_) { | |
return arguments.length ? (clamp = !!_, scale) : clamp; | |
}; | |
scale.interpolator = function(_) { | |
return arguments.length ? (interpolator = _, scale) : interpolator; | |
}; | |
scale.copy = function() { | |
return sequential(interpolator).domain([x0, x1]).clamp(clamp); | |
}; | |
return linearish(scale); | |
} | |
exports.scaleBand = band; | |
exports.scalePoint = point; | |
exports.scaleIdentity = identity; | |
exports.scaleLinear = linear; | |
exports.scaleLog = log; | |
exports.scaleOrdinal = ordinal; | |
exports.scaleImplicit = implicit; | |
exports.scalePow = pow; | |
exports.scaleSqrt = sqrt; | |
exports.scaleQuantile = quantile$1; | |
exports.scaleQuantize = quantize; | |
exports.scaleThreshold = threshold; | |
exports.scaleTime = time; | |
exports.scaleUtc = utcTime; | |
exports.schemeCategory10 = category10; | |
exports.schemeCategory20b = category20b; | |
exports.schemeCategory20c = category20c; | |
exports.schemeCategory20 = category20; | |
exports.interpolateCubehelixDefault = cubehelix$1; | |
exports.interpolateRainbow = rainbow$1; | |
exports.interpolateWarm = warm; | |
exports.interpolateCool = cool; | |
exports.interpolateViridis = viridis; | |
exports.interpolateMagma = magma; | |
exports.interpolateInferno = inferno; | |
exports.interpolatePlasma = plasma; | |
exports.scaleSequential = sequential; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-array":15,"d3-collection":19,"d3-color":20,"d3-format":26,"d3-interpolate":29,"d3-time":40,"d3-time-format":39}],37:[function(require,module,exports){ | |
// https://d3js.org/d3-selection/ Version 1.1.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var xhtml = "http://www.w3.org/1999/xhtml"; | |
var namespaces = { | |
svg: "http://www.w3.org/2000/svg", | |
xhtml: xhtml, | |
xlink: "http://www.w3.org/1999/xlink", | |
xml: "http://www.w3.org/XML/1998/namespace", | |
xmlns: "http://www.w3.org/2000/xmlns/" | |
}; | |
var namespace = function(name) { | |
var prefix = name += "", i = prefix.indexOf(":"); | |
if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); | |
return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; | |
}; | |
function creatorInherit(name) { | |
return function() { | |
var document = this.ownerDocument, | |
uri = this.namespaceURI; | |
return uri === xhtml && document.documentElement.namespaceURI === xhtml | |
? document.createElement(name) | |
: document.createElementNS(uri, name); | |
}; | |
} | |
function creatorFixed(fullname) { | |
return function() { | |
return this.ownerDocument.createElementNS(fullname.space, fullname.local); | |
}; | |
} | |
var creator = function(name) { | |
var fullname = namespace(name); | |
return (fullname.local | |
? creatorFixed | |
: creatorInherit)(fullname); | |
}; | |
var nextId = 0; | |
function local() { | |
return new Local; | |
} | |
function Local() { | |
this._ = "@" + (++nextId).toString(36); | |
} | |
Local.prototype = local.prototype = { | |
constructor: Local, | |
get: function(node) { | |
var id = this._; | |
while (!(id in node)) if (!(node = node.parentNode)) return; | |
return node[id]; | |
}, | |
set: function(node, value) { | |
return node[this._] = value; | |
}, | |
remove: function(node) { | |
return this._ in node && delete node[this._]; | |
}, | |
toString: function() { | |
return this._; | |
} | |
}; | |
var matcher = function(selector) { | |
return function() { | |
return this.matches(selector); | |
}; | |
}; | |
if (typeof document !== "undefined") { | |
var element = document.documentElement; | |
if (!element.matches) { | |
var vendorMatches = element.webkitMatchesSelector | |
|| element.msMatchesSelector | |
|| element.mozMatchesSelector | |
|| element.oMatchesSelector; | |
matcher = function(selector) { | |
return function() { | |
return vendorMatches.call(this, selector); | |
}; | |
}; | |
} | |
} | |
var matcher$1 = matcher; | |
var filterEvents = {}; | |
exports.event = null; | |
if (typeof document !== "undefined") { | |
var element$1 = document.documentElement; | |
if (!("onmouseenter" in element$1)) { | |
filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; | |
} | |
} | |
function filterContextListener(listener, index, group) { | |
listener = contextListener(listener, index, group); | |
return function(event) { | |
var related = event.relatedTarget; | |
if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { | |
listener.call(this, event); | |
} | |
}; | |
} | |
function contextListener(listener, index, group) { | |
return function(event1) { | |
var event0 = exports.event; // Events can be reentrant (e.g., focus). | |
exports.event = event1; | |
try { | |
listener.call(this, this.__data__, index, group); | |
} finally { | |
exports.event = event0; | |
} | |
}; | |
} | |
function parseTypenames(typenames) { | |
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); | |
return {type: t, name: name}; | |
}); | |
} | |
function onRemove(typename) { | |
return function() { | |
var on = this.__on; | |
if (!on) return; | |
for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { | |
if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { | |
this.removeEventListener(o.type, o.listener, o.capture); | |
} else { | |
on[++i] = o; | |
} | |
} | |
if (++i) on.length = i; | |
else delete this.__on; | |
}; | |
} | |
function onAdd(typename, value, capture) { | |
var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; | |
return function(d, i, group) { | |
var on = this.__on, o, listener = wrap(value, i, group); | |
if (on) for (var j = 0, m = on.length; j < m; ++j) { | |
if ((o = on[j]).type === typename.type && o.name === typename.name) { | |
this.removeEventListener(o.type, o.listener, o.capture); | |
this.addEventListener(o.type, o.listener = listener, o.capture = capture); | |
o.value = value; | |
return; | |
} | |
} | |
this.addEventListener(typename.type, listener, capture); | |
o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; | |
if (!on) this.__on = [o]; | |
else on.push(o); | |
}; | |
} | |
var selection_on = function(typename, value, capture) { | |
var typenames = parseTypenames(typename + ""), i, n = typenames.length, t; | |
if (arguments.length < 2) { | |
var on = this.node().__on; | |
if (on) for (var j = 0, m = on.length, o; j < m; ++j) { | |
for (i = 0, o = on[j]; i < n; ++i) { | |
if ((t = typenames[i]).type === o.type && t.name === o.name) { | |
return o.value; | |
} | |
} | |
} | |
return; | |
} | |
on = value ? onAdd : onRemove; | |
if (capture == null) capture = false; | |
for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); | |
return this; | |
}; | |
function customEvent(event1, listener, that, args) { | |
var event0 = exports.event; | |
event1.sourceEvent = exports.event; | |
exports.event = event1; | |
try { | |
return listener.apply(that, args); | |
} finally { | |
exports.event = event0; | |
} | |
} | |
var sourceEvent = function() { | |
var current = exports.event, source; | |
while (source = current.sourceEvent) current = source; | |
return current; | |
}; | |
var point = function(node, event) { | |
var svg = node.ownerSVGElement || node; | |
if (svg.createSVGPoint) { | |
var point = svg.createSVGPoint(); | |
point.x = event.clientX, point.y = event.clientY; | |
point = point.matrixTransform(node.getScreenCTM().inverse()); | |
return [point.x, point.y]; | |
} | |
var rect = node.getBoundingClientRect(); | |
return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; | |
}; | |
var mouse = function(node) { | |
var event = sourceEvent(); | |
if (event.changedTouches) event = event.changedTouches[0]; | |
return point(node, event); | |
}; | |
function none() {} | |
var selector = function(selector) { | |
return selector == null ? none : function() { | |
return this.querySelector(selector); | |
}; | |
}; | |
var selection_select = function(select) { | |
if (typeof select !== "function") select = selector(select); | |
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { | |
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { | |
if ("__data__" in node) subnode.__data__ = node.__data__; | |
subgroup[i] = subnode; | |
} | |
} | |
} | |
return new Selection(subgroups, this._parents); | |
}; | |
function empty() { | |
return []; | |
} | |
var selectorAll = function(selector) { | |
return selector == null ? empty : function() { | |
return this.querySelectorAll(selector); | |
}; | |
}; | |
var selection_selectAll = function(select) { | |
if (typeof select !== "function") select = selectorAll(select); | |
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { | |
if (node = group[i]) { | |
subgroups.push(select.call(node, node.__data__, i, group)); | |
parents.push(node); | |
} | |
} | |
} | |
return new Selection(subgroups, parents); | |
}; | |
var selection_filter = function(match) { | |
if (typeof match !== "function") match = matcher$1(match); | |
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { | |
if ((node = group[i]) && match.call(node, node.__data__, i, group)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return new Selection(subgroups, this._parents); | |
}; | |
var sparse = function(update) { | |
return new Array(update.length); | |
}; | |
var selection_enter = function() { | |
return new Selection(this._enter || this._groups.map(sparse), this._parents); | |
}; | |
function EnterNode(parent, datum) { | |
this.ownerDocument = parent.ownerDocument; | |
this.namespaceURI = parent.namespaceURI; | |
this._next = null; | |
this._parent = parent; | |
this.__data__ = datum; | |
} | |
EnterNode.prototype = { | |
constructor: EnterNode, | |
appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, | |
insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, | |
querySelector: function(selector) { return this._parent.querySelector(selector); }, | |
querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } | |
}; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
var keyPrefix = "$"; // Protect against keys like “__proto__”. | |
function bindIndex(parent, group, enter, update, exit, data) { | |
var i = 0, | |
node, | |
groupLength = group.length, | |
dataLength = data.length; | |
// Put any non-null nodes that fit into update. | |
// Put any null nodes into enter. | |
// Put any remaining data into enter. | |
for (; i < dataLength; ++i) { | |
if (node = group[i]) { | |
node.__data__ = data[i]; | |
update[i] = node; | |
} else { | |
enter[i] = new EnterNode(parent, data[i]); | |
} | |
} | |
// Put any non-null nodes that don’t fit into exit. | |
for (; i < groupLength; ++i) { | |
if (node = group[i]) { | |
exit[i] = node; | |
} | |
} | |
} | |
function bindKey(parent, group, enter, update, exit, data, key) { | |
var i, | |
node, | |
nodeByKeyValue = {}, | |
groupLength = group.length, | |
dataLength = data.length, | |
keyValues = new Array(groupLength), | |
keyValue; | |
// Compute the key for each node. | |
// If multiple nodes have the same key, the duplicates are added to exit. | |
for (i = 0; i < groupLength; ++i) { | |
if (node = group[i]) { | |
keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); | |
if (keyValue in nodeByKeyValue) { | |
exit[i] = node; | |
} else { | |
nodeByKeyValue[keyValue] = node; | |
} | |
} | |
} | |
// Compute the key for each datum. | |
// If there a node associated with this key, join and add it to update. | |
// If there is not (or the key is a duplicate), add it to enter. | |
for (i = 0; i < dataLength; ++i) { | |
keyValue = keyPrefix + key.call(parent, data[i], i, data); | |
if (node = nodeByKeyValue[keyValue]) { | |
update[i] = node; | |
node.__data__ = data[i]; | |
nodeByKeyValue[keyValue] = null; | |
} else { | |
enter[i] = new EnterNode(parent, data[i]); | |
} | |
} | |
// Add any remaining nodes that were not bound to data to exit. | |
for (i = 0; i < groupLength; ++i) { | |
if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { | |
exit[i] = node; | |
} | |
} | |
} | |
var selection_data = function(value, key) { | |
if (!value) { | |
data = new Array(this.size()), j = -1; | |
this.each(function(d) { data[++j] = d; }); | |
return data; | |
} | |
var bind = key ? bindKey : bindIndex, | |
parents = this._parents, | |
groups = this._groups; | |
if (typeof value !== "function") value = constant(value); | |
for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { | |
var parent = parents[j], | |
group = groups[j], | |
groupLength = group.length, | |
data = value.call(parent, parent && parent.__data__, j, parents), | |
dataLength = data.length, | |
enterGroup = enter[j] = new Array(dataLength), | |
updateGroup = update[j] = new Array(dataLength), | |
exitGroup = exit[j] = new Array(groupLength); | |
bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); | |
// Now connect the enter nodes to their following update node, such that | |
// appendChild can insert the materialized enter node before this node, | |
// rather than at the end of the parent node. | |
for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { | |
if (previous = enterGroup[i0]) { | |
if (i0 >= i1) i1 = i0 + 1; | |
while (!(next = updateGroup[i1]) && ++i1 < dataLength); | |
previous._next = next || null; | |
} | |
} | |
} | |
update = new Selection(update, parents); | |
update._enter = enter; | |
update._exit = exit; | |
return update; | |
}; | |
var selection_exit = function() { | |
return new Selection(this._exit || this._groups.map(sparse), this._parents); | |
}; | |
var selection_merge = function(selection) { | |
for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { | |
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { | |
if (node = group0[i] || group1[i]) { | |
merge[i] = node; | |
} | |
} | |
} | |
for (; j < m0; ++j) { | |
merges[j] = groups0[j]; | |
} | |
return new Selection(merges, this._parents); | |
}; | |
var selection_order = function() { | |
for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { | |
for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { | |
if (node = group[i]) { | |
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); | |
next = node; | |
} | |
} | |
} | |
return this; | |
}; | |
var selection_sort = function(compare) { | |
if (!compare) compare = ascending; | |
function compareNode(a, b) { | |
return a && b ? compare(a.__data__, b.__data__) : !a - !b; | |
} | |
for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { | |
if (node = group[i]) { | |
sortgroup[i] = node; | |
} | |
} | |
sortgroup.sort(compareNode); | |
} | |
return new Selection(sortgroups, this._parents).order(); | |
}; | |
function ascending(a, b) { | |
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; | |
} | |
var selection_call = function() { | |
var callback = arguments[0]; | |
arguments[0] = this; | |
callback.apply(null, arguments); | |
return this; | |
}; | |
var selection_nodes = function() { | |
var nodes = new Array(this.size()), i = -1; | |
this.each(function() { nodes[++i] = this; }); | |
return nodes; | |
}; | |
var selection_node = function() { | |
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { | |
for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { | |
var node = group[i]; | |
if (node) return node; | |
} | |
} | |
return null; | |
}; | |
var selection_size = function() { | |
var size = 0; | |
this.each(function() { ++size; }); | |
return size; | |
}; | |
var selection_empty = function() { | |
return !this.node(); | |
}; | |
var selection_each = function(callback) { | |
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { | |
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { | |
if (node = group[i]) callback.call(node, node.__data__, i, group); | |
} | |
} | |
return this; | |
}; | |
function attrRemove(name) { | |
return function() { | |
this.removeAttribute(name); | |
}; | |
} | |
function attrRemoveNS(fullname) { | |
return function() { | |
this.removeAttributeNS(fullname.space, fullname.local); | |
}; | |
} | |
function attrConstant(name, value) { | |
return function() { | |
this.setAttribute(name, value); | |
}; | |
} | |
function attrConstantNS(fullname, value) { | |
return function() { | |
this.setAttributeNS(fullname.space, fullname.local, value); | |
}; | |
} | |
function attrFunction(name, value) { | |
return function() { | |
var v = value.apply(this, arguments); | |
if (v == null) this.removeAttribute(name); | |
else this.setAttribute(name, v); | |
}; | |
} | |
function attrFunctionNS(fullname, value) { | |
return function() { | |
var v = value.apply(this, arguments); | |
if (v == null) this.removeAttributeNS(fullname.space, fullname.local); | |
else this.setAttributeNS(fullname.space, fullname.local, v); | |
}; | |
} | |
var selection_attr = function(name, value) { | |
var fullname = namespace(name); | |
if (arguments.length < 2) { | |
var node = this.node(); | |
return fullname.local | |
? node.getAttributeNS(fullname.space, fullname.local) | |
: node.getAttribute(fullname); | |
} | |
return this.each((value == null | |
? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" | |
? (fullname.local ? attrFunctionNS : attrFunction) | |
: (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); | |
}; | |
var defaultView = function(node) { | |
return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node | |
|| (node.document && node) // node is a Window | |
|| node.defaultView; // node is a Document | |
}; | |
function styleRemove(name) { | |
return function() { | |
this.style.removeProperty(name); | |
}; | |
} | |
function styleConstant(name, value, priority) { | |
return function() { | |
this.style.setProperty(name, value, priority); | |
}; | |
} | |
function styleFunction(name, value, priority) { | |
return function() { | |
var v = value.apply(this, arguments); | |
if (v == null) this.style.removeProperty(name); | |
else this.style.setProperty(name, v, priority); | |
}; | |
} | |
var selection_style = function(name, value, priority) { | |
return arguments.length > 1 | |
? this.each((value == null | |
? styleRemove : typeof value === "function" | |
? styleFunction | |
: styleConstant)(name, value, priority == null ? "" : priority)) | |
: styleValue(this.node(), name); | |
}; | |
function styleValue(node, name) { | |
return node.style.getPropertyValue(name) | |
|| defaultView(node).getComputedStyle(node, null).getPropertyValue(name); | |
} | |
function propertyRemove(name) { | |
return function() { | |
delete this[name]; | |
}; | |
} | |
function propertyConstant(name, value) { | |
return function() { | |
this[name] = value; | |
}; | |
} | |
function propertyFunction(name, value) { | |
return function() { | |
var v = value.apply(this, arguments); | |
if (v == null) delete this[name]; | |
else this[name] = v; | |
}; | |
} | |
var selection_property = function(name, value) { | |
return arguments.length > 1 | |
? this.each((value == null | |
? propertyRemove : typeof value === "function" | |
? propertyFunction | |
: propertyConstant)(name, value)) | |
: this.node()[name]; | |
}; | |
function classArray(string) { | |
return string.trim().split(/^|\s+/); | |
} | |
function classList(node) { | |
return node.classList || new ClassList(node); | |
} | |
function ClassList(node) { | |
this._node = node; | |
this._names = classArray(node.getAttribute("class") || ""); | |
} | |
ClassList.prototype = { | |
add: function(name) { | |
var i = this._names.indexOf(name); | |
if (i < 0) { | |
this._names.push(name); | |
this._node.setAttribute("class", this._names.join(" ")); | |
} | |
}, | |
remove: function(name) { | |
var i = this._names.indexOf(name); | |
if (i >= 0) { | |
this._names.splice(i, 1); | |
this._node.setAttribute("class", this._names.join(" ")); | |
} | |
}, | |
contains: function(name) { | |
return this._names.indexOf(name) >= 0; | |
} | |
}; | |
function classedAdd(node, names) { | |
var list = classList(node), i = -1, n = names.length; | |
while (++i < n) list.add(names[i]); | |
} | |
function classedRemove(node, names) { | |
var list = classList(node), i = -1, n = names.length; | |
while (++i < n) list.remove(names[i]); | |
} | |
function classedTrue(names) { | |
return function() { | |
classedAdd(this, names); | |
}; | |
} | |
function classedFalse(names) { | |
return function() { | |
classedRemove(this, names); | |
}; | |
} | |
function classedFunction(names, value) { | |
return function() { | |
(value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); | |
}; | |
} | |
var selection_classed = function(name, value) { | |
var names = classArray(name + ""); | |
if (arguments.length < 2) { | |
var list = classList(this.node()), i = -1, n = names.length; | |
while (++i < n) if (!list.contains(names[i])) return false; | |
return true; | |
} | |
return this.each((typeof value === "function" | |
? classedFunction : value | |
? classedTrue | |
: classedFalse)(names, value)); | |
}; | |
function textRemove() { | |
this.textContent = ""; | |
} | |
function textConstant(value) { | |
return function() { | |
this.textContent = value; | |
}; | |
} | |
function textFunction(value) { | |
return function() { | |
var v = value.apply(this, arguments); | |
this.textContent = v == null ? "" : v; | |
}; | |
} | |
var selection_text = function(value) { | |
return arguments.length | |
? this.each(value == null | |
? textRemove : (typeof value === "function" | |
? textFunction | |
: textConstant)(value)) | |
: this.node().textContent; | |
}; | |
function htmlRemove() { | |
this.innerHTML = ""; | |
} | |
function htmlConstant(value) { | |
return function() { | |
this.innerHTML = value; | |
}; | |
} | |
function htmlFunction(value) { | |
return function() { | |
var v = value.apply(this, arguments); | |
this.innerHTML = v == null ? "" : v; | |
}; | |
} | |
var selection_html = function(value) { | |
return arguments.length | |
? this.each(value == null | |
? htmlRemove : (typeof value === "function" | |
? htmlFunction | |
: htmlConstant)(value)) | |
: this.node().innerHTML; | |
}; | |
function raise() { | |
if (this.nextSibling) this.parentNode.appendChild(this); | |
} | |
var selection_raise = function() { | |
return this.each(raise); | |
}; | |
function lower() { | |
if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); | |
} | |
var selection_lower = function() { | |
return this.each(lower); | |
}; | |
var selection_append = function(name) { | |
var create = typeof name === "function" ? name : creator(name); | |
return this.select(function() { | |
return this.appendChild(create.apply(this, arguments)); | |
}); | |
}; | |
function constantNull() { | |
return null; | |
} | |
var selection_insert = function(name, before) { | |
var create = typeof name === "function" ? name : creator(name), | |
select = before == null ? constantNull : typeof before === "function" ? before : selector(before); | |
return this.select(function() { | |
return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); | |
}); | |
}; | |
function remove() { | |
var parent = this.parentNode; | |
if (parent) parent.removeChild(this); | |
} | |
var selection_remove = function() { | |
return this.each(remove); | |
}; | |
var selection_datum = function(value) { | |
return arguments.length | |
? this.property("__data__", value) | |
: this.node().__data__; | |
}; | |
function dispatchEvent(node, type, params) { | |
var window = defaultView(node), | |
event = window.CustomEvent; | |
if (typeof event === "function") { | |
event = new event(type, params); | |
} else { | |
event = window.document.createEvent("Event"); | |
if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; | |
else event.initEvent(type, false, false); | |
} | |
node.dispatchEvent(event); | |
} | |
function dispatchConstant(type, params) { | |
return function() { | |
return dispatchEvent(this, type, params); | |
}; | |
} | |
function dispatchFunction(type, params) { | |
return function() { | |
return dispatchEvent(this, type, params.apply(this, arguments)); | |
}; | |
} | |
var selection_dispatch = function(type, params) { | |
return this.each((typeof params === "function" | |
? dispatchFunction | |
: dispatchConstant)(type, params)); | |
}; | |
var root = [null]; | |
function Selection(groups, parents) { | |
this._groups = groups; | |
this._parents = parents; | |
} | |
function selection() { | |
return new Selection([[document.documentElement]], root); | |
} | |
Selection.prototype = selection.prototype = { | |
constructor: Selection, | |
select: selection_select, | |
selectAll: selection_selectAll, | |
filter: selection_filter, | |
data: selection_data, | |
enter: selection_enter, | |
exit: selection_exit, | |
merge: selection_merge, | |
order: selection_order, | |
sort: selection_sort, | |
call: selection_call, | |
nodes: selection_nodes, | |
node: selection_node, | |
size: selection_size, | |
empty: selection_empty, | |
each: selection_each, | |
attr: selection_attr, | |
style: selection_style, | |
property: selection_property, | |
classed: selection_classed, | |
text: selection_text, | |
html: selection_html, | |
raise: selection_raise, | |
lower: selection_lower, | |
append: selection_append, | |
insert: selection_insert, | |
remove: selection_remove, | |
datum: selection_datum, | |
on: selection_on, | |
dispatch: selection_dispatch | |
}; | |
var select = function(selector) { | |
return typeof selector === "string" | |
? new Selection([[document.querySelector(selector)]], [document.documentElement]) | |
: new Selection([[selector]], root); | |
}; | |
var selectAll = function(selector) { | |
return typeof selector === "string" | |
? new Selection([document.querySelectorAll(selector)], [document.documentElement]) | |
: new Selection([selector == null ? [] : selector], root); | |
}; | |
var touch = function(node, touches, identifier) { | |
if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; | |
for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { | |
if ((touch = touches[i]).identifier === identifier) { | |
return point(node, touch); | |
} | |
} | |
return null; | |
}; | |
var touches = function(node, touches) { | |
if (touches == null) touches = sourceEvent().touches; | |
for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { | |
points[i] = point(node, touches[i]); | |
} | |
return points; | |
}; | |
exports.creator = creator; | |
exports.local = local; | |
exports.matcher = matcher$1; | |
exports.mouse = mouse; | |
exports.namespace = namespace; | |
exports.namespaces = namespaces; | |
exports.select = select; | |
exports.selectAll = selectAll; | |
exports.selection = selection; | |
exports.selector = selector; | |
exports.selectorAll = selectorAll; | |
exports.style = styleValue; | |
exports.touch = touch; | |
exports.touches = touches; | |
exports.window = defaultView; | |
exports.customEvent = customEvent; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],38:[function(require,module,exports){ | |
// https://d3js.org/d3-shape/ Version 1.2.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-path')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-path'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3)); | |
}(this, (function (exports,d3Path) { 'use strict'; | |
var constant = function(x) { | |
return function constant() { | |
return x; | |
}; | |
}; | |
var abs = Math.abs; | |
var atan2 = Math.atan2; | |
var cos = Math.cos; | |
var max = Math.max; | |
var min = Math.min; | |
var sin = Math.sin; | |
var sqrt = Math.sqrt; | |
var epsilon = 1e-12; | |
var pi = Math.PI; | |
var halfPi = pi / 2; | |
var tau = 2 * pi; | |
function acos(x) { | |
return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); | |
} | |
function asin(x) { | |
return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); | |
} | |
function arcInnerRadius(d) { | |
return d.innerRadius; | |
} | |
function arcOuterRadius(d) { | |
return d.outerRadius; | |
} | |
function arcStartAngle(d) { | |
return d.startAngle; | |
} | |
function arcEndAngle(d) { | |
return d.endAngle; | |
} | |
function arcPadAngle(d) { | |
return d && d.padAngle; // Note: optional! | |
} | |
function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { | |
var x10 = x1 - x0, y10 = y1 - y0, | |
x32 = x3 - x2, y32 = y3 - y2, | |
t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); | |
return [x0 + t * x10, y0 + t * y10]; | |
} | |
// Compute perpendicular offset line of length rc. | |
// http://mathworld.wolfram.com/Circle-LineIntersection.html | |
function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { | |
var x01 = x0 - x1, | |
y01 = y0 - y1, | |
lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01), | |
ox = lo * y01, | |
oy = -lo * x01, | |
x11 = x0 + ox, | |
y11 = y0 + oy, | |
x10 = x1 + ox, | |
y10 = y1 + oy, | |
x00 = (x11 + x10) / 2, | |
y00 = (y11 + y10) / 2, | |
dx = x10 - x11, | |
dy = y10 - y11, | |
d2 = dx * dx + dy * dy, | |
r = r1 - rc, | |
D = x11 * y10 - x10 * y11, | |
d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)), | |
cx0 = (D * dy - dx * d) / d2, | |
cy0 = (-D * dx - dy * d) / d2, | |
cx1 = (D * dy + dx * d) / d2, | |
cy1 = (-D * dx + dy * d) / d2, | |
dx0 = cx0 - x00, | |
dy0 = cy0 - y00, | |
dx1 = cx1 - x00, | |
dy1 = cy1 - y00; | |
// Pick the closer of the two intersection points. | |
// TODO Is there a faster way to determine which intersection to use? | |
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; | |
return { | |
cx: cx0, | |
cy: cy0, | |
x01: -ox, | |
y01: -oy, | |
x11: cx0 * (r1 / r - 1), | |
y11: cy0 * (r1 / r - 1) | |
}; | |
} | |
var arc = function() { | |
var innerRadius = arcInnerRadius, | |
outerRadius = arcOuterRadius, | |
cornerRadius = constant(0), | |
padRadius = null, | |
startAngle = arcStartAngle, | |
endAngle = arcEndAngle, | |
padAngle = arcPadAngle, | |
context = null; | |
function arc() { | |
var buffer, | |
r, | |
r0 = +innerRadius.apply(this, arguments), | |
r1 = +outerRadius.apply(this, arguments), | |
a0 = startAngle.apply(this, arguments) - halfPi, | |
a1 = endAngle.apply(this, arguments) - halfPi, | |
da = abs(a1 - a0), | |
cw = a1 > a0; | |
if (!context) context = buffer = d3Path.path(); | |
// Ensure that the outer radius is always larger than the inner radius. | |
if (r1 < r0) r = r1, r1 = r0, r0 = r; | |
// Is it a point? | |
if (!(r1 > epsilon)) context.moveTo(0, 0); | |
// Or is it a circle or annulus? | |
else if (da > tau - epsilon) { | |
context.moveTo(r1 * cos(a0), r1 * sin(a0)); | |
context.arc(0, 0, r1, a0, a1, !cw); | |
if (r0 > epsilon) { | |
context.moveTo(r0 * cos(a1), r0 * sin(a1)); | |
context.arc(0, 0, r0, a1, a0, cw); | |
} | |
} | |
// Or is it a circular or annular sector? | |
else { | |
var a01 = a0, | |
a11 = a1, | |
a00 = a0, | |
a10 = a1, | |
da0 = da, | |
da1 = da, | |
ap = padAngle.apply(this, arguments) / 2, | |
rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)), | |
rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), | |
rc0 = rc, | |
rc1 = rc, | |
t0, | |
t1; | |
// Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. | |
if (rp > epsilon) { | |
var p0 = asin(rp / r0 * sin(ap)), | |
p1 = asin(rp / r1 * sin(ap)); | |
if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; | |
else da0 = 0, a00 = a10 = (a0 + a1) / 2; | |
if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; | |
else da1 = 0, a01 = a11 = (a0 + a1) / 2; | |
} | |
var x01 = r1 * cos(a01), | |
y01 = r1 * sin(a01), | |
x10 = r0 * cos(a10), | |
y10 = r0 * sin(a10); | |
// Apply rounded corners? | |
if (rc > epsilon) { | |
var x11 = r1 * cos(a11), | |
y11 = r1 * sin(a11), | |
x00 = r0 * cos(a00), | |
y00 = r0 * sin(a00); | |
// Restrict the corner radius according to the sector angle. | |
if (da < pi) { | |
var oc = da0 > epsilon ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], | |
ax = x01 - oc[0], | |
ay = y01 - oc[1], | |
bx = x11 - oc[0], | |
by = y11 - oc[1], | |
kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2), | |
lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]); | |
rc0 = min(rc, (r0 - lc) / (kc - 1)); | |
rc1 = min(rc, (r1 - lc) / (kc + 1)); | |
} | |
} | |
// Is the sector collapsed to a line? | |
if (!(da1 > epsilon)) context.moveTo(x01, y01); | |
// Does the sector’s outer ring have rounded corners? | |
else if (rc1 > epsilon) { | |
t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); | |
t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); | |
context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); | |
// Have the corners merged? | |
if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); | |
// Otherwise, draw the two corners and the ring. | |
else { | |
context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); | |
context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); | |
context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); | |
} | |
} | |
// Or is the outer ring just a circular arc? | |
else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); | |
// Is there no inner ring, and it’s a circular sector? | |
// Or perhaps it’s an annular sector collapsed due to padding? | |
if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10); | |
// Does the sector’s inner ring (or point) have rounded corners? | |
else if (rc0 > epsilon) { | |
t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); | |
t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); | |
context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); | |
// Have the corners merged? | |
if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); | |
// Otherwise, draw the two corners and the ring. | |
else { | |
context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); | |
context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); | |
context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); | |
} | |
} | |
// Or is the inner ring just a circular arc? | |
else context.arc(0, 0, r0, a10, a00, cw); | |
} | |
context.closePath(); | |
if (buffer) return context = null, buffer + "" || null; | |
} | |
arc.centroid = function() { | |
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, | |
a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2; | |
return [cos(a) * r, sin(a) * r]; | |
}; | |
arc.innerRadius = function(_) { | |
return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius; | |
}; | |
arc.outerRadius = function(_) { | |
return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius; | |
}; | |
arc.cornerRadius = function(_) { | |
return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius; | |
}; | |
arc.padRadius = function(_) { | |
return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius; | |
}; | |
arc.startAngle = function(_) { | |
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle; | |
}; | |
arc.endAngle = function(_) { | |
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle; | |
}; | |
arc.padAngle = function(_) { | |
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle; | |
}; | |
arc.context = function(_) { | |
return arguments.length ? ((context = _ == null ? null : _), arc) : context; | |
}; | |
return arc; | |
}; | |
function Linear(context) { | |
this._context = context; | |
} | |
Linear.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; // proceed | |
default: this._context.lineTo(x, y); break; | |
} | |
} | |
}; | |
var curveLinear = function(context) { | |
return new Linear(context); | |
}; | |
function x(p) { | |
return p[0]; | |
} | |
function y(p) { | |
return p[1]; | |
} | |
var line = function() { | |
var x$$1 = x, | |
y$$1 = y, | |
defined = constant(true), | |
context = null, | |
curve = curveLinear, | |
output = null; | |
function line(data) { | |
var i, | |
n = data.length, | |
d, | |
defined0 = false, | |
buffer; | |
if (context == null) output = curve(buffer = d3Path.path()); | |
for (i = 0; i <= n; ++i) { | |
if (!(i < n && defined(d = data[i], i, data)) === defined0) { | |
if (defined0 = !defined0) output.lineStart(); | |
else output.lineEnd(); | |
} | |
if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); | |
} | |
if (buffer) return output = null, buffer + "" || null; | |
} | |
line.x = function(_) { | |
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), line) : x$$1; | |
}; | |
line.y = function(_) { | |
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), line) : y$$1; | |
}; | |
line.defined = function(_) { | |
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined; | |
}; | |
line.curve = function(_) { | |
return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; | |
}; | |
line.context = function(_) { | |
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; | |
}; | |
return line; | |
}; | |
var area = function() { | |
var x0 = x, | |
x1 = null, | |
y0 = constant(0), | |
y1 = y, | |
defined = constant(true), | |
context = null, | |
curve = curveLinear, | |
output = null; | |
function area(data) { | |
var i, | |
j, | |
k, | |
n = data.length, | |
d, | |
defined0 = false, | |
buffer, | |
x0z = new Array(n), | |
y0z = new Array(n); | |
if (context == null) output = curve(buffer = d3Path.path()); | |
for (i = 0; i <= n; ++i) { | |
if (!(i < n && defined(d = data[i], i, data)) === defined0) { | |
if (defined0 = !defined0) { | |
j = i; | |
output.areaStart(); | |
output.lineStart(); | |
} else { | |
output.lineEnd(); | |
output.lineStart(); | |
for (k = i - 1; k >= j; --k) { | |
output.point(x0z[k], y0z[k]); | |
} | |
output.lineEnd(); | |
output.areaEnd(); | |
} | |
} | |
if (defined0) { | |
x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); | |
output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); | |
} | |
} | |
if (buffer) return output = null, buffer + "" || null; | |
} | |
function arealine() { | |
return line().defined(defined).curve(curve).context(context); | |
} | |
area.x = function(_) { | |
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0; | |
}; | |
area.x0 = function(_) { | |
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0; | |
}; | |
area.x1 = function(_) { | |
return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1; | |
}; | |
area.y = function(_) { | |
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0; | |
}; | |
area.y0 = function(_) { | |
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0; | |
}; | |
area.y1 = function(_) { | |
return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1; | |
}; | |
area.lineX0 = | |
area.lineY0 = function() { | |
return arealine().x(x0).y(y0); | |
}; | |
area.lineY1 = function() { | |
return arealine().x(x0).y(y1); | |
}; | |
area.lineX1 = function() { | |
return arealine().x(x1).y(y0); | |
}; | |
area.defined = function(_) { | |
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined; | |
}; | |
area.curve = function(_) { | |
return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; | |
}; | |
area.context = function(_) { | |
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; | |
}; | |
return area; | |
}; | |
var descending = function(a, b) { | |
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; | |
}; | |
var identity = function(d) { | |
return d; | |
}; | |
var pie = function() { | |
var value = identity, | |
sortValues = descending, | |
sort = null, | |
startAngle = constant(0), | |
endAngle = constant(tau), | |
padAngle = constant(0); | |
function pie(data) { | |
var i, | |
n = data.length, | |
j, | |
k, | |
sum = 0, | |
index = new Array(n), | |
arcs = new Array(n), | |
a0 = +startAngle.apply(this, arguments), | |
da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), | |
a1, | |
p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), | |
pa = p * (da < 0 ? -1 : 1), | |
v; | |
for (i = 0; i < n; ++i) { | |
if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { | |
sum += v; | |
} | |
} | |
// Optionally sort the arcs by previously-computed values or by data. | |
if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); | |
else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); | |
// Compute the arcs! They are stored in the original data's order. | |
for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { | |
j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { | |
data: data[j], | |
index: i, | |
value: v, | |
startAngle: a0, | |
endAngle: a1, | |
padAngle: p | |
}; | |
} | |
return arcs; | |
} | |
pie.value = function(_) { | |
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value; | |
}; | |
pie.sortValues = function(_) { | |
return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; | |
}; | |
pie.sort = function(_) { | |
return arguments.length ? (sort = _, sortValues = null, pie) : sort; | |
}; | |
pie.startAngle = function(_) { | |
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle; | |
}; | |
pie.endAngle = function(_) { | |
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle; | |
}; | |
pie.padAngle = function(_) { | |
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle; | |
}; | |
return pie; | |
}; | |
var curveRadialLinear = curveRadial(curveLinear); | |
function Radial(curve) { | |
this._curve = curve; | |
} | |
Radial.prototype = { | |
areaStart: function() { | |
this._curve.areaStart(); | |
}, | |
areaEnd: function() { | |
this._curve.areaEnd(); | |
}, | |
lineStart: function() { | |
this._curve.lineStart(); | |
}, | |
lineEnd: function() { | |
this._curve.lineEnd(); | |
}, | |
point: function(a, r) { | |
this._curve.point(r * Math.sin(a), r * -Math.cos(a)); | |
} | |
}; | |
function curveRadial(curve) { | |
function radial(context) { | |
return new Radial(curve(context)); | |
} | |
radial._curve = curve; | |
return radial; | |
} | |
function lineRadial(l) { | |
var c = l.curve; | |
l.angle = l.x, delete l.x; | |
l.radius = l.y, delete l.y; | |
l.curve = function(_) { | |
return arguments.length ? c(curveRadial(_)) : c()._curve; | |
}; | |
return l; | |
} | |
var lineRadial$1 = function() { | |
return lineRadial(line().curve(curveRadialLinear)); | |
}; | |
var areaRadial = function() { | |
var a = area().curve(curveRadialLinear), | |
c = a.curve, | |
x0 = a.lineX0, | |
x1 = a.lineX1, | |
y0 = a.lineY0, | |
y1 = a.lineY1; | |
a.angle = a.x, delete a.x; | |
a.startAngle = a.x0, delete a.x0; | |
a.endAngle = a.x1, delete a.x1; | |
a.radius = a.y, delete a.y; | |
a.innerRadius = a.y0, delete a.y0; | |
a.outerRadius = a.y1, delete a.y1; | |
a.lineStartAngle = function() { return lineRadial(x0()); }, delete a.lineX0; | |
a.lineEndAngle = function() { return lineRadial(x1()); }, delete a.lineX1; | |
a.lineInnerRadius = function() { return lineRadial(y0()); }, delete a.lineY0; | |
a.lineOuterRadius = function() { return lineRadial(y1()); }, delete a.lineY1; | |
a.curve = function(_) { | |
return arguments.length ? c(curveRadial(_)) : c()._curve; | |
}; | |
return a; | |
}; | |
var pointRadial = function(x, y) { | |
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; | |
}; | |
var slice = Array.prototype.slice; | |
function linkSource(d) { | |
return d.source; | |
} | |
function linkTarget(d) { | |
return d.target; | |
} | |
function link(curve) { | |
var source = linkSource, | |
target = linkTarget, | |
x$$1 = x, | |
y$$1 = y, | |
context = null; | |
function link() { | |
var buffer, argv = slice.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); | |
if (!context) context = buffer = d3Path.path(); | |
curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); | |
if (buffer) return context = null, buffer + "" || null; | |
} | |
link.source = function(_) { | |
return arguments.length ? (source = _, link) : source; | |
}; | |
link.target = function(_) { | |
return arguments.length ? (target = _, link) : target; | |
}; | |
link.x = function(_) { | |
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), link) : x$$1; | |
}; | |
link.y = function(_) { | |
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), link) : y$$1; | |
}; | |
link.context = function(_) { | |
return arguments.length ? ((context = _ == null ? null : _), link) : context; | |
}; | |
return link; | |
} | |
function curveHorizontal(context, x0, y0, x1, y1) { | |
context.moveTo(x0, y0); | |
context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); | |
} | |
function curveVertical(context, x0, y0, x1, y1) { | |
context.moveTo(x0, y0); | |
context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); | |
} | |
function curveRadial$1(context, x0, y0, x1, y1) { | |
var p0 = pointRadial(x0, y0), | |
p1 = pointRadial(x0, y0 = (y0 + y1) / 2), | |
p2 = pointRadial(x1, y0), | |
p3 = pointRadial(x1, y1); | |
context.moveTo(p0[0], p0[1]); | |
context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); | |
} | |
function linkHorizontal() { | |
return link(curveHorizontal); | |
} | |
function linkVertical() { | |
return link(curveVertical); | |
} | |
function linkRadial() { | |
var l = link(curveRadial$1); | |
l.angle = l.x, delete l.x; | |
l.radius = l.y, delete l.y; | |
return l; | |
} | |
var circle = { | |
draw: function(context, size) { | |
var r = Math.sqrt(size / pi); | |
context.moveTo(r, 0); | |
context.arc(0, 0, r, 0, tau); | |
} | |
}; | |
var cross = { | |
draw: function(context, size) { | |
var r = Math.sqrt(size / 5) / 2; | |
context.moveTo(-3 * r, -r); | |
context.lineTo(-r, -r); | |
context.lineTo(-r, -3 * r); | |
context.lineTo(r, -3 * r); | |
context.lineTo(r, -r); | |
context.lineTo(3 * r, -r); | |
context.lineTo(3 * r, r); | |
context.lineTo(r, r); | |
context.lineTo(r, 3 * r); | |
context.lineTo(-r, 3 * r); | |
context.lineTo(-r, r); | |
context.lineTo(-3 * r, r); | |
context.closePath(); | |
} | |
}; | |
var tan30 = Math.sqrt(1 / 3); | |
var tan30_2 = tan30 * 2; | |
var diamond = { | |
draw: function(context, size) { | |
var y = Math.sqrt(size / tan30_2), | |
x = y * tan30; | |
context.moveTo(0, -y); | |
context.lineTo(x, 0); | |
context.lineTo(0, y); | |
context.lineTo(-x, 0); | |
context.closePath(); | |
} | |
}; | |
var ka = 0.89081309152928522810; | |
var kr = Math.sin(pi / 10) / Math.sin(7 * pi / 10); | |
var kx = Math.sin(tau / 10) * kr; | |
var ky = -Math.cos(tau / 10) * kr; | |
var star = { | |
draw: function(context, size) { | |
var r = Math.sqrt(size * ka), | |
x = kx * r, | |
y = ky * r; | |
context.moveTo(0, -r); | |
context.lineTo(x, y); | |
for (var i = 1; i < 5; ++i) { | |
var a = tau * i / 5, | |
c = Math.cos(a), | |
s = Math.sin(a); | |
context.lineTo(s * r, -c * r); | |
context.lineTo(c * x - s * y, s * x + c * y); | |
} | |
context.closePath(); | |
} | |
}; | |
var square = { | |
draw: function(context, size) { | |
var w = Math.sqrt(size), | |
x = -w / 2; | |
context.rect(x, x, w, w); | |
} | |
}; | |
var sqrt3 = Math.sqrt(3); | |
var triangle = { | |
draw: function(context, size) { | |
var y = -Math.sqrt(size / (sqrt3 * 3)); | |
context.moveTo(0, y * 2); | |
context.lineTo(-sqrt3 * y, -y); | |
context.lineTo(sqrt3 * y, -y); | |
context.closePath(); | |
} | |
}; | |
var c = -0.5; | |
var s = Math.sqrt(3) / 2; | |
var k = 1 / Math.sqrt(12); | |
var a = (k / 2 + 1) * 3; | |
var wye = { | |
draw: function(context, size) { | |
var r = Math.sqrt(size / a), | |
x0 = r / 2, | |
y0 = r * k, | |
x1 = x0, | |
y1 = r * k + r, | |
x2 = -x1, | |
y2 = y1; | |
context.moveTo(x0, y0); | |
context.lineTo(x1, y1); | |
context.lineTo(x2, y2); | |
context.lineTo(c * x0 - s * y0, s * x0 + c * y0); | |
context.lineTo(c * x1 - s * y1, s * x1 + c * y1); | |
context.lineTo(c * x2 - s * y2, s * x2 + c * y2); | |
context.lineTo(c * x0 + s * y0, c * y0 - s * x0); | |
context.lineTo(c * x1 + s * y1, c * y1 - s * x1); | |
context.lineTo(c * x2 + s * y2, c * y2 - s * x2); | |
context.closePath(); | |
} | |
}; | |
var symbols = [ | |
circle, | |
cross, | |
diamond, | |
square, | |
star, | |
triangle, | |
wye | |
]; | |
var symbol = function() { | |
var type = constant(circle), | |
size = constant(64), | |
context = null; | |
function symbol() { | |
var buffer; | |
if (!context) context = buffer = d3Path.path(); | |
type.apply(this, arguments).draw(context, +size.apply(this, arguments)); | |
if (buffer) return context = null, buffer + "" || null; | |
} | |
symbol.type = function(_) { | |
return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type; | |
}; | |
symbol.size = function(_) { | |
return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size; | |
}; | |
symbol.context = function(_) { | |
return arguments.length ? (context = _ == null ? null : _, symbol) : context; | |
}; | |
return symbol; | |
}; | |
var noop = function() {}; | |
function point(that, x, y) { | |
that._context.bezierCurveTo( | |
(2 * that._x0 + that._x1) / 3, | |
(2 * that._y0 + that._y1) / 3, | |
(that._x0 + 2 * that._x1) / 3, | |
(that._y0 + 2 * that._y1) / 3, | |
(that._x0 + 4 * that._x1 + x) / 6, | |
(that._y0 + 4 * that._y1 + y) / 6 | |
); | |
} | |
function Basis(context) { | |
this._context = context; | |
} | |
Basis.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = | |
this._y0 = this._y1 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 3: point(this, this._x1, this._y1); // proceed | |
case 2: this._context.lineTo(this._x1, this._y1); break; | |
} | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed | |
default: point(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = x; | |
this._y0 = this._y1, this._y1 = y; | |
} | |
}; | |
var basis = function(context) { | |
return new Basis(context); | |
}; | |
function BasisClosed(context) { | |
this._context = context; | |
} | |
BasisClosed.prototype = { | |
areaStart: noop, | |
areaEnd: noop, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = | |
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 1: { | |
this._context.moveTo(this._x2, this._y2); | |
this._context.closePath(); | |
break; | |
} | |
case 2: { | |
this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); | |
this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); | |
this._context.closePath(); | |
break; | |
} | |
case 3: { | |
this.point(this._x2, this._y2); | |
this.point(this._x3, this._y3); | |
this.point(this._x4, this._y4); | |
break; | |
} | |
} | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._x2 = x, this._y2 = y; break; | |
case 1: this._point = 2; this._x3 = x, this._y3 = y; break; | |
case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; | |
default: point(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = x; | |
this._y0 = this._y1, this._y1 = y; | |
} | |
}; | |
var basisClosed = function(context) { | |
return new BasisClosed(context); | |
}; | |
function BasisOpen(context) { | |
this._context = context; | |
} | |
BasisOpen.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = | |
this._y0 = this._y1 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; | |
case 3: this._point = 4; // proceed | |
default: point(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = x; | |
this._y0 = this._y1, this._y1 = y; | |
} | |
}; | |
var basisOpen = function(context) { | |
return new BasisOpen(context); | |
}; | |
function Bundle(context, beta) { | |
this._basis = new Basis(context); | |
this._beta = beta; | |
} | |
Bundle.prototype = { | |
lineStart: function() { | |
this._x = []; | |
this._y = []; | |
this._basis.lineStart(); | |
}, | |
lineEnd: function() { | |
var x = this._x, | |
y = this._y, | |
j = x.length - 1; | |
if (j > 0) { | |
var x0 = x[0], | |
y0 = y[0], | |
dx = x[j] - x0, | |
dy = y[j] - y0, | |
i = -1, | |
t; | |
while (++i <= j) { | |
t = i / j; | |
this._basis.point( | |
this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), | |
this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) | |
); | |
} | |
} | |
this._x = this._y = null; | |
this._basis.lineEnd(); | |
}, | |
point: function(x, y) { | |
this._x.push(+x); | |
this._y.push(+y); | |
} | |
}; | |
var bundle = ((function custom(beta) { | |
function bundle(context) { | |
return beta === 1 ? new Basis(context) : new Bundle(context, beta); | |
} | |
bundle.beta = function(beta) { | |
return custom(+beta); | |
}; | |
return bundle; | |
}))(0.85); | |
function point$1(that, x, y) { | |
that._context.bezierCurveTo( | |
that._x1 + that._k * (that._x2 - that._x0), | |
that._y1 + that._k * (that._y2 - that._y0), | |
that._x2 + that._k * (that._x1 - x), | |
that._y2 + that._k * (that._y1 - y), | |
that._x2, | |
that._y2 | |
); | |
} | |
function Cardinal(context, tension) { | |
this._context = context; | |
this._k = (1 - tension) / 6; | |
} | |
Cardinal.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = | |
this._y0 = this._y1 = this._y2 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 2: this._context.lineTo(this._x2, this._y2); break; | |
case 3: point$1(this, this._x1, this._y1); break; | |
} | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; this._x1 = x, this._y1 = y; break; | |
case 2: this._point = 3; // proceed | |
default: point$1(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var cardinal = ((function custom(tension) { | |
function cardinal(context) { | |
return new Cardinal(context, tension); | |
} | |
cardinal.tension = function(tension) { | |
return custom(+tension); | |
}; | |
return cardinal; | |
}))(0); | |
function CardinalClosed(context, tension) { | |
this._context = context; | |
this._k = (1 - tension) / 6; | |
} | |
CardinalClosed.prototype = { | |
areaStart: noop, | |
areaEnd: noop, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = | |
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 1: { | |
this._context.moveTo(this._x3, this._y3); | |
this._context.closePath(); | |
break; | |
} | |
case 2: { | |
this._context.lineTo(this._x3, this._y3); | |
this._context.closePath(); | |
break; | |
} | |
case 3: { | |
this.point(this._x3, this._y3); | |
this.point(this._x4, this._y4); | |
this.point(this._x5, this._y5); | |
break; | |
} | |
} | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._x3 = x, this._y3 = y; break; | |
case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; | |
case 2: this._point = 3; this._x5 = x, this._y5 = y; break; | |
default: point$1(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var cardinalClosed = ((function custom(tension) { | |
function cardinal(context) { | |
return new CardinalClosed(context, tension); | |
} | |
cardinal.tension = function(tension) { | |
return custom(+tension); | |
}; | |
return cardinal; | |
}))(0); | |
function CardinalOpen(context, tension) { | |
this._context = context; | |
this._k = (1 - tension) / 6; | |
} | |
CardinalOpen.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = | |
this._y0 = this._y1 = this._y2 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; | |
case 3: this._point = 4; // proceed | |
default: point$1(this, x, y); break; | |
} | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var cardinalOpen = ((function custom(tension) { | |
function cardinal(context) { | |
return new CardinalOpen(context, tension); | |
} | |
cardinal.tension = function(tension) { | |
return custom(+tension); | |
}; | |
return cardinal; | |
}))(0); | |
function point$2(that, x, y) { | |
var x1 = that._x1, | |
y1 = that._y1, | |
x2 = that._x2, | |
y2 = that._y2; | |
if (that._l01_a > epsilon) { | |
var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, | |
n = 3 * that._l01_a * (that._l01_a + that._l12_a); | |
x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; | |
y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; | |
} | |
if (that._l23_a > epsilon) { | |
var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, | |
m = 3 * that._l23_a * (that._l23_a + that._l12_a); | |
x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; | |
y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; | |
} | |
that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); | |
} | |
function CatmullRom(context, alpha) { | |
this._context = context; | |
this._alpha = alpha; | |
} | |
CatmullRom.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = | |
this._y0 = this._y1 = this._y2 = NaN; | |
this._l01_a = this._l12_a = this._l23_a = | |
this._l01_2a = this._l12_2a = this._l23_2a = | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 2: this._context.lineTo(this._x2, this._y2); break; | |
case 3: this.point(this._x2, this._y2); break; | |
} | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
if (this._point) { | |
var x23 = this._x2 - x, | |
y23 = this._y2 - y; | |
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); | |
} | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; // proceed | |
default: point$2(this, x, y); break; | |
} | |
this._l01_a = this._l12_a, this._l12_a = this._l23_a; | |
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var catmullRom = ((function custom(alpha) { | |
function catmullRom(context) { | |
return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); | |
} | |
catmullRom.alpha = function(alpha) { | |
return custom(+alpha); | |
}; | |
return catmullRom; | |
}))(0.5); | |
function CatmullRomClosed(context, alpha) { | |
this._context = context; | |
this._alpha = alpha; | |
} | |
CatmullRomClosed.prototype = { | |
areaStart: noop, | |
areaEnd: noop, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = | |
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; | |
this._l01_a = this._l12_a = this._l23_a = | |
this._l01_2a = this._l12_2a = this._l23_2a = | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 1: { | |
this._context.moveTo(this._x3, this._y3); | |
this._context.closePath(); | |
break; | |
} | |
case 2: { | |
this._context.lineTo(this._x3, this._y3); | |
this._context.closePath(); | |
break; | |
} | |
case 3: { | |
this.point(this._x3, this._y3); | |
this.point(this._x4, this._y4); | |
this.point(this._x5, this._y5); | |
break; | |
} | |
} | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
if (this._point) { | |
var x23 = this._x2 - x, | |
y23 = this._y2 - y; | |
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); | |
} | |
switch (this._point) { | |
case 0: this._point = 1; this._x3 = x, this._y3 = y; break; | |
case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; | |
case 2: this._point = 3; this._x5 = x, this._y5 = y; break; | |
default: point$2(this, x, y); break; | |
} | |
this._l01_a = this._l12_a, this._l12_a = this._l23_a; | |
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var catmullRomClosed = ((function custom(alpha) { | |
function catmullRom(context) { | |
return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); | |
} | |
catmullRom.alpha = function(alpha) { | |
return custom(+alpha); | |
}; | |
return catmullRom; | |
}))(0.5); | |
function CatmullRomOpen(context, alpha) { | |
this._context = context; | |
this._alpha = alpha; | |
} | |
CatmullRomOpen.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = this._x2 = | |
this._y0 = this._y1 = this._y2 = NaN; | |
this._l01_a = this._l12_a = this._l23_a = | |
this._l01_2a = this._l12_2a = this._l23_2a = | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
if (this._point) { | |
var x23 = this._x2 - x, | |
y23 = this._y2 - y; | |
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); | |
} | |
switch (this._point) { | |
case 0: this._point = 1; break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; | |
case 3: this._point = 4; // proceed | |
default: point$2(this, x, y); break; | |
} | |
this._l01_a = this._l12_a, this._l12_a = this._l23_a; | |
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; | |
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; | |
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; | |
} | |
}; | |
var catmullRomOpen = ((function custom(alpha) { | |
function catmullRom(context) { | |
return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); | |
} | |
catmullRom.alpha = function(alpha) { | |
return custom(+alpha); | |
}; | |
return catmullRom; | |
}))(0.5); | |
function LinearClosed(context) { | |
this._context = context; | |
} | |
LinearClosed.prototype = { | |
areaStart: noop, | |
areaEnd: noop, | |
lineStart: function() { | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (this._point) this._context.closePath(); | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
if (this._point) this._context.lineTo(x, y); | |
else this._point = 1, this._context.moveTo(x, y); | |
} | |
}; | |
var linearClosed = function(context) { | |
return new LinearClosed(context); | |
}; | |
function sign(x) { | |
return x < 0 ? -1 : 1; | |
} | |
// Calculate the slopes of the tangents (Hermite-type interpolation) based on | |
// the following paper: Steffen, M. 1990. A Simple Method for Monotonic | |
// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. | |
// NOV(II), P. 443, 1990. | |
function slope3(that, x2, y2) { | |
var h0 = that._x1 - that._x0, | |
h1 = x2 - that._x1, | |
s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), | |
s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), | |
p = (s0 * h1 + s1 * h0) / (h0 + h1); | |
return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; | |
} | |
// Calculate a one-sided slope. | |
function slope2(that, t) { | |
var h = that._x1 - that._x0; | |
return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; | |
} | |
// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations | |
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves | |
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". | |
function point$3(that, t0, t1) { | |
var x0 = that._x0, | |
y0 = that._y0, | |
x1 = that._x1, | |
y1 = that._y1, | |
dx = (x1 - x0) / 3; | |
that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); | |
} | |
function MonotoneX(context) { | |
this._context = context; | |
} | |
MonotoneX.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x0 = this._x1 = | |
this._y0 = this._y1 = | |
this._t0 = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
switch (this._point) { | |
case 2: this._context.lineTo(this._x1, this._y1); break; | |
case 3: point$3(this, this._t0, slope2(this, this._t0)); break; | |
} | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
var t1 = NaN; | |
x = +x, y = +y; | |
if (x === this._x1 && y === this._y1) return; // Ignore coincident points. | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; break; | |
case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; | |
default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; | |
} | |
this._x0 = this._x1, this._x1 = x; | |
this._y0 = this._y1, this._y1 = y; | |
this._t0 = t1; | |
} | |
}; | |
function MonotoneY(context) { | |
this._context = new ReflectContext(context); | |
} | |
(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { | |
MonotoneX.prototype.point.call(this, y, x); | |
}; | |
function ReflectContext(context) { | |
this._context = context; | |
} | |
ReflectContext.prototype = { | |
moveTo: function(x, y) { this._context.moveTo(y, x); }, | |
closePath: function() { this._context.closePath(); }, | |
lineTo: function(x, y) { this._context.lineTo(y, x); }, | |
bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } | |
}; | |
function monotoneX(context) { | |
return new MonotoneX(context); | |
} | |
function monotoneY(context) { | |
return new MonotoneY(context); | |
} | |
function Natural(context) { | |
this._context = context; | |
} | |
Natural.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x = []; | |
this._y = []; | |
}, | |
lineEnd: function() { | |
var x = this._x, | |
y = this._y, | |
n = x.length; | |
if (n) { | |
this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); | |
if (n === 2) { | |
this._context.lineTo(x[1], y[1]); | |
} else { | |
var px = controlPoints(x), | |
py = controlPoints(y); | |
for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { | |
this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); | |
} | |
} | |
} | |
if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); | |
this._line = 1 - this._line; | |
this._x = this._y = null; | |
}, | |
point: function(x, y) { | |
this._x.push(+x); | |
this._y.push(+y); | |
} | |
}; | |
// See https://www.particleincell.com/2012/bezier-splines/ for derivation. | |
function controlPoints(x) { | |
var i, | |
n = x.length - 1, | |
m, | |
a = new Array(n), | |
b = new Array(n), | |
r = new Array(n); | |
a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; | |
for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; | |
a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; | |
for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; | |
a[n - 1] = r[n - 1] / b[n - 1]; | |
for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; | |
b[n - 1] = (x[n] + a[n - 1]) / 2; | |
for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; | |
return [a, b]; | |
} | |
var natural = function(context) { | |
return new Natural(context); | |
}; | |
function Step(context, t) { | |
this._context = context; | |
this._t = t; | |
} | |
Step.prototype = { | |
areaStart: function() { | |
this._line = 0; | |
}, | |
areaEnd: function() { | |
this._line = NaN; | |
}, | |
lineStart: function() { | |
this._x = this._y = NaN; | |
this._point = 0; | |
}, | |
lineEnd: function() { | |
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); | |
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); | |
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; | |
}, | |
point: function(x, y) { | |
x = +x, y = +y; | |
switch (this._point) { | |
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; | |
case 1: this._point = 2; // proceed | |
default: { | |
if (this._t <= 0) { | |
this._context.lineTo(this._x, y); | |
this._context.lineTo(x, y); | |
} else { | |
var x1 = this._x * (1 - this._t) + x * this._t; | |
this._context.lineTo(x1, this._y); | |
this._context.lineTo(x1, y); | |
} | |
break; | |
} | |
} | |
this._x = x, this._y = y; | |
} | |
}; | |
var step = function(context) { | |
return new Step(context, 0.5); | |
}; | |
function stepBefore(context) { | |
return new Step(context, 0); | |
} | |
function stepAfter(context) { | |
return new Step(context, 1); | |
} | |
var none = function(series, order) { | |
if (!((n = series.length) > 1)) return; | |
for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { | |
s0 = s1, s1 = series[order[i]]; | |
for (j = 0; j < m; ++j) { | |
s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; | |
} | |
} | |
}; | |
var none$1 = function(series) { | |
var n = series.length, o = new Array(n); | |
while (--n >= 0) o[n] = n; | |
return o; | |
}; | |
function stackValue(d, key) { | |
return d[key]; | |
} | |
var stack = function() { | |
var keys = constant([]), | |
order = none$1, | |
offset = none, | |
value = stackValue; | |
function stack(data) { | |
var kz = keys.apply(this, arguments), | |
i, | |
m = data.length, | |
n = kz.length, | |
sz = new Array(n), | |
oz; | |
for (i = 0; i < n; ++i) { | |
for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { | |
si[j] = sij = [0, +value(data[j], ki, j, data)]; | |
sij.data = data[j]; | |
} | |
si.key = ki; | |
} | |
for (i = 0, oz = order(sz); i < n; ++i) { | |
sz[oz[i]].index = i; | |
} | |
offset(sz, oz); | |
return sz; | |
} | |
stack.keys = function(_) { | |
return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys; | |
}; | |
stack.value = function(_) { | |
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value; | |
}; | |
stack.order = function(_) { | |
return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order; | |
}; | |
stack.offset = function(_) { | |
return arguments.length ? (offset = _ == null ? none : _, stack) : offset; | |
}; | |
return stack; | |
}; | |
var expand = function(series, order) { | |
if (!((n = series.length) > 0)) return; | |
for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { | |
for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; | |
if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; | |
} | |
none(series, order); | |
}; | |
var diverging = function(series, order) { | |
if (!((n = series.length) > 1)) return; | |
for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { | |
for (yp = yn = 0, i = 0; i < n; ++i) { | |
if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { | |
d[0] = yp, d[1] = yp += dy; | |
} else if (dy < 0) { | |
d[1] = yn, d[0] = yn += dy; | |
} else { | |
d[0] = yp; | |
} | |
} | |
} | |
}; | |
var silhouette = function(series, order) { | |
if (!((n = series.length) > 0)) return; | |
for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { | |
for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; | |
s0[j][1] += s0[j][0] = -y / 2; | |
} | |
none(series, order); | |
}; | |
var wiggle = function(series, order) { | |
if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; | |
for (var y = 0, j = 1, s0, m, n; j < m; ++j) { | |
for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { | |
var si = series[order[i]], | |
sij0 = si[j][1] || 0, | |
sij1 = si[j - 1][1] || 0, | |
s3 = (sij0 - sij1) / 2; | |
for (var k = 0; k < i; ++k) { | |
var sk = series[order[k]], | |
skj0 = sk[j][1] || 0, | |
skj1 = sk[j - 1][1] || 0; | |
s3 += skj0 - skj1; | |
} | |
s1 += sij0, s2 += s3 * sij0; | |
} | |
s0[j - 1][1] += s0[j - 1][0] = y; | |
if (s1) y -= s2 / s1; | |
} | |
s0[j - 1][1] += s0[j - 1][0] = y; | |
none(series, order); | |
}; | |
var ascending = function(series) { | |
var sums = series.map(sum); | |
return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); | |
}; | |
function sum(series) { | |
var s = 0, i = -1, n = series.length, v; | |
while (++i < n) if (v = +series[i][1]) s += v; | |
return s; | |
} | |
var descending$1 = function(series) { | |
return ascending(series).reverse(); | |
}; | |
var insideOut = function(series) { | |
var n = series.length, | |
i, | |
j, | |
sums = series.map(sum), | |
order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }), | |
top = 0, | |
bottom = 0, | |
tops = [], | |
bottoms = []; | |
for (i = 0; i < n; ++i) { | |
j = order[i]; | |
if (top < bottom) { | |
top += sums[j]; | |
tops.push(j); | |
} else { | |
bottom += sums[j]; | |
bottoms.push(j); | |
} | |
} | |
return bottoms.reverse().concat(tops); | |
}; | |
var reverse = function(series) { | |
return none$1(series).reverse(); | |
}; | |
exports.arc = arc; | |
exports.area = area; | |
exports.line = line; | |
exports.pie = pie; | |
exports.areaRadial = areaRadial; | |
exports.radialArea = areaRadial; | |
exports.lineRadial = lineRadial$1; | |
exports.radialLine = lineRadial$1; | |
exports.pointRadial = pointRadial; | |
exports.linkHorizontal = linkHorizontal; | |
exports.linkVertical = linkVertical; | |
exports.linkRadial = linkRadial; | |
exports.symbol = symbol; | |
exports.symbols = symbols; | |
exports.symbolCircle = circle; | |
exports.symbolCross = cross; | |
exports.symbolDiamond = diamond; | |
exports.symbolSquare = square; | |
exports.symbolStar = star; | |
exports.symbolTriangle = triangle; | |
exports.symbolWye = wye; | |
exports.curveBasisClosed = basisClosed; | |
exports.curveBasisOpen = basisOpen; | |
exports.curveBasis = basis; | |
exports.curveBundle = bundle; | |
exports.curveCardinalClosed = cardinalClosed; | |
exports.curveCardinalOpen = cardinalOpen; | |
exports.curveCardinal = cardinal; | |
exports.curveCatmullRomClosed = catmullRomClosed; | |
exports.curveCatmullRomOpen = catmullRomOpen; | |
exports.curveCatmullRom = catmullRom; | |
exports.curveLinearClosed = linearClosed; | |
exports.curveLinear = curveLinear; | |
exports.curveMonotoneX = monotoneX; | |
exports.curveMonotoneY = monotoneY; | |
exports.curveNatural = natural; | |
exports.curveStep = step; | |
exports.curveStepAfter = stepAfter; | |
exports.curveStepBefore = stepBefore; | |
exports.stack = stack; | |
exports.stackOffsetExpand = expand; | |
exports.stackOffsetDiverging = diverging; | |
exports.stackOffsetNone = none; | |
exports.stackOffsetSilhouette = silhouette; | |
exports.stackOffsetWiggle = wiggle; | |
exports.stackOrderAscending = ascending; | |
exports.stackOrderDescending = descending$1; | |
exports.stackOrderInsideOut = insideOut; | |
exports.stackOrderNone = none$1; | |
exports.stackOrderReverse = reverse; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-path":30}],39:[function(require,module,exports){ | |
// https://d3js.org/d3-time-format/ Version 2.0.5. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-time')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-time'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3)); | |
}(this, (function (exports,d3Time) { 'use strict'; | |
function localDate(d) { | |
if (0 <= d.y && d.y < 100) { | |
var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); | |
date.setFullYear(d.y); | |
return date; | |
} | |
return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); | |
} | |
function utcDate(d) { | |
if (0 <= d.y && d.y < 100) { | |
var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); | |
date.setUTCFullYear(d.y); | |
return date; | |
} | |
return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); | |
} | |
function newYear(y) { | |
return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; | |
} | |
function formatLocale(locale) { | |
var locale_dateTime = locale.dateTime, | |
locale_date = locale.date, | |
locale_time = locale.time, | |
locale_periods = locale.periods, | |
locale_weekdays = locale.days, | |
locale_shortWeekdays = locale.shortDays, | |
locale_months = locale.months, | |
locale_shortMonths = locale.shortMonths; | |
var periodRe = formatRe(locale_periods), | |
periodLookup = formatLookup(locale_periods), | |
weekdayRe = formatRe(locale_weekdays), | |
weekdayLookup = formatLookup(locale_weekdays), | |
shortWeekdayRe = formatRe(locale_shortWeekdays), | |
shortWeekdayLookup = formatLookup(locale_shortWeekdays), | |
monthRe = formatRe(locale_months), | |
monthLookup = formatLookup(locale_months), | |
shortMonthRe = formatRe(locale_shortMonths), | |
shortMonthLookup = formatLookup(locale_shortMonths); | |
var formats = { | |
"a": formatShortWeekday, | |
"A": formatWeekday, | |
"b": formatShortMonth, | |
"B": formatMonth, | |
"c": null, | |
"d": formatDayOfMonth, | |
"e": formatDayOfMonth, | |
"H": formatHour24, | |
"I": formatHour12, | |
"j": formatDayOfYear, | |
"L": formatMilliseconds, | |
"m": formatMonthNumber, | |
"M": formatMinutes, | |
"p": formatPeriod, | |
"S": formatSeconds, | |
"U": formatWeekNumberSunday, | |
"w": formatWeekdayNumber, | |
"W": formatWeekNumberMonday, | |
"x": null, | |
"X": null, | |
"y": formatYear, | |
"Y": formatFullYear, | |
"Z": formatZone, | |
"%": formatLiteralPercent | |
}; | |
var utcFormats = { | |
"a": formatUTCShortWeekday, | |
"A": formatUTCWeekday, | |
"b": formatUTCShortMonth, | |
"B": formatUTCMonth, | |
"c": null, | |
"d": formatUTCDayOfMonth, | |
"e": formatUTCDayOfMonth, | |
"H": formatUTCHour24, | |
"I": formatUTCHour12, | |
"j": formatUTCDayOfYear, | |
"L": formatUTCMilliseconds, | |
"m": formatUTCMonthNumber, | |
"M": formatUTCMinutes, | |
"p": formatUTCPeriod, | |
"S": formatUTCSeconds, | |
"U": formatUTCWeekNumberSunday, | |
"w": formatUTCWeekdayNumber, | |
"W": formatUTCWeekNumberMonday, | |
"x": null, | |
"X": null, | |
"y": formatUTCYear, | |
"Y": formatUTCFullYear, | |
"Z": formatUTCZone, | |
"%": formatLiteralPercent | |
}; | |
var parses = { | |
"a": parseShortWeekday, | |
"A": parseWeekday, | |
"b": parseShortMonth, | |
"B": parseMonth, | |
"c": parseLocaleDateTime, | |
"d": parseDayOfMonth, | |
"e": parseDayOfMonth, | |
"H": parseHour24, | |
"I": parseHour24, | |
"j": parseDayOfYear, | |
"L": parseMilliseconds, | |
"m": parseMonthNumber, | |
"M": parseMinutes, | |
"p": parsePeriod, | |
"S": parseSeconds, | |
"U": parseWeekNumberSunday, | |
"w": parseWeekdayNumber, | |
"W": parseWeekNumberMonday, | |
"x": parseLocaleDate, | |
"X": parseLocaleTime, | |
"y": parseYear, | |
"Y": parseFullYear, | |
"Z": parseZone, | |
"%": parseLiteralPercent | |
}; | |
// These recursive directive definitions must be deferred. | |
formats.x = newFormat(locale_date, formats); | |
formats.X = newFormat(locale_time, formats); | |
formats.c = newFormat(locale_dateTime, formats); | |
utcFormats.x = newFormat(locale_date, utcFormats); | |
utcFormats.X = newFormat(locale_time, utcFormats); | |
utcFormats.c = newFormat(locale_dateTime, utcFormats); | |
function newFormat(specifier, formats) { | |
return function(date) { | |
var string = [], | |
i = -1, | |
j = 0, | |
n = specifier.length, | |
c, | |
pad, | |
format; | |
if (!(date instanceof Date)) date = new Date(+date); | |
while (++i < n) { | |
if (specifier.charCodeAt(i) === 37) { | |
string.push(specifier.slice(j, i)); | |
if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); | |
else pad = c === "e" ? " " : "0"; | |
if (format = formats[c]) c = format(date, pad); | |
string.push(c); | |
j = i + 1; | |
} | |
} | |
string.push(specifier.slice(j, i)); | |
return string.join(""); | |
}; | |
} | |
function newParse(specifier, newDate) { | |
return function(string) { | |
var d = newYear(1900), | |
i = parseSpecifier(d, specifier, string += "", 0); | |
if (i != string.length) return null; | |
// The am-pm flag is 0 for AM, and 1 for PM. | |
if ("p" in d) d.H = d.H % 12 + d.p * 12; | |
// Convert day-of-week and week-of-year to day-of-year. | |
if ("W" in d || "U" in d) { | |
if (!("w" in d)) d.w = "W" in d ? 1 : 0; | |
var day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); | |
d.m = 0; | |
d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7; | |
} | |
// If a time zone is specified, all fields are interpreted as UTC and then | |
// offset according to the specified time zone. | |
if ("Z" in d) { | |
d.H += d.Z / 100 | 0; | |
d.M += d.Z % 100; | |
return utcDate(d); | |
} | |
// Otherwise, all fields are in local time. | |
return newDate(d); | |
}; | |
} | |
function parseSpecifier(d, specifier, string, j) { | |
var i = 0, | |
n = specifier.length, | |
m = string.length, | |
c, | |
parse; | |
while (i < n) { | |
if (j >= m) return -1; | |
c = specifier.charCodeAt(i++); | |
if (c === 37) { | |
c = specifier.charAt(i++); | |
parse = parses[c in pads ? specifier.charAt(i++) : c]; | |
if (!parse || ((j = parse(d, string, j)) < 0)) return -1; | |
} else if (c != string.charCodeAt(j++)) { | |
return -1; | |
} | |
} | |
return j; | |
} | |
function parsePeriod(d, string, i) { | |
var n = periodRe.exec(string.slice(i)); | |
return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; | |
} | |
function parseShortWeekday(d, string, i) { | |
var n = shortWeekdayRe.exec(string.slice(i)); | |
return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; | |
} | |
function parseWeekday(d, string, i) { | |
var n = weekdayRe.exec(string.slice(i)); | |
return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; | |
} | |
function parseShortMonth(d, string, i) { | |
var n = shortMonthRe.exec(string.slice(i)); | |
return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; | |
} | |
function parseMonth(d, string, i) { | |
var n = monthRe.exec(string.slice(i)); | |
return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; | |
} | |
function parseLocaleDateTime(d, string, i) { | |
return parseSpecifier(d, locale_dateTime, string, i); | |
} | |
function parseLocaleDate(d, string, i) { | |
return parseSpecifier(d, locale_date, string, i); | |
} | |
function parseLocaleTime(d, string, i) { | |
return parseSpecifier(d, locale_time, string, i); | |
} | |
function formatShortWeekday(d) { | |
return locale_shortWeekdays[d.getDay()]; | |
} | |
function formatWeekday(d) { | |
return locale_weekdays[d.getDay()]; | |
} | |
function formatShortMonth(d) { | |
return locale_shortMonths[d.getMonth()]; | |
} | |
function formatMonth(d) { | |
return locale_months[d.getMonth()]; | |
} | |
function formatPeriod(d) { | |
return locale_periods[+(d.getHours() >= 12)]; | |
} | |
function formatUTCShortWeekday(d) { | |
return locale_shortWeekdays[d.getUTCDay()]; | |
} | |
function formatUTCWeekday(d) { | |
return locale_weekdays[d.getUTCDay()]; | |
} | |
function formatUTCShortMonth(d) { | |
return locale_shortMonths[d.getUTCMonth()]; | |
} | |
function formatUTCMonth(d) { | |
return locale_months[d.getUTCMonth()]; | |
} | |
function formatUTCPeriod(d) { | |
return locale_periods[+(d.getUTCHours() >= 12)]; | |
} | |
return { | |
format: function(specifier) { | |
var f = newFormat(specifier += "", formats); | |
f.toString = function() { return specifier; }; | |
return f; | |
}, | |
parse: function(specifier) { | |
var p = newParse(specifier += "", localDate); | |
p.toString = function() { return specifier; }; | |
return p; | |
}, | |
utcFormat: function(specifier) { | |
var f = newFormat(specifier += "", utcFormats); | |
f.toString = function() { return specifier; }; | |
return f; | |
}, | |
utcParse: function(specifier) { | |
var p = newParse(specifier, utcDate); | |
p.toString = function() { return specifier; }; | |
return p; | |
} | |
}; | |
} | |
var pads = {"-": "", "_": " ", "0": "0"}; | |
var numberRe = /^\s*\d+/; | |
var percentRe = /^%/; | |
var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; | |
function pad(value, fill, width) { | |
var sign = value < 0 ? "-" : "", | |
string = (sign ? -value : value) + "", | |
length = string.length; | |
return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); | |
} | |
function requote(s) { | |
return s.replace(requoteRe, "\\$&"); | |
} | |
function formatRe(names) { | |
return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); | |
} | |
function formatLookup(names) { | |
var map = {}, i = -1, n = names.length; | |
while (++i < n) map[names[i].toLowerCase()] = i; | |
return map; | |
} | |
function parseWeekdayNumber(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 1)); | |
return n ? (d.w = +n[0], i + n[0].length) : -1; | |
} | |
function parseWeekNumberSunday(d, string, i) { | |
var n = numberRe.exec(string.slice(i)); | |
return n ? (d.U = +n[0], i + n[0].length) : -1; | |
} | |
function parseWeekNumberMonday(d, string, i) { | |
var n = numberRe.exec(string.slice(i)); | |
return n ? (d.W = +n[0], i + n[0].length) : -1; | |
} | |
function parseFullYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 4)); | |
return n ? (d.y = +n[0], i + n[0].length) : -1; | |
} | |
function parseYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; | |
} | |
function parseZone(d, string, i) { | |
var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6)); | |
return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; | |
} | |
function parseMonthNumber(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.m = n[0] - 1, i + n[0].length) : -1; | |
} | |
function parseDayOfMonth(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.d = +n[0], i + n[0].length) : -1; | |
} | |
function parseDayOfYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 3)); | |
return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; | |
} | |
function parseHour24(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.H = +n[0], i + n[0].length) : -1; | |
} | |
function parseMinutes(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.M = +n[0], i + n[0].length) : -1; | |
} | |
function parseSeconds(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.S = +n[0], i + n[0].length) : -1; | |
} | |
function parseMilliseconds(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 3)); | |
return n ? (d.L = +n[0], i + n[0].length) : -1; | |
} | |
function parseLiteralPercent(d, string, i) { | |
var n = percentRe.exec(string.slice(i, i + 1)); | |
return n ? i + n[0].length : -1; | |
} | |
function formatDayOfMonth(d, p) { | |
return pad(d.getDate(), p, 2); | |
} | |
function formatHour24(d, p) { | |
return pad(d.getHours(), p, 2); | |
} | |
function formatHour12(d, p) { | |
return pad(d.getHours() % 12 || 12, p, 2); | |
} | |
function formatDayOfYear(d, p) { | |
return pad(1 + d3Time.timeDay.count(d3Time.timeYear(d), d), p, 3); | |
} | |
function formatMilliseconds(d, p) { | |
return pad(d.getMilliseconds(), p, 3); | |
} | |
function formatMonthNumber(d, p) { | |
return pad(d.getMonth() + 1, p, 2); | |
} | |
function formatMinutes(d, p) { | |
return pad(d.getMinutes(), p, 2); | |
} | |
function formatSeconds(d, p) { | |
return pad(d.getSeconds(), p, 2); | |
} | |
function formatWeekNumberSunday(d, p) { | |
return pad(d3Time.timeSunday.count(d3Time.timeYear(d), d), p, 2); | |
} | |
function formatWeekdayNumber(d) { | |
return d.getDay(); | |
} | |
function formatWeekNumberMonday(d, p) { | |
return pad(d3Time.timeMonday.count(d3Time.timeYear(d), d), p, 2); | |
} | |
function formatYear(d, p) { | |
return pad(d.getFullYear() % 100, p, 2); | |
} | |
function formatFullYear(d, p) { | |
return pad(d.getFullYear() % 10000, p, 4); | |
} | |
function formatZone(d) { | |
var z = d.getTimezoneOffset(); | |
return (z > 0 ? "-" : (z *= -1, "+")) | |
+ pad(z / 60 | 0, "0", 2) | |
+ pad(z % 60, "0", 2); | |
} | |
function formatUTCDayOfMonth(d, p) { | |
return pad(d.getUTCDate(), p, 2); | |
} | |
function formatUTCHour24(d, p) { | |
return pad(d.getUTCHours(), p, 2); | |
} | |
function formatUTCHour12(d, p) { | |
return pad(d.getUTCHours() % 12 || 12, p, 2); | |
} | |
function formatUTCDayOfYear(d, p) { | |
return pad(1 + d3Time.utcDay.count(d3Time.utcYear(d), d), p, 3); | |
} | |
function formatUTCMilliseconds(d, p) { | |
return pad(d.getUTCMilliseconds(), p, 3); | |
} | |
function formatUTCMonthNumber(d, p) { | |
return pad(d.getUTCMonth() + 1, p, 2); | |
} | |
function formatUTCMinutes(d, p) { | |
return pad(d.getUTCMinutes(), p, 2); | |
} | |
function formatUTCSeconds(d, p) { | |
return pad(d.getUTCSeconds(), p, 2); | |
} | |
function formatUTCWeekNumberSunday(d, p) { | |
return pad(d3Time.utcSunday.count(d3Time.utcYear(d), d), p, 2); | |
} | |
function formatUTCWeekdayNumber(d) { | |
return d.getUTCDay(); | |
} | |
function formatUTCWeekNumberMonday(d, p) { | |
return pad(d3Time.utcMonday.count(d3Time.utcYear(d), d), p, 2); | |
} | |
function formatUTCYear(d, p) { | |
return pad(d.getUTCFullYear() % 100, p, 2); | |
} | |
function formatUTCFullYear(d, p) { | |
return pad(d.getUTCFullYear() % 10000, p, 4); | |
} | |
function formatUTCZone() { | |
return "+0000"; | |
} | |
function formatLiteralPercent() { | |
return "%"; | |
} | |
var locale$1; | |
defaultLocale({ | |
dateTime: "%x, %X", | |
date: "%-m/%-d/%Y", | |
time: "%-I:%M:%S %p", | |
periods: ["AM", "PM"], | |
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | |
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], | |
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | |
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
}); | |
function defaultLocale(definition) { | |
locale$1 = formatLocale(definition); | |
exports.timeFormat = locale$1.format; | |
exports.timeParse = locale$1.parse; | |
exports.utcFormat = locale$1.utcFormat; | |
exports.utcParse = locale$1.utcParse; | |
return locale$1; | |
} | |
var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; | |
function formatIsoNative(date) { | |
return date.toISOString(); | |
} | |
var formatIso = Date.prototype.toISOString | |
? formatIsoNative | |
: exports.utcFormat(isoSpecifier); | |
function parseIsoNative(string) { | |
var date = new Date(string); | |
return isNaN(date) ? null : date; | |
} | |
var parseIso = +new Date("2000-01-01T00:00:00.000Z") | |
? parseIsoNative | |
: exports.utcParse(isoSpecifier); | |
exports.timeFormatDefaultLocale = defaultLocale; | |
exports.timeFormatLocale = formatLocale; | |
exports.isoFormat = formatIso; | |
exports.isoParse = parseIso; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-time":40}],40:[function(require,module,exports){ | |
// https://d3js.org/d3-time/ Version 1.0.7. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var t0 = new Date; | |
var t1 = new Date; | |
function newInterval(floori, offseti, count, field) { | |
function interval(date) { | |
return floori(date = new Date(+date)), date; | |
} | |
interval.floor = interval; | |
interval.ceil = function(date) { | |
return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; | |
}; | |
interval.round = function(date) { | |
var d0 = interval(date), | |
d1 = interval.ceil(date); | |
return date - d0 < d1 - date ? d0 : d1; | |
}; | |
interval.offset = function(date, step) { | |
return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; | |
}; | |
interval.range = function(start, stop, step) { | |
var range = []; | |
start = interval.ceil(start); | |
step = step == null ? 1 : Math.floor(step); | |
if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date | |
do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) | |
return range; | |
}; | |
interval.filter = function(test) { | |
return newInterval(function(date) { | |
if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); | |
}, function(date, step) { | |
if (date >= date) { | |
if (step < 0) while (++step <= 0) { | |
while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty | |
} else while (--step >= 0) { | |
while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty | |
} | |
} | |
}); | |
}; | |
if (count) { | |
interval.count = function(start, end) { | |
t0.setTime(+start), t1.setTime(+end); | |
floori(t0), floori(t1); | |
return Math.floor(count(t0, t1)); | |
}; | |
interval.every = function(step) { | |
step = Math.floor(step); | |
return !isFinite(step) || !(step > 0) ? null | |
: !(step > 1) ? interval | |
: interval.filter(field | |
? function(d) { return field(d) % step === 0; } | |
: function(d) { return interval.count(0, d) % step === 0; }); | |
}; | |
} | |
return interval; | |
} | |
var millisecond = newInterval(function() { | |
// noop | |
}, function(date, step) { | |
date.setTime(+date + step); | |
}, function(start, end) { | |
return end - start; | |
}); | |
// An optimized implementation for this simple case. | |
millisecond.every = function(k) { | |
k = Math.floor(k); | |
if (!isFinite(k) || !(k > 0)) return null; | |
if (!(k > 1)) return millisecond; | |
return newInterval(function(date) { | |
date.setTime(Math.floor(date / k) * k); | |
}, function(date, step) { | |
date.setTime(+date + step * k); | |
}, function(start, end) { | |
return (end - start) / k; | |
}); | |
}; | |
var milliseconds = millisecond.range; | |
var durationSecond = 1e3; | |
var durationMinute = 6e4; | |
var durationHour = 36e5; | |
var durationDay = 864e5; | |
var durationWeek = 6048e5; | |
var second = newInterval(function(date) { | |
date.setTime(Math.floor(date / durationSecond) * durationSecond); | |
}, function(date, step) { | |
date.setTime(+date + step * durationSecond); | |
}, function(start, end) { | |
return (end - start) / durationSecond; | |
}, function(date) { | |
return date.getUTCSeconds(); | |
}); | |
var seconds = second.range; | |
var minute = newInterval(function(date) { | |
date.setTime(Math.floor(date / durationMinute) * durationMinute); | |
}, function(date, step) { | |
date.setTime(+date + step * durationMinute); | |
}, function(start, end) { | |
return (end - start) / durationMinute; | |
}, function(date) { | |
return date.getMinutes(); | |
}); | |
var minutes = minute.range; | |
var hour = newInterval(function(date) { | |
var offset = date.getTimezoneOffset() * durationMinute % durationHour; | |
if (offset < 0) offset += durationHour; | |
date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset); | |
}, function(date, step) { | |
date.setTime(+date + step * durationHour); | |
}, function(start, end) { | |
return (end - start) / durationHour; | |
}, function(date) { | |
return date.getHours(); | |
}); | |
var hours = hour.range; | |
var day = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay; | |
}, function(date) { | |
return date.getDate() - 1; | |
}); | |
var days = day.range; | |
function weekday(i) { | |
return newInterval(function(date) { | |
date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step * 7); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek; | |
}); | |
} | |
var sunday = weekday(0); | |
var monday = weekday(1); | |
var tuesday = weekday(2); | |
var wednesday = weekday(3); | |
var thursday = weekday(4); | |
var friday = weekday(5); | |
var saturday = weekday(6); | |
var sundays = sunday.range; | |
var mondays = monday.range; | |
var tuesdays = tuesday.range; | |
var wednesdays = wednesday.range; | |
var thursdays = thursday.range; | |
var fridays = friday.range; | |
var saturdays = saturday.range; | |
var month = newInterval(function(date) { | |
date.setDate(1); | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setMonth(date.getMonth() + step); | |
}, function(start, end) { | |
return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; | |
}, function(date) { | |
return date.getMonth(); | |
}); | |
var months = month.range; | |
var year = newInterval(function(date) { | |
date.setMonth(0, 1); | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setFullYear(date.getFullYear() + step); | |
}, function(start, end) { | |
return end.getFullYear() - start.getFullYear(); | |
}, function(date) { | |
return date.getFullYear(); | |
}); | |
// An optimized implementation for this simple case. | |
year.every = function(k) { | |
return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { | |
date.setFullYear(Math.floor(date.getFullYear() / k) * k); | |
date.setMonth(0, 1); | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setFullYear(date.getFullYear() + step * k); | |
}); | |
}; | |
var years = year.range; | |
var utcMinute = newInterval(function(date) { | |
date.setUTCSeconds(0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * durationMinute); | |
}, function(start, end) { | |
return (end - start) / durationMinute; | |
}, function(date) { | |
return date.getUTCMinutes(); | |
}); | |
var utcMinutes = utcMinute.range; | |
var utcHour = newInterval(function(date) { | |
date.setUTCMinutes(0, 0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * durationHour); | |
}, function(start, end) { | |
return (end - start) / durationHour; | |
}, function(date) { | |
return date.getUTCHours(); | |
}); | |
var utcHours = utcHour.range; | |
var utcDay = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step); | |
}, function(start, end) { | |
return (end - start) / durationDay; | |
}, function(date) { | |
return date.getUTCDate() - 1; | |
}); | |
var utcDays = utcDay.range; | |
function utcWeekday(i) { | |
return newInterval(function(date) { | |
date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step * 7); | |
}, function(start, end) { | |
return (end - start) / durationWeek; | |
}); | |
} | |
var utcSunday = utcWeekday(0); | |
var utcMonday = utcWeekday(1); | |
var utcTuesday = utcWeekday(2); | |
var utcWednesday = utcWeekday(3); | |
var utcThursday = utcWeekday(4); | |
var utcFriday = utcWeekday(5); | |
var utcSaturday = utcWeekday(6); | |
var utcSundays = utcSunday.range; | |
var utcMondays = utcMonday.range; | |
var utcTuesdays = utcTuesday.range; | |
var utcWednesdays = utcWednesday.range; | |
var utcThursdays = utcThursday.range; | |
var utcFridays = utcFriday.range; | |
var utcSaturdays = utcSaturday.range; | |
var utcMonth = newInterval(function(date) { | |
date.setUTCDate(1); | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCMonth(date.getUTCMonth() + step); | |
}, function(start, end) { | |
return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; | |
}, function(date) { | |
return date.getUTCMonth(); | |
}); | |
var utcMonths = utcMonth.range; | |
var utcYear = newInterval(function(date) { | |
date.setUTCMonth(0, 1); | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCFullYear(date.getUTCFullYear() + step); | |
}, function(start, end) { | |
return end.getUTCFullYear() - start.getUTCFullYear(); | |
}, function(date) { | |
return date.getUTCFullYear(); | |
}); | |
// An optimized implementation for this simple case. | |
utcYear.every = function(k) { | |
return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { | |
date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); | |
date.setUTCMonth(0, 1); | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCFullYear(date.getUTCFullYear() + step * k); | |
}); | |
}; | |
var utcYears = utcYear.range; | |
exports.timeInterval = newInterval; | |
exports.timeMillisecond = millisecond; | |
exports.timeMilliseconds = milliseconds; | |
exports.utcMillisecond = millisecond; | |
exports.utcMilliseconds = milliseconds; | |
exports.timeSecond = second; | |
exports.timeSeconds = seconds; | |
exports.utcSecond = second; | |
exports.utcSeconds = seconds; | |
exports.timeMinute = minute; | |
exports.timeMinutes = minutes; | |
exports.timeHour = hour; | |
exports.timeHours = hours; | |
exports.timeDay = day; | |
exports.timeDays = days; | |
exports.timeWeek = sunday; | |
exports.timeWeeks = sundays; | |
exports.timeSunday = sunday; | |
exports.timeSundays = sundays; | |
exports.timeMonday = monday; | |
exports.timeMondays = mondays; | |
exports.timeTuesday = tuesday; | |
exports.timeTuesdays = tuesdays; | |
exports.timeWednesday = wednesday; | |
exports.timeWednesdays = wednesdays; | |
exports.timeThursday = thursday; | |
exports.timeThursdays = thursdays; | |
exports.timeFriday = friday; | |
exports.timeFridays = fridays; | |
exports.timeSaturday = saturday; | |
exports.timeSaturdays = saturdays; | |
exports.timeMonth = month; | |
exports.timeMonths = months; | |
exports.timeYear = year; | |
exports.timeYears = years; | |
exports.utcMinute = utcMinute; | |
exports.utcMinutes = utcMinutes; | |
exports.utcHour = utcHour; | |
exports.utcHours = utcHours; | |
exports.utcDay = utcDay; | |
exports.utcDays = utcDays; | |
exports.utcWeek = utcSunday; | |
exports.utcWeeks = utcSundays; | |
exports.utcSunday = utcSunday; | |
exports.utcSundays = utcSundays; | |
exports.utcMonday = utcMonday; | |
exports.utcMondays = utcMondays; | |
exports.utcTuesday = utcTuesday; | |
exports.utcTuesdays = utcTuesdays; | |
exports.utcWednesday = utcWednesday; | |
exports.utcWednesdays = utcWednesdays; | |
exports.utcThursday = utcThursday; | |
exports.utcThursdays = utcThursdays; | |
exports.utcFriday = utcFriday; | |
exports.utcFridays = utcFridays; | |
exports.utcSaturday = utcSaturday; | |
exports.utcSaturdays = utcSaturdays; | |
exports.utcMonth = utcMonth; | |
exports.utcMonths = utcMonths; | |
exports.utcYear = utcYear; | |
exports.utcYears = utcYears; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],41:[function(require,module,exports){ | |
// https://d3js.org/d3-timer/ Version 1.0.7. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var frame = 0; | |
var timeout = 0; | |
var interval = 0; | |
var pokeDelay = 1000; | |
var taskHead; | |
var taskTail; | |
var clockLast = 0; | |
var clockNow = 0; | |
var clockSkew = 0; | |
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); }; | |
function now() { | |
return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); | |
} | |
function clearNow() { | |
clockNow = 0; | |
} | |
function Timer() { | |
this._call = | |
this._time = | |
this._next = null; | |
} | |
Timer.prototype = timer.prototype = { | |
constructor: Timer, | |
restart: function(callback, delay, time) { | |
if (typeof callback !== "function") throw new TypeError("callback is not a function"); | |
time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); | |
if (!this._next && taskTail !== this) { | |
if (taskTail) taskTail._next = this; | |
else taskHead = this; | |
taskTail = this; | |
} | |
this._call = callback; | |
this._time = time; | |
sleep(); | |
}, | |
stop: function() { | |
if (this._call) { | |
this._call = null; | |
this._time = Infinity; | |
sleep(); | |
} | |
} | |
}; | |
function timer(callback, delay, time) { | |
var t = new Timer; | |
t.restart(callback, delay, time); | |
return t; | |
} | |
function timerFlush() { | |
now(); // Get the current time, if not already set. | |
++frame; // Pretend we’ve set an alarm, if we haven’t already. | |
var t = taskHead, e; | |
while (t) { | |
if ((e = clockNow - t._time) >= 0) t._call.call(null, e); | |
t = t._next; | |
} | |
--frame; | |
} | |
function wake() { | |
clockNow = (clockLast = clock.now()) + clockSkew; | |
frame = timeout = 0; | |
try { | |
timerFlush(); | |
} finally { | |
frame = 0; | |
nap(); | |
clockNow = 0; | |
} | |
} | |
function poke() { | |
var now = clock.now(), delay = now - clockLast; | |
if (delay > pokeDelay) clockSkew -= delay, clockLast = now; | |
} | |
function nap() { | |
var t0, t1 = taskHead, t2, time = Infinity; | |
while (t1) { | |
if (t1._call) { | |
if (time > t1._time) time = t1._time; | |
t0 = t1, t1 = t1._next; | |
} else { | |
t2 = t1._next, t1._next = null; | |
t1 = t0 ? t0._next = t2 : taskHead = t2; | |
} | |
} | |
taskTail = t0; | |
sleep(time); | |
} | |
function sleep(time) { | |
if (frame) return; // Soonest alarm already set, or will be. | |
if (timeout) timeout = clearTimeout(timeout); | |
var delay = time - clockNow; // Strictly less than if we recomputed clockNow. | |
if (delay > 24) { | |
if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); | |
if (interval) interval = clearInterval(interval); | |
} else { | |
if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); | |
frame = 1, setFrame(wake); | |
} | |
} | |
var timeout$1 = function(callback, delay, time) { | |
var t = new Timer; | |
delay = delay == null ? 0 : +delay; | |
t.restart(function(elapsed) { | |
t.stop(); | |
callback(elapsed + delay); | |
}, delay, time); | |
return t; | |
}; | |
var interval$1 = function(callback, delay, time) { | |
var t = new Timer, total = delay; | |
if (delay == null) return t.restart(callback, delay, time), t; | |
delay = +delay, time = time == null ? now() : +time; | |
t.restart(function tick(elapsed) { | |
elapsed += total; | |
t.restart(tick, total += delay, time); | |
callback(elapsed); | |
}, delay, time); | |
return t; | |
}; | |
exports.now = now; | |
exports.timer = timer; | |
exports.timerFlush = timerFlush; | |
exports.timeout = timeout$1; | |
exports.interval = interval$1; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{}],42:[function(require,module,exports){ | |
// https://d3js.org/d3-transition/ Version 1.1.0. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-selection'), require('d3-dispatch'), require('d3-timer'), require('d3-interpolate'), require('d3-color'), require('d3-ease')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-selection', 'd3-dispatch', 'd3-timer', 'd3-interpolate', 'd3-color', 'd3-ease'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); | |
}(this, (function (exports,d3Selection,d3Dispatch,d3Timer,d3Interpolate,d3Color,d3Ease) { 'use strict'; | |
var emptyOn = d3Dispatch.dispatch("start", "end", "interrupt"); | |
var emptyTween = []; | |
var CREATED = 0; | |
var SCHEDULED = 1; | |
var STARTING = 2; | |
var STARTED = 3; | |
var RUNNING = 4; | |
var ENDING = 5; | |
var ENDED = 6; | |
var schedule = function(node, name, id, index, group, timing) { | |
var schedules = node.__transition; | |
if (!schedules) node.__transition = {}; | |
else if (id in schedules) return; | |
create(node, id, { | |
name: name, | |
index: index, // For context during callback. | |
group: group, // For context during callback. | |
on: emptyOn, | |
tween: emptyTween, | |
time: timing.time, | |
delay: timing.delay, | |
duration: timing.duration, | |
ease: timing.ease, | |
timer: null, | |
state: CREATED | |
}); | |
}; | |
function init(node, id) { | |
var schedule = node.__transition; | |
if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); | |
return schedule; | |
} | |
function set(node, id) { | |
var schedule = node.__transition; | |
if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); | |
return schedule; | |
} | |
function get(node, id) { | |
var schedule = node.__transition; | |
if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); | |
return schedule; | |
} | |
function create(node, id, self) { | |
var schedules = node.__transition, | |
tween; | |
// Initialize the self timer when the transition is created. | |
// Note the actual delay is not known until the first callback! | |
schedules[id] = self; | |
self.timer = d3Timer.timer(schedule, 0, self.time); | |
function schedule(elapsed) { | |
self.state = SCHEDULED; | |
self.timer.restart(start, self.delay, self.time); | |
// If the elapsed delay is less than our first sleep, start immediately. | |
if (self.delay <= elapsed) start(elapsed - self.delay); | |
} | |
function start(elapsed) { | |
var i, j, n, o; | |
// If the state is not SCHEDULED, then we previously errored on start. | |
if (self.state !== SCHEDULED) return stop(); | |
for (i in schedules) { | |
o = schedules[i]; | |
if (o.name !== self.name) continue; | |
// While this element already has a starting transition during this frame, | |
// defer starting an interrupting transition until that transition has a | |
// chance to tick (and possibly end); see d3/d3-transition#54! | |
if (o.state === STARTED) return d3Timer.timeout(start); | |
// Interrupt the active transition, if any. | |
// Dispatch the interrupt event. | |
if (o.state === RUNNING) { | |
o.state = ENDED; | |
o.timer.stop(); | |
o.on.call("interrupt", node, node.__data__, o.index, o.group); | |
delete schedules[i]; | |
} | |
// Cancel any pre-empted transitions. No interrupt event is dispatched | |
// because the cancelled transitions never started. Note that this also | |
// removes this transition from the pending list! | |
else if (+i < id) { | |
o.state = ENDED; | |
o.timer.stop(); | |
delete schedules[i]; | |
} | |
} | |
// Defer the first tick to end of the current frame; see d3/d3#1576. | |
// Note the transition may be canceled after start and before the first tick! | |
// Note this must be scheduled before the start event; see d3/d3-transition#16! | |
// Assuming this is successful, subsequent callbacks go straight to tick. | |
d3Timer.timeout(function() { | |
if (self.state === STARTED) { | |
self.state = RUNNING; | |
self.timer.restart(tick, self.delay, self.time); | |
tick(elapsed); | |
} | |
}); | |
// Dispatch the start event. | |
// Note this must be done before the tween are initialized. | |
self.state = STARTING; | |
self.on.call("start", node, node.__data__, self.index, self.group); | |
if (self.state !== STARTING) return; // interrupted | |
self.state = STARTED; | |
// Initialize the tween, deleting null tween. | |
tween = new Array(n = self.tween.length); | |
for (i = 0, j = -1; i < n; ++i) { | |
if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { | |
tween[++j] = o; | |
} | |
} | |
tween.length = j + 1; | |
} | |
function tick(elapsed) { | |
var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), | |
i = -1, | |
n = tween.length; | |
while (++i < n) { | |
tween[i].call(null, t); | |
} | |
// Dispatch the end event. | |
if (self.state === ENDING) { | |
self.on.call("end", node, node.__data__, self.index, self.group); | |
stop(); | |
} | |
} | |
function stop() { | |
self.state = ENDED; | |
self.timer.stop(); | |
delete schedules[id]; | |
for (var i in schedules) return; // eslint-disable-line no-unused-vars | |
delete node.__transition; | |
} | |
} | |
var interrupt = function(node, name) { | |
var schedules = node.__transition, | |
schedule, | |
active, | |
empty = true, | |
i; | |
if (!schedules) return; | |
name = name == null ? null : name + ""; | |
for (i in schedules) { | |
if ((schedule = schedules[i]).name !== name) { empty = false; continue; } | |
active = schedule.state > STARTING && schedule.state < ENDING; | |
schedule.state = ENDED; | |
schedule.timer.stop(); | |
if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); | |
delete schedules[i]; | |
} | |
if (empty) delete node.__transition; | |
}; | |
var selection_interrupt = function(name) { | |
return this.each(function() { | |
interrupt(this, name); | |
}); | |
}; | |
function tweenRemove(id, name) { | |
var tween0, tween1; | |
return function() { | |
var schedule = set(this, id), | |
tween = schedule.tween; | |
// If this node shared tween with the previous node, | |
// just assign the updated shared tween and we’re done! | |
// Otherwise, copy-on-write. | |
if (tween !== tween0) { | |
tween1 = tween0 = tween; | |
for (var i = 0, n = tween1.length; i < n; ++i) { | |
if (tween1[i].name === name) { | |
tween1 = tween1.slice(); | |
tween1.splice(i, 1); | |
break; | |
} | |
} | |
} | |
schedule.tween = tween1; | |
}; | |
} | |
function tweenFunction(id, name, value) { | |
var tween0, tween1; | |
if (typeof value !== "function") throw new Error; | |
return function() { | |
var schedule = set(this, id), | |
tween = schedule.tween; | |
// If this node shared tween with the previous node, | |
// just assign the updated shared tween and we’re done! | |
// Otherwise, copy-on-write. | |
if (tween !== tween0) { | |
tween1 = (tween0 = tween).slice(); | |
for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { | |
if (tween1[i].name === name) { | |
tween1[i] = t; | |
break; | |
} | |
} | |
if (i === n) tween1.push(t); | |
} | |
schedule.tween = tween1; | |
}; | |
} | |
var transition_tween = function(name, value) { | |
var id = this._id; | |
name += ""; | |
if (arguments.length < 2) { | |
var tween = get(this.node(), id).tween; | |
for (var i = 0, n = tween.length, t; i < n; ++i) { | |
if ((t = tween[i]).name === name) { | |
return t.value; | |
} | |
} | |
return null; | |
} | |
return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); | |
}; | |
function tweenValue(transition, name, value) { | |
var id = transition._id; | |
transition.each(function() { | |
var schedule = set(this, id); | |
(schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); | |
}); | |
return function(node) { | |
return get(node, id).value[name]; | |
}; | |
} | |
var interpolate = function(a, b) { | |
var c; | |
return (typeof b === "number" ? d3Interpolate.interpolateNumber | |
: b instanceof d3Color.color ? d3Interpolate.interpolateRgb | |
: (c = d3Color.color(b)) ? (b = c, d3Interpolate.interpolateRgb) | |
: d3Interpolate.interpolateString)(a, b); | |
}; | |
function attrRemove(name) { | |
return function() { | |
this.removeAttribute(name); | |
}; | |
} | |
function attrRemoveNS(fullname) { | |
return function() { | |
this.removeAttributeNS(fullname.space, fullname.local); | |
}; | |
} | |
function attrConstant(name, interpolate$$1, value1) { | |
var value00, | |
interpolate0; | |
return function() { | |
var value0 = this.getAttribute(name); | |
return value0 === value1 ? null | |
: value0 === value00 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value1); | |
}; | |
} | |
function attrConstantNS(fullname, interpolate$$1, value1) { | |
var value00, | |
interpolate0; | |
return function() { | |
var value0 = this.getAttributeNS(fullname.space, fullname.local); | |
return value0 === value1 ? null | |
: value0 === value00 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value1); | |
}; | |
} | |
function attrFunction(name, interpolate$$1, value) { | |
var value00, | |
value10, | |
interpolate0; | |
return function() { | |
var value0, value1 = value(this); | |
if (value1 == null) return void this.removeAttribute(name); | |
value0 = this.getAttribute(name); | |
return value0 === value1 ? null | |
: value0 === value00 && value1 === value10 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value10 = value1); | |
}; | |
} | |
function attrFunctionNS(fullname, interpolate$$1, value) { | |
var value00, | |
value10, | |
interpolate0; | |
return function() { | |
var value0, value1 = value(this); | |
if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); | |
value0 = this.getAttributeNS(fullname.space, fullname.local); | |
return value0 === value1 ? null | |
: value0 === value00 && value1 === value10 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value10 = value1); | |
}; | |
} | |
var transition_attr = function(name, value) { | |
var fullname = d3Selection.namespace(name), i = fullname === "transform" ? d3Interpolate.interpolateTransformSvg : interpolate; | |
return this.attrTween(name, typeof value === "function" | |
? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) | |
: value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) | |
: (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value + "")); | |
}; | |
function attrTweenNS(fullname, value) { | |
function tween() { | |
var node = this, i = value.apply(node, arguments); | |
return i && function(t) { | |
node.setAttributeNS(fullname.space, fullname.local, i(t)); | |
}; | |
} | |
tween._value = value; | |
return tween; | |
} | |
function attrTween(name, value) { | |
function tween() { | |
var node = this, i = value.apply(node, arguments); | |
return i && function(t) { | |
node.setAttribute(name, i(t)); | |
}; | |
} | |
tween._value = value; | |
return tween; | |
} | |
var transition_attrTween = function(name, value) { | |
var key = "attr." + name; | |
if (arguments.length < 2) return (key = this.tween(key)) && key._value; | |
if (value == null) return this.tween(key, null); | |
if (typeof value !== "function") throw new Error; | |
var fullname = d3Selection.namespace(name); | |
return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); | |
}; | |
function delayFunction(id, value) { | |
return function() { | |
init(this, id).delay = +value.apply(this, arguments); | |
}; | |
} | |
function delayConstant(id, value) { | |
return value = +value, function() { | |
init(this, id).delay = value; | |
}; | |
} | |
var transition_delay = function(value) { | |
var id = this._id; | |
return arguments.length | |
? this.each((typeof value === "function" | |
? delayFunction | |
: delayConstant)(id, value)) | |
: get(this.node(), id).delay; | |
}; | |
function durationFunction(id, value) { | |
return function() { | |
set(this, id).duration = +value.apply(this, arguments); | |
}; | |
} | |
function durationConstant(id, value) { | |
return value = +value, function() { | |
set(this, id).duration = value; | |
}; | |
} | |
var transition_duration = function(value) { | |
var id = this._id; | |
return arguments.length | |
? this.each((typeof value === "function" | |
? durationFunction | |
: durationConstant)(id, value)) | |
: get(this.node(), id).duration; | |
}; | |
function easeConstant(id, value) { | |
if (typeof value !== "function") throw new Error; | |
return function() { | |
set(this, id).ease = value; | |
}; | |
} | |
var transition_ease = function(value) { | |
var id = this._id; | |
return arguments.length | |
? this.each(easeConstant(id, value)) | |
: get(this.node(), id).ease; | |
}; | |
var transition_filter = function(match) { | |
if (typeof match !== "function") match = d3Selection.matcher(match); | |
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { | |
if ((node = group[i]) && match.call(node, node.__data__, i, group)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return new Transition(subgroups, this._parents, this._name, this._id); | |
}; | |
var transition_merge = function(transition) { | |
if (transition._id !== this._id) throw new Error; | |
for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { | |
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { | |
if (node = group0[i] || group1[i]) { | |
merge[i] = node; | |
} | |
} | |
} | |
for (; j < m0; ++j) { | |
merges[j] = groups0[j]; | |
} | |
return new Transition(merges, this._parents, this._name, this._id); | |
}; | |
function start(name) { | |
return (name + "").trim().split(/^|\s+/).every(function(t) { | |
var i = t.indexOf("."); | |
if (i >= 0) t = t.slice(0, i); | |
return !t || t === "start"; | |
}); | |
} | |
function onFunction(id, name, listener) { | |
var on0, on1, sit = start(name) ? init : set; | |
return function() { | |
var schedule = sit(this, id), | |
on = schedule.on; | |
// If this node shared a dispatch with the previous node, | |
// just assign the updated shared dispatch and we’re done! | |
// Otherwise, copy-on-write. | |
if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); | |
schedule.on = on1; | |
}; | |
} | |
var transition_on = function(name, listener) { | |
var id = this._id; | |
return arguments.length < 2 | |
? get(this.node(), id).on.on(name) | |
: this.each(onFunction(id, name, listener)); | |
}; | |
function removeFunction(id) { | |
return function() { | |
var parent = this.parentNode; | |
for (var i in this.__transition) if (+i !== id) return; | |
if (parent) parent.removeChild(this); | |
}; | |
} | |
var transition_remove = function() { | |
return this.on("end.remove", removeFunction(this._id)); | |
}; | |
var transition_select = function(select) { | |
var name = this._name, | |
id = this._id; | |
if (typeof select !== "function") select = d3Selection.selector(select); | |
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { | |
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { | |
if ("__data__" in node) subnode.__data__ = node.__data__; | |
subgroup[i] = subnode; | |
schedule(subgroup[i], name, id, i, subgroup, get(node, id)); | |
} | |
} | |
} | |
return new Transition(subgroups, this._parents, name, id); | |
}; | |
var transition_selectAll = function(select) { | |
var name = this._name, | |
id = this._id; | |
if (typeof select !== "function") select = d3Selection.selectorAll(select); | |
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { | |
if (node = group[i]) { | |
for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { | |
if (child = children[k]) { | |
schedule(child, name, id, k, children, inherit); | |
} | |
} | |
subgroups.push(children); | |
parents.push(node); | |
} | |
} | |
} | |
return new Transition(subgroups, parents, name, id); | |
}; | |
var Selection = d3Selection.selection.prototype.constructor; | |
var transition_selection = function() { | |
return new Selection(this._groups, this._parents); | |
}; | |
function styleRemove(name, interpolate$$1) { | |
var value00, | |
value10, | |
interpolate0; | |
return function() { | |
var value0 = d3Selection.style(this, name), | |
value1 = (this.style.removeProperty(name), d3Selection.style(this, name)); | |
return value0 === value1 ? null | |
: value0 === value00 && value1 === value10 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value10 = value1); | |
}; | |
} | |
function styleRemoveEnd(name) { | |
return function() { | |
this.style.removeProperty(name); | |
}; | |
} | |
function styleConstant(name, interpolate$$1, value1) { | |
var value00, | |
interpolate0; | |
return function() { | |
var value0 = d3Selection.style(this, name); | |
return value0 === value1 ? null | |
: value0 === value00 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value1); | |
}; | |
} | |
function styleFunction(name, interpolate$$1, value) { | |
var value00, | |
value10, | |
interpolate0; | |
return function() { | |
var value0 = d3Selection.style(this, name), | |
value1 = value(this); | |
if (value1 == null) value1 = (this.style.removeProperty(name), d3Selection.style(this, name)); | |
return value0 === value1 ? null | |
: value0 === value00 && value1 === value10 ? interpolate0 | |
: interpolate0 = interpolate$$1(value00 = value0, value10 = value1); | |
}; | |
} | |
var transition_style = function(name, value, priority) { | |
var i = (name += "") === "transform" ? d3Interpolate.interpolateTransformCss : interpolate; | |
return value == null ? this | |
.styleTween(name, styleRemove(name, i)) | |
.on("end.style." + name, styleRemoveEnd(name)) | |
: this.styleTween(name, typeof value === "function" | |
? styleFunction(name, i, tweenValue(this, "style." + name, value)) | |
: styleConstant(name, i, value + ""), priority); | |
}; | |
function styleTween(name, value, priority) { | |
function tween() { | |
var node = this, i = value.apply(node, arguments); | |
return i && function(t) { | |
node.style.setProperty(name, i(t), priority); | |
}; | |
} | |
tween._value = value; | |
return tween; | |
} | |
var transition_styleTween = function(name, value, priority) { | |
var key = "style." + (name += ""); | |
if (arguments.length < 2) return (key = this.tween(key)) && key._value; | |
if (value == null) return this.tween(key, null); | |
if (typeof value !== "function") throw new Error; | |
return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); | |
}; | |
function textConstant(value) { | |
return function() { | |
this.textContent = value; | |
}; | |
} | |
function textFunction(value) { | |
return function() { | |
var value1 = value(this); | |
this.textContent = value1 == null ? "" : value1; | |
}; | |
} | |
var transition_text = function(value) { | |
return this.tween("text", typeof value === "function" | |
? textFunction(tweenValue(this, "text", value)) | |
: textConstant(value == null ? "" : value + "")); | |
}; | |
var transition_transition = function() { | |
var name = this._name, | |
id0 = this._id, | |
id1 = newId(); | |
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { | |
if (node = group[i]) { | |
var inherit = get(node, id0); | |
schedule(node, name, id1, i, group, { | |
time: inherit.time + inherit.delay + inherit.duration, | |
delay: 0, | |
duration: inherit.duration, | |
ease: inherit.ease | |
}); | |
} | |
} | |
} | |
return new Transition(groups, this._parents, name, id1); | |
}; | |
var id = 0; | |
function Transition(groups, parents, name, id) { | |
this._groups = groups; | |
this._parents = parents; | |
this._name = name; | |
this._id = id; | |
} | |
function transition(name) { | |
return d3Selection.selection().transition(name); | |
} | |
function newId() { | |
return ++id; | |
} | |
var selection_prototype = d3Selection.selection.prototype; | |
Transition.prototype = transition.prototype = { | |
constructor: Transition, | |
select: transition_select, | |
selectAll: transition_selectAll, | |
filter: transition_filter, | |
merge: transition_merge, | |
selection: transition_selection, | |
transition: transition_transition, | |
call: selection_prototype.call, | |
nodes: selection_prototype.nodes, | |
node: selection_prototype.node, | |
size: selection_prototype.size, | |
empty: selection_prototype.empty, | |
each: selection_prototype.each, | |
on: transition_on, | |
attr: transition_attr, | |
attrTween: transition_attrTween, | |
style: transition_style, | |
styleTween: transition_styleTween, | |
text: transition_text, | |
remove: transition_remove, | |
tween: transition_tween, | |
delay: transition_delay, | |
duration: transition_duration, | |
ease: transition_ease | |
}; | |
var defaultTiming = { | |
time: null, // Set on use. | |
delay: 0, | |
duration: 250, | |
ease: d3Ease.easeCubicInOut | |
}; | |
function inherit(node, id) { | |
var timing; | |
while (!(timing = node.__transition) || !(timing = timing[id])) { | |
if (!(node = node.parentNode)) { | |
return defaultTiming.time = d3Timer.now(), defaultTiming; | |
} | |
} | |
return timing; | |
} | |
var selection_transition = function(name) { | |
var id, | |
timing; | |
if (name instanceof Transition) { | |
id = name._id, name = name._name; | |
} else { | |
id = newId(), (timing = defaultTiming).time = d3Timer.now(), name = name == null ? null : name + ""; | |
} | |
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { | |
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { | |
if (node = group[i]) { | |
schedule(node, name, id, i, group, timing || inherit(node, id)); | |
} | |
} | |
} | |
return new Transition(groups, this._parents, name, id); | |
}; | |
d3Selection.selection.prototype.interrupt = selection_interrupt; | |
d3Selection.selection.prototype.transition = selection_transition; | |
var root = [null]; | |
var active = function(node, name) { | |
var schedules = node.__transition, | |
schedule, | |
i; | |
if (schedules) { | |
name = name == null ? null : name + ""; | |
for (i in schedules) { | |
if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { | |
return new Transition([[node]], root, name, +i); | |
} | |
} | |
} | |
return null; | |
}; | |
exports.transition = transition; | |
exports.active = active; | |
exports.interrupt = interrupt; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
}))); | |
},{"d3-color":20,"d3-dispatch":21,"d3-ease":24,"d3-interpolate":29,"d3-selection":37,"d3-timer":41}],43:[function(require,module,exports){ | |
// https://d3js.org/d3-voronoi/ Version 1.1.2. Copyright 2017 Mike Bostock. | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
(factory((global.d3 = global.d3 || {}))); | |
}(this, (function (exports) { 'use strict'; | |
var constant = function(x) { | |
return function() { | |
return x; | |
}; | |
}; | |
function x(d) { | |
return d[0]; | |
} | |
function y(d) { | |
return d[1]; | |
} | |
function RedBlackTree() { | |
this._ = null; // root node | |
} | |
function RedBlackNode(node) { | |
node.U = // parent node | |
node.C = // color - true for red, false for black | |
node.L = // left node | |
node.R = // right node | |
node.P = // previous node | |
node.N = null; // next node | |
} | |
RedBlackTree.prototype = { | |
constructor: RedBlackTree, | |
insert: function(after, node) { | |
var parent, grandpa, uncle; | |
if (after) { | |
node.P = after; | |
node.N = after.N; | |
if (after.N) after.N.P = node; | |
after.N = node; | |
if (after.R) { | |
after = after.R; | |
while (after.L) after = after.L; | |
after.L = node; | |
} else { | |
after.R = node; | |
} | |
parent = after; | |
} else if (this._) { | |
after = RedBlackFirst(this._); | |
node.P = null; | |
node.N = after; | |
after.P = after.L = node; | |
parent = after; | |
} else { | |
node.P = node.N = null; | |
this._ = node; | |
parent = null; | |
} | |
node.L = node.R = null; | |
node.U = parent; | |
node.C = true; | |
after = node; | |
while (parent && parent.C) { | |
grandpa = parent.U; | |
if (parent === grandpa.L) { | |
uncle = grandpa.R; | |
if (uncle && uncle.C) { | |
parent.C = uncle.C = false; | |
grandpa.C = true; | |
after = grandpa; | |
} else { | |
if (after === parent.R) { | |
RedBlackRotateLeft(this, parent); | |
after = parent; | |
parent = after.U; | |
} | |
parent.C = false; | |
grandpa.C = true; | |
RedBlackRotateRight(this, grandpa); | |
} | |
} else { | |
uncle = grandpa.L; | |
if (uncle && uncle.C) { | |
parent.C = uncle.C = false; | |
grandpa.C = true; | |
after = grandpa; | |
} else { | |
if (after === parent.L) { | |
RedBlackRotateRight(this, parent); | |
after = parent; | |
parent = after.U; | |
} | |
parent.C = false; | |
grandpa.C = true; | |
RedBlackRotateLeft(this, grandpa); | |
} | |
} | |
parent = after.U; | |
} | |
this._.C = false; | |
}, | |