Last active
December 14, 2015 03:39
-
-
Save ronnywang/5023138 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.insights-tooltip { | |
font-family: "proxima-nova",sans-serif; | |
padding: 12px; | |
color:#FFF; | |
font-size:13px; | |
background-color:#757575; | |
border-radius:5px; | |
-moz-border-radius:5px; | |
-webkit-border-radius:5px; | |
box-shadow:0 1px 2px rgba(0,0,0,.65),0 -1px 2px rgba(0,0,0,.65) inset; | |
text-shadow:0 1px 1px rgba(0,0,0,.8); | |
} | |
.insights-graph .link { | |
fill: none; | |
stroke: #666; | |
} | |
.insights-graph .node circle { | |
fill: #ccc; | |
stroke: #fff; | |
stroke-width: 1.5px; | |
cursor:pointer; | |
} | |
.insights-graph text { | |
fill: #444; | |
font: 9px sans-serif; | |
pointer-events: none; | |
text-shadow: -1px 0px 3px white, -1px 0px 9px white; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* hasOwnProperty. | |
*/ | |
var has = Object.prototype.hasOwnProperty; | |
/** | |
* Require the given path. | |
* | |
* @param {String} path | |
* @return {Object} exports | |
* @api public | |
*/ | |
function require(path, parent, orig) { | |
var resolved = require.resolve(path); | |
// lookup failed | |
if (null == resolved) { | |
orig = orig || path; | |
parent = parent || 'root'; | |
var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); | |
err.path = orig; | |
err.parent = parent; | |
err.require = true; | |
throw err; | |
} | |
var module = require.modules[resolved]; | |
// perform real require() | |
// by invoking the module's | |
// registered function | |
if (!module.exports) { | |
module.exports = {}; | |
module.client = module.component = true; | |
module.call(this, module.exports, require.relative(resolved), module); | |
} | |
return module.exports; | |
} | |
/** | |
* Registered modules. | |
*/ | |
require.modules = {}; | |
/** | |
* Registered aliases. | |
*/ | |
require.aliases = {}; | |
/** | |
* Resolve `path`. | |
* | |
* Lookup: | |
* | |
* - PATH/index.js | |
* - PATH.js | |
* - PATH | |
* | |
* @param {String} path | |
* @return {String} path or null | |
* @api private | |
*/ | |
require.resolve = function(path) { | |
var index = path + '/index.js'; | |
var paths = [ | |
path, | |
path + '.js', | |
path + '.json', | |
path + '/index.js', | |
path + '/index.json' | |
]; | |
for (var i = 0; i < paths.length; i++) { | |
var path = paths[i]; | |
if (has.call(require.modules, path)) return path; | |
} | |
if (has.call(require.aliases, index)) { | |
return require.aliases[index]; | |
} | |
}; | |
/** | |
* Normalize `path` relative to the current path. | |
* | |
* @param {String} curr | |
* @param {String} path | |
* @return {String} | |
* @api private | |
*/ | |
require.normalize = function(curr, path) { | |
var segs = []; | |
if ('.' != path.charAt(0)) return path; | |
curr = curr.split('/'); | |
path = path.split('/'); | |
for (var i = 0; i < path.length; ++i) { | |
if ('..' == path[i]) { | |
curr.pop(); | |
} else if ('.' != path[i] && '' != path[i]) { | |
segs.push(path[i]); | |
} | |
} | |
return curr.concat(segs).join('/'); | |
}; | |
/** | |
* Register module at `path` with callback `definition`. | |
* | |
* @param {String} path | |
* @param {Function} definition | |
* @api private | |
*/ | |
require.register = function(path, definition) { | |
require.modules[path] = definition; | |
}; | |
/** | |
* Alias a module definition. | |
* | |
* @param {String} from | |
* @param {String} to | |
* @api private | |
*/ | |
require.alias = function(from, to) { | |
if (!has.call(require.modules, from)) { | |
throw new Error('Failed to alias "' + from + '", it does not exist'); | |
} | |
require.aliases[to] = from; | |
}; | |
/** | |
* Return a require function relative to the `parent` path. | |
* | |
* @param {String} parent | |
* @return {Function} | |
* @api private | |
*/ | |
require.relative = function(parent) { | |
var p = require.normalize(parent, '..'); | |
/** | |
* lastIndexOf helper. | |
*/ | |
function lastIndexOf(arr, obj) { | |
var i = arr.length; | |
while (i--) { | |
if (arr[i] === obj) return i; | |
} | |
return -1; | |
} | |
/** | |
* The relative require() itself. | |
*/ | |
function localRequire(path) { | |
var resolved = localRequire.resolve(path); | |
return require(resolved, parent, path); | |
} | |
/** | |
* Resolve relative to the parent. | |
*/ | |
localRequire.resolve = function(path) { | |
// resolve deps by returning | |
// the dep in the nearest "deps" | |
// directory | |
if ('.' != path.charAt(0)) { | |
var segs = parent.split('/'); | |
var i = lastIndexOf(segs, 'deps') + 1; | |
if (!i) i = 0; | |
path = segs.slice(0, i + 1).join('/') + '/deps/' + path; | |
return path; | |
} | |
return require.normalize(p, path); | |
}; | |
/** | |
* Check if module is defined at `path`. | |
*/ | |
localRequire.exists = function(path) { | |
return has.call(require.modules, localRequire.resolve(path)); | |
}; | |
return localRequire; | |
}; | |
require.register("ignacioola-d3/d3.js", function(exports, require, module){ | |
(function() { | |
var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ]; | |
if (!Date.now) Date.now = function() { | |
return +new Date(); | |
}; | |
try { | |
document.createElement("div").style.setProperty("opacity", 0, ""); | |
} catch (error) { | |
var d3_style_prototype = CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; | |
d3_style_prototype.setProperty = function(name, value, priority) { | |
d3_style_setProperty.call(this, name, value + "", priority); | |
}; | |
} | |
d3 = { | |
version: "3.0.2" | |
}; | |
var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π; | |
function d3_target(d) { | |
return d.target; | |
} | |
function d3_source(d) { | |
return d.source; | |
} | |
function d3_class(ctor, properties) { | |
try { | |
for (var key in properties) { | |
Object.defineProperty(ctor.prototype, key, { | |
value: properties[key], | |
enumerable: false | |
}); | |
} | |
} catch (e) { | |
ctor.prototype = properties; | |
} | |
} | |
var d3_array = d3_arraySlice; | |
function d3_arrayCopy(pseudoarray) { | |
var i = -1, n = pseudoarray.length, array = []; | |
while (++i < n) array.push(pseudoarray[i]); | |
return array; | |
} | |
function d3_arraySlice(pseudoarray) { | |
return Array.prototype.slice.call(pseudoarray); | |
} | |
try { | |
d3_array(document.documentElement.childNodes)[0].nodeType; | |
} catch (e) { | |
d3_array = d3_arrayCopy; | |
} | |
var d3_arraySubclass = [].__proto__ ? function(array, prototype) { | |
array.__proto__ = prototype; | |
} : function(array, prototype) { | |
for (var property in prototype) array[property] = prototype[property]; | |
}; | |
d3.map = function(object) { | |
var map = new d3_Map(); | |
for (var key in object) map.set(key, object[key]); | |
return map; | |
}; | |
function d3_Map() {} | |
d3_class(d3_Map, { | |
has: function(key) { | |
return d3_map_prefix + key in this; | |
}, | |
get: function(key) { | |
return this[d3_map_prefix + key]; | |
}, | |
set: function(key, value) { | |
return this[d3_map_prefix + key] = value; | |
}, | |
remove: function(key) { | |
key = d3_map_prefix + key; | |
return key in this && delete this[key]; | |
}, | |
keys: function() { | |
var keys = []; | |
this.forEach(function(key) { | |
keys.push(key); | |
}); | |
return keys; | |
}, | |
values: function() { | |
var values = []; | |
this.forEach(function(key, value) { | |
values.push(value); | |
}); | |
return values; | |
}, | |
entries: function() { | |
var entries = []; | |
this.forEach(function(key, value) { | |
entries.push({ | |
key: key, | |
value: value | |
}); | |
}); | |
return entries; | |
}, | |
forEach: function(f) { | |
for (var key in this) { | |
if (key.charCodeAt(0) === d3_map_prefixCode) { | |
f.call(this, key.substring(1), this[key]); | |
} | |
} | |
} | |
}); | |
var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0); | |
function d3_identity(d) { | |
return d; | |
} | |
function d3_true() { | |
return true; | |
} | |
function d3_functor(v) { | |
return typeof v === "function" ? v : function() { | |
return v; | |
}; | |
} | |
d3.functor = d3_functor; | |
d3.rebind = function(target, source) { | |
var i = 1, n = arguments.length, method; | |
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); | |
return target; | |
}; | |
function d3_rebind(target, source, method) { | |
return function() { | |
var value = method.apply(source, arguments); | |
return arguments.length ? target : value; | |
}; | |
} | |
d3.ascending = function(a, b) { | |
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; | |
}; | |
d3.descending = function(a, b) { | |
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; | |
}; | |
d3.mean = function(array, f) { | |
var n = array.length, a, m = 0, i = -1, j = 0; | |
if (arguments.length === 1) { | |
while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; | |
} else { | |
while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; | |
} | |
return j ? m : undefined; | |
}; | |
d3.median = function(array, f) { | |
if (arguments.length > 1) array = array.map(f); | |
array = array.filter(d3_number); | |
return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; | |
}; | |
d3.min = function(array, f) { | |
var i = -1, n = array.length, a, b; | |
if (arguments.length === 1) { | |
while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; | |
while (++i < n) if ((b = array[i]) != null && a > b) a = b; | |
} else { | |
while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; | |
} | |
return a; | |
}; | |
d3.max = function(array, f) { | |
var i = -1, n = array.length, a, b; | |
if (arguments.length === 1) { | |
while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; | |
while (++i < n) if ((b = array[i]) != null && b > a) a = b; | |
} else { | |
while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; | |
} | |
return a; | |
}; | |
d3.extent = function(array, f) { | |
var i = -1, n = array.length, a, b, c; | |
if (arguments.length === 1) { | |
while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined; | |
while (++i < n) if ((b = array[i]) != null) { | |
if (a > b) a = b; | |
if (c < b) c = b; | |
} | |
} else { | |
while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined; | |
while (++i < n) if ((b = f.call(array, array[i], i)) != null) { | |
if (a > b) a = b; | |
if (c < b) c = b; | |
} | |
} | |
return [ a, c ]; | |
}; | |
d3.random = { | |
normal: function(µ, σ) { | |
var n = arguments.length; | |
if (n < 2) σ = 1; | |
if (n < 1) µ = 0; | |
return function() { | |
var x, y, r; | |
do { | |
x = Math.random() * 2 - 1; | |
y = Math.random() * 2 - 1; | |
r = x * x + y * y; | |
} while (!r || r > 1); | |
return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); | |
}; | |
}, | |
logNormal: function(µ, σ) { | |
var n = arguments.length; | |
if (n < 2) σ = 1; | |
if (n < 1) µ = 0; | |
var random = d3.random.normal(); | |
return function() { | |
return Math.exp(µ + σ * random()); | |
}; | |
}, | |
irwinHall: function(m) { | |
return function() { | |
for (var s = 0, j = 0; j < m; j++) s += Math.random(); | |
return s / m; | |
}; | |
} | |
}; | |
function d3_number(x) { | |
return x != null && !isNaN(x); | |
} | |
d3.sum = function(array, f) { | |
var s = 0, n = array.length, a, i = -1; | |
if (arguments.length === 1) { | |
while (++i < n) if (!isNaN(a = +array[i])) s += a; | |
} else { | |
while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; | |
} | |
return s; | |
}; | |
d3.quantile = function(values, p) { | |
var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; | |
return e ? v + e * (values[h] - v) : v; | |
}; | |
d3.shuffle = function(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; | |
}; | |
d3.transpose = function(matrix) { | |
return d3.zip.apply(d3, matrix); | |
}; | |
d3.zip = function() { | |
if (!(n = arguments.length)) return []; | |
for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { | |
for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { | |
zip[j] = arguments[j][i]; | |
} | |
} | |
return zips; | |
}; | |
function d3_zipLength(d) { | |
return d.length; | |
} | |
d3.bisector = function(f) { | |
return { | |
left: function(a, x, lo, hi) { | |
if (arguments.length < 3) lo = 0; | |
if (arguments.length < 4) hi = a.length; | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid; | |
} | |
return lo; | |
}, | |
right: function(a, x, lo, hi) { | |
if (arguments.length < 3) lo = 0; | |
if (arguments.length < 4) hi = a.length; | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1; | |
} | |
return lo; | |
} | |
}; | |
}; | |
var d3_bisector = d3.bisector(function(d) { | |
return d; | |
}); | |
d3.bisectLeft = d3_bisector.left; | |
d3.bisect = d3.bisectRight = d3_bisector.right; | |
d3.nest = function() { | |
var nest = {}, keys = [], sortKeys = [], sortValues, rollup; | |
function map(array, depth) { | |
if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; | |
var i = -1, n = array.length, key = keys[depth++], keyValue, object, valuesByKey = new d3_Map(), values, o = {}; | |
while (++i < n) { | |
if (values = valuesByKey.get(keyValue = key(object = array[i]))) { | |
values.push(object); | |
} else { | |
valuesByKey.set(keyValue, [ object ]); | |
} | |
} | |
valuesByKey.forEach(function(keyValue, values) { | |
o[keyValue] = map(values, depth); | |
}); | |
return o; | |
} | |
function entries(map, depth) { | |
if (depth >= keys.length) return map; | |
var a = [], sortKey = sortKeys[depth++], key; | |
for (key in map) { | |
a.push({ | |
key: key, | |
values: entries(map[key], depth) | |
}); | |
} | |
if (sortKey) a.sort(function(a, b) { | |
return sortKey(a.key, b.key); | |
}); | |
return a; | |
} | |
nest.map = function(array) { | |
return map(array, 0); | |
}; | |
nest.entries = function(array) { | |
return entries(map(array, 0), 0); | |
}; | |
nest.key = function(d) { | |
keys.push(d); | |
return nest; | |
}; | |
nest.sortKeys = function(order) { | |
sortKeys[keys.length - 1] = order; | |
return nest; | |
}; | |
nest.sortValues = function(order) { | |
sortValues = order; | |
return nest; | |
}; | |
nest.rollup = function(f) { | |
rollup = f; | |
return nest; | |
}; | |
return nest; | |
}; | |
d3.keys = function(map) { | |
var keys = []; | |
for (var key in map) keys.push(key); | |
return keys; | |
}; | |
d3.values = function(map) { | |
var values = []; | |
for (var key in map) values.push(map[key]); | |
return values; | |
}; | |
d3.entries = function(map) { | |
var entries = []; | |
for (var key in map) entries.push({ | |
key: key, | |
value: map[key] | |
}); | |
return entries; | |
}; | |
d3.permute = function(array, indexes) { | |
var permutes = [], i = -1, n = indexes.length; | |
while (++i < n) permutes[i] = array[indexes[i]]; | |
return permutes; | |
}; | |
d3.merge = function(arrays) { | |
return Array.prototype.concat.apply([], arrays); | |
}; | |
function d3_collapse(s) { | |
return s.trim().replace(/\s+/g, " "); | |
} | |
d3.range = function(start, stop, step) { | |
if (arguments.length < 3) { | |
step = 1; | |
if (arguments.length < 2) { | |
stop = start; | |
start = 0; | |
} | |
} | |
if ((stop - start) / step === Infinity) throw new Error("infinite range"); | |
var range = [], k = d3_range_integerScale(Math.abs(step)), i = -1, j; | |
start *= k, stop *= k, step *= k; | |
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); | |
return range; | |
}; | |
function d3_range_integerScale(x) { | |
var k = 1; | |
while (x * k % 1) k *= 10; | |
return k; | |
} | |
d3.requote = function(s) { | |
return s.replace(d3_requote_re, "\\$&"); | |
}; | |
var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; | |
d3.round = function(x, n) { | |
return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); | |
}; | |
d3.xhr = function(url, mimeType, callback) { | |
var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, response = d3_identity, request = new (window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)(); | |
"onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { | |
request.readyState > 3 && respond(); | |
}; | |
function respond() { | |
var s = request.status; | |
!s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request); | |
} | |
request.onprogress = function(event) { | |
var o = d3.event; | |
d3.event = event; | |
try { | |
dispatch.progress.call(xhr, request); | |
} finally { | |
d3.event = o; | |
} | |
}; | |
xhr.header = function(name, value) { | |
name = (name + "").toLowerCase(); | |
if (arguments.length < 2) return headers[name]; | |
if (value == null) delete headers[name]; else headers[name] = value + ""; | |
return xhr; | |
}; | |
xhr.mimeType = function(value) { | |
if (!arguments.length) return mimeType; | |
mimeType = value == null ? null : value + ""; | |
return xhr; | |
}; | |
xhr.response = function(value) { | |
response = value; | |
return xhr; | |
}; | |
[ "get", "post" ].forEach(function(method) { | |
xhr[method] = function() { | |
return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); | |
}; | |
}); | |
xhr.send = function(method, data, callback) { | |
if (arguments.length === 2 && typeof data === "function") callback = data, data = null; | |
request.open(method, url, true); | |
if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; | |
if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); | |
if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); | |
if (callback != null) xhr.on("error", callback).on("load", function(request) { | |
callback(null, request); | |
}); | |
request.send(data == null ? null : data); | |
return xhr; | |
}; | |
xhr.abort = function() { | |
request.abort(); | |
return xhr; | |
}; | |
d3.rebind(xhr, dispatch, "on"); | |
if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, | |
mimeType = null; | |
return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); | |
}; | |
function d3_xhr_fixCallback(callback) { | |
return callback.length === 1 ? function(error, request) { | |
callback(error == null ? request : null); | |
} : callback; | |
} | |
d3.text = function() { | |
return d3.xhr.apply(d3, arguments).response(d3_text); | |
}; | |
function d3_text(request) { | |
return request.responseText; | |
} | |
d3.json = function(url, callback) { | |
return d3.xhr(url, "application/json", callback).response(d3_json); | |
}; | |
function d3_json(request) { | |
return JSON.parse(request.responseText); | |
} | |
d3.html = function(url, callback) { | |
return d3.xhr(url, "text/html", callback).response(d3_html); | |
}; | |
function d3_html(request) { | |
var range = document.createRange(); | |
range.selectNode(document.body); | |
return range.createContextualFragment(request.responseText); | |
} | |
d3.xml = function() { | |
return d3.xhr.apply(d3, arguments).response(d3_xml); | |
}; | |
function d3_xml(request) { | |
return request.responseXML; | |
} | |
var d3_nsPrefix = { | |
svg: "http://www.w3.org/2000/svg", | |
xhtml: "http://www.w3.org/1999/xhtml", | |
xlink: "http://www.w3.org/1999/xlink", | |
xml: "http://www.w3.org/XML/1998/namespace", | |
xmlns: "http://www.w3.org/2000/xmlns/" | |
}; | |
d3.ns = { | |
prefix: d3_nsPrefix, | |
qualify: function(name) { | |
var i = name.indexOf(":"), prefix = name; | |
if (i >= 0) { | |
prefix = name.substring(0, i); | |
name = name.substring(i + 1); | |
} | |
return d3_nsPrefix.hasOwnProperty(prefix) ? { | |
space: d3_nsPrefix[prefix], | |
local: name | |
} : name; | |
} | |
}; | |
d3.dispatch = function() { | |
var dispatch = new d3_dispatch(), i = -1, n = arguments.length; | |
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); | |
return dispatch; | |
}; | |
function d3_dispatch() {} | |
d3_dispatch.prototype.on = function(type, listener) { | |
var i = type.indexOf("."), name = ""; | |
if (i > 0) { | |
name = type.substring(i + 1); | |
type = type.substring(0, i); | |
} | |
return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); | |
}; | |
function d3_dispatch_event(dispatch) { | |
var listeners = [], listenerByName = new d3_Map(); | |
function event() { | |
var z = listeners, i = -1, n = z.length, l; | |
while (++i < n) if (l = z[i].on) l.apply(this, arguments); | |
return dispatch; | |
} | |
event.on = function(name, listener) { | |
var l = listenerByName.get(name), i; | |
if (arguments.length < 2) return l && l.on; | |
if (l) { | |
l.on = null; | |
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); | |
listenerByName.remove(name); | |
} | |
if (listener) listeners.push(listenerByName.set(name, { | |
on: listener | |
})); | |
return dispatch; | |
}; | |
return event; | |
} | |
d3.format = function(specifier) { | |
var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false; | |
if (precision) precision = +precision.substring(1); | |
if (zfill || fill === "0" && align === "=") { | |
zfill = fill = "0"; | |
align = "="; | |
if (comma) width -= Math.floor((width - 1) / 4); | |
} | |
switch (type) { | |
case "n": | |
comma = true; | |
type = "g"; | |
break; | |
case "%": | |
scale = 100; | |
suffix = "%"; | |
type = "f"; | |
break; | |
case "p": | |
scale = 100; | |
suffix = "%"; | |
type = "r"; | |
break; | |
case "b": | |
case "o": | |
case "x": | |
case "X": | |
if (basePrefix) basePrefix = "0" + type.toLowerCase(); | |
case "c": | |
case "d": | |
integer = true; | |
precision = 0; | |
break; | |
case "s": | |
scale = -1; | |
type = "r"; | |
break; | |
} | |
if (basePrefix === "#") basePrefix = ""; | |
if (type == "r" && !precision) type = "g"; | |
type = d3_format_types.get(type) || d3_format_typeDefault; | |
var zcomma = zfill && comma; | |
return function(value) { | |
if (integer && value % 1) return ""; | |
var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign; | |
if (scale < 0) { | |
var prefix = d3.formatPrefix(value, precision); | |
value = prefix.scale(value); | |
suffix = prefix.symbol; | |
} else { | |
value *= scale; | |
} | |
value = type(value, precision); | |
if (!zfill && comma) value = d3_format_group(value); | |
var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; | |
if (zcomma) value = d3_format_group(padding + value); | |
if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint); | |
negative += basePrefix; | |
return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix; | |
}; | |
}; | |
var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/; | |
var d3_format_types = d3.map({ | |
b: function(x) { | |
return x.toString(2); | |
}, | |
c: function(x) { | |
return String.fromCharCode(x); | |
}, | |
o: function(x) { | |
return x.toString(8); | |
}, | |
x: function(x) { | |
return x.toString(16); | |
}, | |
X: function(x) { | |
return x.toString(16).toUpperCase(); | |
}, | |
g: function(x, p) { | |
return x.toPrecision(p); | |
}, | |
e: function(x, p) { | |
return x.toExponential(p); | |
}, | |
f: function(x, p) { | |
return x.toFixed(p); | |
}, | |
r: function(x, p) { | |
return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); | |
} | |
}); | |
function d3_format_precision(x, p) { | |
return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1); | |
} | |
function d3_format_typeDefault(x) { | |
return x + ""; | |
} | |
var d3_format_group = d3_identity; | |
if (d3_format_grouping) { | |
var d3_format_groupingLength = d3_format_grouping.length; | |
d3_format_group = function(value) { | |
var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length, | |
""), t = [], j = 0, g = d3_format_grouping[0]; | |
while (i > 0 && g > 0) { | |
t.push(value.substring(i -= g, i + g)); | |
g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength]; | |
} | |
return t.reverse().join(d3_format_thousandsSeparator || "") + f; | |
}; | |
} | |
var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); | |
d3.formatPrefix = function(value, precision) { | |
var i = 0; | |
if (value) { | |
if (value < 0) value *= -1; | |
if (precision) value = d3.round(value, d3_format_precision(value, precision)); | |
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); | |
i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); | |
} | |
return d3_formatPrefixes[8 + i / 3]; | |
}; | |
function d3_formatPrefix(d, i) { | |
var k = Math.pow(10, Math.abs(8 - i) * 3); | |
return { | |
scale: i > 8 ? function(d) { | |
return d / k; | |
} : function(d) { | |
return d * k; | |
}, | |
symbol: d | |
}; | |
} | |
var d3_ease_default = function() { | |
return d3_identity; | |
}; | |
var d3_ease = d3.map({ | |
linear: d3_ease_default, | |
poly: d3_ease_poly, | |
quad: function() { | |
return d3_ease_quad; | |
}, | |
cubic: function() { | |
return d3_ease_cubic; | |
}, | |
sin: function() { | |
return d3_ease_sin; | |
}, | |
exp: function() { | |
return d3_ease_exp; | |
}, | |
circle: function() { | |
return d3_ease_circle; | |
}, | |
elastic: d3_ease_elastic, | |
back: d3_ease_back, | |
bounce: function() { | |
return d3_ease_bounce; | |
} | |
}); | |
var d3_ease_mode = d3.map({ | |
"in": d3_identity, | |
out: d3_ease_reverse, | |
"in-out": d3_ease_reflect, | |
"out-in": function(f) { | |
return d3_ease_reflect(d3_ease_reverse(f)); | |
} | |
}); | |
d3.ease = function(name) { | |
var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in"; | |
t = d3_ease.get(t) || d3_ease_default; | |
m = d3_ease_mode.get(m) || d3_identity; | |
return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1)))); | |
}; | |
function d3_ease_clamp(f) { | |
return function(t) { | |
return t <= 0 ? 0 : t >= 1 ? 1 : f(t); | |
}; | |
} | |
function d3_ease_reverse(f) { | |
return function(t) { | |
return 1 - f(1 - t); | |
}; | |
} | |
function d3_ease_reflect(f) { | |
return function(t) { | |
return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); | |
}; | |
} | |
function d3_ease_quad(t) { | |
return t * t; | |
} | |
function d3_ease_cubic(t) { | |
return t * t * t; | |
} | |
function d3_ease_cubicInOut(t) { | |
if (t <= 0) return 0; | |
if (t >= 1) return 1; | |
var t2 = t * t, t3 = t2 * t; | |
return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); | |
} | |
function d3_ease_poly(e) { | |
return function(t) { | |
return Math.pow(t, e); | |
}; | |
} | |
function d3_ease_sin(t) { | |
return 1 - Math.cos(t * π / 2); | |
} | |
function d3_ease_exp(t) { | |
return Math.pow(2, 10 * (t - 1)); | |
} | |
function d3_ease_circle(t) { | |
return 1 - Math.sqrt(1 - t * t); | |
} | |
function d3_ease_elastic(a, p) { | |
var s; | |
if (arguments.length < 2) p = .45; | |
if (arguments.length) s = p / (2 * π) * Math.asin(1 / a); else a = 1, s = p / 4; | |
return function(t) { | |
return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * π / p); | |
}; | |
} | |
function d3_ease_back(s) { | |
if (!s) s = 1.70158; | |
return function(t) { | |
return t * t * ((s + 1) * t - s); | |
}; | |
} | |
function d3_ease_bounce(t) { | |
return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; | |
} | |
d3.event = null; | |
function d3_eventCancel() { | |
d3.event.stopPropagation(); | |
d3.event.preventDefault(); | |
} | |
function d3_eventSource() { | |
var e = d3.event, s; | |
while (s = e.sourceEvent) e = s; | |
return e; | |
} | |
function d3_eventDispatch(target) { | |
var dispatch = new d3_dispatch(), i = 0, n = arguments.length; | |
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); | |
dispatch.of = function(thiz, argumentz) { | |
return function(e1) { | |
try { | |
var e0 = e1.sourceEvent = d3.event; | |
e1.target = target; | |
d3.event = e1; | |
dispatch[e1.type].apply(thiz, argumentz); | |
} finally { | |
d3.event = e0; | |
} | |
}; | |
}; | |
return dispatch; | |
} | |
d3.transform = function(string) { | |
var g = document.createElementNS(d3.ns.prefix.svg, "g"); | |
return (d3.transform = function(string) { | |
g.setAttribute("transform", string); | |
var t = g.transform.baseVal.consolidate(); | |
return new d3_transform(t ? t.matrix : d3_transformIdentity); | |
})(string); | |
}; | |
function d3_transform(m) { | |
var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; | |
if (r0[0] * r1[1] < r1[0] * r0[1]) { | |
r0[0] *= -1; | |
r0[1] *= -1; | |
kx *= -1; | |
kz *= -1; | |
} | |
this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; | |
this.translate = [ m.e, m.f ]; | |
this.scale = [ kx, ky ]; | |
this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; | |
} | |
d3_transform.prototype.toString = function() { | |
return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; | |
}; | |
function d3_transformDot(a, b) { | |
return a[0] * b[0] + a[1] * b[1]; | |
} | |
function d3_transformNormalize(a) { | |
var k = Math.sqrt(d3_transformDot(a, a)); | |
if (k) { | |
a[0] /= k; | |
a[1] /= k; | |
} | |
return k; | |
} | |
function d3_transformCombine(a, b, k) { | |
a[0] += k * b[0]; | |
a[1] += k * b[1]; | |
return a; | |
} | |
var d3_transformIdentity = { | |
a: 1, | |
b: 0, | |
c: 0, | |
d: 1, | |
e: 0, | |
f: 0 | |
}; | |
d3.interpolate = function(a, b) { | |
var i = d3.interpolators.length, f; | |
while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; | |
return f; | |
}; | |
d3.interpolateNumber = function(a, b) { | |
b -= a; | |
return function(t) { | |
return a + b * t; | |
}; | |
}; | |
d3.interpolateRound = function(a, b) { | |
b -= a; | |
return function(t) { | |
return Math.round(a + b * t); | |
}; | |
}; | |
d3.interpolateString = function(a, b) { | |
var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o; | |
d3_interpolate_number.lastIndex = 0; | |
for (i = 0; m = d3_interpolate_number.exec(b); ++i) { | |
if (m.index) s.push(b.substring(s0, s1 = m.index)); | |
q.push({ | |
i: s.length, | |
x: m[0] | |
}); | |
s.push(null); | |
s0 = d3_interpolate_number.lastIndex; | |
} | |
if (s0 < b.length) s.push(b.substring(s0)); | |
for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) { | |
o = q[i]; | |
if (o.x == m[0]) { | |
if (o.i) { | |
if (s[o.i + 1] == null) { | |
s[o.i - 1] += o.x; | |
s.splice(o.i, 1); | |
for (j = i + 1; j < n; ++j) q[j].i--; | |
} else { | |
s[o.i - 1] += o.x + s[o.i + 1]; | |
s.splice(o.i, 2); | |
for (j = i + 1; j < n; ++j) q[j].i -= 2; | |
} | |
} else { | |
if (s[o.i + 1] == null) { | |
s[o.i] = o.x; | |
} else { | |
s[o.i] = o.x + s[o.i + 1]; | |
s.splice(o.i + 1, 1); | |
for (j = i + 1; j < n; ++j) q[j].i--; | |
} | |
} | |
q.splice(i, 1); | |
n--; | |
i--; | |
} else { | |
o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x)); | |
} | |
} | |
while (i < n) { | |
o = q.pop(); | |
if (s[o.i + 1] == null) { | |
s[o.i] = o.x; | |
} else { | |
s[o.i] = o.x + s[o.i + 1]; | |
s.splice(o.i + 1, 1); | |
} | |
n--; | |
} | |
if (s.length === 1) { | |
return s[0] == null ? q[0].x : function() { | |
return b; | |
}; | |
} | |
return function(t) { | |
for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}; | |
}; | |
d3.interpolateTransform = function(a, b) { | |
var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; | |
if (ta[0] != tb[0] || ta[1] != tb[1]) { | |
s.push("translate(", null, ",", null, ")"); | |
q.push({ | |
i: 1, | |
x: d3.interpolateNumber(ta[0], tb[0]) | |
}, { | |
i: 3, | |
x: d3.interpolateNumber(ta[1], tb[1]) | |
}); | |
} else if (tb[0] || tb[1]) { | |
s.push("translate(" + tb + ")"); | |
} else { | |
s.push(""); | |
} | |
if (ra != rb) { | |
if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; | |
q.push({ | |
i: s.push(s.pop() + "rotate(", null, ")") - 2, | |
x: d3.interpolateNumber(ra, rb) | |
}); | |
} else if (rb) { | |
s.push(s.pop() + "rotate(" + rb + ")"); | |
} | |
if (wa != wb) { | |
q.push({ | |
i: s.push(s.pop() + "skewX(", null, ")") - 2, | |
x: d3.interpolateNumber(wa, wb) | |
}); | |
} else if (wb) { | |
s.push(s.pop() + "skewX(" + wb + ")"); | |
} | |
if (ka[0] != kb[0] || ka[1] != kb[1]) { | |
n = s.push(s.pop() + "scale(", null, ",", null, ")"); | |
q.push({ | |
i: n - 4, | |
x: d3.interpolateNumber(ka[0], kb[0]) | |
}, { | |
i: n - 2, | |
x: d3.interpolateNumber(ka[1], kb[1]) | |
}); | |
} else if (kb[0] != 1 || kb[1] != 1) { | |
s.push(s.pop() + "scale(" + kb + ")"); | |
} | |
n = q.length; | |
return function(t) { | |
var i = -1, o; | |
while (++i < n) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}; | |
}; | |
d3.interpolateRgb = function(a, b) { | |
a = d3.rgb(a); | |
b = d3.rgb(b); | |
var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; | |
return function(t) { | |
return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); | |
}; | |
}; | |
d3.interpolateHsl = function(a, b) { | |
a = d3.hsl(a); | |
b = d3.hsl(b); | |
var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0; | |
if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360; | |
return function(t) { | |
return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + ""; | |
}; | |
}; | |
d3.interpolateLab = function(a, b) { | |
a = d3.lab(a); | |
b = d3.lab(b); | |
var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; | |
return function(t) { | |
return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; | |
}; | |
}; | |
d3.interpolateHcl = function(a, b) { | |
a = d3.hcl(a); | |
b = d3.hcl(b); | |
var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; | |
if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; | |
return function(t) { | |
return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; | |
}; | |
}; | |
d3.interpolateArray = function(a, b) { | |
var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; | |
for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i])); | |
for (;i < na; ++i) c[i] = a[i]; | |
for (;i < nb; ++i) c[i] = b[i]; | |
return function(t) { | |
for (i = 0; i < n0; ++i) c[i] = x[i](t); | |
return c; | |
}; | |
}; | |
d3.interpolateObject = function(a, b) { | |
var i = {}, c = {}, k; | |
for (k in a) { | |
if (k in b) { | |
i[k] = d3_interpolateByName(k)(a[k], b[k]); | |
} else { | |
c[k] = a[k]; | |
} | |
} | |
for (k in b) { | |
if (!(k in a)) { | |
c[k] = b[k]; | |
} | |
} | |
return function(t) { | |
for (k in i) c[k] = i[k](t); | |
return c; | |
}; | |
}; | |
var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; | |
function d3_interpolateByName(name) { | |
return name == "transform" ? d3.interpolateTransform : d3.interpolate; | |
} | |
d3.interpolators = [ d3.interpolateObject, function(a, b) { | |
return b instanceof Array && d3.interpolateArray(a, b); | |
}, function(a, b) { | |
return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + ""); | |
}, function(a, b) { | |
return (typeof b === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Color) && d3.interpolateRgb(a, b); | |
}, function(a, b) { | |
return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b); | |
} ]; | |
function d3_uninterpolateNumber(a, b) { | |
b = b - (a = +a) ? 1 / (b - a) : 0; | |
return function(x) { | |
return (x - a) * b; | |
}; | |
} | |
function d3_uninterpolateClamp(a, b) { | |
b = b - (a = +a) ? 1 / (b - a) : 0; | |
return function(x) { | |
return Math.max(0, Math.min(1, (x - a) * b)); | |
}; | |
} | |
function d3_Color() {} | |
d3_Color.prototype.toString = function() { | |
return this.rgb() + ""; | |
}; | |
d3.rgb = function(r, g, b) { | |
return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b); | |
}; | |
function d3_rgb(r, g, b) { | |
return new d3_Rgb(r, g, b); | |
} | |
function d3_Rgb(r, g, b) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
} | |
var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color(); | |
d3_rgbPrototype.brighter = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
var r = this.r, g = this.g, b = this.b, i = 30; | |
if (!r && !g && !b) return d3_rgb(i, i, i); | |
if (r && r < i) r = i; | |
if (g && g < i) g = i; | |
if (b && b < i) b = i; | |
return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k))); | |
}; | |
d3_rgbPrototype.darker = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b)); | |
}; | |
d3_rgbPrototype.hsl = function() { | |
return d3_rgb_hsl(this.r, this.g, this.b); | |
}; | |
d3_rgbPrototype.toString = function() { | |
return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); | |
}; | |
function d3_rgb_hex(v) { | |
return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); | |
} | |
function d3_rgb_parse(format, rgb, hsl) { | |
var r = 0, g = 0, b = 0, m1, m2, name; | |
m1 = /([a-z]+)\((.*)\)/i.exec(format); | |
if (m1) { | |
m2 = m1[2].split(","); | |
switch (m1[1]) { | |
case "hsl": | |
{ | |
return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); | |
} | |
case "rgb": | |
{ | |
return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); | |
} | |
} | |
} | |
if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b); | |
if (format != null && format.charAt(0) === "#") { | |
if (format.length === 4) { | |
r = format.charAt(1); | |
r += r; | |
g = format.charAt(2); | |
g += g; | |
b = format.charAt(3); | |
b += b; | |
} else if (format.length === 7) { | |
r = format.substring(1, 3); | |
g = format.substring(3, 5); | |
b = format.substring(5, 7); | |
} | |
r = parseInt(r, 16); | |
g = parseInt(g, 16); | |
b = parseInt(b, 16); | |
} | |
return rgb(r, g, b); | |
} | |
function d3_rgb_hsl(r, g, b) { | |
var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; | |
if (d) { | |
s = l < .5 ? d / (max + min) : d / (2 - max - min); | |
if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; | |
h *= 60; | |
} else { | |
s = h = 0; | |
} | |
return d3_hsl(h, s, l); | |
} | |
function d3_rgb_lab(r, g, b) { | |
r = d3_rgb_xyz(r); | |
g = d3_rgb_xyz(g); | |
b = d3_rgb_xyz(b); | |
var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); | |
return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); | |
} | |
function d3_rgb_xyz(r) { | |
return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); | |
} | |
function d3_rgb_parseNumber(c) { | |
var f = parseFloat(c); | |
return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; | |
} | |
var d3_rgb_names = d3.map({ | |
aliceblue: "#f0f8ff", | |
antiquewhite: "#faebd7", | |
aqua: "#00ffff", | |
aquamarine: "#7fffd4", | |
azure: "#f0ffff", | |
beige: "#f5f5dc", | |
bisque: "#ffe4c4", | |
black: "#000000", | |
blanchedalmond: "#ffebcd", | |
blue: "#0000ff", | |
blueviolet: "#8a2be2", | |
brown: "#a52a2a", | |
burlywood: "#deb887", | |
cadetblue: "#5f9ea0", | |
chartreuse: "#7fff00", | |
chocolate: "#d2691e", | |
coral: "#ff7f50", | |
cornflowerblue: "#6495ed", | |
cornsilk: "#fff8dc", | |
crimson: "#dc143c", | |
cyan: "#00ffff", | |
darkblue: "#00008b", | |
darkcyan: "#008b8b", | |
darkgoldenrod: "#b8860b", | |
darkgray: "#a9a9a9", | |
darkgreen: "#006400", | |
darkgrey: "#a9a9a9", | |
darkkhaki: "#bdb76b", | |
darkmagenta: "#8b008b", | |
darkolivegreen: "#556b2f", | |
darkorange: "#ff8c00", | |
darkorchid: "#9932cc", | |
darkred: "#8b0000", | |
darksalmon: "#e9967a", | |
darkseagreen: "#8fbc8f", | |
darkslateblue: "#483d8b", | |
darkslategray: "#2f4f4f", | |
darkslategrey: "#2f4f4f", | |
darkturquoise: "#00ced1", | |
darkviolet: "#9400d3", | |
deeppink: "#ff1493", | |
deepskyblue: "#00bfff", | |
dimgray: "#696969", | |
dimgrey: "#696969", | |
dodgerblue: "#1e90ff", | |
firebrick: "#b22222", | |
floralwhite: "#fffaf0", | |
forestgreen: "#228b22", | |
fuchsia: "#ff00ff", | |
gainsboro: "#dcdcdc", | |
ghostwhite: "#f8f8ff", | |
gold: "#ffd700", | |
goldenrod: "#daa520", | |
gray: "#808080", | |
green: "#008000", | |
greenyellow: "#adff2f", | |
grey: "#808080", | |
honeydew: "#f0fff0", | |
hotpink: "#ff69b4", | |
indianred: "#cd5c5c", | |
indigo: "#4b0082", | |
ivory: "#fffff0", | |
khaki: "#f0e68c", | |
lavender: "#e6e6fa", | |
lavenderblush: "#fff0f5", | |
lawngreen: "#7cfc00", | |
lemonchiffon: "#fffacd", | |
lightblue: "#add8e6", | |
lightcoral: "#f08080", | |
lightcyan: "#e0ffff", | |
lightgoldenrodyellow: "#fafad2", | |
lightgray: "#d3d3d3", | |
lightgreen: "#90ee90", | |
lightgrey: "#d3d3d3", | |
lightpink: "#ffb6c1", | |
lightsalmon: "#ffa07a", | |
lightseagreen: "#20b2aa", | |
lightskyblue: "#87cefa", | |
lightslategray: "#778899", | |
lightslategrey: "#778899", | |
lightsteelblue: "#b0c4de", | |
lightyellow: "#ffffe0", | |
lime: "#00ff00", | |
limegreen: "#32cd32", | |
linen: "#faf0e6", | |
magenta: "#ff00ff", | |
maroon: "#800000", | |
mediumaquamarine: "#66cdaa", | |
mediumblue: "#0000cd", | |
mediumorchid: "#ba55d3", | |
mediumpurple: "#9370db", | |
mediumseagreen: "#3cb371", | |
mediumslateblue: "#7b68ee", | |
mediumspringgreen: "#00fa9a", | |
mediumturquoise: "#48d1cc", | |
mediumvioletred: "#c71585", | |
midnightblue: "#191970", | |
mintcream: "#f5fffa", | |
mistyrose: "#ffe4e1", | |
moccasin: "#ffe4b5", | |
navajowhite: "#ffdead", | |
navy: "#000080", | |
oldlace: "#fdf5e6", | |
olive: "#808000", | |
olivedrab: "#6b8e23", | |
orange: "#ffa500", | |
orangered: "#ff4500", | |
orchid: "#da70d6", | |
palegoldenrod: "#eee8aa", | |
palegreen: "#98fb98", | |
paleturquoise: "#afeeee", | |
palevioletred: "#db7093", | |
papayawhip: "#ffefd5", | |
peachpuff: "#ffdab9", | |
peru: "#cd853f", | |
pink: "#ffc0cb", | |
plum: "#dda0dd", | |
powderblue: "#b0e0e6", | |
purple: "#800080", | |
red: "#ff0000", | |
rosybrown: "#bc8f8f", | |
royalblue: "#4169e1", | |
saddlebrown: "#8b4513", | |
salmon: "#fa8072", | |
sandybrown: "#f4a460", | |
seagreen: "#2e8b57", | |
seashell: "#fff5ee", | |
sienna: "#a0522d", | |
silver: "#c0c0c0", | |
skyblue: "#87ceeb", | |
slateblue: "#6a5acd", | |
slategray: "#708090", | |
slategrey: "#708090", | |
snow: "#fffafa", | |
springgreen: "#00ff7f", | |
steelblue: "#4682b4", | |
tan: "#d2b48c", | |
teal: "#008080", | |
thistle: "#d8bfd8", | |
tomato: "#ff6347", | |
turquoise: "#40e0d0", | |
violet: "#ee82ee", | |
wheat: "#f5deb3", | |
white: "#ffffff", | |
whitesmoke: "#f5f5f5", | |
yellow: "#ffff00", | |
yellowgreen: "#9acd32" | |
}); | |
d3_rgb_names.forEach(function(key, value) { | |
d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb)); | |
}); | |
d3.hsl = function(h, s, l) { | |
return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l); | |
}; | |
function d3_hsl(h, s, l) { | |
return new d3_Hsl(h, s, l); | |
} | |
function d3_Hsl(h, s, l) { | |
this.h = h; | |
this.s = s; | |
this.l = l; | |
} | |
var d3_hslPrototype = d3_Hsl.prototype = new d3_Color(); | |
d3_hslPrototype.brighter = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return d3_hsl(this.h, this.s, this.l / k); | |
}; | |
d3_hslPrototype.darker = function(k) { | |
k = Math.pow(.7, arguments.length ? k : 1); | |
return d3_hsl(this.h, this.s, k * this.l); | |
}; | |
d3_hslPrototype.rgb = function() { | |
return d3_hsl_rgb(this.h, this.s, this.l); | |
}; | |
function d3_hsl_rgb(h, s, l) { | |
var m1, m2; | |
h = h % 360; | |
if (h < 0) h += 360; | |
s = s < 0 ? 0 : s > 1 ? 1 : s; | |
l = l < 0 ? 0 : l > 1 ? 1 : l; | |
m2 = l <= .5 ? l * (1 + s) : l + s - l * s; | |
m1 = 2 * l - m2; | |
function v(h) { | |
if (h > 360) h -= 360; else if (h < 0) h += 360; | |
if (h < 60) return m1 + (m2 - m1) * h / 60; | |
if (h < 180) return m2; | |
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; | |
return m1; | |
} | |
function vv(h) { | |
return Math.round(v(h) * 255); | |
} | |
return d3_rgb(vv(h + 120), vv(h), vv(h - 120)); | |
} | |
d3.hcl = function(h, c, l) { | |
return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l); | |
}; | |
function d3_hcl(h, c, l) { | |
return new d3_Hcl(h, c, l); | |
} | |
function d3_Hcl(h, c, l) { | |
this.h = h; | |
this.c = c; | |
this.l = l; | |
} | |
var d3_hclPrototype = d3_Hcl.prototype = new d3_Color(); | |
d3_hclPrototype.brighter = function(k) { | |
return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); | |
}; | |
d3_hclPrototype.darker = function(k) { | |
return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); | |
}; | |
d3_hclPrototype.rgb = function() { | |
return d3_hcl_lab(this.h, this.c, this.l).rgb(); | |
}; | |
function d3_hcl_lab(h, c, l) { | |
return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); | |
} | |
d3.lab = function(l, a, b) { | |
return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b); | |
}; | |
function d3_lab(l, a, b) { | |
return new d3_Lab(l, a, b); | |
} | |
function d3_Lab(l, a, b) { | |
this.l = l; | |
this.a = a; | |
this.b = b; | |
} | |
var d3_lab_K = 18; | |
var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; | |
var d3_labPrototype = d3_Lab.prototype = new d3_Color(); | |
d3_labPrototype.brighter = function(k) { | |
return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | |
}; | |
d3_labPrototype.darker = function(k) { | |
return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | |
}; | |
d3_labPrototype.rgb = function() { | |
return d3_lab_rgb(this.l, this.a, this.b); | |
}; | |
function d3_lab_rgb(l, a, b) { | |
var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; | |
x = d3_lab_xyz(x) * d3_lab_X; | |
y = d3_lab_xyz(y) * d3_lab_Y; | |
z = d3_lab_xyz(z) * d3_lab_Z; | |
return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); | |
} | |
function d3_lab_hcl(l, a, b) { | |
return d3_hcl(Math.atan2(b, a) / π * 180, Math.sqrt(a * a + b * b), l); | |
} | |
function d3_lab_xyz(x) { | |
return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; | |
} | |
function d3_xyz_lab(x) { | |
return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; | |
} | |
function d3_xyz_rgb(r) { | |
return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); | |
} | |
function d3_selection(groups) { | |
d3_arraySubclass(groups, d3_selectionPrototype); | |
return groups; | |
} | |
var d3_select = function(s, n) { | |
return n.querySelector(s); | |
}, d3_selectAll = function(s, n) { | |
return n.querySelectorAll(s); | |
}, d3_selectRoot = document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) { | |
return d3_selectMatcher.call(n, s); | |
}; | |
if (typeof Sizzle === "function") { | |
d3_select = function(s, n) { | |
return Sizzle(s, n)[0] || null; | |
}; | |
d3_selectAll = function(s, n) { | |
return Sizzle.uniqueSort(Sizzle(s, n)); | |
}; | |
d3_selectMatches = Sizzle.matchesSelector; | |
} | |
var d3_selectionPrototype = []; | |
d3.selection = function() { | |
return d3_selectionRoot; | |
}; | |
d3.selection.prototype = d3_selectionPrototype; | |
d3_selectionPrototype.select = function(selector) { | |
var subgroups = [], subgroup, subnode, group, node; | |
if (typeof selector !== "function") selector = d3_selection_selector(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = (group = this[j]).parentNode; | |
for (var i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroup.push(subnode = selector.call(node, node.__data__, i)); | |
if (subnode && "__data__" in node) subnode.__data__ = node.__data__; | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_selector(selector) { | |
return function() { | |
return d3_select(selector, this); | |
}; | |
} | |
d3_selectionPrototype.selectAll = function(selector) { | |
var subgroups = [], subgroup, node; | |
if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i))); | |
subgroup.parentNode = node; | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_selectorAll(selector) { | |
return function() { | |
return d3_selectAll(selector, this); | |
}; | |
} | |
d3_selectionPrototype.attr = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") { | |
var node = this.node(); | |
name = d3.ns.qualify(name); | |
return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); | |
} | |
for (value in name) this.each(d3_selection_attr(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_attr(name, value)); | |
}; | |
function d3_selection_attr(name, value) { | |
name = d3.ns.qualify(name); | |
function attrNull() { | |
this.removeAttribute(name); | |
} | |
function attrNullNS() { | |
this.removeAttributeNS(name.space, name.local); | |
} | |
function attrConstant() { | |
this.setAttribute(name, value); | |
} | |
function attrConstantNS() { | |
this.setAttributeNS(name.space, name.local, value); | |
} | |
function attrFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); | |
} | |
function attrFunctionNS() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); | |
} | |
return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; | |
} | |
d3_selectionPrototype.classed = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") { | |
var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1; | |
if (value = node.classList) { | |
while (++i < n) if (!value.contains(name[i])) return false; | |
} else { | |
value = node.className; | |
if (value.baseVal != null) value = value.baseVal; | |
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; | |
} | |
return true; | |
} | |
for (value in name) this.each(d3_selection_classed(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_classed(name, value)); | |
}; | |
function d3_selection_classedRe(name) { | |
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); | |
} | |
function d3_selection_classed(name, value) { | |
name = name.trim().split(/\s+/).map(d3_selection_classedName); | |
var n = name.length; | |
function classedConstant() { | |
var i = -1; | |
while (++i < n) name[i](this, value); | |
} | |
function classedFunction() { | |
var i = -1, x = value.apply(this, arguments); | |
while (++i < n) name[i](this, x); | |
} | |
return typeof value === "function" ? classedFunction : classedConstant; | |
} | |
function d3_selection_classedName(name) { | |
var re = d3_selection_classedRe(name); | |
return function(node, value) { | |
if (c = node.classList) return value ? c.add(name) : c.remove(name); | |
var c = node.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c; | |
if (value) { | |
re.lastIndex = 0; | |
if (!re.test(cv)) { | |
cv = d3_collapse(cv + " " + name); | |
if (cb) c.baseVal = cv; else node.className = cv; | |
} | |
} else if (cv) { | |
cv = d3_collapse(cv.replace(re, " ")); | |
if (cb) c.baseVal = cv; else node.className = cv; | |
} | |
}; | |
} | |
d3_selectionPrototype.style = function(name, value, priority) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof name !== "string") { | |
if (n < 2) value = ""; | |
for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); | |
return this; | |
} | |
if (n < 2) return getComputedStyle(this.node(), null).getPropertyValue(name); | |
priority = ""; | |
} | |
return this.each(d3_selection_style(name, value, priority)); | |
}; | |
function d3_selection_style(name, value, priority) { | |
function styleNull() { | |
this.style.removeProperty(name); | |
} | |
function styleConstant() { | |
this.style.setProperty(name, value, priority); | |
} | |
function styleFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); | |
} | |
return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; | |
} | |
d3_selectionPrototype.property = function(name, value) { | |
if (arguments.length < 2) { | |
if (typeof name === "string") return this.node()[name]; | |
for (value in name) this.each(d3_selection_property(value, name[value])); | |
return this; | |
} | |
return this.each(d3_selection_property(name, value)); | |
}; | |
function d3_selection_property(name, value) { | |
function propertyNull() { | |
delete this[name]; | |
} | |
function propertyConstant() { | |
this[name] = value; | |
} | |
function propertyFunction() { | |
var x = value.apply(this, arguments); | |
if (x == null) delete this[name]; else this[name] = x; | |
} | |
return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; | |
} | |
d3_selectionPrototype.text = function(value) { | |
return arguments.length ? this.each(typeof value === "function" ? function() { | |
var v = value.apply(this, arguments); | |
this.textContent = v == null ? "" : v; | |
} : value == null ? function() { | |
this.textContent = ""; | |
} : function() { | |
this.textContent = value; | |
}) : this.node().textContent; | |
}; | |
d3_selectionPrototype.html = function(value) { | |
return arguments.length ? this.each(typeof value === "function" ? function() { | |
var v = value.apply(this, arguments); | |
this.innerHTML = v == null ? "" : v; | |
} : value == null ? function() { | |
this.innerHTML = ""; | |
} : function() { | |
this.innerHTML = value; | |
}) : this.node().innerHTML; | |
}; | |
d3_selectionPrototype.append = function(name) { | |
name = d3.ns.qualify(name); | |
function append() { | |
return this.appendChild(document.createElementNS(this.namespaceURI, name)); | |
} | |
function appendNS() { | |
return this.appendChild(document.createElementNS(name.space, name.local)); | |
} | |
return this.select(name.local ? appendNS : append); | |
}; | |
d3_selectionPrototype.insert = function(name, before) { | |
name = d3.ns.qualify(name); | |
function insert() { | |
return this.insertBefore(document.createElementNS(this.namespaceURI, name), d3_select(before, this)); | |
} | |
function insertNS() { | |
return this.insertBefore(document.createElementNS(name.space, name.local), d3_select(before, this)); | |
} | |
return this.select(name.local ? insertNS : insert); | |
}; | |
d3_selectionPrototype.remove = function() { | |
return this.each(function() { | |
var parent = this.parentNode; | |
if (parent) parent.removeChild(this); | |
}); | |
}; | |
d3_selectionPrototype.data = function(value, key) { | |
var i = -1, n = this.length, group, node; | |
if (!arguments.length) { | |
value = new Array(n = (group = this[0]).length); | |
while (++i < n) { | |
if (node = group[i]) { | |
value[i] = node.__data__; | |
} | |
} | |
return value; | |
} | |
function bind(group, groupData) { | |
var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), n1 = Math.max(n, m), updateNodes = [], enterNodes = [], exitNodes = [], node, nodeData; | |
if (key) { | |
var nodeByKeyValue = new d3_Map(), keyValues = [], keyValue, j = groupData.length; | |
for (i = -1; ++i < n; ) { | |
keyValue = key.call(node = group[i], node.__data__, i); | |
if (nodeByKeyValue.has(keyValue)) { | |
exitNodes[j++] = node; | |
} else { | |
nodeByKeyValue.set(keyValue, node); | |
} | |
keyValues.push(keyValue); | |
} | |
for (i = -1; ++i < m; ) { | |
keyValue = key.call(groupData, nodeData = groupData[i], i); | |
if (nodeByKeyValue.has(keyValue)) { | |
updateNodes[i] = node = nodeByKeyValue.get(keyValue); | |
node.__data__ = nodeData; | |
enterNodes[i] = exitNodes[i] = null; | |
} else { | |
enterNodes[i] = d3_selection_dataNode(nodeData); | |
updateNodes[i] = exitNodes[i] = null; | |
} | |
nodeByKeyValue.remove(keyValue); | |
} | |
for (i = -1; ++i < n; ) { | |
if (nodeByKeyValue.has(keyValues[i])) { | |
exitNodes[i] = group[i]; | |
} | |
} | |
} else { | |
for (i = -1; ++i < n0; ) { | |
node = group[i]; | |
nodeData = groupData[i]; | |
if (node) { | |
node.__data__ = nodeData; | |
updateNodes[i] = node; | |
enterNodes[i] = exitNodes[i] = null; | |
} else { | |
enterNodes[i] = d3_selection_dataNode(nodeData); | |
updateNodes[i] = exitNodes[i] = null; | |
} | |
} | |
for (;i < m; ++i) { | |
enterNodes[i] = d3_selection_dataNode(groupData[i]); | |
updateNodes[i] = exitNodes[i] = null; | |
} | |
for (;i < n1; ++i) { | |
exitNodes[i] = group[i]; | |
enterNodes[i] = updateNodes[i] = null; | |
} | |
} | |
enterNodes.update = updateNodes; | |
enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; | |
enter.push(enterNodes); | |
update.push(updateNodes); | |
exit.push(exitNodes); | |
} | |
var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); | |
if (typeof value === "function") { | |
while (++i < n) { | |
bind(group = this[i], value.call(group, group.parentNode.__data__, i)); | |
} | |
} else { | |
while (++i < n) { | |
bind(group = this[i], value); | |
} | |
} | |
update.enter = function() { | |
return enter; | |
}; | |
update.exit = function() { | |
return exit; | |
}; | |
return update; | |
}; | |
function d3_selection_dataNode(data) { | |
return { | |
__data__: data | |
}; | |
} | |
d3_selectionPrototype.datum = function(value) { | |
return arguments.length ? this.property("__data__", value) : this.property("__data__"); | |
}; | |
d3_selectionPrototype.filter = function(filter) { | |
var subgroups = [], subgroup, group, node; | |
if (typeof filter !== "function") filter = d3_selection_filter(filter); | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = (group = this[j]).parentNode; | |
for (var i = 0, n = group.length; i < n; i++) { | |
if ((node = group[i]) && filter.call(node, node.__data__, i)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_selection_filter(selector) { | |
return function() { | |
return d3_selectMatches(this, selector); | |
}; | |
} | |
d3_selectionPrototype.order = function() { | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[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; | |
}; | |
d3_selectionPrototype.sort = function(comparator) { | |
comparator = d3_selection_sortComparator.apply(this, arguments); | |
for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); | |
return this.order(); | |
}; | |
function d3_selection_sortComparator(comparator) { | |
if (!arguments.length) comparator = d3.ascending; | |
return function(a, b) { | |
return comparator(a && a.__data__, b && b.__data__); | |
}; | |
} | |
d3_selectionPrototype.on = function(type, listener, capture) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof type !== "string") { | |
if (n < 2) listener = false; | |
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); | |
return this; | |
} | |
if (n < 2) return (n = this.node()["__on" + type]) && n._; | |
capture = false; | |
} | |
return this.each(d3_selection_on(type, listener, capture)); | |
}; | |
function d3_selection_on(type, listener, capture) { | |
var name = "__on" + type, i = type.indexOf("."); | |
if (i > 0) type = type.substring(0, i); | |
function onRemove() { | |
var wrapper = this[name]; | |
if (wrapper) { | |
this.removeEventListener(type, wrapper, wrapper.$); | |
delete this[name]; | |
} | |
} | |
function onAdd() { | |
var node = this, args = d3_array(arguments); | |
onRemove.call(this); | |
this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture); | |
wrapper._ = listener; | |
function wrapper(e) { | |
var o = d3.event; | |
d3.event = e; | |
args[0] = node.__data__; | |
try { | |
listener.apply(node, args); | |
} finally { | |
d3.event = o; | |
} | |
} | |
} | |
return listener ? onAdd : onRemove; | |
} | |
d3_selectionPrototype.each = function(callback) { | |
return d3_selection_each(this, function(node, i, j) { | |
callback.call(node, node.__data__, i, j); | |
}); | |
}; | |
function d3_selection_each(groups, callback) { | |
for (var 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(node, i, j); | |
} | |
} | |
return groups; | |
} | |
d3_selectionPrototype.call = function(callback) { | |
var args = d3_array(arguments); | |
callback.apply(args[0] = this, args); | |
return this; | |
}; | |
d3_selectionPrototype.empty = function() { | |
return !this.node(); | |
}; | |
d3_selectionPrototype.node = function() { | |
for (var j = 0, m = this.length; j < m; j++) { | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
var node = group[i]; | |
if (node) return node; | |
} | |
} | |
return null; | |
}; | |
d3_selectionPrototype.transition = function() { | |
var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit); | |
transition.time = Date.now(); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) d3_transitionNode(node, i, id, transition); | |
subgroup.push(node); | |
} | |
} | |
return d3_transition(subgroups, id); | |
}; | |
var d3_selectionRoot = d3_selection([ [ document ] ]); | |
d3_selectionRoot[0].parentNode = d3_selectRoot; | |
d3.select = function(selector) { | |
return typeof selector === "string" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]); | |
}; | |
d3.selectAll = function(selector) { | |
return typeof selector === "string" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]); | |
}; | |
function d3_selection_enter(selection) { | |
d3_arraySubclass(selection, d3_selection_enterPrototype); | |
return selection; | |
} | |
var d3_selection_enterPrototype = []; | |
d3.selection.enter = d3_selection_enter; | |
d3.selection.enter.prototype = d3_selection_enterPrototype; | |
d3_selection_enterPrototype.append = d3_selectionPrototype.append; | |
d3_selection_enterPrototype.insert = d3_selectionPrototype.insert; | |
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; | |
d3_selection_enterPrototype.node = d3_selectionPrototype.node; | |
d3_selection_enterPrototype.select = function(selector) { | |
var subgroups = [], subgroup, subnode, upgroup, group, node; | |
for (var j = -1, m = this.length; ++j < m; ) { | |
upgroup = (group = this[j]).update; | |
subgroups.push(subgroup = []); | |
subgroup.parentNode = group.parentNode; | |
for (var i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i)); | |
subnode.__data__ = node.__data__; | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_selection(subgroups); | |
}; | |
function d3_transition(groups, id) { | |
d3_arraySubclass(groups, d3_transitionPrototype); | |
groups.id = id; | |
return groups; | |
} | |
var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = { | |
ease: d3_ease_cubicInOut, | |
delay: 0, | |
duration: 250 | |
}; | |
d3_transitionPrototype.call = d3_selectionPrototype.call; | |
d3_transitionPrototype.empty = d3_selectionPrototype.empty; | |
d3_transitionPrototype.node = d3_selectionPrototype.node; | |
d3.transition = function(selection) { | |
return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition(); | |
}; | |
d3.transition.prototype = d3_transitionPrototype; | |
function d3_transitionNode(node, i, id, inherit) { | |
var lock = node.__transition__ || (node.__transition__ = { | |
active: 0, | |
count: 0 | |
}), transition = lock[id]; | |
if (!transition) { | |
var time = inherit.time; | |
transition = lock[id] = { | |
tween: new d3_Map(), | |
event: d3.dispatch("start", "end"), | |
time: time, | |
ease: inherit.ease, | |
delay: inherit.delay, | |
duration: inherit.duration | |
}; | |
++lock.count; | |
d3.timer(function(elapsed) { | |
var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = []; | |
return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1; | |
function start(elapsed) { | |
if (lock.active > id) return stop(); | |
lock.active = id; | |
event.start.call(node, d, i); | |
transition.tween.forEach(function(key, value) { | |
if (value = value.call(node, d, i)) { | |
tweened.push(value); | |
} | |
}); | |
if (!tick(elapsed)) d3.timer(tick, 0, time); | |
return 1; | |
} | |
function tick(elapsed) { | |
if (lock.active !== id) return stop(); | |
var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length; | |
while (n > 0) { | |
tweened[--n].call(node, e); | |
} | |
if (t >= 1) { | |
stop(); | |
event.end.call(node, d, i); | |
return 1; | |
} | |
} | |
function stop() { | |
if (--lock.count) delete lock[id]; else delete node.__transition__; | |
return 1; | |
} | |
}, 0, time); | |
return transition; | |
} | |
} | |
d3_transitionPrototype.select = function(selector) { | |
var id = this.id, subgroups = [], subgroup, subnode, node; | |
if (typeof selector !== "function") selector = d3_selection_selector(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i))) { | |
if ("__data__" in node) subnode.__data__ = node.__data__; | |
d3_transitionNode(subnode, i, id, node.__transition__[id]); | |
subgroup.push(subnode); | |
} else { | |
subgroup.push(null); | |
} | |
} | |
} | |
return d3_transition(subgroups, id); | |
}; | |
d3_transitionPrototype.selectAll = function(selector) { | |
var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition; | |
if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); | |
for (var j = -1, m = this.length; ++j < m; ) { | |
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { | |
if (node = group[i]) { | |
transition = node.__transition__[id]; | |
subnodes = selector.call(node, node.__data__, i); | |
subgroups.push(subgroup = []); | |
for (var k = -1, o = subnodes.length; ++k < o; ) { | |
d3_transitionNode(subnode = subnodes[k], k, id, transition); | |
subgroup.push(subnode); | |
} | |
} | |
} | |
} | |
return d3_transition(subgroups, id); | |
}; | |
d3_transitionPrototype.filter = function(filter) { | |
var subgroups = [], subgroup, group, node; | |
if (typeof filter !== "function") filter = d3_selection_filter(filter); | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
if ((node = group[i]) && filter.call(node, node.__data__, i)) { | |
subgroup.push(node); | |
} | |
} | |
} | |
return d3_transition(subgroups, this.id, this.time).ease(this.ease()); | |
}; | |
d3_transitionPrototype.attr = function(nameNS, value) { | |
if (arguments.length < 2) { | |
for (value in nameNS) this.attr(value, nameNS[value]); | |
return this; | |
} | |
var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS); | |
function attrNull() { | |
this.removeAttribute(name); | |
} | |
function attrNullNS() { | |
this.removeAttributeNS(name.space, name.local); | |
} | |
return d3_transition_tween(this, "attr." + nameNS, value, function(b) { | |
function attrString() { | |
var a = this.getAttribute(name), i; | |
return a !== b && (i = interpolate(a, b), function(t) { | |
this.setAttribute(name, i(t)); | |
}); | |
} | |
function attrStringNS() { | |
var a = this.getAttributeNS(name.space, name.local), i; | |
return a !== b && (i = interpolate(a, b), function(t) { | |
this.setAttributeNS(name.space, name.local, i(t)); | |
}); | |
} | |
return b == null ? name.local ? attrNullNS : attrNull : (b += "", name.local ? attrStringNS : attrString); | |
}); | |
}; | |
d3_transitionPrototype.attrTween = function(nameNS, tween) { | |
var name = d3.ns.qualify(nameNS); | |
function attrTween(d, i) { | |
var f = tween.call(this, d, i, this.getAttribute(name)); | |
return f && function(t) { | |
this.setAttribute(name, f(t)); | |
}; | |
} | |
function attrTweenNS(d, i) { | |
var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); | |
return f && function(t) { | |
this.setAttributeNS(name.space, name.local, f(t)); | |
}; | |
} | |
return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); | |
}; | |
d3_transitionPrototype.style = function(name, value, priority) { | |
var n = arguments.length; | |
if (n < 3) { | |
if (typeof name !== "string") { | |
if (n < 2) value = ""; | |
for (priority in name) this.style(priority, name[priority], value); | |
return this; | |
} | |
priority = ""; | |
} | |
var interpolate = d3_interpolateByName(name); | |
function styleNull() { | |
this.style.removeProperty(name); | |
} | |
return d3_transition_tween(this, "style." + name, value, function(b) { | |
function styleString() { | |
var a = getComputedStyle(this, null).getPropertyValue(name), i; | |
return a !== b && (i = interpolate(a, b), function(t) { | |
this.style.setProperty(name, i(t), priority); | |
}); | |
} | |
return b == null ? styleNull : (b += "", styleString); | |
}); | |
}; | |
d3_transitionPrototype.styleTween = function(name, tween, priority) { | |
if (arguments.length < 3) priority = ""; | |
return this.tween("style." + name, function(d, i) { | |
var f = tween.call(this, d, i, getComputedStyle(this, null).getPropertyValue(name)); | |
return f && function(t) { | |
this.style.setProperty(name, f(t), priority); | |
}; | |
}); | |
}; | |
d3_transitionPrototype.text = function(value) { | |
return d3_transition_tween(this, "text", value, d3_transition_text); | |
}; | |
function d3_transition_text(b) { | |
if (b == null) b = ""; | |
return function() { | |
this.textContent = b; | |
}; | |
} | |
d3_transitionPrototype.remove = function() { | |
return this.each("end.transition", function() { | |
var p; | |
if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this); | |
}); | |
}; | |
d3_transitionPrototype.ease = function(value) { | |
var id = this.id; | |
if (arguments.length < 1) return this.node().__transition__[id].ease; | |
if (typeof value !== "function") value = d3.ease.apply(d3, arguments); | |
return d3_selection_each(this, function(node) { | |
node.__transition__[id].ease = value; | |
}); | |
}; | |
d3_transitionPrototype.delay = function(value) { | |
var id = this.id; | |
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { | |
node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0; | |
} : (value |= 0, function(node) { | |
node.__transition__[id].delay = value; | |
})); | |
}; | |
d3_transitionPrototype.duration = function(value) { | |
var id = this.id; | |
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { | |
node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0); | |
} : (value = Math.max(1, value | 0), function(node) { | |
node.__transition__[id].duration = value; | |
})); | |
}; | |
d3_transitionPrototype.each = function(type, listener) { | |
var id = this.id; | |
if (arguments.length < 2) { | |
var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; | |
d3_transitionInheritId = id; | |
d3_selection_each(this, function(node, i, j) { | |
d3_transitionInherit = node.__transition__[id]; | |
type.call(node, node.__data__, i, j); | |
}); | |
d3_transitionInherit = inherit; | |
d3_transitionInheritId = inheritId; | |
} else { | |
d3_selection_each(this, function(node) { | |
node.__transition__[id].event.on(type, listener); | |
}); | |
} | |
return this; | |
}; | |
d3_transitionPrototype.transition = function() { | |
var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition; | |
for (var j = 0, m = this.length; j < m; j++) { | |
subgroups.push(subgroup = []); | |
for (var group = this[j], i = 0, n = group.length; i < n; i++) { | |
if (node = group[i]) { | |
transition = Object.create(node.__transition__[id0]); | |
transition.delay += transition.duration; | |
d3_transitionNode(node, i, id1, transition); | |
} | |
subgroup.push(node); | |
} | |
} | |
return d3_transition(subgroups, id1); | |
}; | |
d3_transitionPrototype.tween = function(name, tween) { | |
var id = this.id; | |
if (arguments.length < 2) return this.node().__transition__[id].tween.get(name); | |
return d3_selection_each(this, tween == null ? function(node) { | |
node.__transition__[id].tween.remove(name); | |
} : function(node) { | |
node.__transition__[id].tween.set(name, tween); | |
}); | |
}; | |
function d3_transition_tween(groups, name, value, tween) { | |
var id = groups.id; | |
return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { | |
node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); | |
} : (value = tween(value), function(node) { | |
node.__transition__[id].tween.set(name, value); | |
})); | |
} | |
var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout; | |
d3.timer = function(callback, delay, then) { | |
if (arguments.length < 3) { | |
if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return; | |
then = Date.now(); | |
} | |
var timer = d3_timer_byId[callback.id]; | |
if (timer && timer.callback === callback) { | |
timer.then = then; | |
timer.delay = delay; | |
} else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = { | |
callback: callback, | |
then: then, | |
delay: delay, | |
next: d3_timer_queue | |
}; | |
if (!d3_timer_interval) { | |
d3_timer_timeout = clearTimeout(d3_timer_timeout); | |
d3_timer_interval = 1; | |
d3_timer_frame(d3_timer_step); | |
} | |
}; | |
function d3_timer_step() { | |
var elapsed, now = Date.now(), t1 = d3_timer_queue; | |
while (t1) { | |
elapsed = now - t1.then; | |
if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed); | |
t1 = t1.next; | |
} | |
var delay = d3_timer_flush() - now; | |
if (delay > 24) { | |
if (isFinite(delay)) { | |
clearTimeout(d3_timer_timeout); | |
d3_timer_timeout = setTimeout(d3_timer_step, delay); | |
} | |
d3_timer_interval = 0; | |
} else { | |
d3_timer_interval = 1; | |
d3_timer_frame(d3_timer_step); | |
} | |
} | |
d3.timer.flush = function() { | |
var elapsed, now = Date.now(), t1 = d3_timer_queue; | |
while (t1) { | |
elapsed = now - t1.then; | |
if (!t1.delay) t1.flush = t1.callback(elapsed); | |
t1 = t1.next; | |
} | |
d3_timer_flush(); | |
}; | |
function d3_timer_flush() { | |
var t0 = null, t1 = d3_timer_queue, then = Infinity; | |
while (t1) { | |
if (t1.flush) { | |
delete d3_timer_byId[t1.callback.id]; | |
t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next; | |
} else { | |
then = Math.min(then, t1.then + t1.delay); | |
t1 = (t0 = t1).next; | |
} | |
} | |
return then; | |
} | |
var d3_timer_frame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { | |
setTimeout(callback, 17); | |
}; | |
d3.mouse = function(container) { | |
return d3_mousePoint(container, d3_eventSource()); | |
}; | |
var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; | |
function d3_mousePoint(container, e) { | |
var svg = container.ownerSVGElement || container; | |
if (svg.createSVGPoint) { | |
var point = svg.createSVGPoint(); | |
if (d3_mouse_bug44083 < 0 && (window.scrollX || window.scrollY)) { | |
svg = d3.select(document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0); | |
var ctm = svg[0][0].getScreenCTM(); | |
d3_mouse_bug44083 = !(ctm.f || ctm.e); | |
svg.remove(); | |
} | |
if (d3_mouse_bug44083) { | |
point.x = e.pageX; | |
point.y = e.pageY; | |
} else { | |
point.x = e.clientX; | |
point.y = e.clientY; | |
} | |
point = point.matrixTransform(container.getScreenCTM().inverse()); | |
return [ point.x, point.y ]; | |
} | |
var rect = container.getBoundingClientRect(); | |
return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; | |
} | |
d3.touches = function(container, touches) { | |
if (arguments.length < 2) touches = d3_eventSource().touches; | |
return touches ? d3_array(touches).map(function(touch) { | |
var point = d3_mousePoint(container, touch); | |
point.identifier = touch.identifier; | |
return point; | |
}) : []; | |
}; | |
function d3_noop() {} | |
d3.scale = {}; | |
function d3_scaleExtent(domain) { | |
var start = domain[0], stop = domain[domain.length - 1]; | |
return start < stop ? [ start, stop ] : [ stop, start ]; | |
} | |
function d3_scaleRange(scale) { | |
return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); | |
} | |
function d3_scale_nice(domain, nice) { | |
var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; | |
if (x1 < x0) { | |
dx = i0, i0 = i1, i1 = dx; | |
dx = x0, x0 = x1, x1 = dx; | |
} | |
if (nice = nice(x1 - x0)) { | |
domain[i0] = nice.floor(x0); | |
domain[i1] = nice.ceil(x1); | |
} | |
return domain; | |
} | |
function d3_scale_niceDefault() { | |
return Math; | |
} | |
d3.scale.linear = function() { | |
return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3.interpolate, false); | |
}; | |
function d3_scale_linear(domain, range, interpolate, clamp) { | |
var output, input; | |
function rescale() { | |
var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; | |
output = linear(domain, range, uninterpolate, interpolate); | |
input = linear(range, domain, uninterpolate, d3.interpolate); | |
return scale; | |
} | |
function scale(x) { | |
return output(x); | |
} | |
scale.invert = function(y) { | |
return input(y); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.map(Number); | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.rangeRound = function(x) { | |
return scale.range(x).interpolate(d3.interpolateRound); | |
}; | |
scale.clamp = function(x) { | |
if (!arguments.length) return clamp; | |
clamp = x; | |
return rescale(); | |
}; | |
scale.interpolate = function(x) { | |
if (!arguments.length) return interpolate; | |
interpolate = x; | |
return rescale(); | |
}; | |
scale.ticks = function(m) { | |
return d3_scale_linearTicks(domain, m); | |
}; | |
scale.tickFormat = function(m) { | |
return d3_scale_linearTickFormat(domain, m); | |
}; | |
scale.nice = function() { | |
d3_scale_nice(domain, d3_scale_linearNice); | |
return rescale(); | |
}; | |
scale.copy = function() { | |
return d3_scale_linear(domain, range, interpolate, clamp); | |
}; | |
return rescale(); | |
} | |
function d3_scale_linearRebind(scale, linear) { | |
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); | |
} | |
function d3_scale_linearNice(dx) { | |
dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1); | |
return dx && { | |
floor: function(x) { | |
return Math.floor(x / dx) * dx; | |
}, | |
ceil: function(x) { | |
return Math.ceil(x / dx) * dx; | |
} | |
}; | |
} | |
function d3_scale_linearTickRange(domain, m) { | |
var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; | |
if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; | |
extent[0] = Math.ceil(extent[0] / step) * step; | |
extent[1] = Math.floor(extent[1] / step) * step + step * .5; | |
extent[2] = step; | |
return extent; | |
} | |
function d3_scale_linearTicks(domain, m) { | |
return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); | |
} | |
function d3_scale_linearTickFormat(domain, m) { | |
return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f"); | |
} | |
function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { | |
var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); | |
return function(x) { | |
return i(u(x)); | |
}; | |
} | |
function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { | |
var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; | |
if (domain[k] < domain[0]) { | |
domain = domain.slice().reverse(); | |
range = range.slice().reverse(); | |
} | |
while (++j <= k) { | |
u.push(uninterpolate(domain[j - 1], domain[j])); | |
i.push(interpolate(range[j - 1], range[j])); | |
} | |
return function(x) { | |
var j = d3.bisect(domain, x, 1, k) - 1; | |
return i[j](u[j](x)); | |
}; | |
} | |
d3.scale.log = function() { | |
return d3_scale_log(d3.scale.linear(), d3_scale_logp); | |
}; | |
function d3_scale_log(linear, log) { | |
var pow = log.pow; | |
function scale(x) { | |
return linear(log(x)); | |
} | |
scale.invert = function(x) { | |
return pow(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return linear.domain().map(pow); | |
log = x[0] < 0 ? d3_scale_logn : d3_scale_logp; | |
pow = log.pow; | |
linear.domain(x.map(log)); | |
return scale; | |
}; | |
scale.nice = function() { | |
linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault)); | |
return scale; | |
}; | |
scale.ticks = function() { | |
var extent = d3_scaleExtent(linear.domain()), ticks = []; | |
if (extent.every(isFinite)) { | |
var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]); | |
if (log === d3_scale_logn) { | |
ticks.push(pow(i)); | |
for (;i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k); | |
} else { | |
for (;i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k); | |
ticks.push(pow(i)); | |
} | |
for (i = 0; ticks[i] < u; i++) {} | |
for (j = ticks.length; ticks[j - 1] > v; j--) {} | |
ticks = ticks.slice(i, j); | |
} | |
return ticks; | |
}; | |
scale.tickFormat = function(n, format) { | |
if (arguments.length < 2) format = d3_scale_logFormat; | |
if (!arguments.length) return format; | |
var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12, | |
Math.floor) : (e = 1e-12, Math.ceil), e; | |
return function(d) { | |
return d / pow(f(log(d) + e)) <= k ? format(d) : ""; | |
}; | |
}; | |
scale.copy = function() { | |
return d3_scale_log(linear.copy(), log); | |
}; | |
return d3_scale_linearRebind(scale, linear); | |
} | |
var d3_scale_logFormat = d3.format(".0e"); | |
function d3_scale_logp(x) { | |
return Math.log(x < 0 ? 0 : x) / Math.LN10; | |
} | |
function d3_scale_logn(x) { | |
return -Math.log(x > 0 ? 0 : -x) / Math.LN10; | |
} | |
d3_scale_logp.pow = function(x) { | |
return Math.pow(10, x); | |
}; | |
d3_scale_logn.pow = function(x) { | |
return -Math.pow(10, -x); | |
}; | |
d3.scale.pow = function() { | |
return d3_scale_pow(d3.scale.linear(), 1); | |
}; | |
function d3_scale_pow(linear, exponent) { | |
var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); | |
function scale(x) { | |
return linear(powp(x)); | |
} | |
scale.invert = function(x) { | |
return powb(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return linear.domain().map(powb); | |
linear.domain(x.map(powp)); | |
return scale; | |
}; | |
scale.ticks = function(m) { | |
return d3_scale_linearTicks(scale.domain(), m); | |
}; | |
scale.tickFormat = function(m) { | |
return d3_scale_linearTickFormat(scale.domain(), m); | |
}; | |
scale.nice = function() { | |
return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice)); | |
}; | |
scale.exponent = function(x) { | |
if (!arguments.length) return exponent; | |
var domain = scale.domain(); | |
powp = d3_scale_powPow(exponent = x); | |
powb = d3_scale_powPow(1 / exponent); | |
return scale.domain(domain); | |
}; | |
scale.copy = function() { | |
return d3_scale_pow(linear.copy(), exponent); | |
}; | |
return d3_scale_linearRebind(scale, linear); | |
} | |
function d3_scale_powPow(e) { | |
return function(x) { | |
return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); | |
}; | |
} | |
d3.scale.sqrt = function() { | |
return d3.scale.pow().exponent(.5); | |
}; | |
d3.scale.ordinal = function() { | |
return d3_scale_ordinal([], { | |
t: "range", | |
a: [ [] ] | |
}); | |
}; | |
function d3_scale_ordinal(domain, ranger) { | |
var index, range, rangeBand; | |
function scale(x) { | |
return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length]; | |
} | |
function steps(start, step) { | |
return d3.range(domain.length).map(function(i) { | |
return start + step * i; | |
}); | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = []; | |
index = new d3_Map(); | |
var i = -1, n = x.length, xi; | |
while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); | |
return scale[ranger.t].apply(scale, ranger.a); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
rangeBand = 0; | |
ranger = { | |
t: "range", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangePoints = function(x, padding) { | |
if (arguments.length < 2) padding = 0; | |
var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding); | |
range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); | |
rangeBand = 0; | |
ranger = { | |
t: "rangePoints", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeBands = function(x, padding, outerPadding) { | |
if (arguments.length < 2) padding = 0; | |
if (arguments.length < 3) outerPadding = padding; | |
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); | |
range = steps(start + step * outerPadding, step); | |
if (reverse) range.reverse(); | |
rangeBand = step * (1 - padding); | |
ranger = { | |
t: "rangeBands", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeRoundBands = function(x, padding, outerPadding) { | |
if (arguments.length < 2) padding = 0; | |
if (arguments.length < 3) outerPadding = padding; | |
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step; | |
range = steps(start + Math.round(error / 2), step); | |
if (reverse) range.reverse(); | |
rangeBand = Math.round(step * (1 - padding)); | |
ranger = { | |
t: "rangeRoundBands", | |
a: arguments | |
}; | |
return scale; | |
}; | |
scale.rangeBand = function() { | |
return rangeBand; | |
}; | |
scale.rangeExtent = function() { | |
return d3_scaleExtent(ranger.a[0]); | |
}; | |
scale.copy = function() { | |
return d3_scale_ordinal(domain, ranger); | |
}; | |
return scale.domain(domain); | |
} | |
d3.scale.category10 = function() { | |
return d3.scale.ordinal().range(d3_category10); | |
}; | |
d3.scale.category20 = function() { | |
return d3.scale.ordinal().range(d3_category20); | |
}; | |
d3.scale.category20b = function() { | |
return d3.scale.ordinal().range(d3_category20b); | |
}; | |
d3.scale.category20c = function() { | |
return d3.scale.ordinal().range(d3_category20c); | |
}; | |
var d3_category10 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ]; | |
var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ]; | |
var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ]; | |
var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ]; | |
d3.scale.quantile = function() { | |
return d3_scale_quantile([], []); | |
}; | |
function d3_scale_quantile(domain, range) { | |
var thresholds; | |
function rescale() { | |
var k = 0, q = range.length; | |
thresholds = []; | |
while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); | |
return scale; | |
} | |
function scale(x) { | |
if (isNaN(x = +x)) return NaN; | |
return range[d3.bisect(thresholds, x)]; | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.filter(function(d) { | |
return !isNaN(d); | |
}).sort(d3.ascending); | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.quantiles = function() { | |
return thresholds; | |
}; | |
scale.copy = function() { | |
return d3_scale_quantile(domain, range); | |
}; | |
return rescale(); | |
} | |
d3.scale.quantize = function() { | |
return d3_scale_quantize(0, 1, [ 0, 1 ]); | |
}; | |
function d3_scale_quantize(x0, x1, range) { | |
var kx, i; | |
function scale(x) { | |
return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; | |
} | |
function rescale() { | |
kx = range.length / (x1 - x0); | |
i = range.length - 1; | |
return scale; | |
} | |
scale.domain = function(x) { | |
if (!arguments.length) return [ x0, x1 ]; | |
x0 = +x[0]; | |
x1 = +x[x.length - 1]; | |
return rescale(); | |
}; | |
scale.range = function(x) { | |
if (!arguments.length) return range; | |
range = x; | |
return rescale(); | |
}; | |
scale.copy = function() { | |
return d3_scale_quantize(x0, x1, range); | |
}; | |
return rescale(); | |
} | |
d3.scale.threshold = function() { | |
return d3_scale_threshold([ .5 ], [ 0, 1 ]); | |
}; | |
function d3_scale_threshold(domain, range) { | |
function scale(x) { | |
return range[d3.bisect(domain, x)]; | |
} | |
scale.domain = function(_) { | |
if (!arguments.length) return domain; | |
domain = _; | |
return scale; | |
}; | |
scale.range = function(_) { | |
if (!arguments.length) return range; | |
range = _; | |
return scale; | |
}; | |
scale.copy = function() { | |
return d3_scale_threshold(domain, range); | |
}; | |
return scale; | |
} | |
d3.scale.identity = function() { | |
return d3_scale_identity([ 0, 1 ]); | |
}; | |
function d3_scale_identity(domain) { | |
function identity(x) { | |
return +x; | |
} | |
identity.invert = identity; | |
identity.domain = identity.range = function(x) { | |
if (!arguments.length) return domain; | |
domain = x.map(identity); | |
return identity; | |
}; | |
identity.ticks = function(m) { | |
return d3_scale_linearTicks(domain, m); | |
}; | |
identity.tickFormat = function(m) { | |
return d3_scale_linearTickFormat(domain, m); | |
}; | |
identity.copy = function() { | |
return d3_scale_identity(domain); | |
}; | |
return identity; | |
} | |
d3.svg = {}; | |
d3.svg.arc = function() { | |
var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; | |
function arc() { | |
var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, | |
a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1); | |
return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z"; | |
} | |
arc.innerRadius = function(v) { | |
if (!arguments.length) return innerRadius; | |
innerRadius = d3_functor(v); | |
return arc; | |
}; | |
arc.outerRadius = function(v) { | |
if (!arguments.length) return outerRadius; | |
outerRadius = d3_functor(v); | |
return arc; | |
}; | |
arc.startAngle = function(v) { | |
if (!arguments.length) return startAngle; | |
startAngle = d3_functor(v); | |
return arc; | |
}; | |
arc.endAngle = function(v) { | |
if (!arguments.length) return endAngle; | |
endAngle = d3_functor(v); | |
return arc; | |
}; | |
arc.centroid = function() { | |
var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; | |
return [ Math.cos(a) * r, Math.sin(a) * r ]; | |
}; | |
return arc; | |
}; | |
var d3_svg_arcOffset = -π / 2, d3_svg_arcMax = 2 * π - 1e-6; | |
function d3_svg_arcInnerRadius(d) { | |
return d.innerRadius; | |
} | |
function d3_svg_arcOuterRadius(d) { | |
return d.outerRadius; | |
} | |
function d3_svg_arcStartAngle(d) { | |
return d.startAngle; | |
} | |
function d3_svg_arcEndAngle(d) { | |
return d.endAngle; | |
} | |
function d3_svg_line(projection) { | |
var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; | |
function line(data) { | |
var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); | |
function segment() { | |
segments.push("M", interpolate(projection(points), tension)); | |
} | |
while (++i < n) { | |
if (defined.call(this, d = data[i], i)) { | |
points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); | |
} else if (points.length) { | |
segment(); | |
points = []; | |
} | |
} | |
if (points.length) segment(); | |
return segments.length ? segments.join("") : null; | |
} | |
line.x = function(_) { | |
if (!arguments.length) return x; | |
x = _; | |
return line; | |
}; | |
line.y = function(_) { | |
if (!arguments.length) return y; | |
y = _; | |
return line; | |
}; | |
line.defined = function(_) { | |
if (!arguments.length) return defined; | |
defined = _; | |
return line; | |
}; | |
line.interpolate = function(_) { | |
if (!arguments.length) return interpolateKey; | |
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; | |
return line; | |
}; | |
line.tension = function(_) { | |
if (!arguments.length) return tension; | |
tension = _; | |
return line; | |
}; | |
return line; | |
} | |
d3.svg.line = function() { | |
return d3_svg_line(d3_identity); | |
}; | |
function d3_svg_lineX(d) { | |
return d[0]; | |
} | |
function d3_svg_lineY(d) { | |
return d[1]; | |
} | |
var d3_svg_lineInterpolators = d3.map({ | |
linear: d3_svg_lineLinear, | |
"linear-closed": d3_svg_lineLinearClosed, | |
"step-before": d3_svg_lineStepBefore, | |
"step-after": d3_svg_lineStepAfter, | |
basis: d3_svg_lineBasis, | |
"basis-open": d3_svg_lineBasisOpen, | |
"basis-closed": d3_svg_lineBasisClosed, | |
bundle: d3_svg_lineBundle, | |
cardinal: d3_svg_lineCardinal, | |
"cardinal-open": d3_svg_lineCardinalOpen, | |
"cardinal-closed": d3_svg_lineCardinalClosed, | |
monotone: d3_svg_lineMonotone | |
}); | |
d3_svg_lineInterpolators.forEach(function(key, value) { | |
value.key = key; | |
value.closed = /-closed$/.test(key); | |
}); | |
function d3_svg_lineLinear(points) { | |
return points.join("L"); | |
} | |
function d3_svg_lineLinearClosed(points) { | |
return d3_svg_lineLinear(points) + "Z"; | |
} | |
function d3_svg_lineStepBefore(points) { | |
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; | |
while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); | |
return path.join(""); | |
} | |
function d3_svg_lineStepAfter(points) { | |
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; | |
while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); | |
return path.join(""); | |
} | |
function d3_svg_lineCardinalOpen(points, tension) { | |
return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension)); | |
} | |
function d3_svg_lineCardinalClosed(points, tension) { | |
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), | |
points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); | |
} | |
function d3_svg_lineCardinal(points, tension) { | |
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); | |
} | |
function d3_svg_lineHermite(points, tangents) { | |
if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { | |
return d3_svg_lineLinear(points); | |
} | |
var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; | |
if (quad) { | |
path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; | |
p0 = points[1]; | |
pi = 2; | |
} | |
if (tangents.length > 1) { | |
t = tangents[1]; | |
p = points[pi]; | |
pi++; | |
path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; | |
for (var i = 2; i < tangents.length; i++, pi++) { | |
p = points[pi]; | |
t = tangents[i]; | |
path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; | |
} | |
} | |
if (quad) { | |
var lp = points[pi]; | |
path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; | |
} | |
return path; | |
} | |
function d3_svg_lineCardinalTangents(points, tension) { | |
var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; | |
while (++i < n) { | |
p0 = p1; | |
p1 = p2; | |
p2 = points[i]; | |
tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); | |
} | |
return tangents; | |
} | |
function d3_svg_lineBasis(points) { | |
if (points.length < 3) return d3_svg_lineLinear(points); | |
var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0 ]; | |
d3_svg_lineBasisBezier(path, px, py); | |
while (++i < n) { | |
pi = points[i]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
i = -1; | |
while (++i < 2) { | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
return path.join(""); | |
} | |
function d3_svg_lineBasisOpen(points) { | |
if (points.length < 4) return d3_svg_lineLinear(points); | |
var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; | |
while (++i < 3) { | |
pi = points[i]; | |
px.push(pi[0]); | |
py.push(pi[1]); | |
} | |
path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); | |
--i; | |
while (++i < n) { | |
pi = points[i]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
return path.join(""); | |
} | |
function d3_svg_lineBasisClosed(points) { | |
var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; | |
while (++i < 4) { | |
pi = points[i % n]; | |
px.push(pi[0]); | |
py.push(pi[1]); | |
} | |
path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; | |
--i; | |
while (++i < m) { | |
pi = points[i % n]; | |
px.shift(); | |
px.push(pi[0]); | |
py.shift(); | |
py.push(pi[1]); | |
d3_svg_lineBasisBezier(path, px, py); | |
} | |
return path.join(""); | |
} | |
function d3_svg_lineBundle(points, tension) { | |
var n = points.length - 1; | |
if (n) { | |
var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; | |
while (++i <= n) { | |
p = points[i]; | |
t = i / n; | |
p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); | |
p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); | |
} | |
} | |
return d3_svg_lineBasis(points); | |
} | |
function d3_svg_lineDot4(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; | |
} | |
var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; | |
function d3_svg_lineBasisBezier(path, x, y) { | |
path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); | |
} | |
function d3_svg_lineSlope(p0, p1) { | |
return (p1[1] - p0[1]) / (p1[0] - p0[0]); | |
} | |
function d3_svg_lineFiniteDifferences(points) { | |
var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); | |
while (++i < j) { | |
m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; | |
} | |
m[i] = d; | |
return m; | |
} | |
function d3_svg_lineMonotoneTangents(points) { | |
var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; | |
while (++i < j) { | |
d = d3_svg_lineSlope(points[i], points[i + 1]); | |
if (Math.abs(d) < 1e-6) { | |
m[i] = m[i + 1] = 0; | |
} else { | |
a = m[i] / d; | |
b = m[i + 1] / d; | |
s = a * a + b * b; | |
if (s > 9) { | |
s = d * 3 / Math.sqrt(s); | |
m[i] = s * a; | |
m[i + 1] = s * b; | |
} | |
} | |
} | |
i = -1; | |
while (++i <= j) { | |
s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); | |
tangents.push([ s || 0, m[i] * s || 0 ]); | |
} | |
return tangents; | |
} | |
function d3_svg_lineMonotone(points) { | |
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); | |
} | |
d3.svg.line.radial = function() { | |
var line = d3_svg_line(d3_svg_lineRadial); | |
line.radius = line.x, delete line.x; | |
line.angle = line.y, delete line.y; | |
return line; | |
}; | |
function d3_svg_lineRadial(points) { | |
var point, i = -1, n = points.length, r, a; | |
while (++i < n) { | |
point = points[i]; | |
r = point[0]; | |
a = point[1] + d3_svg_arcOffset; | |
point[0] = r * Math.cos(a); | |
point[1] = r * Math.sin(a); | |
} | |
return points; | |
} | |
function d3_svg_area(projection) { | |
var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; | |
function area(data) { | |
var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { | |
return x; | |
} : d3_functor(x1), fy1 = y0 === y1 ? function() { | |
return y; | |
} : d3_functor(y1), x, y; | |
function segment() { | |
segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); | |
} | |
while (++i < n) { | |
if (defined.call(this, d = data[i], i)) { | |
points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); | |
points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); | |
} else if (points0.length) { | |
segment(); | |
points0 = []; | |
points1 = []; | |
} | |
} | |
if (points0.length) segment(); | |
return segments.length ? segments.join("") : null; | |
} | |
area.x = function(_) { | |
if (!arguments.length) return x1; | |
x0 = x1 = _; | |
return area; | |
}; | |
area.x0 = function(_) { | |
if (!arguments.length) return x0; | |
x0 = _; | |
return area; | |
}; | |
area.x1 = function(_) { | |
if (!arguments.length) return x1; | |
x1 = _; | |
return area; | |
}; | |
area.y = function(_) { | |
if (!arguments.length) return y1; | |
y0 = y1 = _; | |
return area; | |
}; | |
area.y0 = function(_) { | |
if (!arguments.length) return y0; | |
y0 = _; | |
return area; | |
}; | |
area.y1 = function(_) { | |
if (!arguments.length) return y1; | |
y1 = _; | |
return area; | |
}; | |
area.defined = function(_) { | |
if (!arguments.length) return defined; | |
defined = _; | |
return area; | |
}; | |
area.interpolate = function(_) { | |
if (!arguments.length) return interpolateKey; | |
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; | |
interpolateReverse = interpolate.reverse || interpolate; | |
L = interpolate.closed ? "M" : "L"; | |
return area; | |
}; | |
area.tension = function(_) { | |
if (!arguments.length) return tension; | |
tension = _; | |
return area; | |
}; | |
return area; | |
} | |
d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; | |
d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; | |
d3.svg.area = function() { | |
return d3_svg_area(d3_identity); | |
}; | |
d3.svg.area.radial = function() { | |
var area = d3_svg_area(d3_svg_lineRadial); | |
area.radius = area.x, delete area.x; | |
area.innerRadius = area.x0, delete area.x0; | |
area.outerRadius = area.x1, delete area.x1; | |
area.angle = area.y, delete area.y; | |
area.startAngle = area.y0, delete area.y0; | |
area.endAngle = area.y1, delete area.y1; | |
return area; | |
}; | |
d3.svg.chord = function() { | |
var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; | |
function chord(d, i) { | |
var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); | |
return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; | |
} | |
function subgroup(self, f, d, i) { | |
var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; | |
return { | |
r: r, | |
a0: a0, | |
a1: a1, | |
p0: [ r * Math.cos(a0), r * Math.sin(a0) ], | |
p1: [ r * Math.cos(a1), r * Math.sin(a1) ] | |
}; | |
} | |
function equals(a, b) { | |
return a.a0 == b.a0 && a.a1 == b.a1; | |
} | |
function arc(r, p, a) { | |
return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; | |
} | |
function curve(r0, p0, r1, p1) { | |
return "Q 0,0 " + p1; | |
} | |
chord.radius = function(v) { | |
if (!arguments.length) return radius; | |
radius = d3_functor(v); | |
return chord; | |
}; | |
chord.source = function(v) { | |
if (!arguments.length) return source; | |
source = d3_functor(v); | |
return chord; | |
}; | |
chord.target = function(v) { | |
if (!arguments.length) return target; | |
target = d3_functor(v); | |
return chord; | |
}; | |
chord.startAngle = function(v) { | |
if (!arguments.length) return startAngle; | |
startAngle = d3_functor(v); | |
return chord; | |
}; | |
chord.endAngle = function(v) { | |
if (!arguments.length) return endAngle; | |
endAngle = d3_functor(v); | |
return chord; | |
}; | |
return chord; | |
}; | |
function d3_svg_chordRadius(d) { | |
return d.radius; | |
} | |
d3.svg.diagonal = function() { | |
var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; | |
function diagonal(d, i) { | |
var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { | |
x: p0.x, | |
y: m | |
}, { | |
x: p3.x, | |
y: m | |
}, p3 ]; | |
p = p.map(projection); | |
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; | |
} | |
diagonal.source = function(x) { | |
if (!arguments.length) return source; | |
source = d3_functor(x); | |
return diagonal; | |
}; | |
diagonal.target = function(x) { | |
if (!arguments.length) return target; | |
target = d3_functor(x); | |
return diagonal; | |
}; | |
diagonal.projection = function(x) { | |
if (!arguments.length) return projection; | |
projection = x; | |
return diagonal; | |
}; | |
return diagonal; | |
}; | |
function d3_svg_diagonalProjection(d) { | |
return [ d.x, d.y ]; | |
} | |
d3.svg.diagonal.radial = function() { | |
var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; | |
diagonal.projection = function(x) { | |
return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; | |
}; | |
return diagonal; | |
}; | |
function d3_svg_diagonalRadialProjection(projection) { | |
return function() { | |
var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset; | |
return [ r * Math.cos(a), r * Math.sin(a) ]; | |
}; | |
} | |
d3.svg.symbol = function() { | |
var type = d3_svg_symbolType, size = d3_svg_symbolSize; | |
function symbol(d, i) { | |
return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); | |
} | |
symbol.type = function(x) { | |
if (!arguments.length) return type; | |
type = d3_functor(x); | |
return symbol; | |
}; | |
symbol.size = function(x) { | |
if (!arguments.length) return size; | |
size = d3_functor(x); | |
return symbol; | |
}; | |
return symbol; | |
}; | |
function d3_svg_symbolSize() { | |
return 64; | |
} | |
function d3_svg_symbolType() { | |
return "circle"; | |
} | |
function d3_svg_symbolCircle(size) { | |
var r = Math.sqrt(size / π); | |
return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; | |
} | |
var d3_svg_symbols = d3.map({ | |
circle: d3_svg_symbolCircle, | |
cross: function(size) { | |
var r = Math.sqrt(size / 5) / 2; | |
return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; | |
}, | |
diamond: function(size) { | |
var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; | |
return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; | |
}, | |
square: function(size) { | |
var r = Math.sqrt(size) / 2; | |
return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; | |
}, | |
"triangle-down": function(size) { | |
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; | |
return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; | |
}, | |
"triangle-up": function(size) { | |
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; | |
return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; | |
} | |
}); | |
d3.svg.symbolTypes = d3_svg_symbols.keys(); | |
var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); | |
d3.svg.axis = function() { | |
var scale = d3.scale.linear(), orient = "bottom", tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0; | |
function axis(g) { | |
g.each(function() { | |
var g = d3.select(this); | |
var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_; | |
var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", "g").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1); | |
var tick = g.selectAll("g").data(ticks, String), tickEnter = tick.enter().insert("g", "path").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform; | |
var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = d3.transition(path); | |
var scale1 = scale.copy(), scale0 = this.__chart__ || scale1; | |
this.__chart__ = scale1; | |
path.enter().append("path").attr("class", "domain"); | |
tickEnter.append("line").attr("class", "tick"); | |
tickEnter.append("text"); | |
var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"); | |
switch (orient) { | |
case "bottom": | |
{ | |
tickTransform = d3_svg_axisX; | |
subtickEnter.attr("y2", tickMinorSize); | |
subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize); | |
lineEnter.attr("y2", tickMajorSize); | |
textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding); | |
lineUpdate.attr("x2", 0).attr("y2", tickMajorSize); | |
textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding); | |
text.attr("dy", ".71em").style("text-anchor", "middle"); | |
pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize); | |
break; | |
} | |
case "top": | |
{ | |
tickTransform = d3_svg_axisX; | |
subtickEnter.attr("y2", -tickMinorSize); | |
subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize); | |
lineEnter.attr("y2", -tickMajorSize); | |
textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)); | |
lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize); | |
textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)); | |
text.attr("dy", "0em").style("text-anchor", "middle"); | |
pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize); | |
break; | |
} | |
case "left": | |
{ | |
tickTransform = d3_svg_axisY; | |
subtickEnter.attr("x2", -tickMinorSize); | |
subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0); | |
lineEnter.attr("x2", -tickMajorSize); | |
textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)); | |
lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0); | |
textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0); | |
text.attr("dy", ".32em").style("text-anchor", "end"); | |
pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize); | |
break; | |
} | |
case "right": | |
{ | |
tickTransform = d3_svg_axisY; | |
subtickEnter.attr("x2", tickMinorSize); | |
subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0); | |
lineEnter.attr("x2", tickMajorSize); | |
textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding); | |
lineUpdate.attr("x2", tickMajorSize).attr("y2", 0); | |
textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0); | |
text.attr("dy", ".32em").style("text-anchor", "start"); | |
pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize); | |
break; | |
} | |
} | |
if (scale.ticks) { | |
tickEnter.call(tickTransform, scale0); | |
tickUpdate.call(tickTransform, scale1); | |
tickExit.call(tickTransform, scale1); | |
subtickEnter.call(tickTransform, scale0); | |
subtickUpdate.call(tickTransform, scale1); | |
subtickExit.call(tickTransform, scale1); | |
} else { | |
var dx = scale1.rangeBand() / 2, x = function(d) { | |
return scale1(d) + dx; | |
}; | |
tickEnter.call(tickTransform, x); | |
tickUpdate.call(tickTransform, x); | |
} | |
}); | |
} | |
axis.scale = function(x) { | |
if (!arguments.length) return scale; | |
scale = x; | |
return axis; | |
}; | |
axis.orient = function(x) { | |
if (!arguments.length) return orient; | |
orient = x; | |
return axis; | |
}; | |
axis.ticks = function() { | |
if (!arguments.length) return tickArguments_; | |
tickArguments_ = arguments; | |
return axis; | |
}; | |
axis.tickValues = function(x) { | |
if (!arguments.length) return tickValues; | |
tickValues = x; | |
return axis; | |
}; | |
axis.tickFormat = function(x) { | |
if (!arguments.length) return tickFormat_; | |
tickFormat_ = x; | |
return axis; | |
}; | |
axis.tickSize = function(x, y) { | |
if (!arguments.length) return tickMajorSize; | |
var n = arguments.length - 1; | |
tickMajorSize = +x; | |
tickMinorSize = n > 1 ? +y : tickMajorSize; | |
tickEndSize = n > 0 ? +arguments[n] : tickMajorSize; | |
return axis; | |
}; | |
axis.tickPadding = function(x) { | |
if (!arguments.length) return tickPadding; | |
tickPadding = +x; | |
return axis; | |
}; | |
axis.tickSubdivide = function(x) { | |
if (!arguments.length) return tickSubdivide; | |
tickSubdivide = +x; | |
return axis; | |
}; | |
return axis; | |
}; | |
function d3_svg_axisX(selection, x) { | |
selection.attr("transform", function(d) { | |
return "translate(" + x(d) + ",0)"; | |
}); | |
} | |
function d3_svg_axisY(selection, y) { | |
selection.attr("transform", function(d) { | |
return "translate(0," + y(d) + ")"; | |
}); | |
} | |
function d3_svg_axisSubdivide(scale, ticks, m) { | |
subticks = []; | |
if (m && ticks.length > 1) { | |
var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v; | |
while (++i < n) { | |
for (j = m; --j > 0; ) { | |
if ((v = +ticks[i] - j * d) >= extent[0]) { | |
subticks.push(v); | |
} | |
} | |
} | |
for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) { | |
subticks.push(v); | |
} | |
} | |
return subticks; | |
} | |
d3.svg.brush = function() { | |
var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain; | |
function brush(g) { | |
g.each(function() { | |
var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e; | |
g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); | |
bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); | |
fg.enter().append("rect").attr("class", "extent").style("cursor", "move"); | |
tz.enter().append("g").attr("class", function(d) { | |
return "resize " + d; | |
}).style("cursor", function(d) { | |
return d3_svg_brushCursor[d]; | |
}).append("rect").attr("x", function(d) { | |
return /[ew]$/.test(d) ? -3 : null; | |
}).attr("y", function(d) { | |
return /^[ns]/.test(d) ? -3 : null; | |
}).attr("width", 6).attr("height", 6).style("visibility", "hidden"); | |
tz.style("display", brush.empty() ? "none" : null); | |
tz.exit().remove(); | |
if (x) { | |
e = d3_scaleRange(x); | |
bg.attr("x", e[0]).attr("width", e[1] - e[0]); | |
redrawX(g); | |
} | |
if (y) { | |
e = d3_scaleRange(y); | |
bg.attr("y", e[0]).attr("height", e[1] - e[0]); | |
redrawY(g); | |
} | |
redraw(g); | |
}); | |
} | |
function redraw(g) { | |
g.selectAll(".resize").attr("transform", function(d) { | |
return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")"; | |
}); | |
} | |
function redrawX(g) { | |
g.select(".extent").attr("x", extent[0][0]); | |
g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]); | |
} | |
function redrawY(g) { | |
g.select(".extent").attr("y", extent[0][1]); | |
g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]); | |
} | |
function brushstart() { | |
var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), center, origin = mouse(), offset; | |
var w = d3.select(window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup); | |
if (dragging) { | |
origin[0] = extent[0][0] - origin[0]; | |
origin[1] = extent[0][1] - origin[1]; | |
} else if (resizing) { | |
var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); | |
offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ]; | |
origin[0] = extent[ex][0]; | |
origin[1] = extent[ey][1]; | |
} else if (d3.event.altKey) center = origin.slice(); | |
g.style("pointer-events", "none").selectAll(".resize").style("display", null); | |
d3.select("body").style("cursor", eventTarget.style("cursor")); | |
event_({ | |
type: "brushstart" | |
}); | |
brushmove(); | |
d3_eventCancel(); | |
function mouse() { | |
var touches = d3.event.changedTouches; | |
return touches ? d3.touches(target, touches)[0] : d3.mouse(target); | |
} | |
function keydown() { | |
if (d3.event.keyCode == 32) { | |
if (!dragging) { | |
center = null; | |
origin[0] -= extent[1][0]; | |
origin[1] -= extent[1][1]; | |
dragging = 2; | |
} | |
d3_eventCancel(); | |
} | |
} | |
function keyup() { | |
if (d3.event.keyCode == 32 && dragging == 2) { | |
origin[0] += extent[1][0]; | |
origin[1] += extent[1][1]; | |
dragging = 0; | |
d3_eventCancel(); | |
} | |
} | |
function brushmove() { | |
var point = mouse(), moved = false; | |
if (offset) { | |
point[0] += offset[0]; | |
point[1] += offset[1]; | |
} | |
if (!dragging) { | |
if (d3.event.altKey) { | |
if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ]; | |
origin[0] = extent[+(point[0] < center[0])][0]; | |
origin[1] = extent[+(point[1] < center[1])][1]; | |
} else center = null; | |
} | |
if (resizingX && move1(point, x, 0)) { | |
redrawX(g); | |
moved = true; | |
} | |
if (resizingY && move1(point, y, 1)) { | |
redrawY(g); | |
moved = true; | |
} | |
if (moved) { | |
redraw(g); | |
event_({ | |
type: "brush", | |
mode: dragging ? "move" : "resize" | |
}); | |
} | |
} | |
function move1(point, scale, i) { | |
var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max; | |
if (dragging) { | |
r0 -= position; | |
r1 -= size + position; | |
} | |
min = Math.max(r0, Math.min(r1, point[i])); | |
if (dragging) { | |
max = (min += position) + size; | |
} else { | |
if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); | |
if (position < min) { | |
max = min; | |
min = position; | |
} else { | |
max = position; | |
} | |
} | |
if (extent[0][i] !== min || extent[1][i] !== max) { | |
extentDomain = null; | |
extent[0][i] = min; | |
extent[1][i] = max; | |
return true; | |
} | |
} | |
function brushend() { | |
brushmove(); | |
g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); | |
d3.select("body").style("cursor", null); | |
w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); | |
event_({ | |
type: "brushend" | |
}); | |
d3_eventCancel(); | |
} | |
} | |
brush.x = function(z) { | |
if (!arguments.length) return x; | |
x = z; | |
resizes = d3_svg_brushResizes[!x << 1 | !y]; | |
return brush; | |
}; | |
brush.y = function(z) { | |
if (!arguments.length) return y; | |
y = z; | |
resizes = d3_svg_brushResizes[!x << 1 | !y]; | |
return brush; | |
}; | |
brush.extent = function(z) { | |
var x0, x1, y0, y1, t; | |
if (!arguments.length) { | |
z = extentDomain || extent; | |
if (x) { | |
x0 = z[0][0], x1 = z[1][0]; | |
if (!extentDomain) { | |
x0 = extent[0][0], x1 = extent[1][0]; | |
if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); | |
if (x1 < x0) t = x0, x0 = x1, x1 = t; | |
} | |
} | |
if (y) { | |
y0 = z[0][1], y1 = z[1][1]; | |
if (!extentDomain) { | |
y0 = extent[0][1], y1 = extent[1][1]; | |
if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); | |
if (y1 < y0) t = y0, y0 = y1, y1 = t; | |
} | |
} | |
return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; | |
} | |
extentDomain = [ [ 0, 0 ], [ 0, 0 ] ]; | |
if (x) { | |
x0 = z[0], x1 = z[1]; | |
if (y) x0 = x0[0], x1 = x1[0]; | |
extentDomain[0][0] = x0, extentDomain[1][0] = x1; | |
if (x.invert) x0 = x(x0), x1 = x(x1); | |
if (x1 < x0) t = x0, x0 = x1, x1 = t; | |
extent[0][0] = x0 | 0, extent[1][0] = x1 | 0; | |
} | |
if (y) { | |
y0 = z[0], y1 = z[1]; | |
if (x) y0 = y0[1], y1 = y1[1]; | |
extentDomain[0][1] = y0, extentDomain[1][1] = y1; | |
if (y.invert) y0 = y(y0), y1 = y(y1); | |
if (y1 < y0) t = y0, y0 = y1, y1 = t; | |
extent[0][1] = y0 | 0, extent[1][1] = y1 | 0; | |
} | |
return brush; | |
}; | |
brush.clear = function() { | |
extentDomain = null; | |
extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0; | |
return brush; | |
}; | |
brush.empty = function() { | |
return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1]; | |
}; | |
return d3.rebind(brush, event, "on"); | |
}; | |
var d3_svg_brushCursor = { | |
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 d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; | |
d3.behavior = {}; | |
d3.behavior.drag = function() { | |
var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null; | |
function drag() { | |
this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown); | |
} | |
function mousedown() { | |
var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0; | |
var w = d3.select(window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true); | |
if (origin) { | |
offset = origin.apply(target, arguments); | |
offset = [ offset.x - origin_[0], offset.y - origin_[1] ]; | |
} else { | |
offset = [ 0, 0 ]; | |
} | |
if (touchId == null) d3_eventCancel(); | |
event_({ | |
type: "dragstart" | |
}); | |
function point() { | |
var p = target.parentNode; | |
return touchId != null ? d3.touches(p).filter(function(p) { | |
return p.identifier === touchId; | |
})[0] : d3.mouse(p); | |
} | |
function dragmove() { | |
if (!target.parentNode) return dragend(); | |
var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1]; | |
moved |= dx | dy; | |
origin_ = p; | |
d3_eventCancel(); | |
event_({ | |
type: "drag", | |
x: p[0] + offset[0], | |
y: p[1] + offset[1], | |
dx: dx, | |
dy: dy | |
}); | |
} | |
function dragend() { | |
event_({ | |
type: "dragend" | |
}); | |
if (moved) { | |
d3_eventCancel(); | |
if (d3.event.target === eventTarget) w.on("click.drag", click, true); | |
} | |
w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null); | |
} | |
function click() { | |
d3_eventCancel(); | |
w.on("click.drag", null); | |
} | |
} | |
drag.origin = function(x) { | |
if (!arguments.length) return origin; | |
origin = x; | |
return drag; | |
}; | |
return d3.rebind(drag, event, "on"); | |
}; | |
d3.behavior.zoom = function() { | |
var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime; | |
function zoom() { | |
this.on("mousedown.zoom", mousedown).on("mousewheel.zoom", mousewheel).on("mousemove.zoom", mousemove).on("DOMMouseScroll.zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart); | |
} | |
zoom.translate = function(x) { | |
if (!arguments.length) return translate; | |
translate = x.map(Number); | |
rescale(); | |
return zoom; | |
}; | |
zoom.scale = function(x) { | |
if (!arguments.length) return scale; | |
scale = +x; | |
rescale(); | |
return zoom; | |
}; | |
zoom.scaleExtent = function(x) { | |
if (!arguments.length) return scaleExtent; | |
scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number); | |
return zoom; | |
}; | |
zoom.x = function(z) { | |
if (!arguments.length) return x1; | |
x1 = z; | |
x0 = z.copy(); | |
translate = [ 0, 0 ]; | |
scale = 1; | |
return zoom; | |
}; | |
zoom.y = function(z) { | |
if (!arguments.length) return y1; | |
y1 = z; | |
y0 = z.copy(); | |
translate = [ 0, 0 ]; | |
scale = 1; | |
return zoom; | |
}; | |
function location(p) { | |
return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ]; | |
} | |
function point(l) { | |
return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ]; | |
} | |
function scaleTo(s) { | |
scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); | |
} | |
function translateTo(p, l) { | |
l = point(l); | |
translate[0] += p[0] - l[0]; | |
translate[1] += p[1] - l[1]; | |
} | |
function rescale() { | |
if (x1) x1.domain(x0.range().map(function(x) { | |
return (x - translate[0]) / scale; | |
}).map(x0.invert)); | |
if (y1) y1.domain(y0.range().map(function(y) { | |
return (y - translate[1]) / scale; | |
}).map(y0.invert)); | |
} | |
function dispatch(event) { | |
rescale(); | |
d3.event.preventDefault(); | |
event({ | |
type: "zoom", | |
scale: scale, | |
translate: translate | |
}); | |
} | |
function mousedown() { | |
var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target)); | |
window.focus(); | |
d3_eventCancel(); | |
function mousemove() { | |
moved = 1; | |
translateTo(d3.mouse(target), l); | |
dispatch(event_); | |
} | |
function mouseup() { | |
if (moved) d3_eventCancel(); | |
w.on("mousemove.zoom", null).on("mouseup.zoom", null); | |
if (moved && d3.event.target === eventTarget) w.on("click.zoom", click, true); | |
} | |
function click() { | |
d3_eventCancel(); | |
w.on("click.zoom", null); | |
} | |
} | |
function mousewheel() { | |
if (!translate0) translate0 = location(d3.mouse(this)); | |
scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale); | |
translateTo(d3.mouse(this), translate0); | |
dispatch(event.of(this, arguments)); | |
} | |
function mousemove() { | |
translate0 = null; | |
} | |
function dblclick() { | |
var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2; | |
scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); | |
translateTo(p, l); | |
dispatch(event.of(this, arguments)); | |
} | |
function touchstart() { | |
var touches = d3.touches(this), now = Date.now(); | |
scale0 = scale; | |
translate0 = {}; | |
touches.forEach(function(t) { | |
translate0[t.identifier] = location(t); | |
}); | |
d3_eventCancel(); | |
if (touches.length === 1) { | |
if (now - touchtime < 500) { | |
var p = touches[0], l = location(touches[0]); | |
scaleTo(scale * 2); | |
translateTo(p, l); | |
dispatch(event.of(this, arguments)); | |
} | |
touchtime = now; | |
} | |
} | |
function touchmove() { | |
var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier]; | |
if (p1 = touches[1]) { | |
var p1, l1 = translate0[p1.identifier]; | |
p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; | |
l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; | |
scaleTo(d3.event.scale * scale0); | |
} | |
translateTo(p0, l0); | |
touchtime = null; | |
dispatch(event.of(this, arguments)); | |
} | |
return d3.rebind(zoom, event, "on"); | |
}; | |
var d3_behavior_zoomDiv, d3_behavior_zoomInfinity = [ 0, Infinity ]; | |
function d3_behavior_zoomDelta() { | |
if (!d3_behavior_zoomDiv) { | |
d3_behavior_zoomDiv = d3.select("body").append("div").style("visibility", "hidden").style("top", 0).style("height", 0).style("width", 0).style("overflow-y", "scroll").append("div").style("height", "2000px").node().parentNode; | |
} | |
var e = d3.event, delta; | |
try { | |
d3_behavior_zoomDiv.scrollTop = 1e3; | |
d3_behavior_zoomDiv.dispatchEvent(e); | |
delta = 1e3 - d3_behavior_zoomDiv.scrollTop; | |
} catch (error) { | |
delta = e.wheelDelta || -e.detail * 5; | |
} | |
return delta; | |
} | |
d3.layout = {}; | |
d3.layout.bundle = function() { | |
return function(links) { | |
var paths = [], i = -1, n = links.length; | |
while (++i < n) paths.push(d3_layout_bundlePath(links[i])); | |
return paths; | |
}; | |
}; | |
function d3_layout_bundlePath(link) { | |
var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; | |
while (start !== lca) { | |
start = start.parent; | |
points.push(start); | |
} | |
var k = points.length; | |
while (end !== lca) { | |
points.splice(k, 0, end); | |
end = end.parent; | |
} | |
return points; | |
} | |
function d3_layout_bundleAncestors(node) { | |
var ancestors = [], parent = node.parent; | |
while (parent != null) { | |
ancestors.push(node); | |
node = parent; | |
parent = parent.parent; | |
} | |
ancestors.push(node); | |
return ancestors; | |
} | |
function d3_layout_bundleLeastCommonAncestor(a, b) { | |
if (a === b) return a; | |
var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; | |
while (aNode === bNode) { | |
sharedNode = aNode; | |
aNode = aNodes.pop(); | |
bNode = bNodes.pop(); | |
} | |
return sharedNode; | |
} | |
d3.layout.chord = function() { | |
var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; | |
function relayout() { | |
var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; | |
chords = []; | |
groups = []; | |
k = 0, i = -1; | |
while (++i < n) { | |
x = 0, j = -1; | |
while (++j < n) { | |
x += matrix[i][j]; | |
} | |
groupSums.push(x); | |
subgroupIndex.push(d3.range(n)); | |
k += x; | |
} | |
if (sortGroups) { | |
groupIndex.sort(function(a, b) { | |
return sortGroups(groupSums[a], groupSums[b]); | |
}); | |
} | |
if (sortSubgroups) { | |
subgroupIndex.forEach(function(d, i) { | |
d.sort(function(a, b) { | |
return sortSubgroups(matrix[i][a], matrix[i][b]); | |
}); | |
}); | |
} | |
k = (2 * π - padding * n) / k; | |
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[di + "-" + dj] = { | |
index: di, | |
subindex: dj, | |
startAngle: a0, | |
endAngle: a1, | |
value: v | |
}; | |
} | |
groups[di] = { | |
index: di, | |
startAngle: x0, | |
endAngle: x, | |
value: (x - x0) / k | |
}; | |
x += padding; | |
} | |
i = -1; | |
while (++i < n) { | |
j = i - 1; | |
while (++j < n) { | |
var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; | |
if (source.value || target.value) { | |
chords.push(source.value < target.value ? { | |
source: target, | |
target: source | |
} : { | |
source: source, | |
target: target | |
}); | |
} | |
} | |
} | |
if (sortChords) resort(); | |
} | |
function resort() { | |
chords.sort(function(a, b) { | |
return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); | |
}); | |
} | |
chord.matrix = function(x) { | |
if (!arguments.length) return matrix; | |
n = (matrix = x) && matrix.length; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.padding = function(x) { | |
if (!arguments.length) return padding; | |
padding = x; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.sortGroups = function(x) { | |
if (!arguments.length) return sortGroups; | |
sortGroups = x; | |
chords = groups = null; | |
return chord; | |
}; | |
chord.sortSubgroups = function(x) { | |
if (!arguments.length) return sortSubgroups; | |
sortSubgroups = x; | |
chords = null; | |
return chord; | |
}; | |
chord.sortChords = function(x) { | |
if (!arguments.length) return sortChords; | |
sortChords = x; | |
if (chords) resort(); | |
return chord; | |
}; | |
chord.chords = function() { | |
if (!chords) relayout(); | |
return chords; | |
}; | |
chord.groups = function() { | |
if (!groups) relayout(); | |
return groups; | |
}; | |
return chord; | |
}; | |
d3.layout.force = function() { | |
var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, gravity = .1, theta = .8, nodes = [], links = [], distances, strengths, charges; | |
function repulse(node) { | |
return function(quad, x1, _, x2) { | |
if (quad.point !== node) { | |
var dx = quad.cx - node.x, dy = quad.cy - node.y, dn = 1 / Math.sqrt(dx * dx + dy * dy); | |
if ((x2 - x1) * dn < theta) { | |
var k = quad.charge * dn * dn; | |
node.px -= dx * k; | |
node.py -= dy * k; | |
return true; | |
} | |
if (quad.point && isFinite(dn)) { | |
var k = quad.pointCharge * dn * dn; | |
node.px -= dx * k; | |
node.py -= dy * k; | |
} | |
} | |
return !quad.charge; | |
}; | |
} | |
force.tick = function() { | |
if ((alpha *= .99) < .005) { | |
event.end({ | |
type: "end", | |
alpha: alpha = 0 | |
}); | |
return true; | |
} | |
var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; | |
for (i = 0; i < m; ++i) { | |
o = links[i]; | |
s = o.source; | |
t = o.target; | |
x = t.x - s.x; | |
y = t.y - s.y; | |
if (l = x * x + y * y) { | |
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; | |
x *= l; | |
y *= l; | |
t.x -= x * (k = s.weight / (t.weight + s.weight)); | |
t.y -= y * k; | |
s.x += x * (k = 1 - k); | |
s.y += y * k; | |
} | |
} | |
if (k = alpha * gravity) { | |
x = size[0] / 2; | |
y = size[1] / 2; | |
i = -1; | |
if (k) while (++i < n) { | |
o = nodes[i]; | |
o.x += (x - o.x) * k; | |
o.y += (y - o.y) * k; | |
} | |
} | |
if (charge) { | |
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); | |
i = -1; | |
while (++i < n) { | |
if (!(o = nodes[i]).fixed) { | |
q.visit(repulse(o)); | |
} | |
} | |
} | |
i = -1; | |
while (++i < n) { | |
o = nodes[i]; | |
if (o.fixed) { | |
o.x = o.px; | |
o.y = o.py; | |
} else { | |
o.x -= (o.px - (o.px = o.x)) * friction; | |
o.y -= (o.py - (o.py = o.y)) * friction; | |
} | |
} | |
event.tick({ | |
type: "tick", | |
alpha: alpha | |
}); | |
}; | |
force.nodes = function(x) { | |
if (!arguments.length) return nodes; | |
nodes = x; | |
return force; | |
}; | |
force.links = function(x) { | |
if (!arguments.length) return links; | |
links = x; | |
return force; | |
}; | |
force.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return force; | |
}; | |
force.linkDistance = function(x) { | |
if (!arguments.length) return linkDistance; | |
linkDistance = d3_functor(x); | |
return force; | |
}; | |
force.distance = force.linkDistance; | |
force.linkStrength = function(x) { | |
if (!arguments.length) return linkStrength; | |
linkStrength = d3_functor(x); | |
return force; | |
}; | |
force.friction = function(x) { | |
if (!arguments.length) return friction; | |
friction = x; | |
return force; | |
}; | |
force.charge = function(x) { | |
if (!arguments.length) return charge; | |
charge = typeof x === "function" ? x : +x; | |
return force; | |
}; | |
force.gravity = function(x) { | |
if (!arguments.length) return gravity; | |
gravity = x; | |
return force; | |
}; | |
force.theta = function(x) { | |
if (!arguments.length) return theta; | |
theta = x; | |
return force; | |
}; | |
force.alpha = function(x) { | |
if (!arguments.length) return alpha; | |
if (alpha) { | |
if (x > 0) alpha = x; else alpha = 0; | |
} else if (x > 0) { | |
event.start({ | |
type: "start", | |
alpha: alpha = x | |
}); | |
d3.timer(force.tick); | |
} | |
return force; | |
}; | |
force.start = function() { | |
var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; | |
for (i = 0; i < n; ++i) { | |
(o = nodes[i]).index = i; | |
o.weight = 0; | |
} | |
distances = []; | |
strengths = []; | |
for (i = 0; i < m; ++i) { | |
o = links[i]; | |
if (typeof o.source == "number") o.source = nodes[o.source]; | |
if (typeof o.target == "number") o.target = nodes[o.target]; | |
distances[i] = linkDistance.call(this, o, i); | |
strengths[i] = linkStrength.call(this, o, i); | |
++o.source.weight; | |
++o.target.weight; | |
} | |
for (i = 0; i < n; ++i) { | |
o = nodes[i]; | |
if (isNaN(o.x)) o.x = position("x", w); | |
if (isNaN(o.y)) o.y = position("y", h); | |
if (isNaN(o.px)) o.px = o.x; | |
if (isNaN(o.py)) o.py = o.y; | |
} | |
charges = []; | |
if (typeof charge === "function") { | |
for (i = 0; i < n; ++i) { | |
charges[i] = +charge.call(this, nodes[i], i); | |
} | |
} else { | |
for (i = 0; i < n; ++i) { | |
charges[i] = charge; | |
} | |
} | |
function position(dimension, size) { | |
var neighbors = neighbor(i), j = -1, m = neighbors.length, x; | |
while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x; | |
return Math.random() * size; | |
} | |
function neighbor() { | |
if (!neighbors) { | |
neighbors = []; | |
for (j = 0; j < n; ++j) { | |
neighbors[j] = []; | |
} | |
for (j = 0; j < m; ++j) { | |
var o = links[j]; | |
neighbors[o.source.index].push(o.target); | |
neighbors[o.target.index].push(o.source); | |
} | |
} | |
return neighbors[i]; | |
} | |
return force.resume(); | |
}; | |
force.resume = function() { | |
return force.alpha(.1); | |
}; | |
force.stop = function() { | |
return force.alpha(0); | |
}; | |
force.drag = function() { | |
if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart", d3_layout_forceDragstart).on("drag", dragmove).on("dragend", d3_layout_forceDragend); | |
this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); | |
}; | |
function dragmove(d) { | |
d.px = d3.event.x, d.py = d3.event.y; | |
force.resume(); | |
} | |
return d3.rebind(force, event, "on"); | |
}; | |
function d3_layout_forceDragstart(d) { | |
d.fixed |= 2; | |
} | |
function d3_layout_forceDragend(d) { | |
d.fixed &= 1; | |
} | |
function d3_layout_forceMouseover(d) { | |
d.fixed |= 4; | |
d.px = d.x, d.py = d.y; | |
} | |
function d3_layout_forceMouseout(d) { | |
d.fixed &= 3; | |
} | |
function d3_layout_forceAccumulate(quad, alpha, charges) { | |
var cx = 0, cy = 0; | |
quad.charge = 0; | |
if (!quad.leaf) { | |
var nodes = quad.nodes, n = nodes.length, i = -1, c; | |
while (++i < n) { | |
c = nodes[i]; | |
if (c == null) continue; | |
d3_layout_forceAccumulate(c, alpha, charges); | |
quad.charge += c.charge; | |
cx += c.charge * c.cx; | |
cy += c.charge * c.cy; | |
} | |
} | |
if (quad.point) { | |
if (!quad.leaf) { | |
quad.point.x += Math.random() - .5; | |
quad.point.y += Math.random() - .5; | |
} | |
var k = alpha * charges[quad.point.index]; | |
quad.charge += quad.pointCharge = k; | |
cx += k * quad.point.x; | |
cy += k * quad.point.y; | |
} | |
quad.cx = cx / quad.charge; | |
quad.cy = cy / quad.charge; | |
} | |
function d3_layout_forceLinkDistance() { | |
return 20; | |
} | |
function d3_layout_forceLinkStrength() { | |
return 1; | |
} | |
d3.layout.partition = function() { | |
var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; | |
function position(node, x, dx, dy) { | |
var children = node.children; | |
node.x = x; | |
node.y = node.depth * dy; | |
node.dx = dx; | |
node.dy = dy; | |
if (children && (n = children.length)) { | |
var i = -1, n, c, d; | |
dx = node.value ? dx / node.value : 0; | |
while (++i < n) { | |
position(c = children[i], x, d = c.value * dx, dy); | |
x += d; | |
} | |
} | |
} | |
function depth(node) { | |
var children = node.children, d = 0; | |
if (children && (n = children.length)) { | |
var i = -1, n; | |
while (++i < n) d = Math.max(d, depth(children[i])); | |
} | |
return 1 + d; | |
} | |
function partition(d, i) { | |
var nodes = hierarchy.call(this, d, i); | |
position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); | |
return nodes; | |
} | |
partition.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return partition; | |
}; | |
return d3_layout_hierarchyRebind(partition, hierarchy); | |
}; | |
d3.layout.pie = function() { | |
var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * π; | |
function pie(data) { | |
var values = data.map(function(d, i) { | |
return +value.call(pie, d, i); | |
}); | |
var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle); | |
var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values); | |
var index = d3.range(data.length); | |
if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { | |
return values[j] - values[i]; | |
} : function(i, j) { | |
return sort(data[i], data[j]); | |
}); | |
var arcs = []; | |
index.forEach(function(i) { | |
var d; | |
arcs[i] = { | |
data: data[i], | |
value: d = values[i], | |
startAngle: a, | |
endAngle: a += d * k | |
}; | |
}); | |
return arcs; | |
} | |
pie.value = function(x) { | |
if (!arguments.length) return value; | |
value = x; | |
return pie; | |
}; | |
pie.sort = function(x) { | |
if (!arguments.length) return sort; | |
sort = x; | |
return pie; | |
}; | |
pie.startAngle = function(x) { | |
if (!arguments.length) return startAngle; | |
startAngle = x; | |
return pie; | |
}; | |
pie.endAngle = function(x) { | |
if (!arguments.length) return endAngle; | |
endAngle = x; | |
return pie; | |
}; | |
return pie; | |
}; | |
var d3_layout_pieSortByValue = {}; | |
d3.layout.stack = function() { | |
var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; | |
function stack(data, index) { | |
var series = data.map(function(d, i) { | |
return values.call(stack, d, i); | |
}); | |
var points = series.map(function(d) { | |
return d.map(function(v, i) { | |
return [ x.call(stack, v, i), y.call(stack, v, i) ]; | |
}); | |
}); | |
var orders = order.call(stack, points, index); | |
series = d3.permute(series, orders); | |
points = d3.permute(points, orders); | |
var offsets = offset.call(stack, points, index); | |
var n = series.length, m = series[0].length, i, j, o; | |
for (j = 0; j < m; ++j) { | |
out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); | |
for (i = 1; i < n; ++i) { | |
out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); | |
} | |
} | |
return data; | |
} | |
stack.values = function(x) { | |
if (!arguments.length) return values; | |
values = x; | |
return stack; | |
}; | |
stack.order = function(x) { | |
if (!arguments.length) return order; | |
order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; | |
return stack; | |
}; | |
stack.offset = function(x) { | |
if (!arguments.length) return offset; | |
offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; | |
return stack; | |
}; | |
stack.x = function(z) { | |
if (!arguments.length) return x; | |
x = z; | |
return stack; | |
}; | |
stack.y = function(z) { | |
if (!arguments.length) return y; | |
y = z; | |
return stack; | |
}; | |
stack.out = function(z) { | |
if (!arguments.length) return out; | |
out = z; | |
return stack; | |
}; | |
return stack; | |
}; | |
function d3_layout_stackX(d) { | |
return d.x; | |
} | |
function d3_layout_stackY(d) { | |
return d.y; | |
} | |
function d3_layout_stackOut(d, y0, y) { | |
d.y0 = y0; | |
d.y = y; | |
} | |
var d3_layout_stackOrders = d3.map({ | |
"inside-out": function(data) { | |
var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { | |
return max[a] - max[b]; | |
}), top = 0, bottom = 0, tops = [], bottoms = []; | |
for (i = 0; i < n; ++i) { | |
j = index[i]; | |
if (top < bottom) { | |
top += sums[j]; | |
tops.push(j); | |
} else { | |
bottom += sums[j]; | |
bottoms.push(j); | |
} | |
} | |
return bottoms.reverse().concat(tops); | |
}, | |
reverse: function(data) { | |
return d3.range(data.length).reverse(); | |
}, | |
"default": d3_layout_stackOrderDefault | |
}); | |
var d3_layout_stackOffsets = d3.map({ | |
silhouette: function(data) { | |
var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; | |
for (j = 0; j < m; ++j) { | |
for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; | |
if (o > max) max = o; | |
sums.push(o); | |
} | |
for (j = 0; j < m; ++j) { | |
y0[j] = (max - sums[j]) / 2; | |
} | |
return y0; | |
}, | |
wiggle: function(data) { | |
var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; | |
y0[0] = o = o0 = 0; | |
for (j = 1; j < m; ++j) { | |
for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; | |
for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { | |
for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { | |
s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; | |
} | |
s2 += s3 * data[i][j][1]; | |
} | |
y0[j] = o -= s1 ? s2 / s1 * dx : 0; | |
if (o < o0) o0 = o; | |
} | |
for (j = 0; j < m; ++j) y0[j] -= o0; | |
return y0; | |
}, | |
expand: function(data) { | |
var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; | |
for (j = 0; j < m; ++j) { | |
for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; | |
if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; | |
} | |
for (j = 0; j < m; ++j) y0[j] = 0; | |
return y0; | |
}, | |
zero: d3_layout_stackOffsetZero | |
}); | |
function d3_layout_stackOrderDefault(data) { | |
return d3.range(data.length); | |
} | |
function d3_layout_stackOffsetZero(data) { | |
var j = -1, m = data[0].length, y0 = []; | |
while (++j < m) y0[j] = 0; | |
return y0; | |
} | |
function d3_layout_stackMaxIndex(array) { | |
var i = 1, j = 0, v = array[0][1], k, n = array.length; | |
for (;i < n; ++i) { | |
if ((k = array[i][1]) > v) { | |
j = i; | |
v = k; | |
} | |
} | |
return j; | |
} | |
function d3_layout_stackReduceSum(d) { | |
return d.reduce(d3_layout_stackSum, 0); | |
} | |
function d3_layout_stackSum(p, d) { | |
return p + d[1]; | |
} | |
d3.layout.histogram = function() { | |
var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; | |
function histogram(data, i) { | |
var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; | |
while (++i < m) { | |
bin = bins[i] = []; | |
bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); | |
bin.y = 0; | |
} | |
if (m > 0) { | |
i = -1; | |
while (++i < n) { | |
x = values[i]; | |
if (x >= range[0] && x <= range[1]) { | |
bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; | |
bin.y += k; | |
bin.push(data[i]); | |
} | |
} | |
} | |
return bins; | |
} | |
histogram.value = function(x) { | |
if (!arguments.length) return valuer; | |
valuer = x; | |
return histogram; | |
}; | |
histogram.range = function(x) { | |
if (!arguments.length) return ranger; | |
ranger = d3_functor(x); | |
return histogram; | |
}; | |
histogram.bins = function(x) { | |
if (!arguments.length) return binner; | |
binner = typeof x === "number" ? function(range) { | |
return d3_layout_histogramBinFixed(range, x); | |
} : d3_functor(x); | |
return histogram; | |
}; | |
histogram.frequency = function(x) { | |
if (!arguments.length) return frequency; | |
frequency = !!x; | |
return histogram; | |
}; | |
return histogram; | |
}; | |
function d3_layout_histogramBinSturges(range, values) { | |
return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); | |
} | |
function d3_layout_histogramBinFixed(range, n) { | |
var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; | |
while (++x <= n) f[x] = m * x + b; | |
return f; | |
} | |
function d3_layout_histogramRange(values) { | |
return [ d3.min(values), d3.max(values) ]; | |
} | |
d3.layout.hierarchy = function() { | |
var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; | |
function recurse(node, depth, nodes) { | |
var childs = children.call(hierarchy, node, depth); | |
node.depth = depth; | |
nodes.push(node); | |
if (childs && (n = childs.length)) { | |
var i = -1, n, c = node.children = [], v = 0, j = depth + 1, d; | |
while (++i < n) { | |
d = recurse(childs[i], j, nodes); | |
d.parent = node; | |
c.push(d); | |
v += d.value; | |
} | |
if (sort) c.sort(sort); | |
if (value) node.value = v; | |
} else if (value) { | |
node.value = +value.call(hierarchy, node, depth) || 0; | |
} | |
return node; | |
} | |
function revalue(node, depth) { | |
var children = node.children, v = 0; | |
if (children && (n = children.length)) { | |
var i = -1, n, j = depth + 1; | |
while (++i < n) v += revalue(children[i], j); | |
} else if (value) { | |
v = +value.call(hierarchy, node, depth) || 0; | |
} | |
if (value) node.value = v; | |
return v; | |
} | |
function hierarchy(d) { | |
var nodes = []; | |
recurse(d, 0, nodes); | |
return nodes; | |
} | |
hierarchy.sort = function(x) { | |
if (!arguments.length) return sort; | |
sort = x; | |
return hierarchy; | |
}; | |
hierarchy.children = function(x) { | |
if (!arguments.length) return children; | |
children = x; | |
return hierarchy; | |
}; | |
hierarchy.value = function(x) { | |
if (!arguments.length) return value; | |
value = x; | |
return hierarchy; | |
}; | |
hierarchy.revalue = function(root) { | |
revalue(root, 0); | |
return root; | |
}; | |
return hierarchy; | |
}; | |
function d3_layout_hierarchyRebind(object, hierarchy) { | |
d3.rebind(object, hierarchy, "sort", "children", "value"); | |
object.nodes = object; | |
object.links = d3_layout_hierarchyLinks; | |
return object; | |
} | |
function d3_layout_hierarchyChildren(d) { | |
return d.children; | |
} | |
function d3_layout_hierarchyValue(d) { | |
return d.value; | |
} | |
function d3_layout_hierarchySort(a, b) { | |
return b.value - a.value; | |
} | |
function d3_layout_hierarchyLinks(nodes) { | |
return d3.merge(nodes.map(function(parent) { | |
return (parent.children || []).map(function(child) { | |
return { | |
source: parent, | |
target: child | |
}; | |
}); | |
})); | |
} | |
d3.layout.pack = function() { | |
var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ]; | |
function pack(d, i) { | |
var nodes = hierarchy.call(this, d, i), root = nodes[0]; | |
root.x = 0; | |
root.y = 0; | |
d3_layout_treeVisitAfter(root, function(d) { | |
d.r = Math.sqrt(d.value); | |
}); | |
d3_layout_treeVisitAfter(root, d3_layout_packSiblings); | |
var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h); | |
if (padding > 0) { | |
var dr = padding * k / 2; | |
d3_layout_treeVisitAfter(root, function(d) { | |
d.r += dr; | |
}); | |
d3_layout_treeVisitAfter(root, d3_layout_packSiblings); | |
d3_layout_treeVisitAfter(root, function(d) { | |
d.r -= dr; | |
}); | |
k = Math.max(2 * root.r / w, 2 * root.r / h); | |
} | |
d3_layout_packTransform(root, w / 2, h / 2, 1 / k); | |
return nodes; | |
} | |
pack.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return pack; | |
}; | |
pack.padding = function(_) { | |
if (!arguments.length) return padding; | |
padding = +_; | |
return pack; | |
}; | |
return d3_layout_hierarchyRebind(pack, hierarchy); | |
}; | |
function d3_layout_packSort(a, b) { | |
return a.value - b.value; | |
} | |
function d3_layout_packInsert(a, b) { | |
var c = a._pack_next; | |
a._pack_next = b; | |
b._pack_prev = a; | |
b._pack_next = c; | |
c._pack_prev = b; | |
} | |
function d3_layout_packSplice(a, b) { | |
a._pack_next = b; | |
b._pack_prev = a; | |
} | |
function d3_layout_packIntersects(a, b) { | |
var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; | |
return dr * dr - dx * dx - dy * dy > .001; | |
} | |
function d3_layout_packSiblings(node) { | |
if (!(nodes = node.children) || !(n = nodes.length)) return; | |
var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; | |
function bound(node) { | |
xMin = Math.min(node.x - node.r, xMin); | |
xMax = Math.max(node.x + node.r, xMax); | |
yMin = Math.min(node.y - node.r, yMin); | |
yMax = Math.max(node.y + node.r, yMax); | |
} | |
nodes.forEach(d3_layout_packLink); | |
a = nodes[0]; | |
a.x = -a.r; | |
a.y = 0; | |
bound(a); | |
if (n > 1) { | |
b = nodes[1]; | |
b.x = b.r; | |
b.y = 0; | |
bound(b); | |
if (n > 2) { | |
c = nodes[2]; | |
d3_layout_packPlace(a, b, c); | |
bound(c); | |
d3_layout_packInsert(a, c); | |
a._pack_prev = c; | |
d3_layout_packInsert(c, b); | |
b = a._pack_next; | |
for (i = 3; i < n; i++) { | |
d3_layout_packPlace(a, b, c = nodes[i]); | |
var isect = 0, s1 = 1, s2 = 1; | |
for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { | |
if (d3_layout_packIntersects(j, c)) { | |
isect = 1; | |
break; | |
} | |
} | |
if (isect == 1) { | |
for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { | |
if (d3_layout_packIntersects(k, c)) { | |
break; | |
} | |
} | |
} | |
if (isect) { | |
if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); | |
i--; | |
} else { | |
d3_layout_packInsert(a, c); | |
b = c; | |
bound(c); | |
} | |
} | |
} | |
} | |
var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; | |
for (i = 0; i < n; i++) { | |
c = nodes[i]; | |
c.x -= cx; | |
c.y -= cy; | |
cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); | |
} | |
node.r = cr; | |
nodes.forEach(d3_layout_packUnlink); | |
} | |
function d3_layout_packLink(node) { | |
node._pack_next = node._pack_prev = node; | |
} | |
function d3_layout_packUnlink(node) { | |
delete node._pack_next; | |
delete node._pack_prev; | |
} | |
function d3_layout_packTransform(node, x, y, k) { | |
var children = node.children; | |
node.x = x += k * node.x; | |
node.y = y += k * node.y; | |
node.r *= k; | |
if (children) { | |
var i = -1, n = children.length; | |
while (++i < n) d3_layout_packTransform(children[i], x, y, k); | |
} | |
} | |
function d3_layout_packPlace(a, b, c) { | |
var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; | |
if (db && (dx || dy)) { | |
var da = b.r + c.r, dc = dx * dx + dy * dy; | |
da *= da; | |
db *= db; | |
var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); | |
c.x = a.x + x * dx + y * dy; | |
c.y = a.y + x * dy - y * dx; | |
} else { | |
c.x = a.x + db; | |
c.y = a.y; | |
} | |
} | |
d3.layout.cluster = function() { | |
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ]; | |
function cluster(d, i) { | |
var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; | |
d3_layout_treeVisitAfter(root, function(node) { | |
var children = node.children; | |
if (children && children.length) { | |
node.x = d3_layout_clusterX(children); | |
node.y = d3_layout_clusterY(children); | |
} else { | |
node.x = previousNode ? x += separation(node, previousNode) : 0; | |
node.y = 0; | |
previousNode = node; | |
} | |
}); | |
var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; | |
d3_layout_treeVisitAfter(root, function(node) { | |
node.x = (node.x - x0) / (x1 - x0) * size[0]; | |
node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; | |
}); | |
return nodes; | |
} | |
cluster.separation = function(x) { | |
if (!arguments.length) return separation; | |
separation = x; | |
return cluster; | |
}; | |
cluster.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return cluster; | |
}; | |
return d3_layout_hierarchyRebind(cluster, hierarchy); | |
}; | |
function d3_layout_clusterY(children) { | |
return 1 + d3.max(children, function(child) { | |
return child.y; | |
}); | |
} | |
function d3_layout_clusterX(children) { | |
return children.reduce(function(x, child) { | |
return x + child.x; | |
}, 0) / children.length; | |
} | |
function d3_layout_clusterLeft(node) { | |
var children = node.children; | |
return children && children.length ? d3_layout_clusterLeft(children[0]) : node; | |
} | |
function d3_layout_clusterRight(node) { | |
var children = node.children, n; | |
return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; | |
} | |
d3.layout.tree = function() { | |
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ]; | |
function tree(d, i) { | |
var nodes = hierarchy.call(this, d, i), root = nodes[0]; | |
function firstWalk(node, previousSibling) { | |
var children = node.children, layout = node._tree; | |
if (children && (n = children.length)) { | |
var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1; | |
while (++i < n) { | |
child = children[i]; | |
firstWalk(child, previousChild); | |
ancestor = apportion(child, previousChild, ancestor); | |
previousChild = child; | |
} | |
d3_layout_treeShift(node); | |
var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim); | |
if (previousSibling) { | |
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); | |
layout.mod = layout.prelim - midpoint; | |
} else { | |
layout.prelim = midpoint; | |
} | |
} else { | |
if (previousSibling) { | |
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling); | |
} | |
} | |
} | |
function secondWalk(node, x) { | |
node.x = node._tree.prelim + x; | |
var children = node.children; | |
if (children && (n = children.length)) { | |
var i = -1, n; | |
x += node._tree.mod; | |
while (++i < n) { | |
secondWalk(children[i], x); | |
} | |
} | |
} | |
function apportion(node, previousSibling, ancestor) { | |
if (previousSibling) { | |
var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift; | |
while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { | |
vom = d3_layout_treeLeft(vom); | |
vop = d3_layout_treeRight(vop); | |
vop._tree.ancestor = node; | |
shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip); | |
if (shift > 0) { | |
d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift); | |
sip += shift; | |
sop += shift; | |
} | |
sim += vim._tree.mod; | |
sip += vip._tree.mod; | |
som += vom._tree.mod; | |
sop += vop._tree.mod; | |
} | |
if (vim && !d3_layout_treeRight(vop)) { | |
vop._tree.thread = vim; | |
vop._tree.mod += sim - sop; | |
} | |
if (vip && !d3_layout_treeLeft(vom)) { | |
vom._tree.thread = vip; | |
vom._tree.mod += sip - som; | |
ancestor = node; | |
} | |
} | |
return ancestor; | |
} | |
d3_layout_treeVisitAfter(root, function(node, previousSibling) { | |
node._tree = { | |
ancestor: node, | |
prelim: 0, | |
mod: 0, | |
change: 0, | |
shift: 0, | |
number: previousSibling ? previousSibling._tree.number + 1 : 0 | |
}; | |
}); | |
firstWalk(root); | |
secondWalk(root, -root._tree.prelim); | |
var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1; | |
d3_layout_treeVisitAfter(root, function(node) { | |
node.x = (node.x - x0) / (x1 - x0) * size[0]; | |
node.y = node.depth / y1 * size[1]; | |
delete node._tree; | |
}); | |
return nodes; | |
} | |
tree.separation = function(x) { | |
if (!arguments.length) return separation; | |
separation = x; | |
return tree; | |
}; | |
tree.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return tree; | |
}; | |
return d3_layout_hierarchyRebind(tree, hierarchy); | |
}; | |
function d3_layout_treeSeparation(a, b) { | |
return a.parent == b.parent ? 1 : 2; | |
} | |
function d3_layout_treeLeft(node) { | |
var children = node.children; | |
return children && children.length ? children[0] : node._tree.thread; | |
} | |
function d3_layout_treeRight(node) { | |
var children = node.children, n; | |
return children && (n = children.length) ? children[n - 1] : node._tree.thread; | |
} | |
function d3_layout_treeSearch(node, compare) { | |
var children = node.children; | |
if (children && (n = children.length)) { | |
var child, n, i = -1; | |
while (++i < n) { | |
if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) { | |
node = child; | |
} | |
} | |
} | |
return node; | |
} | |
function d3_layout_treeRightmost(a, b) { | |
return a.x - b.x; | |
} | |
function d3_layout_treeLeftmost(a, b) { | |
return b.x - a.x; | |
} | |
function d3_layout_treeDeepest(a, b) { | |
return a.depth - b.depth; | |
} | |
function d3_layout_treeVisitAfter(node, callback) { | |
function visit(node, previousSibling) { | |
var children = node.children; | |
if (children && (n = children.length)) { | |
var child, previousChild = null, i = -1, n; | |
while (++i < n) { | |
child = children[i]; | |
visit(child, previousChild); | |
previousChild = child; | |
} | |
} | |
callback(node, previousSibling); | |
} | |
visit(node, null); | |
} | |
function d3_layout_treeShift(node) { | |
var shift = 0, change = 0, children = node.children, i = children.length, child; | |
while (--i >= 0) { | |
child = children[i]._tree; | |
child.prelim += shift; | |
child.mod += shift; | |
shift += child.shift + (change += child.change); | |
} | |
} | |
function d3_layout_treeMove(ancestor, node, shift) { | |
ancestor = ancestor._tree; | |
node = node._tree; | |
var change = shift / (node.number - ancestor.number); | |
ancestor.change += change; | |
node.change -= change; | |
node.shift += shift; | |
node.prelim += shift; | |
node.mod += shift; | |
} | |
function d3_layout_treeAncestor(vim, node, ancestor) { | |
return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor; | |
} | |
d3.layout.treemap = function() { | |
var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); | |
function scale(children, k) { | |
var i = -1, n = children.length, child, area; | |
while (++i < n) { | |
area = (child = children[i]).value * (k < 0 ? 0 : k); | |
child.area = isNaN(area) || area <= 0 ? 0 : area; | |
} | |
} | |
function squarify(node) { | |
var children = node.children; | |
if (children && children.length) { | |
var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; | |
scale(remaining, rect.dx * rect.dy / node.value); | |
row.area = 0; | |
while ((n = remaining.length) > 0) { | |
row.push(child = remaining[n - 1]); | |
row.area += child.area; | |
if (mode !== "squarify" || (score = worst(row, u)) <= best) { | |
remaining.pop(); | |
best = score; | |
} else { | |
row.area -= row.pop().area; | |
position(row, u, rect, false); | |
u = Math.min(rect.dx, rect.dy); | |
row.length = row.area = 0; | |
best = Infinity; | |
} | |
} | |
if (row.length) { | |
position(row, u, rect, true); | |
row.length = row.area = 0; | |
} | |
children.forEach(squarify); | |
} | |
} | |
function stickify(node) { | |
var children = node.children; | |
if (children && children.length) { | |
var rect = pad(node), remaining = children.slice(), child, row = []; | |
scale(remaining, rect.dx * rect.dy / node.value); | |
row.area = 0; | |
while (child = remaining.pop()) { | |
row.push(child); | |
row.area += child.area; | |
if (child.z != null) { | |
position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); | |
row.length = row.area = 0; | |
} | |
} | |
children.forEach(stickify); | |
} | |
} | |
function worst(row, u) { | |
var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; | |
while (++i < n) { | |
if (!(r = row[i].area)) continue; | |
if (r < rmin) rmin = r; | |
if (r > rmax) rmax = r; | |
} | |
s *= s; | |
u *= u; | |
return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; | |
} | |
function position(row, u, rect, flush) { | |
var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; | |
if (u == rect.dx) { | |
if (flush || v > rect.dy) v = rect.dy; | |
while (++i < n) { | |
o = row[i]; | |
o.x = x; | |
o.y = y; | |
o.dy = v; | |
x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); | |
} | |
o.z = true; | |
o.dx += rect.x + rect.dx - x; | |
rect.y += v; | |
rect.dy -= v; | |
} else { | |
if (flush || v > rect.dx) v = rect.dx; | |
while (++i < n) { | |
o = row[i]; | |
o.x = x; | |
o.y = y; | |
o.dx = v; | |
y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); | |
} | |
o.z = false; | |
o.dy += rect.y + rect.dy - y; | |
rect.x += v; | |
rect.dx -= v; | |
} | |
} | |
function treemap(d) { | |
var nodes = stickies || hierarchy(d), root = nodes[0]; | |
root.x = 0; | |
root.y = 0; | |
root.dx = size[0]; | |
root.dy = size[1]; | |
if (stickies) hierarchy.revalue(root); | |
scale([ root ], root.dx * root.dy / root.value); | |
(stickies ? stickify : squarify)(root); | |
if (sticky) stickies = nodes; | |
return nodes; | |
} | |
treemap.size = function(x) { | |
if (!arguments.length) return size; | |
size = x; | |
return treemap; | |
}; | |
treemap.padding = function(x) { | |
if (!arguments.length) return padding; | |
function padFunction(node) { | |
var p = x.call(treemap, node, node.depth); | |
return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); | |
} | |
function padConstant(node) { | |
return d3_layout_treemapPad(node, x); | |
} | |
var type; | |
pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], | |
padConstant) : padConstant; | |
return treemap; | |
}; | |
treemap.round = function(x) { | |
if (!arguments.length) return round != Number; | |
round = x ? Math.round : Number; | |
return treemap; | |
}; | |
treemap.sticky = function(x) { | |
if (!arguments.length) return sticky; | |
sticky = x; | |
stickies = null; | |
return treemap; | |
}; | |
treemap.ratio = function(x) { | |
if (!arguments.length) return ratio; | |
ratio = x; | |
return treemap; | |
}; | |
treemap.mode = function(x) { | |
if (!arguments.length) return mode; | |
mode = x + ""; | |
return treemap; | |
}; | |
return d3_layout_hierarchyRebind(treemap, hierarchy); | |
}; | |
function d3_layout_treemapPadNull(node) { | |
return { | |
x: node.x, | |
y: node.y, | |
dx: node.dx, | |
dy: node.dy | |
}; | |
} | |
function d3_layout_treemapPad(node, padding) { | |
var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; | |
if (dx < 0) { | |
x += dx / 2; | |
dx = 0; | |
} | |
if (dy < 0) { | |
y += dy / 2; | |
dy = 0; | |
} | |
return { | |
x: x, | |
y: y, | |
dx: dx, | |
dy: dy | |
}; | |
} | |
function d3_dsv(delimiter, mimeType) { | |
var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); | |
function dsv(url, callback) { | |
return d3.xhr(url, mimeType, callback).response(response); | |
} | |
function response(request) { | |
return dsv.parse(request.responseText); | |
} | |
dsv.parse = function(text) { | |
var o; | |
return dsv.parseRows(text, function(row) { | |
if (o) return o(row); | |
o = new Function("d", "return {" + row.map(function(name, i) { | |
return JSON.stringify(name) + ": d[" + i + "]"; | |
}).join(",") + "}"); | |
}); | |
}; | |
dsv.parseRows = function(text, f) { | |
var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; | |
function token() { | |
if (I >= N) return EOF; | |
if (eol) return eol = false, EOL; | |
var j = I; | |
if (text.charCodeAt(j) === 34) { | |
var i = j; | |
while (i++ < N) { | |
if (text.charCodeAt(i) === 34) { | |
if (text.charCodeAt(i + 1) !== 34) break; | |
++i; | |
} | |
} | |
I = i + 2; | |
var c = text.charCodeAt(i + 1); | |
if (c === 13) { | |
eol = true; | |
if (text.charCodeAt(i + 2) === 10) ++I; | |
} else if (c === 10) { | |
eol = true; | |
} | |
return text.substring(j + 1, i).replace(/""/g, '"'); | |
} | |
while (I < N) { | |
var c = text.charCodeAt(I++), k = 1; | |
if (c === 10) eol = true; else if (c === 13) { | |
eol = true; | |
if (text.charCodeAt(I) === 10) ++I, ++k; | |
} else if (c !== delimiterCode) continue; | |
return text.substring(j, I - k); | |
} | |
return text.substring(j); | |
} | |
while ((t = token()) !== EOF) { | |
var a = []; | |
while (t !== EOL && t !== EOF) { | |
a.push(t); | |
t = token(); | |
} | |
if (f && !(a = f(a, n++))) continue; | |
rows.push(a); | |
} | |
return rows; | |
}; | |
dsv.format = function(rows) { | |
return rows.map(formatRow).join("\n"); | |
}; | |
function formatRow(row) { | |
return row.map(formatValue).join(delimiter); | |
} | |
function formatValue(text) { | |
return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; | |
} | |
return dsv; | |
} | |
d3.csv = d3_dsv(",", "text/csv"); | |
d3.tsv = d3_dsv(" ", "text/tab-separated-values"); | |
d3.geo = {}; | |
d3.geo.stream = function(object, listener) { | |
if (d3_geo_streamObjectType.hasOwnProperty(object.type)) { | |
d3_geo_streamObjectType[object.type](object, listener); | |
} else { | |
d3_geo_streamGeometry(object, listener); | |
} | |
}; | |
function d3_geo_streamGeometry(geometry, listener) { | |
if (d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { | |
d3_geo_streamGeometryType[geometry.type](geometry, listener); | |
} | |
} | |
var d3_geo_streamObjectType = { | |
Feature: function(feature, listener) { | |
d3_geo_streamGeometry(feature.geometry, listener); | |
}, | |
FeatureCollection: function(object, listener) { | |
var features = object.features, i = -1, n = features.length; | |
while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); | |
} | |
}; | |
var d3_geo_streamGeometryType = { | |
Sphere: function(object, listener) { | |
listener.sphere(); | |
}, | |
Point: function(object, listener) { | |
var coordinate = object.coordinates; | |
listener.point(coordinate[0], coordinate[1]); | |
}, | |
MultiPoint: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate; | |
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]); | |
}, | |
LineString: function(object, listener) { | |
d3_geo_streamLine(object.coordinates, listener, 0); | |
}, | |
MultiLineString: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); | |
}, | |
Polygon: function(object, listener) { | |
d3_geo_streamPolygon(object.coordinates, listener); | |
}, | |
MultiPolygon: function(object, listener) { | |
var coordinates = object.coordinates, i = -1, n = coordinates.length; | |
while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); | |
}, | |
GeometryCollection: function(object, listener) { | |
var geometries = object.geometries, i = -1, n = geometries.length; | |
while (++i < n) d3_geo_streamGeometry(geometries[i], listener); | |
} | |
}; | |
function d3_geo_streamLine(coordinates, listener, closed) { | |
var i = -1, n = coordinates.length - closed, coordinate; | |
listener.lineStart(); | |
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]); | |
listener.lineEnd(); | |
} | |
function d3_geo_streamPolygon(coordinates, listener) { | |
var i = -1, n = coordinates.length; | |
listener.polygonStart(); | |
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); | |
listener.polygonEnd(); | |
} | |
function d3_geo_spherical(cartesian) { | |
return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ]; | |
} | |
function d3_geo_sphericalEqual(a, b) { | |
return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; | |
} | |
function d3_geo_cartesian(spherical) { | |
var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); | |
return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; | |
} | |
function d3_geo_cartesianDot(a, b) { | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
} | |
function d3_geo_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] ]; | |
} | |
function d3_geo_cartesianAdd(a, b) { | |
a[0] += b[0]; | |
a[1] += b[1]; | |
a[2] += b[2]; | |
} | |
function d3_geo_cartesianScale(vector, k) { | |
return [ vector[0] * k, vector[1] * k, vector[2] * k ]; | |
} | |
function d3_geo_cartesianNormalize(d) { | |
var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); | |
d[0] /= l; | |
d[1] /= l; | |
d[2] /= l; | |
} | |
function d3_geo_resample(project) { | |
var δ2 = .5, maxDepth = 16; | |
function resample(stream) { | |
var λ0, x0, y0, a0, b0, c0; | |
var resample = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.polygonStart(); | |
resample.lineStart = polygonLineStart; | |
}, | |
polygonEnd: function() { | |
stream.polygonEnd(); | |
resample.lineStart = lineStart; | |
} | |
}; | |
function point(x, y) { | |
x = project(x, y); | |
stream.point(x[0], x[1]); | |
} | |
function lineStart() { | |
x0 = NaN; | |
resample.point = linePoint; | |
stream.lineStart(); | |
} | |
function linePoint(λ, φ) { | |
var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); | |
stream.point(x0, y0); | |
} | |
function lineEnd() { | |
resample.point = point; | |
stream.lineEnd(); | |
} | |
function polygonLineStart() { | |
var λ00, φ00, x00, y00, a00, b00, c00; | |
lineStart(); | |
resample.point = function(λ, φ) { | |
linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; | |
resample.point = linePoint; | |
}; | |
resample.lineEnd = function() { | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); | |
resample.lineEnd = lineEnd; | |
lineEnd(); | |
}; | |
} | |
return resample; | |
} | |
function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { | |
var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; | |
if (d2 > 4 * δ2 && depth--) { | |
var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; | |
if (dz * dz / d2 > δ2 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) { | |
resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); | |
stream.point(x2, y2); | |
resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); | |
} | |
} | |
} | |
resample.precision = function(_) { | |
if (!arguments.length) return Math.sqrt(δ2); | |
maxDepth = (δ2 = _ * _) > 0 && 16; | |
return resample; | |
}; | |
return resample; | |
} | |
d3.geo.albersUsa = function() { | |
var lower48 = d3.geo.albers(); | |
var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]); | |
var hawaii = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 20 ]).parallels([ 8, 18 ]); | |
var puertoRico = d3.geo.albers().rotate([ 60, 0 ]).center([ 0, 10 ]).parallels([ 8, 18 ]); | |
function albersUsa(coordinates) { | |
return projection(coordinates)(coordinates); | |
} | |
function projection(point) { | |
var lon = point[0], lat = point[1]; | |
return lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48; | |
} | |
albersUsa.scale = function(x) { | |
if (!arguments.length) return lower48.scale(); | |
lower48.scale(x); | |
alaska.scale(x * .6); | |
hawaii.scale(x); | |
puertoRico.scale(x * 1.5); | |
return albersUsa.translate(lower48.translate()); | |
}; | |
albersUsa.translate = function(x) { | |
if (!arguments.length) return lower48.translate(); | |
var dz = lower48.scale(), dx = x[0], dy = x[1]; | |
lower48.translate(x); | |
alaska.translate([ dx - .4 * dz, dy + .17 * dz ]); | |
hawaii.translate([ dx - .19 * dz, dy + .2 * dz ]); | |
puertoRico.translate([ dx + .58 * dz, dy + .43 * dz ]); | |
return albersUsa; | |
}; | |
return albersUsa.scale(lower48.scale()); | |
}; | |
function d3_geo_albers(φ0, φ1) { | |
var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; | |
function albers(λ, φ) { | |
var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; | |
return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; | |
} | |
albers.invert = function(x, y) { | |
var ρ0_y = ρ0 - y; | |
return [ Math.atan2(x, ρ0_y) / n, Math.asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; | |
}; | |
return albers; | |
} | |
(d3.geo.albers = function() { | |
var φ0 = 29.5 * d3_radians, φ1 = 45.5 * d3_radians, m = d3_geo_projectionMutator(d3_geo_albers), p = m(φ0, φ1); | |
p.parallels = function(_) { | |
if (!arguments.length) return [ φ0 * d3_degrees, φ1 * d3_degrees ]; | |
return m(φ0 = _[0] * d3_radians, φ1 = _[1] * d3_radians); | |
}; | |
return p.rotate([ 98, 0 ]).center([ 0, 38 ]).scale(1e3); | |
}).raw = d3_geo_albers; | |
var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { | |
return Math.sqrt(2 / (1 + cosλcosφ)); | |
}, function(ρ) { | |
return 2 * Math.asin(ρ / 2); | |
}); | |
(d3.geo.azimuthalEqualArea = function() { | |
return d3_geo_projection(d3_geo_azimuthalEqualArea); | |
}).raw = d3_geo_azimuthalEqualArea; | |
var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { | |
var c = Math.acos(cosλcosφ); | |
return c && c / Math.sin(c); | |
}, d3_identity); | |
(d3.geo.azimuthalEquidistant = function() { | |
return d3_geo_projection(d3_geo_azimuthalEquidistant); | |
}).raw = d3_geo_azimuthalEquidistant; | |
d3.geo.bounds = d3_geo_bounds(d3_identity); | |
function d3_geo_bounds(projectStream) { | |
var x0, y0, x1, y1; | |
var bound = { | |
point: boundPoint, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: function() { | |
bound.lineEnd = boundPolygonLineEnd; | |
}, | |
polygonEnd: function() { | |
bound.point = boundPoint; | |
} | |
}; | |
function boundPoint(x, y) { | |
if (x < x0) x0 = x; | |
if (x > x1) x1 = x; | |
if (y < y0) y0 = y; | |
if (y > y1) y1 = y; | |
} | |
function boundPolygonLineEnd() { | |
bound.point = bound.lineEnd = d3_noop; | |
} | |
return function(feature) { | |
y1 = x1 = -(x0 = y0 = Infinity); | |
d3.geo.stream(feature, projectStream(bound)); | |
return [ [ x0, y0 ], [ x1, y1 ] ]; | |
}; | |
} | |
d3.geo.centroid = function(object) { | |
d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
d3.geo.stream(object, d3_geo_centroid); | |
var m; | |
if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) { | |
return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ]; | |
} | |
}; | |
var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ; | |
var d3_geo_centroid = { | |
sphere: function() { | |
if (d3_geo_centroidDimension < 2) { | |
d3_geo_centroidDimension = 2; | |
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
} | |
}, | |
point: d3_geo_centroidPoint, | |
lineStart: d3_geo_centroidLineStart, | |
lineEnd: d3_geo_centroidLineEnd, | |
polygonStart: function() { | |
if (d3_geo_centroidDimension < 2) { | |
d3_geo_centroidDimension = 2; | |
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
} | |
d3_geo_centroid.lineStart = d3_geo_centroidRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_centroid.lineStart = d3_geo_centroidLineStart; | |
} | |
}; | |
function d3_geo_centroidPoint(λ, φ) { | |
if (d3_geo_centroidDimension) return; | |
++d3_geo_centroidW; | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians); | |
d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW; | |
d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW; | |
d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW; | |
} | |
function d3_geo_centroidRingStart() { | |
var λ00, φ00; | |
d3_geo_centroidDimension = 1; | |
d3_geo_centroidLineStart(); | |
d3_geo_centroidDimension = 2; | |
var linePoint = d3_geo_centroid.point; | |
d3_geo_centroid.point = function(λ, φ) { | |
linePoint(λ00 = λ, φ00 = φ); | |
}; | |
d3_geo_centroid.lineEnd = function() { | |
d3_geo_centroid.point(λ00, φ00); | |
d3_geo_centroidLineEnd(); | |
d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; | |
}; | |
} | |
function d3_geo_centroidLineStart() { | |
var x0, y0, z0; | |
if (d3_geo_centroidDimension > 1) return; | |
if (d3_geo_centroidDimension < 1) { | |
d3_geo_centroidDimension = 1; | |
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
} | |
d3_geo_centroid.point = function(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians); | |
x0 = cosφ * Math.cos(λ); | |
y0 = cosφ * Math.sin(λ); | |
z0 = Math.sin(φ); | |
d3_geo_centroid.point = nextPoint; | |
}; | |
function nextPoint(λ, φ) { | |
λ *= d3_radians; | |
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.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); | |
d3_geo_centroidW += w; | |
d3_geo_centroidX += w * (x0 + (x0 = x)); | |
d3_geo_centroidY += w * (y0 + (y0 = y)); | |
d3_geo_centroidZ += w * (z0 + (z0 = z)); | |
} | |
} | |
function d3_geo_centroidLineEnd() { | |
d3_geo_centroid.point = d3_geo_centroidPoint; | |
} | |
d3.geo.circle = function() { | |
var origin = [ 0, 0 ], angle, precision = 6, interpolate; | |
function circle() { | |
var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; | |
interpolate(null, null, 1, { | |
point: function(x, y) { | |
ring.push(x = rotate(x, y)); | |
x[0] *= d3_degrees, x[1] *= d3_degrees; | |
} | |
}); | |
return { | |
type: "Polygon", | |
coordinates: [ ring ] | |
}; | |
} | |
circle.origin = function(x) { | |
if (!arguments.length) return origin; | |
origin = x; | |
return circle; | |
}; | |
circle.angle = function(x) { | |
if (!arguments.length) return angle; | |
interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); | |
return circle; | |
}; | |
circle.precision = function(_) { | |
if (!arguments.length) return precision; | |
interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); | |
return circle; | |
}; | |
return circle.angle(90); | |
}; | |
function d3_geo_circleInterpolate(radians, precision) { | |
var cr = Math.cos(radians), sr = Math.sin(radians); | |
return function(from, to, direction, listener) { | |
if (from != null) { | |
from = d3_geo_circleAngle(cr, from); | |
to = d3_geo_circleAngle(cr, to); | |
if (direction > 0 ? from < to : from > to) from += direction * 2 * π; | |
} else { | |
from = radians + direction * 2 * π; | |
to = radians; | |
} | |
var point; | |
for (var step = direction * precision, t = from; direction > 0 ? t > to : t < to; t -= step) { | |
listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); | |
} | |
}; | |
} | |
function d3_geo_circleAngle(cr, point) { | |
var a = d3_geo_cartesian(point); | |
a[0] -= cr; | |
d3_geo_cartesianNormalize(a); | |
var angle = Math.acos(Math.max(-1, Math.min(1, -a[1]))); | |
return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); | |
} | |
function d3_geo_clip(pointVisible, clipLine, interpolate) { | |
return function(listener) { | |
var line = clipLine(listener); | |
var clip = { | |
point: point, | |
lineStart: lineStart, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
clip.point = pointRing; | |
clip.lineStart = ringStart; | |
clip.lineEnd = ringEnd; | |
invisible = false; | |
invisibleArea = visibleArea = 0; | |
segments = []; | |
listener.polygonStart(); | |
}, | |
polygonEnd: function() { | |
clip.point = point; | |
clip.lineStart = lineStart; | |
clip.lineEnd = lineEnd; | |
segments = d3.merge(segments); | |
if (segments.length) { | |
d3_geo_clipPolygon(segments, interpolate, listener); | |
} else if (visibleArea < -ε || invisible && invisibleArea < -ε) { | |
listener.lineStart(); | |
interpolate(null, null, 1, listener); | |
listener.lineEnd(); | |
} | |
listener.polygonEnd(); | |
segments = null; | |
}, | |
sphere: function() { | |
listener.polygonStart(); | |
listener.lineStart(); | |
interpolate(null, null, 1, listener); | |
listener.lineEnd(); | |
listener.polygonEnd(); | |
} | |
}; | |
function point(λ, φ) { | |
if (pointVisible(λ, φ)) listener.point(λ, φ); | |
} | |
function pointLine(λ, φ) { | |
line.point(λ, φ); | |
} | |
function lineStart() { | |
clip.point = pointLine; | |
line.lineStart(); | |
} | |
function lineEnd() { | |
clip.point = point; | |
line.lineEnd(); | |
} | |
var segments, visibleArea, invisibleArea, invisible; | |
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring; | |
function pointRing(λ, φ) { | |
ringListener.point(λ, φ); | |
ring.push([ λ, φ ]); | |
} | |
function ringStart() { | |
ringListener.lineStart(); | |
ring = []; | |
} | |
function ringEnd() { | |
pointRing(ring[0][0], ring[0][1]); | |
ringListener.lineEnd(); | |
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; | |
if (!n) { | |
invisible = true; | |
invisibleArea += d3_geo_clipAreaRing(ring, -1); | |
ring = null; | |
return; | |
} | |
ring = null; | |
if (clean & 1) { | |
segment = ringSegments[0]; | |
visibleArea += d3_geo_clipAreaRing(segment, 1); | |
var n = segment.length - 1, i = -1, point; | |
listener.lineStart(); | |
while (++i < n) listener.point((point = segment[i])[0], point[1]); | |
listener.lineEnd(); | |
return; | |
} | |
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); | |
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); | |
} | |
return clip; | |
}; | |
} | |
function d3_geo_clipPolygon(segments, interpolate, listener) { | |
var subject = [], clip = []; | |
segments.forEach(function(segment) { | |
var n = segment.length; | |
if (n <= 1) return; | |
var p0 = segment[0], p1 = segment[n - 1], a = { | |
point: p0, | |
points: segment, | |
other: null, | |
visited: false, | |
entry: true, | |
subject: true | |
}, b = { | |
point: p0, | |
points: [ p0 ], | |
other: a, | |
visited: false, | |
entry: false, | |
subject: false | |
}; | |
a.other = b; | |
subject.push(a); | |
clip.push(b); | |
a = { | |
point: p1, | |
points: [ p1 ], | |
other: null, | |
visited: false, | |
entry: false, | |
subject: true | |
}; | |
b = { | |
point: p1, | |
points: [ p1 ], | |
other: a, | |
visited: false, | |
entry: true, | |
subject: false | |
}; | |
a.other = b; | |
subject.push(a); | |
clip.push(b); | |
}); | |
clip.sort(d3_geo_clipSort); | |
d3_geo_clipLinkCircular(subject); | |
d3_geo_clipLinkCircular(clip); | |
if (!subject.length) return; | |
var start = subject[0], current, points, point; | |
while (1) { | |
current = start; | |
while (current.visited) if ((current = current.next) === start) return; | |
points = current.points; | |
listener.lineStart(); | |
do { | |
current.visited = current.other.visited = true; | |
if (current.entry) { | |
if (current.subject) { | |
for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.point, current.next.point, 1, listener); | |
} | |
current = current.next; | |
} else { | |
if (current.subject) { | |
points = current.prev.points; | |
for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]); | |
} else { | |
interpolate(current.point, current.prev.point, -1, listener); | |
} | |
current = current.prev; | |
} | |
current = current.other; | |
points = current.points; | |
} while (!current.visited); | |
listener.lineEnd(); | |
} | |
} | |
function d3_geo_clipLinkCircular(array) { | |
if (!(n = array.length)) return; | |
var n, i = 0, a = array[0], b; | |
while (++i < n) { | |
a.next = b = array[i]; | |
b.prev = a; | |
a = b; | |
} | |
a.next = b = array[0]; | |
b.prev = a; | |
} | |
function d3_geo_clipSort(a, b) { | |
return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]); | |
} | |
function d3_geo_clipSegmentLength1(segment) { | |
return segment.length > 1; | |
} | |
function d3_geo_clipBufferListener() { | |
var lines = [], line; | |
return { | |
lineStart: function() { | |
lines.push(line = []); | |
}, | |
point: function(λ, φ) { | |
line.push([ λ, φ ]); | |
}, | |
lineEnd: d3_noop, | |
buffer: function() { | |
var buffer = lines; | |
lines = []; | |
line = null; | |
return buffer; | |
} | |
}; | |
} | |
function d3_geo_clipAreaRing(ring, invisible) { | |
if (!(n = ring.length)) return 0; | |
var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y; | |
while (++i < n) { | |
p = ring[i]; | |
cosφ = Math.cos(φ = p[1]); | |
x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ)); | |
y = 1 - invisible * Math.cos(λ) * cosφ; | |
if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue; | |
if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) { | |
if (y + y0 > 2) area += 4 * (x - x0); | |
} else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y); | |
x1 = x0, x0 = x, y0 = y; | |
} | |
return area; | |
} | |
var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate); | |
function d3_geo_clipAntimeridianLine(listener) { | |
var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; | |
return { | |
lineStart: function() { | |
listener.lineStart(); | |
clean = 1; | |
}, | |
point: function(λ1, φ1) { | |
var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0); | |
if (Math.abs(dλ - π) < ε) { | |
listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2); | |
listener.point(sλ0, φ0); | |
listener.lineEnd(); | |
listener.lineStart(); | |
listener.point(sλ1, φ0); | |
listener.point(λ1, φ0); | |
clean = 0; | |
} else if (sλ0 !== sλ1 && dλ >= π) { | |
if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; | |
if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; | |
φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); | |
listener.point(sλ0, φ0); | |
listener.lineEnd(); | |
listener.lineStart(); | |
listener.point(sλ1, φ0); | |
clean = 0; | |
} | |
listener.point(λ0 = λ1, φ0 = φ1); | |
sλ0 = sλ1; | |
}, | |
lineEnd: function() { | |
listener.lineEnd(); | |
λ0 = φ0 = NaN; | |
}, | |
clean: function() { | |
return 2 - clean; | |
} | |
}; | |
} | |
function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { | |
var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); | |
return Math.abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; | |
} | |
function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { | |
var φ; | |
if (from == null) { | |
φ = direction * π / 2; | |
listener.point(-π, φ); | |
listener.point(0, φ); | |
listener.point(π, φ); | |
listener.point(π, 0); | |
listener.point(π, -φ); | |
listener.point(0, -φ); | |
listener.point(-π, -φ); | |
listener.point(-π, 0); | |
listener.point(-π, φ); | |
} else if (Math.abs(from[0] - to[0]) > ε) { | |
var s = (from[0] < to[0] ? 1 : -1) * π; | |
φ = direction * s / 2; | |
listener.point(-s, φ); | |
listener.point(0, φ); | |
listener.point(s, φ); | |
} else { | |
listener.point(to[0], to[1]); | |
} | |
} | |
function d3_geo_clipCircle(degrees) { | |
var radians = degrees * d3_radians, cr = Math.cos(radians), interpolate = d3_geo_circleInterpolate(radians, 6 * d3_radians); | |
return d3_geo_clip(visible, clipLine, interpolate); | |
function visible(λ, φ) { | |
return Math.cos(λ) * Math.cos(φ) > cr; | |
} | |
function clipLine(listener) { | |
var point0, v0, v00, clean; | |
return { | |
lineStart: function() { | |
v00 = v0 = false; | |
clean = 1; | |
}, | |
point: function(λ, φ) { | |
var point1 = [ λ, φ ], point2, v = visible(λ, φ); | |
if (!point0 && (v00 = v0 = v)) listener.lineStart(); | |
if (v !== v0) { | |
point2 = intersect(point0, point1); | |
if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { | |
point1[0] += ε; | |
point1[1] += ε; | |
v = visible(point1[0], point1[1]); | |
} | |
} | |
if (v !== v0) { | |
clean = 0; | |
if (v0 = v) { | |
listener.lineStart(); | |
point2 = intersect(point1, point0); | |
listener.point(point2[0], point2[1]); | |
} else { | |
point2 = intersect(point0, point1); | |
listener.point(point2[0], point2[1]); | |
listener.lineEnd(); | |
} | |
point0 = point2; | |
} | |
if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) listener.point(point1[0], point1[1]); | |
point0 = point1; | |
}, | |
lineEnd: function() { | |
if (v0) listener.lineEnd(); | |
point0 = null; | |
}, | |
clean: function() { | |
return clean | (v00 && v0) << 1; | |
} | |
}; | |
} | |
function intersect(a, b) { | |
var pa = d3_geo_cartesian(a, 0), pb = d3_geo_cartesian(b, 0); | |
var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; | |
if (!determinant) return a; | |
var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); | |
d3_geo_cartesianAdd(A, B); | |
var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t = Math.sqrt(w * w - uu * (d3_geo_cartesianDot(A, A) - 1)), q = d3_geo_cartesianScale(u, (-w - t) / uu); | |
d3_geo_cartesianAdd(q, A); | |
return d3_geo_spherical(q); | |
} | |
} | |
function d3_geo_compose(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), a.invert(x[0], x[1]); | |
}; | |
return compose; | |
} | |
function d3_geo_equirectangular(λ, φ) { | |
return [ λ, φ ]; | |
} | |
(d3.geo.equirectangular = function() { | |
return d3_geo_projection(d3_geo_equirectangular).scale(250 / π); | |
}).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; | |
var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { | |
return 1 / cosλcosφ; | |
}, Math.atan); | |
(d3.geo.gnomonic = function() { | |
return d3_geo_projection(d3_geo_gnomonic); | |
}).raw = d3_geo_gnomonic; | |
d3.geo.graticule = function() { | |
var x1, x0, y1, y0, dx = 22.5, dy = dx, x, y, precision = 2.5; | |
function graticule() { | |
return { | |
type: "MultiLineString", | |
coordinates: lines() | |
}; | |
} | |
function lines() { | |
return d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(x).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).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 [ [ 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 [ dx, dy ]; | |
dx = +_[0], dy = +_[1]; | |
return graticule; | |
}; | |
graticule.precision = function(_) { | |
if (!arguments.length) return precision; | |
precision = +_; | |
x = d3_geo_graticuleX(y0, y1, precision); | |
y = d3_geo_graticuleY(x0, x1, precision); | |
return graticule; | |
}; | |
return graticule.extent([ [ -180 + ε, -90 + ε ], [ 180 - ε, 90 - ε ] ]); | |
}; | |
function d3_geo_graticuleX(y0, y1, dy) { | |
var y = d3.range(y0, y1 - ε, dy).concat(y1); | |
return function(x) { | |
return y.map(function(y) { | |
return [ x, y ]; | |
}); | |
}; | |
} | |
function d3_geo_graticuleY(x0, x1, dx) { | |
var x = d3.range(x0, x1 - ε, dx).concat(x1); | |
return function(y) { | |
return x.map(function(x) { | |
return [ x, y ]; | |
}); | |
}; | |
} | |
d3.geo.interpolate = function(source, target) { | |
return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); | |
}; | |
function d3_geo_interpolate(x0, y0, x1, y1) { | |
var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))), k = 1 / Math.sin(d); | |
function interpolate(t) { | |
var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; | |
return [ Math.atan2(y, x) / d3_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians ]; | |
} | |
interpolate.distance = d; | |
return interpolate; | |
} | |
d3.geo.greatArc = function() { | |
var source = d3_source, s, target = d3_target, t, precision = 6 * d3_radians, interpolate; | |
function greatArc() { | |
var p0 = s || source.apply(this, arguments), p1 = t || target.apply(this, arguments), i = interpolate || d3.geo.interpolate(p0, p1), t = 0, dt = precision / i.distance, coordinates = [ p0 ]; | |
while ((t += dt) < 1) coordinates.push(i(t)); | |
coordinates.push(p1); | |
return { | |
type: "LineString", | |
coordinates: coordinates | |
}; | |
} | |
greatArc.distance = function() { | |
return (interpolate || d3.geo.interpolate(s || source.apply(this, arguments), t || target.apply(this, arguments))).distance; | |
}; | |
greatArc.source = function(_) { | |
if (!arguments.length) return source; | |
source = _, s = typeof _ === "function" ? null : _; | |
interpolate = s && t ? d3.geo.interpolate(s, t) : null; | |
return greatArc; | |
}; | |
greatArc.target = function(_) { | |
if (!arguments.length) return target; | |
target = _, t = typeof _ === "function" ? null : _; | |
interpolate = s && t ? d3.geo.interpolate(s, t) : null; | |
return greatArc; | |
}; | |
greatArc.precision = function(_) { | |
if (!arguments.length) return precision / d3_radians; | |
precision = _ * d3_radians; | |
return greatArc; | |
}; | |
return greatArc; | |
}; | |
function d3_geo_mercator(λ, φ) { | |
return [ λ / (2 * π), Math.max(-.5, Math.min(+.5, Math.log(Math.tan(π / 4 + φ / 2)) / (2 * π))) ]; | |
} | |
d3_geo_mercator.invert = function(x, y) { | |
return [ 2 * π * x, 2 * Math.atan(Math.exp(2 * π * y)) - π / 2 ]; | |
}; | |
(d3.geo.mercator = function() { | |
return d3_geo_projection(d3_geo_mercator).scale(500); | |
}).raw = d3_geo_mercator; | |
var d3_geo_orthographic = d3_geo_azimuthal(function() { | |
return 1; | |
}, Math.asin); | |
(d3.geo.orthographic = function() { | |
return d3_geo_projection(d3_geo_orthographic); | |
}).raw = d3_geo_orthographic; | |
d3.geo.path = function() { | |
var pointRadius = 4.5, projection, context, projectStream, contextStream; | |
function path(object) { | |
if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius))); | |
return contextStream.result(); | |
} | |
path.area = function(object) { | |
d3_geo_pathAreaSum = 0; | |
d3.geo.stream(object, projectStream(d3_geo_pathArea)); | |
return d3_geo_pathAreaSum; | |
}; | |
path.centroid = function(object) { | |
d3_geo_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); | |
return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined; | |
}; | |
path.bounds = function(object) { | |
return d3_geo_bounds(projectStream)(object); | |
}; | |
path.projection = function(_) { | |
if (!arguments.length) return projection; | |
projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; | |
return path; | |
}; | |
path.context = function(_) { | |
if (!arguments.length) return context; | |
contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); | |
return path; | |
}; | |
path.pointRadius = function(_) { | |
if (!arguments.length) return pointRadius; | |
pointRadius = typeof _ === "function" ? _ : +_; | |
return path; | |
}; | |
return path.projection(d3.geo.albersUsa()).context(null); | |
}; | |
function d3_geo_pathCircle(radius) { | |
return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + +2 * radius + "z"; | |
} | |
function d3_geo_pathProjectStream(project) { | |
var resample = d3_geo_resample(function(λ, φ) { | |
return project([ λ * d3_degrees, φ * d3_degrees ]); | |
}); | |
return function(stream) { | |
stream = resample(stream); | |
return { | |
point: function(λ, φ) { | |
stream.point(λ * d3_radians, φ * d3_radians); | |
}, | |
sphere: function() { | |
stream.sphere(); | |
}, | |
lineStart: function() { | |
stream.lineStart(); | |
}, | |
lineEnd: function() { | |
stream.lineEnd(); | |
}, | |
polygonStart: function() { | |
stream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
stream.polygonEnd(); | |
} | |
}; | |
}; | |
} | |
function d3_geo_pathBuffer() { | |
var pointCircle = d3_geo_pathCircle(4.5), buffer = []; | |
var stream = { | |
point: point, | |
lineStart: function() { | |
stream.point = pointLineStart; | |
}, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.lineEnd = lineEndPolygon; | |
}, | |
polygonEnd: function() { | |
stream.lineEnd = lineEnd; | |
stream.point = point; | |
}, | |
pointRadius: function(_) { | |
pointCircle = d3_geo_pathCircle(_); | |
return stream; | |
}, | |
result: function() { | |
if (buffer.length) { | |
var result = buffer.join(""); | |
buffer = []; | |
return result; | |
} | |
} | |
}; | |
function point(x, y) { | |
buffer.push("M", x, ",", y, pointCircle); | |
} | |
function pointLineStart(x, y) { | |
buffer.push("M", x, ",", y); | |
stream.point = pointLine; | |
} | |
function pointLine(x, y) { | |
buffer.push("L", x, ",", y); | |
} | |
function lineEnd() { | |
stream.point = point; | |
} | |
function lineEndPolygon() { | |
buffer.push("Z"); | |
} | |
return stream; | |
} | |
function d3_geo_pathContext(context) { | |
var pointRadius = 4.5; | |
var stream = { | |
point: point, | |
lineStart: function() { | |
stream.point = pointLineStart; | |
}, | |
lineEnd: lineEnd, | |
polygonStart: function() { | |
stream.lineEnd = lineEndPolygon; | |
}, | |
polygonEnd: function() { | |
stream.lineEnd = lineEnd; | |
stream.point = point; | |
}, | |
pointRadius: function(_) { | |
pointRadius = _; | |
return stream; | |
}, | |
result: d3_noop | |
}; | |
function point(x, y) { | |
context.moveTo(x, y); | |
context.arc(x, y, pointRadius, 0, 2 * π); | |
} | |
function pointLineStart(x, y) { | |
context.moveTo(x, y); | |
stream.point = pointLine; | |
} | |
function pointLine(x, y) { | |
context.lineTo(x, y); | |
} | |
function lineEnd() { | |
stream.point = point; | |
} | |
function lineEndPolygon() { | |
context.closePath(); | |
} | |
return stream; | |
} | |
var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { | |
point: d3_noop, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: function() { | |
d3_geo_pathAreaPolygon = 0; | |
d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; | |
d3_geo_pathAreaSum += Math.abs(d3_geo_pathAreaPolygon / 2); | |
} | |
}; | |
function d3_geo_pathAreaRingStart() { | |
var x00, y00, x0, y0; | |
d3_geo_pathArea.point = function(x, y) { | |
d3_geo_pathArea.point = nextPoint; | |
x00 = x0 = x, y00 = y0 = y; | |
}; | |
function nextPoint(x, y) { | |
d3_geo_pathAreaPolygon += y0 * x - x0 * y; | |
x0 = x, y0 = y; | |
} | |
d3_geo_pathArea.lineEnd = function() { | |
nextPoint(x00, y00); | |
}; | |
} | |
var d3_geo_pathCentroid = { | |
point: d3_geo_pathCentroidPoint, | |
lineStart: d3_geo_pathCentroidLineStart, | |
lineEnd: d3_geo_pathCentroidLineEnd, | |
polygonStart: function() { | |
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; | |
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; | |
d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; | |
} | |
}; | |
function d3_geo_pathCentroidPoint(x, y) { | |
if (d3_geo_centroidDimension) return; | |
d3_geo_centroidX += x; | |
d3_geo_centroidY += y; | |
++d3_geo_centroidZ; | |
} | |
function d3_geo_pathCentroidLineStart() { | |
var x0, y0; | |
if (d3_geo_centroidDimension !== 1) { | |
if (d3_geo_centroidDimension < 1) { | |
d3_geo_centroidDimension = 1; | |
d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
} else return; | |
} | |
d3_geo_pathCentroid.point = function(x, y) { | |
d3_geo_pathCentroid.point = nextPoint; | |
x0 = x, y0 = y; | |
}; | |
function nextPoint(x, y) { | |
var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); | |
d3_geo_centroidX += z * (x0 + x) / 2; | |
d3_geo_centroidY += z * (y0 + y) / 2; | |
d3_geo_centroidZ += z; | |
x0 = x, y0 = y; | |
} | |
} | |
function d3_geo_pathCentroidLineEnd() { | |
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; | |
} | |
function d3_geo_pathCentroidRingStart() { | |
var x00, y00, x0, y0; | |
if (d3_geo_centroidDimension < 2) { | |
d3_geo_centroidDimension = 2; | |
d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; | |
} | |
d3_geo_pathCentroid.point = function(x, y) { | |
d3_geo_pathCentroid.point = nextPoint; | |
x00 = x0 = x, y00 = y0 = y; | |
}; | |
function nextPoint(x, y) { | |
var z = y0 * x - x0 * y; | |
d3_geo_centroidX += z * (x0 + x); | |
d3_geo_centroidY += z * (y0 + y); | |
d3_geo_centroidZ += z * 3; | |
x0 = x, y0 = y; | |
} | |
d3_geo_pathCentroid.lineEnd = function() { | |
nextPoint(x00, y00); | |
}; | |
} | |
d3.geo.area = function(object) { | |
d3_geo_areaSum = 0; | |
d3.geo.stream(object, d3_geo_area); | |
return d3_geo_areaSum; | |
}; | |
var d3_geo_areaSum, d3_geo_areaRing; | |
var d3_geo_area = { | |
sphere: function() { | |
d3_geo_areaSum += 4 * π; | |
}, | |
point: d3_noop, | |
lineStart: d3_noop, | |
lineEnd: d3_noop, | |
polygonStart: function() { | |
d3_geo_areaRing = 0; | |
d3_geo_area.lineStart = d3_geo_areaRingStart; | |
}, | |
polygonEnd: function() { | |
d3_geo_areaSum += d3_geo_areaRing < 0 ? 4 * π + d3_geo_areaRing : d3_geo_areaRing; | |
d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; | |
} | |
}; | |
function d3_geo_areaRingStart() { | |
var λ00, φ00, λ1, λ0, φ0, cosφ0, sinφ0; | |
d3_geo_area.point = function(λ, φ) { | |
d3_geo_area.point = nextPoint; | |
λ1 = λ0 = (λ00 = λ) * d3_radians, φ0 = (φ00 = φ) * d3_radians, cosφ0 = Math.cos(φ0), | |
sinφ0 = Math.sin(φ0); | |
}; | |
function nextPoint(λ, φ) { | |
λ *= d3_radians, φ *= d3_radians; | |
if (Math.abs(Math.abs(φ0) - π / 2) < ε && Math.abs(Math.abs(φ) - π / 2) < ε) return; | |
var cosφ = Math.cos(φ), sinφ = Math.sin(φ); | |
if (Math.abs(φ0 - π / 2) < ε) d3_geo_areaRing += (λ - λ1) * 2; else { | |
var dλ = λ - λ0, cosdλ = Math.cos(dλ), d = Math.atan2(Math.sqrt((d = cosφ * Math.sin(dλ)) * d + (d = cosφ0 * sinφ - sinφ0 * cosφ * cosdλ) * d), sinφ0 * sinφ + cosφ0 * cosφ * cosdλ), s = (d + π + φ0 + φ) / 4; | |
d3_geo_areaRing += (dλ < 0 && dλ > -π || dλ > π ? -4 : 4) * Math.atan(Math.sqrt(Math.abs(Math.tan(s) * Math.tan(s - d / 2) * Math.tan(s - π / 4 - φ0 / 2) * Math.tan(s - π / 4 - φ / 2)))); | |
} | |
λ1 = λ0, λ0 = λ, φ0 = φ, cosφ0 = cosφ, sinφ0 = sinφ; | |
} | |
d3_geo_area.lineEnd = function() { | |
nextPoint(λ00, φ00); | |
}; | |
} | |
d3.geo.projection = d3_geo_projection; | |
d3.geo.projectionMutator = d3_geo_projectionMutator; | |
function d3_geo_projection(project) { | |
return d3_geo_projectionMutator(function() { | |
return project; | |
})(); | |
} | |
function d3_geo_projectionMutator(projectAt) { | |
var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { | |
x = project(x, y); | |
return [ x[0] * k + δx, δy - x[1] * k ]; | |
}), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, clip = d3_geo_clipAntimeridian, clipAngle = null; | |
function projection(point) { | |
point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); | |
return [ point[0] * k + δx, δy - point[1] * k ]; | |
} | |
function invert(point) { | |
point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); | |
return [ point[0] * d3_degrees, point[1] * d3_degrees ]; | |
} | |
projection.stream = function(stream) { | |
return d3_geo_projectionRadiansRotate(rotate, clip(projectResample(stream))); | |
}; | |
projection.clipAngle = function(_) { | |
if (!arguments.length) return clipAngle; | |
clip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle(clipAngle = +_); | |
return projection; | |
}; | |
projection.scale = function(_) { | |
if (!arguments.length) return k; | |
k = +_; | |
return reset(); | |
}; | |
projection.translate = function(_) { | |
if (!arguments.length) return [ x, y ]; | |
x = +_[0]; | |
y = +_[1]; | |
return reset(); | |
}; | |
projection.center = function(_) { | |
if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; | |
λ = _[0] % 360 * d3_radians; | |
φ = _[1] % 360 * d3_radians; | |
return reset(); | |
}; | |
projection.rotate = function(_) { | |
if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; | |
δλ = _[0] % 360 * d3_radians; | |
δφ = _[1] % 360 * d3_radians; | |
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; | |
return reset(); | |
}; | |
d3.rebind(projection, projectResample, "precision"); | |
function reset() { | |
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); | |
var center = project(λ, φ); | |
δx = x - center[0] * k; | |
δy = y + center[1] * k; | |
return projection; | |
} | |
return function() { | |
project = projectAt.apply(this, arguments); | |
projection.invert = project.invert && invert; | |
return reset(); | |
}; | |
} | |
function d3_geo_projectionRadiansRotate(rotate, stream) { | |
return { | |
point: function(x, y) { | |
y = rotate(x * d3_radians, y * d3_radians), x = y[0]; | |
stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]); | |
}, | |
sphere: function() { | |
stream.sphere(); | |
}, | |
lineStart: function() { | |
stream.lineStart(); | |
}, | |
lineEnd: function() { | |
stream.lineEnd(); | |
}, | |
polygonStart: function() { | |
stream.polygonStart(); | |
}, | |
polygonEnd: function() { | |
stream.polygonEnd(); | |
} | |
}; | |
} | |
function d3_geo_rotation(δλ, δφ, δγ) { | |
return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_equirectangular; | |
} | |
function d3_geo_forwardRotationλ(δλ) { | |
return function(λ, φ) { | |
return λ += δλ, [ λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ ]; | |
}; | |
} | |
function d3_geo_rotationλ(δλ) { | |
var rotation = d3_geo_forwardRotationλ(δλ); | |
rotation.invert = d3_geo_forwardRotationλ(-δλ); | |
return rotation; | |
} | |
function d3_geo_rotationφγ(δφ, δγ) { | |
var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); | |
function rotation(λ, φ) { | |
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; | |
return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδγ + y * sinδγ))) ]; | |
} | |
rotation.invert = function(λ, φ) { | |
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; | |
return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδφ - x * sinδφ))) ]; | |
}; | |
return rotation; | |
} | |
var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { | |
return 1 / (1 + cosλcosφ); | |
}, function(ρ) { | |
return 2 * Math.atan(ρ); | |
}); | |
(d3.geo.stereographic = function() { | |
return d3_geo_projection(d3_geo_stereographic); | |
}).raw = d3_geo_stereographic; | |
function d3_geo_azimuthal(scale, angle) { | |
function azimuthal(λ, φ) { | |
var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); | |
return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; | |
} | |
azimuthal.invert = function(x, y) { | |
var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); | |
return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; | |
}; | |
return azimuthal; | |
} | |
d3.geom = {}; | |
d3.geom.hull = function(vertices) { | |
if (vertices.length < 3) return []; | |
var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp; | |
for (i = 1; i < len; ++i) { | |
if (vertices[i][1] < vertices[h][1]) { | |
h = i; | |
} else if (vertices[i][1] == vertices[h][1]) { | |
h = vertices[i][0] < vertices[h][0] ? i : h; | |
} | |
} | |
for (i = 0; i < len; ++i) { | |
if (i === h) continue; | |
y1 = vertices[i][1] - vertices[h][1]; | |
x1 = vertices[i][0] - vertices[h][0]; | |
points.push({ | |
angle: Math.atan2(y1, x1), | |
index: i | |
}); | |
} | |
points.sort(function(a, b) { | |
return a.angle - b.angle; | |
}); | |
a = points[0].angle; | |
v = points[0].index; | |
u = 0; | |
for (i = 1; i < plen; ++i) { | |
j = points[i].index; | |
if (a == points[i].angle) { | |
x1 = vertices[v][0] - vertices[h][0]; | |
y1 = vertices[v][1] - vertices[h][1]; | |
x2 = vertices[j][0] - vertices[h][0]; | |
y2 = vertices[j][1] - vertices[h][1]; | |
if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) { | |
points[i].index = -1; | |
} else { | |
points[u].index = -1; | |
a = points[i].angle; | |
u = i; | |
v = j; | |
} | |
} else { | |
a = points[i].angle; | |
u = i; | |
v = j; | |
} | |
} | |
stack.push(h); | |
for (i = 0, j = 0; i < 2; ++j) { | |
if (points[j].index !== -1) { | |
stack.push(points[j].index); | |
i++; | |
} | |
} | |
sp = stack.length; | |
for (;j < plen; ++j) { | |
if (points[j].index === -1) continue; | |
while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) { | |
--sp; | |
} | |
stack[sp++] = points[j].index; | |
} | |
var poly = []; | |
for (i = 0; i < sp; ++i) { | |
poly.push(vertices[stack[i]]); | |
} | |
return poly; | |
}; | |
function d3_geom_hullCCW(i1, i2, i3, v) { | |
var t, a, b, c, d, e, f; | |
t = v[i1]; | |
a = t[0]; | |
b = t[1]; | |
t = v[i2]; | |
c = t[0]; | |
d = t[1]; | |
t = v[i3]; | |
e = t[0]; | |
f = t[1]; | |
return (f - b) * (c - a) - (d - b) * (e - a) > 0; | |
} | |
d3.geom.polygon = function(coordinates) { | |
coordinates.area = function() { | |
var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1]; | |
while (++i < n) { | |
area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1]; | |
} | |
return area * .5; | |
}; | |
coordinates.centroid = function(k) { | |
var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c; | |
if (!arguments.length) k = -1 / (6 * coordinates.area()); | |
while (++i < n) { | |
a = b; | |
b = coordinates[i]; | |
c = a[0] * b[1] - b[0] * a[1]; | |
x += (a[0] + b[0]) * c; | |
y += (a[1] + b[1]) * c; | |
} | |
return [ x * k, y * k ]; | |
}; | |
coordinates.clip = function(subject) { | |
var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d; | |
while (++i < n) { | |
input = subject.slice(); | |
subject.length = 0; | |
b = coordinates[i]; | |
c = input[(m = input.length) - 1]; | |
j = -1; | |
while (++j < m) { | |
d = input[j]; | |
if (d3_geom_polygonInside(d, a, b)) { | |
if (!d3_geom_polygonInside(c, a, b)) { | |
subject.push(d3_geom_polygonIntersect(c, d, a, b)); | |
} | |
subject.push(d); | |
} else if (d3_geom_polygonInside(c, a, b)) { | |
subject.push(d3_geom_polygonIntersect(c, d, a, b)); | |
} | |
c = d; | |
} | |
a = b; | |
} | |
return subject; | |
}; | |
return coordinates; | |
}; | |
function d3_geom_polygonInside(p, a, b) { | |
return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); | |
} | |
function d3_geom_polygonIntersect(c, d, a, b) { | |
var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); | |
return [ x1 + ua * x21, y1 + ua * y21 ]; | |
} | |
d3.geom.voronoi = function(vertices) { | |
var polygons = vertices.map(function() { | |
return []; | |
}), Z = 1e6; | |
d3_voronoi_tessellate(vertices, function(e) { | |
var s1, s2, x1, x2, y1, y2; | |
if (e.a === 1 && e.b >= 0) { | |
s1 = e.ep.r; | |
s2 = e.ep.l; | |
} else { | |
s1 = e.ep.l; | |
s2 = e.ep.r; | |
} | |
if (e.a === 1) { | |
y1 = s1 ? s1.y : -Z; | |
x1 = e.c - e.b * y1; | |
y2 = s2 ? s2.y : Z; | |
x2 = e.c - e.b * y2; | |
} else { | |
x1 = s1 ? s1.x : -Z; | |
y1 = e.c - e.a * x1; | |
x2 = s2 ? s2.x : Z; | |
y2 = e.c - e.a * x2; | |
} | |
var v1 = [ x1, y1 ], v2 = [ x2, y2 ]; | |
polygons[e.region.l.index].push(v1, v2); | |
polygons[e.region.r.index].push(v1, v2); | |
}); | |
polygons = polygons.map(function(polygon, i) { | |
var cx = vertices[i][0], cy = vertices[i][1], angle = polygon.map(function(v) { | |
return Math.atan2(v[0] - cx, v[1] - cy); | |
}); | |
return d3.range(polygon.length).sort(function(a, b) { | |
return angle[a] - angle[b]; | |
}).filter(function(d, i, order) { | |
return !i || angle[d] - angle[order[i - 1]] > ε; | |
}).map(function(d) { | |
return polygon[d]; | |
}); | |
}); | |
polygons.forEach(function(polygon, i) { | |
var n = polygon.length; | |
if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]); | |
if (n > 2) return; | |
var p0 = vertices[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1; | |
if (Math.abs(dy) < ε) { | |
var y = y0 < y1 ? -Z : Z; | |
polygon.push([ -Z, y ], [ Z, y ]); | |
} else if (dx < ε) { | |
var x = x0 < x1 ? -Z : Z; | |
polygon.push([ x, -Z ], [ x, Z ]); | |
} else { | |
var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx; | |
if (Math.abs(z) < ε) { | |
polygon.push([ dy < 0 ? y : -y, y ]); | |
} else { | |
if (z > 0) y *= -1; | |
polygon.push([ -Z, y ], [ Z, y ]); | |
} | |
} | |
}); | |
return polygons; | |
}; | |
var d3_voronoi_opposite = { | |
l: "r", | |
r: "l" | |
}; | |
function d3_voronoi_tessellate(vertices, callback) { | |
var Sites = { | |
list: vertices.map(function(v, i) { | |
return { | |
index: i, | |
x: v[0], | |
y: v[1] | |
}; | |
}).sort(function(a, b) { | |
return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0; | |
}), | |
bottomSite: null | |
}; | |
var EdgeList = { | |
list: [], | |
leftEnd: null, | |
rightEnd: null, | |
init: function() { | |
EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l"); | |
EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l"); | |
EdgeList.leftEnd.r = EdgeList.rightEnd; | |
EdgeList.rightEnd.l = EdgeList.leftEnd; | |
EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd); | |
}, | |
createHalfEdge: function(edge, side) { | |
return { | |
edge: edge, | |
side: side, | |
vertex: null, | |
l: null, | |
r: null | |
}; | |
}, | |
insert: function(lb, he) { | |
he.l = lb; | |
he.r = lb.r; | |
lb.r.l = he; | |
lb.r = he; | |
}, | |
leftBound: function(p) { | |
var he = EdgeList.leftEnd; | |
do { | |
he = he.r; | |
} while (he != EdgeList.rightEnd && Geom.rightOf(he, p)); | |
he = he.l; | |
return he; | |
}, | |
del: function(he) { | |
he.l.r = he.r; | |
he.r.l = he.l; | |
he.edge = null; | |
}, | |
right: function(he) { | |
return he.r; | |
}, | |
left: function(he) { | |
return he.l; | |
}, | |
leftRegion: function(he) { | |
return he.edge == null ? Sites.bottomSite : he.edge.region[he.side]; | |
}, | |
rightRegion: function(he) { | |
return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]]; | |
} | |
}; | |
var Geom = { | |
bisect: function(s1, s2) { | |
var newEdge = { | |
region: { | |
l: s1, | |
r: s2 | |
}, | |
ep: { | |
l: null, | |
r: null | |
} | |
}; | |
var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy; | |
newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5; | |
if (adx > ady) { | |
newEdge.a = 1; | |
newEdge.b = dy / dx; | |
newEdge.c /= dx; | |
} else { | |
newEdge.b = 1; | |
newEdge.a = dx / dy; | |
newEdge.c /= dy; | |
} | |
return newEdge; | |
}, | |
intersect: function(el1, el2) { | |
var e1 = el1.edge, e2 = el2.edge; | |
if (!e1 || !e2 || e1.region.r == e2.region.r) { | |
return null; | |
} | |
var d = e1.a * e2.b - e1.b * e2.a; | |
if (Math.abs(d) < 1e-10) { | |
return null; | |
} | |
var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e; | |
if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) { | |
el = el1; | |
e = e1; | |
} else { | |
el = el2; | |
e = e2; | |
} | |
var rightOfSite = xint >= e.region.r.x; | |
if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") { | |
return null; | |
} | |
return { | |
x: xint, | |
y: yint | |
}; | |
}, | |
rightOf: function(he, p) { | |
var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x; | |
if (rightOfSite && he.side === "l") { | |
return 1; | |
} | |
if (!rightOfSite && he.side === "r") { | |
return 0; | |
} | |
if (e.a === 1) { | |
var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0; | |
if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) { | |
above = fast = dyp >= e.b * dxp; | |
} else { | |
above = p.x + p.y * e.b > e.c; | |
if (e.b < 0) { | |
above = !above; | |
} | |
if (!above) { | |
fast = 1; | |
} | |
} | |
if (!fast) { | |
var dxs = topsite.x - e.region.l.x; | |
above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b); | |
if (e.b < 0) { | |
above = !above; | |
} | |
} | |
} else { | |
var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y; | |
above = t1 * t1 > t2 * t2 + t3 * t3; | |
} | |
return he.side === "l" ? above : !above; | |
}, | |
endPoint: function(edge, side, site) { | |
edge.ep[side] = site; | |
if (!edge.ep[d3_voronoi_opposite[side]]) return; | |
callback(edge); | |
}, | |
distance: function(s, t) { | |
var dx = s.x - t.x, dy = s.y - t.y; | |
return Math.sqrt(dx * dx + dy * dy); | |
} | |
}; | |
var EventQueue = { | |
list: [], | |
insert: function(he, site, offset) { | |
he.vertex = site; | |
he.ystar = site.y + offset; | |
for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) { | |
var next = list[i]; | |
if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) { | |
continue; | |
} else { | |
break; | |
} | |
} | |
list.splice(i, 0, he); | |
}, | |
del: function(he) { | |
for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {} | |
ls.splice(i, 1); | |
}, | |
empty: function() { | |
return EventQueue.list.length === 0; | |
}, | |
nextEvent: function(he) { | |
for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) { | |
if (ls[i] == he) return ls[i + 1]; | |
} | |
return null; | |
}, | |
min: function() { | |
var elem = EventQueue.list[0]; | |
return { | |
x: elem.vertex.x, | |
y: elem.ystar | |
}; | |
}, | |
extractMin: function() { | |
return EventQueue.list.shift(); | |
} | |
}; | |
EdgeList.init(); | |
Sites.bottomSite = Sites.list.shift(); | |
var newSite = Sites.list.shift(), newIntStar; | |
var lbnd, rbnd, llbnd, rrbnd, bisector; | |
var bot, top, temp, p, v; | |
var e, pm; | |
while (true) { | |
if (!EventQueue.empty()) { | |
newIntStar = EventQueue.min(); | |
} | |
if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) { | |
lbnd = EdgeList.leftBound(newSite); | |
rbnd = EdgeList.right(lbnd); | |
bot = EdgeList.rightRegion(lbnd); | |
e = Geom.bisect(bot, newSite); | |
bisector = EdgeList.createHalfEdge(e, "l"); | |
EdgeList.insert(lbnd, bisector); | |
p = Geom.intersect(lbnd, bisector); | |
if (p) { | |
EventQueue.del(lbnd); | |
EventQueue.insert(lbnd, p, Geom.distance(p, newSite)); | |
} | |
lbnd = bisector; | |
bisector = EdgeList.createHalfEdge(e, "r"); | |
EdgeList.insert(lbnd, bisector); | |
p = Geom.intersect(bisector, rbnd); | |
if (p) { | |
EventQueue.insert(bisector, p, Geom.distance(p, newSite)); | |
} | |
newSite = Sites.list.shift(); | |
} else if (!EventQueue.empty()) { | |
lbnd = EventQueue.extractMin(); | |
llbnd = EdgeList.left(lbnd); | |
rbnd = EdgeList.right(lbnd); | |
rrbnd = EdgeList.right(rbnd); | |
bot = EdgeList.leftRegion(lbnd); | |
top = EdgeList.rightRegion(rbnd); | |
v = lbnd.vertex; | |
Geom.endPoint(lbnd.edge, lbnd.side, v); | |
Geom.endPoint(rbnd.edge, rbnd.side, v); | |
EdgeList.del(lbnd); | |
EventQueue.del(rbnd); | |
EdgeList.del(rbnd); | |
pm = "l"; | |
if (bot.y > top.y) { | |
temp = bot; | |
bot = top; | |
top = temp; | |
pm = "r"; | |
} | |
e = Geom.bisect(bot, top); | |
bisector = EdgeList.createHalfEdge(e, pm); | |
EdgeList.insert(llbnd, bisector); | |
Geom.endPoint(e, d3_voronoi_opposite[pm], v); | |
p = Geom.intersect(llbnd, bisector); | |
if (p) { | |
EventQueue.del(llbnd); | |
EventQueue.insert(llbnd, p, Geom.distance(p, bot)); | |
} | |
p = Geom.intersect(bisector, rrbnd); | |
if (p) { | |
EventQueue.insert(bisector, p, Geom.distance(p, bot)); | |
} | |
} else { | |
break; | |
} | |
} | |
for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) { | |
callback(lbnd.edge); | |
} | |
} | |
d3.geom.delaunay = function(vertices) { | |
var edges = vertices.map(function() { | |
return []; | |
}), triangles = []; | |
d3_voronoi_tessellate(vertices, function(e) { | |
edges[e.region.l.index].push(vertices[e.region.r.index]); | |
}); | |
edges.forEach(function(edge, i) { | |
var v = vertices[i], cx = v[0], cy = v[1]; | |
edge.forEach(function(v) { | |
v.angle = Math.atan2(v[0] - cx, v[1] - cy); | |
}); | |
edge.sort(function(a, b) { | |
return a.angle - b.angle; | |
}); | |
for (var j = 0, m = edge.length - 1; j < m; j++) { | |
triangles.push([ v, edge[j], edge[j + 1] ]); | |
} | |
}); | |
return triangles; | |
}; | |
d3.geom.quadtree = function(points, x1, y1, x2, y2) { | |
var p, i = -1, n = points.length; | |
if (arguments.length < 5) { | |
if (arguments.length === 3) { | |
y2 = y1; | |
x2 = x1; | |
y1 = x1 = 0; | |
} else { | |
x1 = y1 = Infinity; | |
x2 = y2 = -Infinity; | |
while (++i < n) { | |
p = points[i]; | |
if (p.x < x1) x1 = p.x; | |
if (p.y < y1) y1 = p.y; | |
if (p.x > x2) x2 = p.x; | |
if (p.y > y2) y2 = p.y; | |
} | |
} | |
} | |
var dx = x2 - x1, dy = y2 - y1; | |
if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy; | |
function insert(n, p, x1, y1, x2, y2) { | |
if (isNaN(p.x) || isNaN(p.y)) return; | |
if (n.leaf) { | |
var v = n.point; | |
if (v) { | |
if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) { | |
insertChild(n, p, x1, y1, x2, y2); | |
} else { | |
n.point = null; | |
insertChild(n, v, x1, y1, x2, y2); | |
insertChild(n, p, x1, y1, x2, y2); | |
} | |
} else { | |
n.point = p; | |
} | |
} else { | |
insertChild(n, p, x1, y1, x2, y2); | |
} | |
} | |
function insertChild(n, p, x1, y1, x2, y2) { | |
var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right; | |
n.leaf = false; | |
n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); | |
if (right) x1 = sx; else x2 = sx; | |
if (bottom) y1 = sy; else y2 = sy; | |
insert(n, p, x1, y1, x2, y2); | |
} | |
var root = d3_geom_quadtreeNode(); | |
root.add = function(p) { | |
insert(root, p, x1, y1, x2, y2); | |
}; | |
root.visit = function(f) { | |
d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2); | |
}; | |
points.forEach(root.add); | |
return root; | |
}; | |
function d3_geom_quadtreeNode() { | |
return { | |
leaf: true, | |
nodes: [], | |
point: null | |
}; | |
} | |
function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { | |
if (!f(node, x1, y1, x2, y2)) { | |
var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; | |
if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); | |
if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); | |
if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); | |
if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); | |
} | |
} | |
d3.time = {}; | |
var d3_time = Date, d3_time_daySymbols = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; | |
function d3_time_utc() { | |
this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); | |
} | |
d3_time_utc.prototype = { | |
getDate: function() { | |
return this._.getUTCDate(); | |
}, | |
getDay: function() { | |
return this._.getUTCDay(); | |
}, | |
getFullYear: function() { | |
return this._.getUTCFullYear(); | |
}, | |
getHours: function() { | |
return this._.getUTCHours(); | |
}, | |
getMilliseconds: function() { | |
return this._.getUTCMilliseconds(); | |
}, | |
getMinutes: function() { | |
return this._.getUTCMinutes(); | |
}, | |
getMonth: function() { | |
return this._.getUTCMonth(); | |
}, | |
getSeconds: function() { | |
return this._.getUTCSeconds(); | |
}, | |
getTime: function() { | |
return this._.getTime(); | |
}, | |
getTimezoneOffset: function() { | |
return 0; | |
}, | |
valueOf: function() { | |
return this._.valueOf(); | |
}, | |
setDate: function() { | |
d3_time_prototype.setUTCDate.apply(this._, arguments); | |
}, | |
setDay: function() { | |
d3_time_prototype.setUTCDay.apply(this._, arguments); | |
}, | |
setFullYear: function() { | |
d3_time_prototype.setUTCFullYear.apply(this._, arguments); | |
}, | |
setHours: function() { | |
d3_time_prototype.setUTCHours.apply(this._, arguments); | |
}, | |
setMilliseconds: function() { | |
d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); | |
}, | |
setMinutes: function() { | |
d3_time_prototype.setUTCMinutes.apply(this._, arguments); | |
}, | |
setMonth: function() { | |
d3_time_prototype.setUTCMonth.apply(this._, arguments); | |
}, | |
setSeconds: function() { | |
d3_time_prototype.setUTCSeconds.apply(this._, arguments); | |
}, | |
setTime: function() { | |
d3_time_prototype.setTime.apply(this._, arguments); | |
} | |
}; | |
var d3_time_prototype = Date.prototype; | |
var d3_time_formatDateTime = "%a %b %e %X %Y", d3_time_formatDate = "%m/%d/%Y", d3_time_formatTime = "%H:%M:%S"; | |
var d3_time_days = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], d3_time_dayAbbreviations = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], d3_time_months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], d3_time_monthAbbreviations = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; | |
d3.time.format = function(template) { | |
var n = template.length; | |
function format(date) { | |
var string = [], i = -1, j = 0, c, p, f; | |
while (++i < n) { | |
if (template.charCodeAt(i) === 37) { | |
string.push(template.substring(j, i)); | |
if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); | |
if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); | |
string.push(c); | |
j = i + 1; | |
} | |
} | |
string.push(template.substring(j, i)); | |
return string.join(""); | |
} | |
format.parse = function(string) { | |
var d = { | |
y: 1900, | |
m: 0, | |
d: 1, | |
H: 0, | |
M: 0, | |
S: 0, | |
L: 0 | |
}, i = d3_time_parse(d, template, string, 0); | |
if (i != string.length) return null; | |
if ("p" in d) d.H = d.H % 12 + d.p * 12; | |
var date = new d3_time(); | |
date.setFullYear(d.y, d.m, d.d); | |
date.setHours(d.H, d.M, d.S, d.L); | |
return date; | |
}; | |
format.toString = function() { | |
return template; | |
}; | |
return format; | |
}; | |
function d3_time_parse(date, template, string, j) { | |
var c, p, i = 0, n = template.length, m = string.length; | |
while (i < n) { | |
if (j >= m) return -1; | |
c = template.charCodeAt(i++); | |
if (c === 37) { | |
p = d3_time_parsers[template.charAt(i++)]; | |
if (!p || (j = p(date, string, j)) < 0) return -1; | |
} else if (c != string.charCodeAt(j++)) { | |
return -1; | |
} | |
} | |
return j; | |
} | |
function d3_time_formatRe(names) { | |
return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); | |
} | |
function d3_time_formatLookup(names) { | |
var map = new d3_Map(), i = -1, n = names.length; | |
while (++i < n) map.set(names[i].toLowerCase(), i); | |
return map; | |
} | |
function d3_time_formatPad(value, fill, width) { | |
value += ""; | |
var length = value.length; | |
return length < width ? new Array(width - length + 1).join(fill) + value : value; | |
} | |
var d3_time_dayRe = d3_time_formatRe(d3_time_days), d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations), d3_time_monthRe = d3_time_formatRe(d3_time_months), d3_time_monthLookup = d3_time_formatLookup(d3_time_months), d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations), d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations); | |
var d3_time_formatPads = { | |
"-": "", | |
_: " ", | |
"0": "0" | |
}; | |
var d3_time_formats = { | |
a: function(d) { | |
return d3_time_dayAbbreviations[d.getDay()]; | |
}, | |
A: function(d) { | |
return d3_time_days[d.getDay()]; | |
}, | |
b: function(d) { | |
return d3_time_monthAbbreviations[d.getMonth()]; | |
}, | |
B: function(d) { | |
return d3_time_months[d.getMonth()]; | |
}, | |
c: d3.time.format(d3_time_formatDateTime), | |
d: function(d, p) { | |
return d3_time_formatPad(d.getDate(), p, 2); | |
}, | |
e: function(d, p) { | |
return d3_time_formatPad(d.getDate(), p, 2); | |
}, | |
H: function(d, p) { | |
return d3_time_formatPad(d.getHours(), p, 2); | |
}, | |
I: function(d, p) { | |
return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); | |
}, | |
j: function(d, p) { | |
return d3_time_formatPad(1 + d3.time.dayOfYear(d), p, 3); | |
}, | |
L: function(d, p) { | |
return d3_time_formatPad(d.getMilliseconds(), p, 3); | |
}, | |
m: function(d, p) { | |
return d3_time_formatPad(d.getMonth() + 1, p, 2); | |
}, | |
M: function(d, p) { | |
return d3_time_formatPad(d.getMinutes(), p, 2); | |
}, | |
p: function(d) { | |
return d.getHours() >= 12 ? "PM" : "AM"; | |
}, | |
S: function(d, p) { | |
return d3_time_formatPad(d.getSeconds(), p, 2); | |
}, | |
U: function(d, p) { | |
return d3_time_formatPad(d3.time.sundayOfYear(d), p, 2); | |
}, | |
w: function(d) { | |
return d.getDay(); | |
}, | |
W: function(d, p) { | |
return d3_time_formatPad(d3.time.mondayOfYear(d), p, 2); | |
}, | |
x: d3.time.format(d3_time_formatDate), | |
X: d3.time.format(d3_time_formatTime), | |
y: function(d, p) { | |
return d3_time_formatPad(d.getFullYear() % 100, p, 2); | |
}, | |
Y: function(d, p) { | |
return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); | |
}, | |
Z: d3_time_zone, | |
"%": function() { | |
return "%"; | |
} | |
}; | |
var d3_time_parsers = { | |
a: d3_time_parseWeekdayAbbrev, | |
A: d3_time_parseWeekday, | |
b: d3_time_parseMonthAbbrev, | |
B: d3_time_parseMonth, | |
c: d3_time_parseLocaleFull, | |
d: d3_time_parseDay, | |
e: d3_time_parseDay, | |
H: d3_time_parseHour24, | |
I: d3_time_parseHour24, | |
L: d3_time_parseMilliseconds, | |
m: d3_time_parseMonthNumber, | |
M: d3_time_parseMinutes, | |
p: d3_time_parseAmPm, | |
S: d3_time_parseSeconds, | |
x: d3_time_parseLocaleDate, | |
X: d3_time_parseLocaleTime, | |
y: d3_time_parseYear, | |
Y: d3_time_parseFullYear | |
}; | |
function d3_time_parseWeekdayAbbrev(date, string, i) { | |
d3_time_dayAbbrevRe.lastIndex = 0; | |
var n = d3_time_dayAbbrevRe.exec(string.substring(i)); | |
return n ? i += n[0].length : -1; | |
} | |
function d3_time_parseWeekday(date, string, i) { | |
d3_time_dayRe.lastIndex = 0; | |
var n = d3_time_dayRe.exec(string.substring(i)); | |
return n ? i += n[0].length : -1; | |
} | |
function d3_time_parseMonthAbbrev(date, string, i) { | |
d3_time_monthAbbrevRe.lastIndex = 0; | |
var n = d3_time_monthAbbrevRe.exec(string.substring(i)); | |
return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i += n[0].length) : -1; | |
} | |
function d3_time_parseMonth(date, string, i) { | |
d3_time_monthRe.lastIndex = 0; | |
var n = d3_time_monthRe.exec(string.substring(i)); | |
return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i += n[0].length) : -1; | |
} | |
function d3_time_parseLocaleFull(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.c.toString(), string, i); | |
} | |
function d3_time_parseLocaleDate(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.x.toString(), string, i); | |
} | |
function d3_time_parseLocaleTime(date, string, i) { | |
return d3_time_parse(date, d3_time_formats.X.toString(), string, i); | |
} | |
function d3_time_parseFullYear(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 4)); | |
return n ? (date.y = +n[0], i += n[0].length) : -1; | |
} | |
function d3_time_parseYear(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.y = d3_time_expandYear(+n[0]), i += n[0].length) : -1; | |
} | |
function d3_time_expandYear(d) { | |
return d + (d > 68 ? 1900 : 2e3); | |
} | |
function d3_time_parseMonthNumber(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.m = n[0] - 1, i += n[0].length) : -1; | |
} | |
function d3_time_parseDay(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.d = +n[0], i += n[0].length) : -1; | |
} | |
function d3_time_parseHour24(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.H = +n[0], i += n[0].length) : -1; | |
} | |
function d3_time_parseMinutes(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.M = +n[0], i += n[0].length) : -1; | |
} | |
function d3_time_parseSeconds(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
return n ? (date.S = +n[0], i += n[0].length) : -1; | |
} | |
function d3_time_parseMilliseconds(date, string, i) { | |
d3_time_numberRe.lastIndex = 0; | |
var n = d3_time_numberRe.exec(string.substring(i, i + 3)); | |
return n ? (date.L = +n[0], i += n[0].length) : -1; | |
} | |
var d3_time_numberRe = /^\s*\d+/; | |
function d3_time_parseAmPm(date, string, i) { | |
var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase()); | |
return n == null ? -1 : (date.p = n, i); | |
} | |
var d3_time_amPmLookup = d3.map({ | |
am: 0, | |
pm: 1 | |
}); | |
function d3_time_zone(d) { | |
var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(Math.abs(z) / 60), zm = Math.abs(z) % 60; | |
return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); | |
} | |
d3.time.format.utc = function(template) { | |
var local = d3.time.format(template); | |
function format(date) { | |
try { | |
d3_time = d3_time_utc; | |
var utc = new d3_time(); | |
utc._ = date; | |
return local(utc); | |
} finally { | |
d3_time = Date; | |
} | |
} | |
format.parse = function(string) { | |
try { | |
d3_time = d3_time_utc; | |
var date = local.parse(string); | |
return date && date._; | |
} finally { | |
d3_time = Date; | |
} | |
}; | |
format.toString = local.toString; | |
return format; | |
}; | |
var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ"); | |
d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso; | |
function d3_time_formatIsoNative(date) { | |
return date.toISOString(); | |
} | |
d3_time_formatIsoNative.parse = function(string) { | |
var date = new Date(string); | |
return isNaN(date) ? null : date; | |
}; | |
d3_time_formatIsoNative.toString = d3_time_formatIso.toString; | |
function d3_time_interval(local, step, number) { | |
function round(date) { | |
var d0 = local(date), d1 = offset(d0, 1); | |
return date - d0 < d1 - date ? d0 : d1; | |
} | |
function ceil(date) { | |
step(date = local(new d3_time(date - 1)), 1); | |
return date; | |
} | |
function offset(date, k) { | |
step(date = new d3_time(+date), k); | |
return date; | |
} | |
function range(t0, t1, dt) { | |
var time = ceil(t0), times = []; | |
if (dt > 1) { | |
while (time < t1) { | |
if (!(number(time) % dt)) times.push(new Date(+time)); | |
step(time, 1); | |
} | |
} else { | |
while (time < t1) times.push(new Date(+time)), step(time, 1); | |
} | |
return times; | |
} | |
function range_utc(t0, t1, dt) { | |
try { | |
d3_time = d3_time_utc; | |
var utc = new d3_time_utc(); | |
utc._ = t0; | |
return range(utc, t1, dt); | |
} finally { | |
d3_time = Date; | |
} | |
} | |
local.floor = local; | |
local.round = round; | |
local.ceil = ceil; | |
local.offset = offset; | |
local.range = range; | |
var utc = local.utc = d3_time_interval_utc(local); | |
utc.floor = utc; | |
utc.round = d3_time_interval_utc(round); | |
utc.ceil = d3_time_interval_utc(ceil); | |
utc.offset = d3_time_interval_utc(offset); | |
utc.range = range_utc; | |
return local; | |
} | |
function d3_time_interval_utc(method) { | |
return function(date, k) { | |
try { | |
d3_time = d3_time_utc; | |
var utc = new d3_time_utc(); | |
utc._ = date; | |
return method(utc, k)._; | |
} finally { | |
d3_time = Date; | |
} | |
}; | |
} | |
d3.time.second = d3_time_interval(function(date) { | |
return new d3_time(Math.floor(date / 1e3) * 1e3); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 1e3); | |
}, function(date) { | |
return date.getSeconds(); | |
}); | |
d3.time.seconds = d3.time.second.range; | |
d3.time.seconds.utc = d3.time.second.utc.range; | |
d3.time.minute = d3_time_interval(function(date) { | |
return new d3_time(Math.floor(date / 6e4) * 6e4); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 6e4); | |
}, function(date) { | |
return date.getMinutes(); | |
}); | |
d3.time.minutes = d3.time.minute.range; | |
d3.time.minutes.utc = d3.time.minute.utc.range; | |
d3.time.hour = d3_time_interval(function(date) { | |
var timezone = date.getTimezoneOffset() / 60; | |
return new d3_time((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); | |
}, function(date, offset) { | |
date.setTime(date.getTime() + Math.floor(offset) * 36e5); | |
}, function(date) { | |
return date.getHours(); | |
}); | |
d3.time.hours = d3.time.hour.range; | |
d3.time.hours.utc = d3.time.hour.utc.range; | |
d3.time.day = d3_time_interval(function(date) { | |
var day = new d3_time(1970, 0); | |
day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); | |
return day; | |
}, function(date, offset) { | |
date.setDate(date.getDate() + offset); | |
}, function(date) { | |
return date.getDate() - 1; | |
}); | |
d3.time.days = d3.time.day.range; | |
d3.time.days.utc = d3.time.day.utc.range; | |
d3.time.dayOfYear = function(date) { | |
var year = d3.time.year(date); | |
return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); | |
}; | |
d3_time_daySymbols.forEach(function(day, i) { | |
day = day.toLowerCase(); | |
i = 7 - i; | |
var interval = d3.time[day] = d3_time_interval(function(date) { | |
(date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); | |
return date; | |
}, function(date, offset) { | |
date.setDate(date.getDate() + Math.floor(offset) * 7); | |
}, function(date) { | |
var day = d3.time.year(date).getDay(); | |
return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); | |
}); | |
d3.time[day + "s"] = interval.range; | |
d3.time[day + "s"].utc = interval.utc.range; | |
d3.time[day + "OfYear"] = function(date) { | |
var day = d3.time.year(date).getDay(); | |
return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7); | |
}; | |
}); | |
d3.time.week = d3.time.sunday; | |
d3.time.weeks = d3.time.sunday.range; | |
d3.time.weeks.utc = d3.time.sunday.utc.range; | |
d3.time.weekOfYear = d3.time.sundayOfYear; | |
d3.time.month = d3_time_interval(function(date) { | |
date = d3.time.day(date); | |
date.setDate(1); | |
return date; | |
}, function(date, offset) { | |
date.setMonth(date.getMonth() + offset); | |
}, function(date) { | |
return date.getMonth(); | |
}); | |
d3.time.months = d3.time.month.range; | |
d3.time.months.utc = d3.time.month.utc.range; | |
d3.time.year = d3_time_interval(function(date) { | |
date = d3.time.day(date); | |
date.setMonth(0, 1); | |
return date; | |
}, function(date, offset) { | |
date.setFullYear(date.getFullYear() + offset); | |
}, function(date) { | |
return date.getFullYear(); | |
}); | |
d3.time.years = d3.time.year.range; | |
d3.time.years.utc = d3.time.year.utc.range; | |
function d3_time_scale(linear, methods, format) { | |
function scale(x) { | |
return linear(x); | |
} | |
scale.invert = function(x) { | |
return d3_time_scaleDate(linear.invert(x)); | |
}; | |
scale.domain = function(x) { | |
if (!arguments.length) return linear.domain().map(d3_time_scaleDate); | |
linear.domain(x); | |
return scale; | |
}; | |
scale.nice = function(m) { | |
return scale.domain(d3_scale_nice(scale.domain(), function() { | |
return m; | |
})); | |
}; | |
scale.ticks = function(m, k) { | |
var extent = d3_time_scaleExtent(scale.domain()); | |
if (typeof m !== "function") { | |
var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target); | |
if (i == d3_time_scaleSteps.length) return methods.year(extent, m); | |
if (!i) return linear.ticks(m).map(d3_time_scaleDate); | |
if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i; | |
m = methods[i]; | |
k = m[1]; | |
m = m[0].range; | |
} | |
return m(extent[0], new Date(+extent[1] + 1), k); | |
}; | |
scale.tickFormat = function() { | |
return format; | |
}; | |
scale.copy = function() { | |
return d3_time_scale(linear.copy(), methods, format); | |
}; | |
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); | |
} | |
function d3_time_scaleExtent(domain) { | |
var start = domain[0], stop = domain[domain.length - 1]; | |
return start < stop ? [ start, stop ] : [ stop, start ]; | |
} | |
function d3_time_scaleDate(t) { | |
return new Date(t); | |
} | |
function d3_time_scaleFormat(formats) { | |
return function(date) { | |
var i = formats.length - 1, f = formats[i]; | |
while (!f[1](date)) f = formats[--i]; | |
return f[0](date); | |
}; | |
} | |
function d3_time_scaleSetYear(y) { | |
var d = new Date(y, 0, 1); | |
d.setFullYear(y); | |
return d; | |
} | |
function d3_time_scaleGetYear(d) { | |
var y = d.getFullYear(), d0 = d3_time_scaleSetYear(y), d1 = d3_time_scaleSetYear(y + 1); | |
return y + (d - d0) / (d1 - d0); | |
} | |
var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; | |
var d3_time_scaleLocalMethods = [ [ d3.time.second, 1 ], [ d3.time.second, 5 ], [ d3.time.second, 15 ], [ d3.time.second, 30 ], [ d3.time.minute, 1 ], [ d3.time.minute, 5 ], [ d3.time.minute, 15 ], [ d3.time.minute, 30 ], [ d3.time.hour, 1 ], [ d3.time.hour, 3 ], [ d3.time.hour, 6 ], [ d3.time.hour, 12 ], [ d3.time.day, 1 ], [ d3.time.day, 2 ], [ d3.time.week, 1 ], [ d3.time.month, 1 ], [ d3.time.month, 3 ], [ d3.time.year, 1 ] ]; | |
var d3_time_scaleLocalFormats = [ [ d3.time.format("%Y"), d3_true ], [ d3.time.format("%B"), function(d) { | |
return d.getMonth(); | |
} ], [ d3.time.format("%b %d"), function(d) { | |
return d.getDate() != 1; | |
} ], [ d3.time.format("%a %d"), function(d) { | |
return d.getDay() && d.getDate() != 1; | |
} ], [ d3.time.format("%I %p"), function(d) { | |
return d.getHours(); | |
} ], [ d3.time.format("%I:%M"), function(d) { | |
return d.getMinutes(); | |
} ], [ d3.time.format(":%S"), function(d) { | |
return d.getSeconds(); | |
} ], [ d3.time.format(".%L"), function(d) { | |
return d.getMilliseconds(); | |
} ] ]; | |
var d3_time_scaleLinear = d3.scale.linear(), d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats); | |
d3_time_scaleLocalMethods.year = function(extent, m) { | |
return d3_time_scaleLinear.domain(extent.map(d3_time_scaleGetYear)).ticks(m).map(d3_time_scaleSetYear); | |
}; | |
d3.time.scale = function() { | |
return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); | |
}; | |
var d3_time_scaleUTCMethods = d3_time_scaleLocalMethods.map(function(m) { | |
return [ m[0].utc, m[1] ]; | |
}); | |
var d3_time_scaleUTCFormats = [ [ d3.time.format.utc("%Y"), d3_true ], [ d3.time.format.utc("%B"), function(d) { | |
return d.getUTCMonth(); | |
} ], [ d3.time.format.utc("%b %d"), function(d) { | |
return d.getUTCDate() != 1; | |
} ], [ d3.time.format.utc("%a %d"), function(d) { | |
return d.getUTCDay() && d.getUTCDate() != 1; | |
} ], [ d3.time.format.utc("%I %p"), function(d) { | |
return d.getUTCHours(); | |
} ], [ d3.time.format.utc("%I:%M"), function(d) { | |
return d.getUTCMinutes(); | |
} ], [ d3.time.format.utc(":%S"), function(d) { | |
return d.getUTCSeconds(); | |
} ], [ d3.time.format.utc(".%L"), function(d) { | |
return d.getUTCMilliseconds(); | |
} ] ]; | |
var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats); | |
function d3_time_scaleUTCSetYear(y) { | |
var d = new Date(Date.UTC(y, 0, 1)); | |
d.setUTCFullYear(y); | |
return d; | |
} | |
function d3_time_scaleUTCGetYear(d) { | |
var y = d.getUTCFullYear(), d0 = d3_time_scaleUTCSetYear(y), d1 = d3_time_scaleUTCSetYear(y + 1); | |
return y + (d - d0) / (d1 - d0); | |
} | |
d3_time_scaleUTCMethods.year = function(extent, m) { | |
return d3_time_scaleLinear.domain(extent.map(d3_time_scaleUTCGetYear)).ticks(m).map(d3_time_scaleUTCSetYear); | |
}; | |
d3.time.scale.utc = function() { | |
return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat); | |
}; | |
if (module && module.exports) { | |
module.exports = d3; | |
} | |
})(); | |
}); | |
require.register("visionmedia-minstache/index.js", function(exports, require, module){ | |
/** | |
* Expose `render()`.` | |
*/ | |
exports = module.exports = render; | |
/** | |
* Expose `compile()`. | |
*/ | |
exports.compile = compile; | |
/** | |
* Render the given mustache `str` with `obj`. | |
* | |
* @param {String} str | |
* @param {Object} obj | |
* @return {String} | |
* @api public | |
*/ | |
function render(str, obj) { | |
obj = obj || {}; | |
var fn = compile(str); | |
return fn(obj); | |
} | |
/** | |
* Compile the given `str` to a `Function`. | |
* | |
* @param {String} str | |
* @return {Function} | |
* @api public | |
*/ | |
function compile(str) { | |
var js = []; | |
var toks = parse(str); | |
var tok; | |
for (var i = 0; i < toks.length; ++i) { | |
tok = toks[i]; | |
if (i % 2 == 0) { | |
js.push('"' + tok.replace(/"/g, '\\"') + '"'); | |
} else { | |
switch (tok[0]) { | |
case '/': | |
tok = tok.slice(1); | |
js.push(') + '); | |
break; | |
case '^': | |
tok = tok.slice(1); | |
assertProperty(tok); | |
js.push(' + section(obj, "' + tok + '", true, '); | |
break; | |
case '#': | |
tok = tok.slice(1); | |
assertProperty(tok); | |
js.push(' + section(obj, "' + tok + '", false, '); | |
break; | |
default: | |
assertProperty(tok); | |
js.push(' + escape(obj.' + tok + ') + '); | |
} | |
} | |
} | |
js = '\n' | |
+ indent(escape.toString()) + ';\n\n' | |
+ indent(section.toString()) + ';\n\n' | |
+ ' return ' + js.join('').replace(/\n/g, '\\n'); | |
js = normalize(js); | |
return new Function('obj', js); | |
} | |
/** | |
* Assert that `prop` is a valid property. | |
* | |
* @param {String} prop | |
* @api private | |
*/ | |
function assertProperty(prop) { | |
if (!prop.match(/^[\w.]+$/)) throw new Error('invalid property "' + prop + '"'); | |
} | |
/** | |
* Parse `str`. | |
* | |
* @param {String} str | |
* @return {Array} | |
* @api private | |
*/ | |
function parse(str) { | |
return str | |
.replace(/\\\{/g, '__LBRACE__') | |
.replace(/\\\}/g, '__RBRACE__') | |
.split(/\{\{?|\}?\}/) | |
} | |
/** | |
* Normalize `str`, adding back braces. | |
* | |
* @param {String} str | |
* @return {String} | |
* @api private | |
*/ | |
function normalize(str) { | |
return str | |
.replace(/__LBRACE__/g, '{') | |
.replace(/__RBRACE__/g, '}'); | |
} | |
/** | |
* Indent `str`. | |
* | |
* @param {String} str | |
* @return {String} | |
* @api private | |
*/ | |
function indent(str) { | |
return str.replace(/^/gm, ' '); | |
} | |
/** | |
* Section handler. | |
* | |
* @param {Object} context obj | |
* @param {String} prop | |
* @param {String} str | |
* @param {Boolean} negate | |
* @api private | |
*/ | |
function section(obj, prop, negate, str) { | |
var val = obj[prop]; | |
if ('function' == typeof val) return val.call(obj, str); | |
if (negate) val = !val; | |
if (val) return str; | |
return ''; | |
} | |
/** | |
* Escape the given `html`. | |
* | |
* @param {String} html | |
* @return {String} | |
* @api private | |
*/ | |
function escape(html) { | |
return String(html) | |
.replace(/&/g, '&') | |
.replace(/"/g, '"') | |
.replace(/</g, '<') | |
.replace(/>/g, '>'); | |
} | |
}); | |
require.register("component-emitter/index.js", function(exports, require, module){ | |
/** | |
* Expose `Emitter`. | |
*/ | |
module.exports = Emitter; | |
/** | |
* Initialize a new `Emitter`. | |
* | |
* @api public | |
*/ | |
function Emitter(obj) { | |
if (obj) return mixin(obj); | |
}; | |
/** | |
* Mixin the emitter properties. | |
* | |
* @param {Object} obj | |
* @return {Object} | |
* @api private | |
*/ | |
function mixin(obj) { | |
for (var key in Emitter.prototype) { | |
obj[key] = Emitter.prototype[key]; | |
} | |
return obj; | |
} | |
/** | |
* Listen on the given `event` with `fn`. | |
* | |
* @param {String} event | |
* @param {Function} fn | |
* @return {Emitter} | |
* @api public | |
*/ | |
Emitter.prototype.on = function(event, fn){ | |
this._callbacks = this._callbacks || {}; | |
(this._callbacks[event] = this._callbacks[event] || []) | |
.push(fn); | |
return this; | |
}; | |
/** | |
* Adds an `event` listener that will be invoked a single | |
* time then automatically removed. | |
* | |
* @param {String} event | |
* @param {Function} fn | |
* @return {Emitter} | |
* @api public | |
*/ | |
Emitter.prototype.once = function(event, fn){ | |
var self = this; | |
this._callbacks = this._callbacks || {}; | |
function on() { | |
self.off(event, on); | |
fn.apply(this, arguments); | |
} | |
fn._off = on; | |
this.on(event, on); | |
return this; | |
}; | |
/** | |
* Remove the given callback for `event` or all | |
* registered callbacks. | |
* | |
* @param {String} event | |
* @param {Function} fn | |
* @return {Emitter} | |
* @api public | |
*/ | |
Emitter.prototype.off = function(event, fn){ | |
this._callbacks = this._callbacks || {}; | |
var callbacks = this._callbacks[event]; | |
if (!callbacks) return this; | |
// remove all handlers | |
if (1 == arguments.length) { | |
delete this._callbacks[event]; | |
return this; | |
} | |
// remove specific handler | |
var i = callbacks.indexOf(fn._off || fn); | |
if (~i) callbacks.splice(i, 1); | |
return this; | |
}; | |
/** | |
* Emit `event` with the given args. | |
* | |
* @param {String} event | |
* @param {Mixed} ... | |
* @return {Emitter} | |
*/ | |
Emitter.prototype.emit = function(event){ | |
this._callbacks = this._callbacks || {}; | |
var args = [].slice.call(arguments, 1) | |
, callbacks = this._callbacks[event]; | |
if (callbacks) { | |
callbacks = callbacks.slice(0); | |
for (var i = 0, len = callbacks.length; i < len; ++i) { | |
callbacks[i].apply(this, args); | |
} | |
} | |
return this; | |
}; | |
/** | |
* Return array of callbacks for `event`. | |
* | |
* @param {String} event | |
* @return {Array} | |
* @api public | |
*/ | |
Emitter.prototype.listeners = function(event){ | |
this._callbacks = this._callbacks || {}; | |
return this._callbacks[event] || []; | |
}; | |
/** | |
* Check if this emitter has `event` handlers. | |
* | |
* @param {String} event | |
* @return {Boolean} | |
* @api public | |
*/ | |
Emitter.prototype.hasListeners = function(event){ | |
return !! this.listeners(event).length; | |
}; | |
}); | |
require.register("component-bind/index.js", function(exports, require, module){ | |
/** | |
* Slice reference. | |
*/ | |
var slice = [].slice; | |
/** | |
* Bind `obj` to `fn`. | |
* | |
* @param {Object} obj | |
* @param {Function|String} fn or string | |
* @return {Function} | |
* @api public | |
*/ | |
module.exports = function(obj, fn){ | |
if ('string' == typeof fn) fn = obj[fn]; | |
if ('function' != typeof fn) throw new Error('bind() requires a function'); | |
var args = [].slice.call(arguments, 2); | |
return function(){ | |
return fn.apply(obj, args.concat(slice.call(arguments))); | |
} | |
}; | |
}); | |
require.register("insights/src/tooltip.js", function(exports, require, module){ | |
var minstache = require("minstache"); | |
function Tooltip(options) { | |
options = options || {}; | |
//this.template = options.template; | |
this._data = {}; | |
this._createElement(); | |
try { | |
this.renderTemplate = minstache.compile(options.template); | |
} catch(err) { | |
throw new Error("Error parsing tooltip template.", err); | |
} | |
} | |
Tooltip.prototype = { | |
constructor: Tooltip, | |
elementId: "insights-tooltip", | |
elementClass: "insights-tooltip", | |
_createElement: function() { | |
var found = document.getElementById(this.elementId); | |
if (!found) { | |
this.el = document.createElement("div"); | |
this.el.id = this.elementId; | |
this.el.className = this.elementClass; | |
this.el.style.position = "absolute"; | |
this.el.style.display = "none"; | |
document.body.appendChild(this.el); | |
} else { | |
this.el = found; | |
} | |
}, | |
render: function() { | |
var content = this.renderTemplate(this.getData()); | |
if (!this._offset) throw new Error("Must set an offset"); | |
this.el.innerHTML = content; | |
this.el.style.top = this._offset.top + "px"; | |
this.el.style.left = this._offset.left + "px"; | |
return this; | |
}, | |
setOffset: function(offset) { | |
this._offset = offset; | |
}, | |
setData: function(data) { | |
this._data = data; | |
}, | |
getData: function() { | |
return this._data; | |
}, | |
show: function(offset, data) { | |
offset && this.setOffset(offset); | |
data && this.setData(data); | |
this.render(); | |
this.el.style.display = ""; | |
}, | |
hide: function() { | |
this.el.style.display = "none"; | |
} | |
}; | |
module.exports = Tooltip; | |
}); | |
require.register("insights/src/graph.js", function(exports, require, module){ | |
var bind = require("bind"), | |
Emitter = require("emitter"), | |
d3 = require("d3"), | |
Tooltip = require("./tooltip"); | |
var UNSELECTED_COLOR = "transparent"; //"#EFEFEF"; | |
var DEFAULT_PATH_STROKE_WIDTH = .3; | |
var SELECTED_PATH_STROKE_WIDTH = 1.5; | |
var DEFAULT_CIRCLE_STROKE = "#FFF"; | |
var ZOOM_SCALE_EXTENT = [0.2, 2.3]; | |
var TOOLTIP_TEMPLATE = "<div>word: {{text}}</div> <div>count: {{count}}</div> <div>資本額: {{amount}}</div>"; | |
var BASE_ELEMENT_CLASS = "insights-graph"; | |
var DEFAULT_WIDTH = 1200; | |
var DEFAULT_HEIGHT = 700; | |
var DEFAULT_COLLISION_ALPHA = .5; | |
var DEFAULT_FORCE_ALPHA_LIMIT = 0.007; | |
var DEFAULT_SIZE_ATTR = "size"; // where to find size info | |
function Graph(el, nodes, links, options) { | |
options = options || {}; | |
this.el = el; | |
this.links = links; | |
this.nodes = nodes; | |
this.width = options.width || DEFAULT_WIDTH; | |
this.height = options.height ||DEFAULT_HEIGHT; | |
this.color = d3.scale.category20(); | |
this.collisionAlpha = options.collisionAlpha || DEFAULT_COLLISION_ALPHA; | |
this.scaleExtent = options.scaleExtent || ZOOM_SCALE_EXTENT; | |
this.sizeAttr = options.sizeAttr || DEFAULT_SIZE_ATTR; | |
if (options.initialScale) { | |
this._initialScale = options.initialScale; | |
} | |
this.max = {}; | |
this.min = {}; | |
this.adjacentNodes = {}; | |
this.processData(); | |
this.processScales(); | |
this.init(); | |
this.tooltipOn(); | |
options.tooltipTemplate && this.tooltip(options.tooltipTemplate); | |
this.render(); | |
} | |
Graph.version = "0.6.1"; | |
Graph.prototype = { | |
constructor: Graph, | |
processData: function() { | |
var self = this, | |
nodesHash = {}, | |
maxSize = 0, | |
maxWeight = 0, | |
adjacents= {}, | |
linksList = [], | |
clusters = {}, | |
getCluster = bind(this, this.getCluster), | |
getSize = bind(this, this.getSize); | |
this.nodes.forEach(function(n) { | |
var cluster = getCluster(n); | |
maxSize = Math.max(maxSize, getSize(n)); | |
n.name = n.id; | |
nodesHash[n.id] = nodesHash[n.id] || n; | |
if (cluster != null) { | |
// caching cluster data | |
clusters[cluster] = self.color(cluster); | |
} | |
}); | |
// Compute the distinct nodes from the links. | |
this.links.forEach(function(link) { | |
var source = nodesHash[link[0]], | |
target = nodesHash[link[1]]; | |
if (!source ||!target) return; | |
if (!(link[0] in adjacents)) { | |
adjacents[link[0]]= {}; | |
adjacents[link[0]][link[0]]= true; | |
} | |
if (!(link[1] in adjacents)) { | |
adjacents[link[1]]= {}; | |
adjacents[link[1]][link[1]]= true; | |
} | |
adjacents[link[0]][link[1]]=true; | |
adjacents[link[1]][link[0]]= true; | |
linksList.push({ | |
source: source, | |
target: target | |
}); | |
}); | |
this.linksList = linksList; | |
this.adjacents = adjacents; | |
this.nodesHash = nodesHash; | |
this.max.size = maxSize; | |
this.clusters = clusters; | |
}, | |
processScales: function() { | |
this.radiusScale = d3.scale.sqrt().domain([1, this.max.size]).range([6, 40]); | |
this.titleScale = d3.scale.log().domain([1, this.max.size]).range([0, 1]); | |
}, | |
processCenterCoords: function() { | |
var self = this; | |
var xMass=0, yMass=0, totalSize=0; | |
this.d3Nodes.each(function(d) { | |
var size = self.getSize(d); | |
xMass += d.x * size; | |
yMass += d.y * size; | |
totalSize += size; | |
}); | |
this.xCenter = xMass / totalSize; | |
this.yCenter = yMass / totalSize; | |
this.massCenter = [this.xCenter, this.yCenter]; | |
}, | |
init: function() { | |
var self = this; | |
this._zoom = d3.behavior.zoom().translate([0,0]); | |
if (this._initialScale) { | |
this._zoom = this._zoom.scale(this._initialScale); | |
} | |
this.$el = this.getElement(); | |
this.svg = this.$el | |
.attr("class", this.$el.attr("class") + " " + BASE_ELEMENT_CLASS) | |
.append("svg") | |
.attr("width", this.width) | |
.attr("height", this.height) | |
.attr("pointer-events", "all") | |
.call(this._zoom.on("zoom", bind(this, this.onZoom)) | |
.scaleExtent(this.scaleExtent)) | |
this.baseGroup = this.svg.append('svg:g') | |
.style('display','none'); | |
this.$el.on("click", function() { self._reset() }); | |
}, | |
onZoom: function() { | |
this.refreshZoom(); | |
}, | |
refreshZoom: function(animate) { | |
var zoom = this._zoom; | |
var trans = this.getTranslation(); | |
var scale = this.getScale(); | |
if (animate) { | |
this.baseGroup.transition().duration(500).attr('transform', | |
'translate(' + zoom.translate() + ') scale(' + zoom.scale() + ')'); | |
} else { | |
this.baseGroup.attr("transform", "translate(" + trans + ")" + " scale(" + scale + ")"); | |
} | |
this.displayTitle(); | |
}, | |
zoom: function(scale) { | |
var trans = this.getTranslation(); | |
var zoom = this._zoom; | |
zoom.scale(scale); | |
this.refreshZoom(true); | |
}, | |
zoomIn: function() { | |
var scale = this.getScale(); | |
var k = Math.pow(2, Math.floor(Math.log(scale) / Math.LN2) + 1); | |
k = Math.min(k, this.scaleExtent[1]); | |
this.zoom(k); | |
}, | |
zoomOut: function() { | |
var scale = this.getScale(); | |
var k = Math.pow(2, Math.ceil(Math.log(scale) / Math.LN2) - 1); | |
k = Math.max(k, this.scaleExtent[0]); | |
this.zoom(k); | |
}, | |
isTitleDisplayable: function(d) { | |
var scale = this.getScale(); | |
var res = this.titleScale(this.getSize(d) || 1); | |
return (scale * res > .8 || scale > 2.2 ); | |
}, | |
displayTitle: function() { | |
var self = this; | |
var scale = this.getScale(); | |
var adjacentNodes = this.adjacentNodes; | |
var selectedNode = this.selectedNode; | |
var hasSelection = !!this.selectedNode; | |
var isThereMatch = this.isThereMatch(); | |
this.d3TitleNodes.style("display", function(d) { | |
var isDisplayable = self.isTitleDisplayable(d); | |
if (isDisplayable && self.isSelected(d)) { | |
if (isThereMatch && !isMatched(d)) { | |
return "none"; | |
} else { | |
return ""; | |
} | |
} | |
if (hasSelection && !adjacentNodes[d.id]) { | |
return "none" | |
} | |
if (isThereMatch && !isMatched(d)) { | |
return "none"; | |
} | |
if (isDisplayable) { | |
return ""; | |
} else { | |
return "none"; | |
} | |
}); | |
}, | |
pathStroke: function(d) { | |
var source = d.source, | |
target = d.target; | |
if (this.getSize(target) > this.getSize(source)) { | |
return this.getClusterColor(target); | |
} else { | |
return this.getClusterColor(source); | |
} | |
}, | |
render: function() { | |
var self = this; | |
var nodesHash = {}; | |
var nodes = this.nodes; | |
function circleFill(d) { return self.getClusterColor(d); } | |
function circleRadius(d) { return self.radiusScale(self.getSize(d) ||1); } | |
var force = this.force = d3.layout.force() | |
.nodes(d3.values(this.nodesHash)) // turns {a:1, b:2} into [1, 2] | |
.links(this.linksList) | |
.size([this.width, this.height]) | |
.linkDistance(60) | |
.linkStrength(1) | |
.gravity(0.2) | |
.charge(-240) | |
.on("tick", tick) | |
.start(); | |
var path = this.d3Path = this.baseGroup.append("svg:g").selectAll("path") | |
.data(force.links()) | |
.enter().append("svg:path") | |
.attr("stroke", bind(this, this.pathStroke)) | |
.attr("stroke-width", DEFAULT_PATH_STROKE_WIDTH) | |
.attr("fill", "none"); | |
var node = this.d3Nodes = this.baseGroup.selectAll(".node") | |
.data(force.nodes()) | |
.enter().append("g") | |
.attr("class", "node") | |
.on("mouseover", bind(this, this.onMouseOver)) | |
.on("mouseout", bind(this, this.onMouseOut)) | |
.on("click", bind(this, this.onCircleClick)); | |
var circle = this.d3Circles = node.append("circle") | |
.style("fill", circleFill) | |
.attr("r", circleRadius) | |
var titleNodes = this.d3TitleNodes = node.append("text") | |
.attr("text-anchor", "middle") | |
.attr("dy", ".35em") | |
.style("display", "none") | |
.text(function(d) { return self.getText(d); }); | |
function tick(e) { | |
if (force.alpha() < DEFAULT_FORCE_ALPHA_LIMIT) { | |
self.handleCollisions(); | |
// to prevent the chart from moving after | |
force.stop(); | |
self.positionNodes(); | |
self.generateLinks(); | |
self.center(); | |
// showing canvas after finished rendering | |
self.show(); | |
self.refreshZoom(); | |
self.emit("rendered"); | |
} | |
} | |
}, | |
show: function() { | |
this.baseGroup.style('display','block') | |
}, | |
hide: function() { | |
this.baseGroup.style('display','none') | |
}, | |
handleCollisions: function() { | |
var nodes = this.nodes, | |
q = d3.geom.quadtree(nodes), | |
i = 0, | |
n = nodes.length; | |
while (++i < n) { | |
q.visit(this.collide(nodes[i], this.collisionAlpha)); | |
} | |
}, | |
// Updates the position of the nodes | |
positionNodes: function() { | |
this.d3Nodes.attr("transform", function(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
}); | |
}, | |
// Updates the position of the links | |
generateLinks: function() { | |
// curve line between nodes | |
this.d3Path.attr("d", function(d) { | |
var dx = d.target.x - d.source.x, | |
dy = d.target.y - d.source.y, | |
dr = Math.sqrt(dx * dx + dy * dy); | |
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; | |
}); | |
}, | |
onCircleClick: function(d) { | |
var self = this; | |
var circle = this.d3Circles; | |
var path = this.d3Path; | |
var adjacentNodes; | |
if (self.selectedNode && !self.isSelected(d) && !self.isAdjacent(d)) { | |
return; | |
} | |
if (self.isThereMatch() && !isMatched(d)) { | |
return; | |
} | |
d3.event.preventDefault(); | |
d3.event.stopPropagation(); | |
this.focus(d); | |
this.emit("node:click", d); | |
}, | |
onMouseOver: function(d) { | |
var selectedNode = this.selectedNode; | |
if (this.selectedNode && !this.isSelected(d) && !this.isAdjacent(d)) { | |
return; | |
} | |
if (this.isThereMatch() && !isMatched(d)) { | |
return; | |
} | |
var offset = { | |
left: currentMousePos.x + 10, | |
top: currentMousePos.y + 10 | |
}; | |
this.showTooltip(offset, d); | |
this.emit("node:mouseover", d, offset); | |
}, | |
onMouseOut: function(d) { | |
this.hideTooltip(); | |
if (this.selectedNode && !this.isSelected(d) && !this.isAdjacent(d)) { | |
return; | |
} | |
if (this.isThereMatch() && !isMatched(d)) { | |
return; | |
} | |
this.emit("node:mouseout", d); | |
}, | |
selectNode: function(d) { | |
var node, fn; | |
// In this case we want no match data, just the clicked circle data | |
if (this.isThereMatch()) { | |
this._reset(); | |
} | |
if (typeof d === "function") { | |
fn = d; | |
this.d3Nodes.each(function(e) { | |
if (fn(e)) { | |
node = e; | |
} | |
}); | |
} else { | |
node = d; | |
} | |
if (!node) { | |
return; | |
} | |
this.selectedNode = node; | |
if (this.adjacents[node.id]) { | |
this.adjacentNodes = this.adjacents[node.id]; | |
} | |
return node; | |
}, | |
isSelected: function(node) { | |
return this.selectedNode && this.selectedNode.id === node.id; | |
}, | |
isAdjacent: function(node) { | |
return !!this.adjacentNodes[node.id] | |
}, | |
isThereMatch: function() { | |
return this.matching; | |
}, | |
draw: function(fn) { | |
var self = this; | |
var circle = this.d3Circles; | |
var path = this.d3Path; | |
var titles = this.d3TitleNodes; | |
var adjacentNodes = this.adjacentNodes || {}; | |
var selectedNode = this.selectedNode; | |
if (fn) { | |
this.matching = true; | |
} | |
var isThereMatch = this.isThereMatch(); | |
circle.style('fill', function(e) { | |
if (fn) { | |
e._matched = fn(e); | |
} | |
var el = this; | |
var $el = d3.select(el); | |
var yes = function(e, highlight) { | |
// HACK: reordering for zindex | |
el.parentNode.parentNode.appendChild(el.parentNode); | |
$el.style("cursor", "pointer"); | |
var stroke = DEFAULT_CIRCLE_STROKE; | |
if (highlight) { | |
stroke = d3.rgb(self.getClusterColor(e)).darker(); | |
} | |
$el.style("stroke", stroke); | |
return self.getClusterColor(e); | |
} | |
var no = function(d) { | |
$el.style("cursor", "default"); | |
$el.style("stroke", UNSELECTED_COLOR); | |
return UNSELECTED_COLOR; | |
} | |
if (self.isSelected(e)) { | |
return yes(e, true); | |
} | |
if (isMatched(e) || selectedNode && self.isAdjacent(e)) { | |
return yes(e); | |
} | |
return no(e); | |
}); | |
path.attr("stroke", function(e) { | |
var yes = function(e) { return self.pathStroke(e) }, | |
no = UNSELECTED_COLOR; | |
if (self.isSelected(e.source) || self.isSelected(e.target) || isMatched(e.source) && isMatched(e.target)) { | |
return yes(e); | |
} | |
return no; | |
}).attr("stroke-width", function(e) { | |
if (self.isSelected(e.source) || self.isSelected(e.target)) { | |
return SELECTED_PATH_STROKE_WIDTH; | |
} | |
return DEFAULT_PATH_STROKE_WIDTH; | |
}); | |
this.displayTitle(); | |
}, | |
reset: function() { | |
var self = this; | |
var circle = this.d3Circles; | |
var path = this.d3Path; | |
this.adjacentNodes = {}; | |
delete this.selectedNode; | |
delete this.matching; | |
circle.style('fill', function(e) { | |
// reseting selection | |
delete e._matched; | |
return self.getClusterColor(e); | |
}).style("stroke", DEFAULT_CIRCLE_STROKE) | |
.style("cursor", "pointer"); | |
path.attr("stroke-width", function(e, i) { | |
return DEFAULT_PATH_STROKE_WIDTH; | |
}) | |
.attr("stroke", function(e, i) { | |
return self.pathStroke(e); | |
}); | |
this.displayTitle(); | |
}, | |
_reset: function(preventTrigger) { | |
this.reset(); | |
if (!preventTrigger) { | |
this.emit("reset"); | |
} | |
}, | |
/** | |
* Will show all the nodes that match fn's result. | |
* | |
* @api public | |
*/ | |
select: function(fn) { | |
if (this.selectedNode) { | |
this.reset(); | |
} | |
this.draw(fn); | |
}, | |
/** | |
* Will put focus in one node that matches the fn result | |
* | |
* @api public | |
* | |
* @param fn {Object|Function} | |
* @param center {Boolean} | |
*/ | |
focus: function(fn, center) { | |
var n = this.selectNode(fn); | |
if (n) { | |
center && this.center([n.x, n.y]); | |
this.draw(); | |
this.emit("focus", n); | |
} | |
}, | |
selectBy: function(fn, focus) { | |
var n; | |
if (focus) { | |
this.focus(fn); | |
} else { | |
this.select(fn); | |
} | |
}, | |
selectByText: function(text, options) { | |
var fn, | |
matchText = text.toLowerCase(), | |
getText = bind(this, this.getText); | |
options = options || {}; | |
if (options.exact) { | |
fn = function(d) { | |
return getText(d).toLowerCase() == matchText; | |
}; | |
this.selectBy(fn, true); | |
} else { | |
fn = function(d) { | |
var nodeText = getText(d).toLowerCase(); | |
return !!(~nodeText.indexOf(matchText)); | |
}; | |
this.selectBy(fn); | |
} | |
}, | |
selectByTextExact: function(text) { | |
return this.selectByText(text, { exact: true } ); | |
}, | |
selectByCluster: function(cluster) { | |
var getCluster = bind(this, this.getCluster); | |
this.selectBy(function(e) { | |
var c = getCluster(e); | |
if (c != null) { | |
c = c.toString() | |
} | |
// if an array is passed | |
if (typeof cluster == "object" && cluster.indexOf) { | |
return ~cluster.indexOf(c); | |
} | |
// if a value is passed | |
return c == cluster; | |
}); | |
}, | |
selectBySize: function(min, max) { | |
var self = this; | |
this.selectBy(function(d) { | |
var s = self.getSize(d); | |
return min <= s && s <= max; | |
}); | |
}, | |
/** | |
* Prevents nodes from sticking up together ( best effort ) | |
*/ | |
collide: function(node, alpha) { | |
var self = this, | |
r = node.radius + 16, | |
nx1 = node.x - r, | |
nx2 = node.x + r, | |
ny1 = node.y - r, | |
ny2 = node.y + r; | |
return function(quad, x1, y1, x2, y2) { | |
if (quad.point && (quad.point !== node)) { | |
var x = node.x - quad.point.x, | |
y = node.y - quad.point.y, | |
l = Math.sqrt(x * x + y * y), | |
r= self.radiusScale(self.getSize(quad.point) ||1)*2; | |
if (l < r) { | |
l = (l - r) / l * alpha; | |
node.x -= x *= l; | |
node.y -= y *= l; | |
quad.point.x += x; | |
quad.point.y += y; | |
} | |
} | |
return x1 > nx2 | |
|| x2 < nx1 | |
|| y1 > ny2 | |
|| y2 < ny1; | |
} | |
}, | |
location: function(p) { | |
var translate = this.getTranslation(), | |
scale = this.getScale(); | |
return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale]; | |
}, | |
point: function(l) { | |
var translate = this.getTranslation(), | |
scale = this.getScale(); | |
return [l[0] * scale + translate[0], l[1] * scale + translate[1]]; | |
}, | |
translateTo: function(p, l) { | |
var translate = this.getTranslation(); | |
l = this.point(l); | |
translate[0] += p[0] - l[0]; | |
translate[1] += p[1] - l[1]; | |
this._zoom.translate(translate); | |
}, | |
/** | |
* centers the graph on a point, if no point is passed, the mass center of | |
* the graph is used. | |
* | |
* @api public | |
* | |
*/ | |
center: function(l) { | |
var n; | |
if (!l) { | |
n = this.selectedNode; | |
if (n) { | |
l = [ n.x, n.y ]; | |
} else { | |
if (!this.massCenter) { | |
this.processCenterCoords(); | |
} | |
l = this.massCenter; | |
} | |
} | |
this.translateTo([this.width/2, this.height/2], l); | |
this.refreshZoom(true); | |
}, | |
getScale: function() { | |
return this._zoom.scale(); | |
}, | |
getTranslation: function() { | |
return this._zoom.translate(); | |
}, | |
getElement: function() { | |
return d3.select(this.el); | |
}, | |
getSize: function(node) { | |
return node[this.sizeAttr] || 0; | |
}, | |
getText: function(node) { | |
return node.text; | |
}, | |
getCluster: function(node) { | |
return node.cluster; | |
}, | |
getClusters: function() { | |
return this.clusters; | |
}, | |
getClusterColor: function(cluster) { | |
var c; | |
if (typeof cluster === "object") { | |
c = this.getCluster(cluster); | |
} else { | |
c= cluster; | |
} | |
return this.clusters[c]; | |
}, | |
tooltip: function(tmpl) { | |
this._tooltip = new Tooltip({ | |
template: tmpl || TOOLTIP_TEMPLATE | |
}); | |
}, | |
showTooltip: function(offset, d) { | |
this._tooltip && this._tooltipOn && this._tooltip.show(offset, d); | |
}, | |
hideTooltip: function() { | |
this._tooltip && this._tooltip.hide(); | |
}, | |
tooltipOn: function() { | |
this._tooltipOn = true; | |
}, | |
tooltipOff: function() { | |
this.hideTooltip(); | |
this._tooltipOn = false; | |
}, | |
getSelectedNode: function() { | |
return this.selectNode; | |
} | |
} | |
Emitter(Graph.prototype); | |
var currentMousePos = { x: -1, y: -1 }; | |
d3.select(window).on("mousemove", function(d) { | |
var ev = d3.event; | |
currentMousePos.x = ev.pageX; | |
currentMousePos.y = ev.pageY; | |
}); | |
// helpers | |
function isMatched(d) { | |
return hasMatchData(d) && d._matched; | |
} | |
function hasMatchData(d) { | |
return d._matched != null; | |
} | |
module.exports = Graph; | |
}); | |
require.register("insights/index.js", function(exports, require, module){ | |
var graph = require("./src/graph"); | |
module.exports = graph; | |
}); | |
require.alias("ignacioola-d3/d3.js", "insights/deps/d3/d3.js"); | |
require.alias("ignacioola-d3/d3.js", "insights/deps/d3/index.js"); | |
require.alias("visionmedia-minstache/index.js", "insights/deps/minstache/index.js"); | |
require.alias("component-emitter/index.js", "insights/deps/emitter/index.js"); | |
require.alias("component-bind/index.js", "insights/deps/bind/index.js"); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[[{"children":null,"cluster":0,"id":0,"count":2,"size":13.104,"amount":"1,310,400,000","no":"69607994","text":"南紡建設"},{"children":null,"cluster":0,"id":1,"count":5,"size":156.9096314,"amount":"15,690,963,140","text":"台南紡織","no":"68919301"},{"children":null,"cluster":0,"id":2,"count":1,"size":5,"amount":"500,000,000","no":"72065712","text":"明大企業"},{"children":null,"cluster":0,"id":3,"count":3,"size":3.402,"amount":"340,200,000","text":"統上開發建設","no":"86518433"},{"children":null,"cluster":0,"id":4,"count":2,"size":120,"amount":"12,000,000,000","no":"72058206","text":"太子建設開發"},{"children":null,"cluster":0,"id":5,"count":2,"size":0.01,"amount":"1,000,000","text":"弘耀投資","no":"28694609"},{"children":null,"cluster":0,"id":6,"count":2,"size":1.88,"amount":"188,000,000","text":"富聖開發","no":"09479186"},{"children":null,"cluster":0,"id":7,"count":5,"size":1.9999,"amount":"199,990,000","text":"九福投資","no":"22001545"},{"children":null,"cluster":0,"id":8,"count":2,"size":0.99,"amount":"99,000,000","text":"成大投資","no":"23414143"},{"children":null,"cluster":0,"id":9,"count":3,"size":1.5,"amount":"150,000,000","text":"承隆投資","no":"07698538"},{"children":null,"cluster":0,"id":10,"count":4,"size":1.7,"amount":"170,000,000","text":"泰伯投資","no":"22265594"},{"children":null,"cluster":0,"id":11,"count":3,"size":1.9,"amount":"190,000,000","text":"光偉投資","no":"22820299"},{"children":null,"cluster":0,"id":12,"count":1,"size":0.01,"amount":"1,000,000","no":"13183973","text":"懷恩慈暉禮儀"},{"children":null,"cluster":0,"id":13,"count":2,"size":6.6,"amount":"660,000,000","text":"懷仁國際","no":"84705050"},{"children":null,"cluster":0,"id":14,"count":2,"size":0.99,"amount":"99,000,000","no":"01509855","text":"長坤投資"},{"children":null,"cluster":0,"id":15,"count":3,"size":0.936,"amount":"93,600,000","text":"會統企業","no":"12179058"},{"children":null,"cluster":0,"id":16,"count":3,"size":1.8,"amount":"180,000,000","text":"會統投資","no":"86926016"},{"children":null,"cluster":0,"id":17,"count":2,"size":0.9368,"amount":"93,680,000","text":"健勤投資","no":"23113364"},{"children":null,"cluster":0,"id":18,"count":38,"size":600,"amount":"60,000,000,000","text":"統一企業","no":"73251209"},{"children":null,"cluster":0,"id":19,"count":1,"size":0.3,"amount":"30,000,000","no":"23534457","text":"統一棒球隊"},{"children":null,"cluster":0,"id":20,"count":1,"size":10,"amount":"1,000,000,000","no":"89589328","text":"統一生活事業"},{"children":null,"cluster":0,"id":21,"count":37,"size":105,"amount":"10,500,000,000","text":"統一超商","no":"22555003"},{"children":null,"cluster":0,"id":22,"count":1,"size":2,"amount":"200,000,000","no":"27309332","text":"統一蘭陽藝文"},{"children":null,"cluster":0,"id":23,"count":1,"size":1,"amount":"100,000,000","no":"16324194","text":"首阜企業管理顧問"},{"children":null,"cluster":0,"id":24,"count":1,"size":0.15,"amount":"15,000,000","no":"28226612","text":"統超保險經紀人"},{"children":null,"cluster":0,"id":25,"count":1,"size":1.7,"amount":"170,000,000","no":"28459597","text":"酷聖石冰淇淋"},{"children":null,"cluster":0,"id":26,"count":1,"size":8.5,"amount":"850,000,000","no":"80178859","text":"統一佳佳"},{"children":null,"cluster":0,"id":27,"count":1,"size":2,"amount":"200,000,000","no":"27741787","text":"高見文化行銷"},{"children":null,"cluster":0,"id":28,"count":2,"size":1.88,"amount":"188,000,000","text":"台灣英文雜誌社","no":"03563708"},{"children":null,"cluster":0,"id":29,"count":3,"size":1.3,"amount":"130,000,000","text":"大智通文化行銷","no":"16778049"},{"children":null,"cluster":0,"id":30,"count":1,"size":1.5,"amount":"150,000,000","no":"16379900","text":"捷盛運輸"},{"children":null,"cluster":0,"id":31,"count":2,"size":2.572,"amount":"257,200,000","text":"捷盟行銷","no":"23529784"},{"children":null,"cluster":0,"id":32,"count":2,"size":3.2605452,"amount":"326,054,520","text":"統昶行銷","no":"16834909"},{"children":null,"cluster":0,"id":33,"count":1,"size":2.9,"amount":"290,000,000","no":"70790935","text":"統一聖娜多堡"},{"children":null,"cluster":0,"id":34,"count":1,"size":3,"amount":"300,000,000","no":"16151427","text":"統一資訊"},{"children":null,"cluster":0,"id":35,"count":2,"size":0,"amount":null,"text":"株式会社野村總合研究所","no":"0"},{"children":null,"cluster":0,"id":36,"count":8,"size":8.5303733,"amount":"853,037,330","text":"仁暉投資","no":"97171964"},{"children":null,"cluster":0,"id":37,"count":1,"size":10,"amount":"1,000,000,000","no":"70762591","text":"統一速達"},{"children":null,"cluster":0,"id":38,"count":2,"size":0,"amount":null,"text":"日商雅馬多控股集團","no":"0"},{"children":null,"cluster":0,"id":39,"count":1,"size":9.9,"amount":"990,000,000","no":"86379116","text":"統一精工"},{"children":null,"cluster":0,"id":40,"count":1,"size":3.7,"amount":"370,000,000","no":"96922355","text":"博客來數位科技"},{"children":null,"cluster":0,"id":41,"count":2,"size":0.5,"amount":"50,000,000","text":"力智投資","no":"04729360"},{"children":null,"cluster":0,"id":42,"count":1,"size":1.8,"amount":"180,000,000","no":"12656354","text":"金財通商務科技服務"},{"children":null,"cluster":0,"id":43,"count":2,"size":45,"amount":"4,500,000,000","text":"財金資訊","no":"16744111"},{"children":null,"cluster":0,"id":44,"count":2,"size":457.25,"amount":"45,725,000,000","text":"玉山商業銀行","no":"86517510"},{"children":null,"cluster":0,"id":45,"count":1,"size":16,"amount":"1,600,000,000","no":"27999646","text":"統一百華"},{"children":null,"cluster":0,"id":46,"count":1,"size":4.3,"amount":"430,000,000","no":"53340231","text":"點鑽整合行銷"},{"children":null,"cluster":0,"id":47,"count":4,"size":1200,"amount":"120,000,000,000","text":"中華電信","no":"96979933"},{"children":null,"cluster":0,"id":48,"count":2,"size":10,"amount":"1,000,000,000","text":"悠遊卡投資控股","no":"28988941"},{"children":null,"cluster":0,"id":49,"count":1,"size":1.55,"amount":"155,000,000","no":"28476006","text":"寵物達人"},{"children":null,"cluster":0,"id":50,"count":1,"size":3.9,"amount":"390,000,000","no":"89627033","text":"二十一世紀生活事業"},{"children":null,"cluster":0,"id":51,"count":1,"size":5.391099,"amount":"539,109,900","no":"16791845","text":"統一武藏野"},{"children":null,"cluster":0,"id":52,"count":2,"size":1.9,"amount":"190,000,000","no":"12120450","text":"亞細亞食品"},{"children":null,"cluster":0,"id":53,"count":2,"size":0,"amount":null,"text":"馬來西亞商MS","no":"0"},{"children":null,"cluster":0,"id":54,"count":1,"size":0.6,"amount":"60,000,000","no":"53085652","text":"統一上都"},{"children":null,"cluster":0,"id":55,"count":2,"size":0,"amount":null,"text":"日商 SATO RESTAURANT SYSTEMS CO., LTD.","no":"0"},{"children":null,"cluster":0,"id":56,"count":1,"size":5,"amount":"500,000,000","no":"84449046","text":"統一藥品"},{"children":null,"cluster":0,"id":57,"count":2,"size":1.95,"amount":"195,000,000","text":"統仁投資","no":"84445914"},{"children":null,"cluster":0,"id":58,"count":1,"size":1.7,"amount":"170,000,000","no":"28845851","text":"統一午茶風光"},{"children":null,"cluster":0,"id":59,"count":2,"size":0,"amount":null,"text":"日商株式會社SAZABY LEAGUE","no":"0"},{"children":null,"cluster":0,"id":60,"count":1,"size":0,"amount":null,"no":"28467549","text":"台灣馬莎"},{"children":null,"cluster":0,"id":61,"count":2,"size":0,"amount":null,"text":"英商 MARKS AND SPENCER p.l.c.","no":"0"},{"children":null,"cluster":0,"id":62,"count":1,"size":3,"amount":"300,000,000","no":"27359304","text":"統一多拿滋"},{"children":null,"cluster":0,"id":63,"count":1,"size":3,"amount":"300,000,000","no":"89283781","text":"樂清服務"},{"children":null,"cluster":0,"id":64,"count":3,"size":0,"amount":null,"text":"日商株式會社樂清","no":"0"},{"children":null,"cluster":0,"id":65,"count":1,"size":3,"amount":"300,000,000","no":"80518858","text":"台灣無印良品"},{"children":null,"cluster":0,"id":66,"count":2,"size":0,"amount":null,"text":"日商株式會社良品計劃","no":"0"},{"children":null,"cluster":0,"id":67,"count":1,"size":10,"amount":"1,000,000,000","no":"97176399","text":"台灣三菱商事"},{"children":null,"cluster":0,"id":68,"count":7,"size":0,"amount":null,"text":"日商三菱商事株式會社","no":"0"},{"children":null,"cluster":0,"id":69,"count":1,"size":0.2,"amount":"20,000,000","no":"70570405","text":"台灣三菱商事物流"},{"children":null,"cluster":0,"id":70,"count":2,"size":0,"amount":null,"text":"日商三菱商事 株式會社 Mitsubishi Corporation LT, Inc.","no":"0"},{"children":null,"cluster":0,"id":71,"count":1,"size":0.1,"amount":"10,000,000","no":"70580902","text":"台灣新幹線國際工程"},{"children":null,"cluster":0,"id":72,"count":2,"size":0,"amount":null,"text":"日商三井物產株式會社","no":"0"},{"children":null,"cluster":0,"id":73,"count":2,"size":0,"amount":null,"text":"日商丸紅株式會社","no":"0"},{"children":null,"cluster":0,"id":74,"count":2,"size":0,"amount":null,"text":"日商住友商事株式會社","no":"0"},{"children":null,"cluster":0,"id":75,"count":1,"size":17.78,"amount":"1,778,000,000","no":"20927014","text":"大統益"},{"children":null,"cluster":0,"id":76,"count":2,"size":4.914,"amount":"491,400,000","text":"泰華油脂工業","no":"75452103"},{"children":null,"cluster":0,"id":77,"count":2,"size":60,"amount":"6,000,000,000","text":"大成長城企業","no":"73008303"},{"children":null,"cluster":0,"id":78,"count":1,"size":0.8,"amount":"80,000,000","no":"22522307","text":"台灣山崎"},{"children":null,"cluster":0,"id":79,"count":2,"size":0,"amount":null,"text":"日本山崎麵包株式會社","no":"0"},{"children":null,"cluster":0,"id":80,"count":1,"size":180,"amount":"18,000,000,000","no":"03098415","text":"中華汽車工業"},{"children":null,"cluster":0,"id":81,"count":2,"size":200,"amount":"20,000,000,000","text":"裕隆汽車製造","no":"03489200"},{"children":null,"cluster":0,"id":82,"count":2,"size":81.8532,"amount":"8,185,320,000","text":"台元紡織","no":"03516001"},{"children":null,"cluster":0,"id":83,"count":2,"size":0,"amount":null,"text":"日商三荾自動車工業株式會社","no":"0"},{"children":null,"cluster":0,"id":84,"count":2,"size":1.995,"amount":"199,500,000","text":"樂文實業","no":"23471328"},{"children":null,"cluster":0,"id":85,"count":1,"size":5.54,"amount":"554,000,000","no":"28847204","text":"台灣樂天市場"},{"children":null,"cluster":0,"id":86,"count":1,"size":4.06,"amount":"406,000,000","no":"27712880","text":"台灣樂天製菓"},{"children":null,"cluster":0,"id":87,"count":2,"size":0,"amount":null,"text":"韓商LOTTE CONFECTIONERY CO.,LTD.","no":"0"},{"children":null,"cluster":0,"id":88,"count":2,"size":0,"amount":null,"text":"日商樂天株式會社(LOTTE CO.,LTD)","no":"0"},{"children":null,"cluster":0,"id":89,"count":2,"size":0,"amount":null,"text":"日商樂天株式會社","no":"0"},{"children":null,"cluster":0,"id":90,"count":1,"size":15,"amount":"1,500,000,000","no":"28472923","text":"安源通訊"},{"children":null,"cluster":0,"id":91,"count":2,"size":420,"amount":"42,000,000,000","no":"97179430","text":"遠傳電信"},{"children":null,"cluster":0,"id":92,"count":2,"size":60,"amount":"6,000,000,000","text":"遠鼎","no":"05707618"},{"children":null,"cluster":0,"id":93,"count":2,"size":250,"amount":"25,000,000,000","text":"遠鼎投資","no":"22266828"},{"children":null,"cluster":0,"id":94,"count":2,"size":20.5,"amount":"2,050,000,000","text":"鼎元國際投資","no":"16744288"},{"children":null,"cluster":0,"id":95,"count":2,"size":88,"amount":"8,800,000,000","text":"裕民航運","no":"47067419"},{"children":null,"cluster":0,"id":96,"count":2,"size":50,"amount":"5,000,000,000","text":"遠銀國際租賃","no":"16740311"},{"children":null,"cluster":0,"id":97,"count":2,"size":15,"amount":"1,500,000,000","text":"亞洲投資","no":"16745097"},{"children":null,"cluster":0,"id":98,"count":1,"size":2,"amount":"200,000,000","no":"16781797","text":"統一生機開發"},{"children":null,"cluster":0,"id":99,"count":2,"size":1.2,"amount":"120,000,000","no":"21251214","text":"統健實業"},{"children":null,"cluster":0,"id":100,"count":5,"size":37.9705428,"amount":"3,797,054,280","text":"凱友投資","no":"84442590"},{"children":null,"cluster":0,"id":101,"count":2,"size":4.6036,"amount":"460,360,000","no":"12368733","text":"台灣恩益禧"},{"children":null,"cluster":0,"id":102,"count":2,"size":0,"amount":null,"text":"日商日本電氣株式會社","no":"0"},{"children":null,"cluster":0,"id":103,"count":1,"size":2,"amount":"200,000,000","no":"12876266","text":"統智科技"},{"children":null,"cluster":0,"id":104,"count":2,"size":1.6,"amount":"160,000,000","no":"84710429","text":"和盟流通"},{"children":null,"cluster":0,"id":105,"count":2,"size":16,"amount":"1,600,000,000","text":"耐斯企業","no":"65403770"},{"children":null,"cluster":0,"id":106,"count":2,"size":50,"amount":"5,000,000,000","text":"愛之味","no":"65534366"},{"children":null,"cluster":0,"id":107,"count":2,"size":1.7995,"amount":"179,950,000","text":"台富食品工業","no":"27599542"},{"children":null,"cluster":0,"id":108,"count":1,"size":3.51,"amount":"351,000,000","no":"86384770","text":"統一證券投資信託"},{"children":null,"cluster":0,"id":109,"count":2,"size":0.05,"amount":"5,000,000","no":"28864293","text":"統一綜合保險代理人"},{"children":null,"cluster":0,"id":110,"count":2,"size":150,"amount":"15,000,000,000","text":"統一綜合證券","no":"23218183"},{"children":null,"cluster":0,"id":111,"count":1,"size":6.3606,"amount":"636,060,000","no":"16747102","text":"家樂福保險經紀人"},{"children":null,"cluster":0,"id":112,"count":5,"size":90,"amount":"9,000,000,000","text":"家福","no":"22662550"},{"children":null,"cluster":0,"id":113,"count":1,"size":46,"amount":"4,600,000,000","no":"70384248","text":"台灣家樂福"},{"children":null,"cluster":0,"id":114,"count":1,"size":15,"amount":"1,500,000,000","no":"12861469","text":"長陽開發"},{"children":null,"cluster":0,"id":115,"count":2,"size":360,"amount":"36,000,000,000","text":"長榮海運","no":"11337775"},{"children":null,"cluster":0,"id":116,"count":5,"size":50.05,"amount":"5,005,000,000","text":"長榮國際","no":"12508713"},{"children":null,"cluster":0,"id":117,"count":1,"size":1.5,"amount":"150,000,000","no":"29043099","text":"家樂福電信"},{"children":null,"cluster":0,"id":118,"count":2,"size":0,"amount":null,"text":"荷蘭商 Effortel Asia B.V.","no":"0"},{"children":null,"cluster":0,"id":119,"count":2,"size":0,"amount":null,"text":"法商家樂福公司","no":"0"},{"children":null,"cluster":0,"id":120,"count":1,"size":2,"amount":"200,000,000","no":"75537308","text":"統一時代"},{"children":null,"cluster":0,"id":121,"count":2,"size":110,"amount":"11,000,000,000","text":"統正開發","no":"96978370"},{"children":null,"cluster":0,"id":122,"count":5,"size":150,"amount":"15,000,000,000","text":"統一國際開發","no":"16095002"},{"children":null,"cluster":0,"id":123,"count":1,"size":0.01,"amount":"1,000,000","no":"27990286","text":"統一渡假村"},{"children":null,"cluster":0,"id":124,"count":2,"size":16,"amount":"1,600,000,000","text":"統合開發","no":"84708084"},{"children":null,"cluster":0,"id":125,"count":2,"size":10,"amount":"1,000,000,000","no":"12208321","text":"南聯國際貿易"},{"children":null,"cluster":0,"id":126,"count":1,"size":5,"amount":"500,000,000","no":"16097091","text":"統一星巴克"},{"children":null,"cluster":0,"id":127,"count":2,"size":0,"amount":null,"text":"美商星源咖啡國際有限公司","no":"0"},{"children":null,"cluster":0,"id":128,"count":1,"size":10,"amount":"1,000,000,000","no":"22377134","text":"太乙精密"},{"children":null,"cluster":0,"id":129,"count":2,"size":1,"amount":"100,000,000","text":"震泰投資","no":"80299072"},{"children":null,"cluster":0,"id":130,"count":2,"size":20,"amount":"2,000,000,000","text":"坤基創業投資","no":"70789542"},{"children":null,"cluster":0,"id":131,"count":2,"size":7,"amount":"700,000,000","text":"坤基貳創業投資","no":"80026853"},{"children":null,"cluster":0,"id":132,"count":2,"size":4.94125,"amount":"494,125,000","text":"山圓建設","no":"22267137"},{"children":null,"cluster":0,"id":133,"count":2,"size":10,"amount":"1,000,000,000","no":"70757788","text":"廣達創業投資"},{"children":null,"cluster":0,"id":134,"count":2,"size":420,"amount":"42,000,000,000","text":"廣達電腦","no":"22822281"},{"children":null,"cluster":0,"id":135,"count":2,"size":1.98,"amount":"198,000,000","text":"富美","no":"07392939"},{"children":null,"cluster":0,"id":136,"count":2,"size":200,"amount":"20,000,000,000","text":"金寶電子工業","no":"04370927"},{"children":null,"cluster":0,"id":137,"count":2,"size":37.11708,"amount":"3,711,708,000","no":"16634206","text":"東安投資"},{"children":null,"cluster":0,"id":138,"count":2,"size":303.055,"amount":"30,305,500,000","text":"東元電機","no":"11332202"},{"children":null,"cluster":0,"id":139,"count":2,"size":1.5,"amount":"150,000,000","text":"安台國際投資","no":"23826588"},{"children":null,"cluster":0,"id":140,"count":2,"size":5.0562,"amount":"505,620,000","text":"東元國際投資","no":"23415446"},{"children":null,"cluster":0,"id":141,"count":2,"size":9.34,"amount":"934,000,000","text":"堉寶實業","no":"12515067"},{"children":null,"cluster":0,"id":142,"count":2,"size":800,"amount":"80,000,000,000","no":"03750168","text":"台北富邦商業銀行"},{"children":null,"cluster":0,"id":143,"count":2,"size":1200,"amount":"120,000,000,000","text":"富邦金融控股","no":"03374805"},{"children":null,"cluster":0,"id":144,"count":2,"size":50,"amount":"5,000,000,000","no":"22354940","text":"信義房屋仲介"},{"children":null,"cluster":0,"id":145,"count":2,"size":11.7758802,"amount":"1,177,588,020","text":"信義投資開發","no":"86521802"},{"children":null,"cluster":0,"id":146,"count":6,"size":8.425,"amount":"842,500,000","text":"高權投資","no":"22267853"},{"children":null,"cluster":0,"id":147,"count":1,"size":1.98,"amount":"198,000,000","no":"70537075","text":"統一數網"},{"children":null,"cluster":0,"id":148,"count":1,"size":3.6,"amount":"360,000,000","no":"70752833","text":"統義玻璃工業"},{"children":null,"cluster":0,"id":149,"count":1,"size":0.7,"amount":"70,000,000","no":"28210772","text":"光泉生技"},{"children":null,"cluster":0,"id":150,"count":2,"size":10,"amount":"1,000,000,000","text":"光泉牧場","no":"04313172"},{"children":null,"cluster":0,"id":151,"count":1,"size":6,"amount":"600,000,000","no":"04351626","text":"光泉食品"},{"children":null,"cluster":0,"id":152,"count":1,"size":0.06,"amount":"6,000,000","no":"80158468","text":"豐泉國際"},{"children":null,"cluster":0,"id":153,"count":5,"size":8,"amount":"800,000,000","text":"萊爾富國際","no":"23285582"},{"children":null,"cluster":0,"id":154,"count":1,"size":0.5,"amount":"50,000,000","no":"53432436","text":"太御食品"},{"children":null,"cluster":0,"id":155,"count":2,"size":0.7,"amount":"70,000,000","text":"統皓食品","no":"97212331"},{"children":null,"cluster":0,"id":156,"count":1,"size":1.5,"amount":"150,000,000","no":"80562220","text":"天下食品興業"},{"children":null,"cluster":0,"id":157,"count":2,"size":1.2,"amount":"120,000,000","text":"河寶投資","no":"29001160"},{"children":null,"cluster":0,"id":158,"count":2,"size":8.9,"amount":"890,000,000","no":"80060768","text":"復興空廚"},{"children":null,"cluster":0,"id":159,"count":3,"size":90,"amount":"9,000,000,000","text":"復興航空運輸","no":"11719802"},{"children":null,"cluster":0,"id":160,"count":2,"size":16,"amount":"1,600,000,000","no":"22853565","text":"來來超商"},{"children":null,"cluster":0,"id":161,"count":2,"size":20.73381,"amount":"2,073,381,000","text":"來來百貨","no":"01505437"},{"children":null,"cluster":0,"id":162,"count":1,"size":0.4,"amount":"40,000,000","no":"12659845","text":"便利達康"},{"children":null,"cluster":0,"id":163,"count":2,"size":24,"amount":"2,400,000,000","no":"23060248","text":"全家便利商店"},{"children":null,"cluster":0,"id":164,"count":2,"size":0,"amount":null,"text":"日商全家便利商店","no":"0"},{"children":null,"cluster":0,"id":165,"count":2,"size":7.8,"amount":"780,000,000","text":"三洋藥品工業","no":"75031602"},{"children":null,"cluster":0,"id":166,"count":3,"size":50,"amount":"5,000,000,000","text":"泰山企業","no":"59661701"},{"children":null,"cluster":0,"id":167,"count":2,"size":0,"amount":null,"text":"日商伊藤忠商事株式會社","no":"0"},{"children":null,"cluster":0,"id":168,"count":2,"size":7.6,"amount":"760,000,000","no":"22853777","text":"福客多商店"},{"children":null,"cluster":0,"id":169,"count":2,"size":2.986,"amount":"298,600,000","text":"喜威世流通","no":"22391207"},{"children":null,"cluster":0,"id":170,"count":1,"size":2.5,"amount":"250,000,000","no":"12643112","text":"統一速邁自販"},{"children":null,"cluster":0,"id":171,"count":1,"size":0.4,"amount":"40,000,000","no":"28497797","text":"常統企業"},{"children":null,"cluster":0,"id":172,"count":2,"size":37.9301362,"amount":"3,793,013,620","text":"凱南投資","no":"70769779"},{"children":null,"cluster":0,"id":173,"count":1,"size":0.21,"amount":"21,000,000","no":"80165539","text":"統一友友旅行社"},{"children":null,"cluster":0,"id":174,"count":2,"size":1.24,"amount":"124,000,000","text":"統一夢公園生活事業","no":"70486723"},{"children":null,"cluster":0,"id":175,"count":1,"size":1.98,"amount":"198,000,000","no":"89396265","text":"統圓事業"},{"children":null,"cluster":0,"id":176,"count":1,"size":178.4700918,"amount":"17,847,009,180","no":"73252657","text":"統一實業"},{"children":null,"cluster":0,"id":177,"count":1,"size":0.025,"amount":"2,500,000","no":"16728631","text":"德通"},{"children":null,"cluster":0,"id":178,"count":2,"size":25,"amount":"2,500,000,000","text":"德記洋行","no":"22358925"},{"children":null,"cluster":0,"id":179,"count":1,"size":2.995,"amount":"299,500,000","no":"27209235","text":"保旺國際投資有限公司"},{"children":null,"cluster":0,"id":180,"count":3,"size":2.81,"amount":"281,000,000","text":"海任有限公司","no":"97361129"},{"children":null,"cluster":0,"id":181,"count":2,"size":3,"amount":"300,000,000","no":"16821279","text":"啟證企業有限公司"},{"children":null,"cluster":0,"id":182,"count":2,"size":0,"amount":null,"text":"高益企業有限公司","no":"0"},{"children":null,"cluster":0,"id":183,"count":1,"size":0.68,"amount":"68,000,000","no":"27443160","text":"統欣生物科技"},{"children":null,"cluster":0,"id":184,"count":2,"size":0.147,"amount":"14,700,000","text":"榮生投資","no":"27200924"},{"children":null,"cluster":0,"id":185,"count":1,"size":16,"amount":"1,600,000,000","no":"23114413","text":"統樂開發事業"},{"children":null,"cluster":0,"id":186,"count":1,"size":1.6,"amount":"160,000,000","no":"23527408","text":"統萬"},{"children":null,"cluster":0,"id":187,"count":2,"size":0,"amount":null,"text":"龜甲萬株式會社","no":"0"},{"children":null,"cluster":0,"id":188,"count":1,"size":4.6313637,"amount":"463,136,370","no":"89209994","text":"統奕包裝"},{"children":null,"cluster":0,"id":189,"count":2,"size":0.3126023,"amount":"31,260,230","no":"84974343","text":"奕榮投資顧問"},{"children":null,"cluster":0,"id":190,"count":2,"size":0.1515323,"amount":"15,153,230","text":"長鴻興開發有限公司","no":"53164945"},{"children":null,"cluster":0,"id":191,"count":2,"size":0.26,"amount":"26,000,000","text":"雍盛投資有限公司","no":"53172229"},{"children":null,"cluster":0,"id":192,"count":2,"size":0.1515323,"amount":"15,153,230","text":"廣懋投資有限公司","no":"53174211"},{"children":null,"cluster":0,"id":193,"count":2,"size":0.1515323,"amount":"15,153,230","text":"鎧陽投資有限公司","no":"53172446"},{"children":null,"cluster":0,"id":194,"count":1,"size":100,"amount":"10,000,000,000","no":"16130161","text":"台灣神隆"},{"children":null,"cluster":0,"id":195,"count":1,"size":22,"amount":"2,200,000,000","no":"28707338","text":"中裕新藥"},{"children":null,"cluster":0,"id":196,"count":25,"size":0,"amount":null,"text":"行政院國家發展基金管理會","no":"0"},{"children":null,"cluster":0,"id":197,"count":1,"size":0.3,"amount":"30,000,000","no":"25149492","text":"創通投資"},{"children":null,"cluster":0,"id":198,"count":2,"size":8.8,"amount":"880,000,000","text":"波若威科技","no":"16586555"},{"children":null,"cluster":0,"id":199,"count":1,"size":135,"amount":"13,500,000,000","no":"28113217","text":"台積太陽能"},{"children":null,"cluster":0,"id":200,"count":7,"size":2705,"amount":"270,500,000,000","text":"台灣積體電路製造","no":"22099131"},{"children":null,"cluster":0,"id":201,"count":1,"size":110,"amount":"11,000,000,000","no":"28113223","text":"台積固態照明"},{"children":null,"cluster":0,"id":202,"count":1,"size":1,"amount":"100,000,000","no":"53732790","text":"台積光能投資有限公司"},{"children":null,"cluster":0,"id":203,"count":1,"size":15,"amount":"1,500,000,000","no":"16299879","text":"創意電子"},{"children":null,"cluster":0,"id":204,"count":2,"size":0.25,"amount":"25,000,000","text":"創一投資","no":"28711500"},{"children":null,"cluster":0,"id":205,"count":1,"size":26,"amount":"2,600,000,000","no":"16741846","text":"精材科技"},{"children":null,"cluster":0,"id":206,"count":2,"size":6.26,"amount":"626,000,000","text":"台灣豪威投資控股","no":"28796726"},{"children":null,"cluster":0,"id":207,"count":2,"size":0,"amount":null,"text":"英屬蓋曼群島商 VisEra Holding Company","no":"0"},{"children":null,"cluster":0,"id":208,"count":1,"size":8,"amount":"800,000,000","no":"23637828","text":"太極影音科技"},{"children":null,"cluster":0,"id":209,"count":2,"size":30,"amount":"3,000,000,000","no":"80333108","text":"中華投資"},{"children":null,"cluster":0,"id":210,"count":2,"size":0.43,"amount":"43,000,000","text":"翔聯投資有限公司","no":"70464431"},{"children":null,"cluster":0,"id":211,"count":2,"size":0.72,"amount":"72,000,000","text":"鹿橋文化事業","no":"09452399"},{"children":null,"cluster":0,"id":212,"count":2,"size":1,"amount":"100,000,000","text":"長橋國際","no":"16436640"},{"children":null,"cluster":0,"id":213,"count":1,"size":20.01,"amount":"2,001,000,000","no":"70557655","text":"藥華醫藥"},{"children":null,"cluster":0,"id":214,"count":2,"size":0.7,"amount":"70,000,000","no":"84931247","text":"閎泰投資"},{"children":null,"cluster":0,"id":215,"count":2,"size":1.63,"amount":"163,000,000","text":"閎泰科技","no":"12332594"},{"children":null,"cluster":0,"id":216,"count":2,"size":39.5139163,"amount":"3,951,391,630","no":"70785145","text":"翔發投資"},{"children":null,"cluster":0,"id":217,"count":2,"size":465.0569992,"amount":"46,505,699,920","text":"旭發投資","no":"70781106"},{"children":null,"cluster":0,"id":218,"count":1,"size":7,"amount":"700,000,000","no":"27638046","text":"晶心科技"},{"children":null,"cluster":0,"id":219,"count":2,"size":6,"amount":"600,000,000","no":"70802931","text":"智宏投資"},{"children":null,"cluster":0,"id":220,"count":2,"size":50,"amount":"5,000,000,000","text":"智原科技","no":"84149060"},{"children":null,"cluster":0,"id":221,"count":2,"size":0.3,"amount":"30,000,000","text":"建邦顧問","no":"23608886"},{"children":null,"cluster":0,"id":222,"count":1,"size":13,"amount":"1,300,000,000","no":"11381701","text":"亞洲航空"},{"children":null,"cluster":0,"id":223,"count":2,"size":52.42252,"amount":"5,242,252,000","text":"台翔航太工業","no":"23932997"},{"children":null,"cluster":0,"id":224,"count":5,"size":782.8819257,"amount":"78,288,192,570","text":"台灣糖業","no":"03794905"},{"children":null,"cluster":0,"id":225,"count":2,"size":710,"amount":"71,000,000,000","no":"03705903","text":"兆豐國際商業銀行"},{"children":null,"cluster":0,"id":226,"count":2,"size":1200,"amount":"120,000,000,000","text":"兆豐金融控股","no":"70796754"},{"children":null,"cluster":0,"id":227,"count":2,"size":44,"amount":"4,400,000,000","no":"81188829","text":"長榮鋼鐵"},{"children":null,"cluster":0,"id":228,"count":2,"size":0,"amount":null,"text":"財團法人張榮發基金會","no":"0"},{"children":null,"cluster":0,"id":229,"count":2,"size":0.6268,"amount":"62,680,000","text":"龍達投資","no":"86381773"},{"children":null,"cluster":0,"id":230,"count":2,"size":4,"amount":"400,000,000","no":"53643586","text":"銓鼎投資"},{"children":null,"cluster":0,"id":231,"count":2,"size":0.3,"amount":"30,000,000","text":"惠安投資有限公司","no":"16102138"},{"children":null,"cluster":0,"id":232,"count":2,"size":1.50616,"amount":"150,616,000","text":"揚子開發","no":"11715910"},{"children":null,"cluster":0,"id":233,"count":2,"size":0.005,"amount":"500,000","text":"上儀投資有限公司","no":"28160490"},{"children":null,"cluster":0,"id":234,"count":2,"size":8,"amount":"800,000,000","text":"國登營造","no":"22265686"},{"children":null,"cluster":0,"id":235,"count":1,"size":1.5002,"amount":"150,020,000","no":"53899138","text":"新能生物科技"},{"children":null,"cluster":0,"id":236,"count":2,"size":100,"amount":"10,000,000,000","text":"李長榮化學工業","no":"39054405"},{"children":null,"cluster":0,"id":237,"count":6,"size":1700,"amount":"170,000,000,000","text":"中國鋼鐵","no":"30414175"},{"children":null,"cluster":0,"id":238,"count":2,"size":1.07,"amount":"107,000,000","text":"惠利投資","no":"28861275"},{"children":null,"cluster":0,"id":239,"count":2,"size":0.5,"amount":"50,000,000","text":"台安生物科技","no":"13166691"},{"children":null,"cluster":0,"id":240,"count":2,"size":98,"amount":"9,800,000,000","no":"03795101","text":"台灣肥料"},{"children":null,"cluster":0,"id":241,"count":2,"size":0,"amount":null,"text":"行政院農業委員會","no":"0"},{"children":null,"cluster":0,"id":242,"count":3,"size":1000,"amount":"100,000,000,000","text":"中華郵政","no":"03741302"},{"children":null,"cluster":0,"id":243,"count":2,"size":0.25,"amount":"25,000,000","text":"華盛資產管理顧問","no":"24484482"},{"children":null,"cluster":0,"id":244,"count":2,"size":100,"amount":"10,000,000,000","no":"14057995","text":"東聯化學"},{"children":null,"cluster":0,"id":245,"count":2,"size":0.2813448,"amount":"28,134,480","text":"裕民貿易","no":"03453809"},{"children":null,"cluster":0,"id":246,"count":2,"size":600,"amount":"60,000,000,000","text":"遠東新世紀","no":"03522600"},{"children":null,"cluster":0,"id":247,"count":3,"size":360,"amount":"36,000,000,000","text":"亞洲水泥","no":"03244509"},{"children":null,"cluster":0,"id":248,"count":2,"size":22,"amount":"2,200,000,000","text":"裕利投資","no":"89392508"},{"children":null,"cluster":0,"id":249,"count":2,"size":0,"amount":null,"text":"財團法人徐有庠先生紀念基金會","no":"0"},{"children":null,"cluster":0,"id":250,"count":2,"size":30,"amount":"3,000,000,000","no":"23221384","text":"中鋼碳素化學"},{"children":null,"cluster":0,"id":251,"count":2,"size":55,"amount":"5,500,000,000","text":"中國合成橡膠","no":"04382114"},{"children":null,"cluster":0,"id":252,"count":2,"size":0.299,"amount":"29,900,000","text":"高瑞投資","no":"97159878"},{"children":null,"cluster":0,"id":253,"count":2,"size":90,"amount":"9,000,000,000","text":"中鼎工程","no":"20817282"},{"children":null,"cluster":0,"id":254,"count":2,"size":0,"amount":null,"text":"巴哈馬國泰投資開發公司","no":"0"},{"children":null,"cluster":0,"id":255,"count":2,"size":230,"amount":"23,000,000,000","no":"07435515","text":"新光合成纖維"},{"children":null,"cluster":0,"id":256,"count":2,"size":0.695,"amount":"69,500,000","text":"新光開發","no":"86155191"},{"children":null,"cluster":0,"id":257,"count":2,"size":1.95,"amount":"195,000,000","text":"臺灣新光實業","no":"07127904"},{"children":null,"cluster":0,"id":258,"count":2,"size":0.28,"amount":"28,000,000","text":"德岳實業","no":"86031431"},{"children":null,"cluster":0,"id":259,"count":2,"size":1,"amount":"100,000,000","text":"進賢投資","no":"22553791"},{"children":null,"cluster":0,"id":260,"count":2,"size":0,"amount":null,"text":"財團法人新光吳火獅文教基金會","no":"0"},{"children":null,"cluster":0,"id":261,"count":2,"size":1.5,"amount":"150,000,000","text":"綿豪實業","no":"01188571"},{"children":null,"cluster":0,"id":262,"count":2,"size":1.96,"amount":"196,000,000","text":"新光育樂","no":"04205933"},{"children":null,"cluster":0,"id":263,"count":1,"size":50,"amount":"5,000,000,000","no":"28230046","text":"達輝光電"},{"children":null,"cluster":0,"id":264,"count":1,"size":8,"amount":"800,000,000","no":"12905993","text":"永昕生物醫藥"},{"children":null,"cluster":0,"id":265,"count":2,"size":15,"amount":"1,500,000,000","text":"晟德大藥廠","no":"18606304"},{"children":null,"cluster":0,"id":266,"count":2,"size":0.215,"amount":"21,500,000","text":"玉群投資有限公司","no":"12676247"},{"children":null,"cluster":0,"id":267,"count":1,"size":5,"amount":"500,000,000","no":"12933631","text":"益芯科技"},{"children":null,"cluster":0,"id":268,"count":2,"size":330,"amount":"33,000,000,000","text":"世界先進積體電路","no":"84149358"},{"children":null,"cluster":0,"id":269,"count":2,"size":15,"amount":"1,500,000,000","no":"96961286","text":"達利投資"},{"children":null,"cluster":0,"id":270,"count":3,"size":500,"amount":"50,000,000,000","text":"佳世達科技","no":"12490306"},{"children":null,"cluster":0,"id":271,"count":1,"size":8,"amount":"800,000,000","no":"80694539","text":"得藝國際媒體"},{"children":null,"cluster":0,"id":272,"count":2,"size":50,"amount":"5,000,000,000","no":"70721522","text":"明基電通"},{"children":null,"cluster":0,"id":273,"count":2,"size":40,"amount":"4,000,000,000","no":"80355806","text":"中國信託創業投資"},{"children":null,"cluster":0,"id":274,"count":3,"size":1500,"amount":"150,000,000,000","text":"中國信託金融控股","no":"80333992"},{"children":null,"cluster":0,"id":275,"count":1,"size":0.3,"amount":"30,000,000","no":"54162327","text":"健如醫藥"},{"children":null,"cluster":0,"id":276,"count":3,"size":15,"amount":"1,500,000,000","text":"健亞生物科技","no":"84149006"},{"children":null,"cluster":0,"id":277,"count":1,"size":0.45,"amount":"45,000,000","no":"29030539","text":"華鼎生技顧問"},{"children":null,"cluster":0,"id":278,"count":2,"size":2,"amount":"200,000,000","text":"昌達生化科技","no":"80524351"},{"children":null,"cluster":0,"id":279,"count":2,"size":0,"amount":null,"text":"英屬維京群島商華智國際有限公司","no":"0"},{"children":null,"cluster":0,"id":280,"count":2,"size":6,"amount":"600,000,000","no":"80499901","text":"躍欣生技醫藥"},{"children":null,"cluster":0,"id":281,"count":2,"size":0,"amount":null,"text":"英屬維京群島商 EQUITY SMART GROUP LIMITED","no":"0"},{"children":null,"cluster":0,"id":282,"count":2,"size":0.05,"amount":"5,000,000","text":"力祥藥品","no":"23749915"},{"children":null,"cluster":0,"id":283,"count":2,"size":0.2,"amount":"20,000,000","text":"一成藥品","no":"12337417"},{"children":null,"cluster":0,"id":284,"count":2,"size":0.72,"amount":"72,000,000","text":"祐僑","no":"12272603"},{"children":null,"cluster":0,"id":285,"count":2,"size":0.1,"amount":"10,000,000","text":"綺麗健康奈米生醫","no":"16756994"},{"children":null,"cluster":0,"id":286,"count":2,"size":35,"amount":"3,500,000,000","no":"11821341","text":"台灣東洋藥品工業"},{"children":null,"cluster":0,"id":287,"count":2,"size":0.6,"amount":"60,000,000","text":"歐室食品","no":"23279224"},{"children":null,"cluster":0,"id":288,"count":2,"size":0.03365,"amount":"3,365,000","text":"大灣科技","no":"12937432"},{"children":null,"cluster":0,"id":289,"count":2,"size":0.05,"amount":"5,000,000","text":"智新投資","no":"12865182"},{"children":null,"cluster":0,"id":290,"count":1,"size":12,"amount":"1,200,000,000","no":"80264691","text":"智擎生技製藥"},{"children":null,"cluster":0,"id":291,"count":2,"size":926.6851,"amount":"92,668,510,000","no":"11147207","text":"中華開發工業銀行"},{"children":null,"cluster":0,"id":292,"count":2,"size":2000,"amount":"200,000,000,000","text":"中華開發金融控股","no":"70827383"},{"children":null,"cluster":0,"id":293,"count":2,"size":8.3,"amount":"830,000,000","no":"80350773","text":"元大壹創業投資"},{"children":null,"cluster":0,"id":294,"count":2,"size":35,"amount":"3,500,000,000","text":"元大創業投資","no":"80349875"},{"children":null,"cluster":0,"id":295,"count":1,"size":6,"amount":"600,000,000","no":"75940820","text":"公準精密工業"},{"children":null,"cluster":0,"id":296,"count":4,"size":0,"amount":null,"text":"耀華玻璃管理委員會","no":"0"},{"children":null,"cluster":0,"id":297,"count":2,"size":0,"amount":null,"text":"台元創業投資","no":"0"},{"children":null,"cluster":0,"id":298,"count":2,"size":0.01,"amount":"1,000,000","text":"巨展投資","no":"13157010"},{"children":null,"cluster":0,"id":299,"count":2,"size":0.01,"amount":"1,000,000","text":"路社投資","no":"13156883"},{"children":null,"cluster":0,"id":300,"count":1,"size":10.78,"amount":"1,078,000,000","no":"84299742","text":"聯亞生技開發"},{"children":null,"cluster":0,"id":301,"count":2,"size":0,"amount":null,"text":"美商聯合生物醫學","no":"0"},{"children":null,"cluster":0,"id":302,"count":2,"size":0,"amount":null,"text":"行政院開發基金管理委員會","no":"0"},{"children":null,"cluster":0,"id":303,"count":1,"size":30,"amount":"3,000,000,000","no":"33259508","text":"國光生物科技"},{"children":null,"cluster":0,"id":304,"count":2,"size":0.25,"amount":"25,000,000","text":"精茂投資","no":"28914815"},{"children":null,"cluster":0,"id":305,"count":2,"size":8.743,"amount":"874,300,000","no":"75370601","text":"南和興產"},{"children":null,"cluster":0,"id":306,"count":2,"size":1.5,"amount":"150,000,000","text":"和川","no":"23988176"},{"children":null,"cluster":0,"id":307,"count":2,"size":0.25,"amount":"25,000,000","text":"川盛","no":"84313815"},{"children":null,"cluster":0,"id":308,"count":2,"size":0.39,"amount":"39,000,000","text":"田潤","no":"86919296"},{"children":null,"cluster":0,"id":309,"count":2,"size":0.7,"amount":"70,000,000","text":"萬利通","no":"23988210"},{"children":null,"cluster":0,"id":310,"count":2,"size":1.5,"amount":"150,000,000","text":"園城企業","no":"23988062"},{"children":null,"cluster":0,"id":311,"count":1,"size":0.001,"amount":"100,000","no":"54152496","text":"理想大地國際開發"},{"children":null,"cluster":0,"id":312,"count":2,"size":80,"amount":"8,000,000,000","text":"理想大地","no":"16450993"},{"children":null,"cluster":0,"id":313,"count":2,"size":1.98,"amount":"198,000,000","text":"理想渡假產業","no":"23533859"},{"children":null,"cluster":0,"id":314,"count":2,"size":25,"amount":"2,500,000,000","text":"豐之谷國際","no":"16084498"},{"children":null,"cluster":0,"id":315,"count":2,"size":1.98,"amount":"198,000,000","text":"金盾開發","no":"23114440"},{"children":null,"cluster":0,"id":316,"count":2,"size":72,"amount":"7,200,000,000","no":"22099532","text":"神基科技"},{"children":null,"cluster":0,"id":317,"count":2,"size":220,"amount":"22,000,000,000","text":"神達電腦","no":"47255708"},{"children":null,"cluster":0,"id":318,"count":2,"size":6.77738,"amount":"677,738,000","text":"和利投資","no":"16839427"},{"children":null,"cluster":0,"id":319,"count":2,"size":128,"amount":"12,800,000,000","text":"聯華實業","no":"11996904"},{"children":null,"cluster":0,"id":320,"count":1,"size":58,"amount":"5,800,000,000","no":"16095404","text":"豐達科技"},{"children":null,"cluster":0,"id":321,"count":2,"size":0.04,"amount":"4,000,000","text":"丰揚電通","no":"80193872"},{"children":null,"cluster":0,"id":322,"count":1,"size":3.5,"amount":"350,000,000","no":"16590495","text":"富堅管理顧問"},{"children":null,"cluster":0,"id":323,"count":9,"size":20,"amount":"2,000,000,000","text":"信東生技","no":"43211700"},{"children":null,"cluster":0,"id":324,"count":1,"size":1.78,"amount":"178,000,000","no":"24244499","text":"信東流通事業"},{"children":null,"cluster":0,"id":325,"count":1,"size":0.17,"amount":"17,000,000","no":"70535652","text":"復御管理"},{"children":null,"cluster":0,"id":326,"count":1,"size":0.0776067,"amount":"7,760,670","no":"79983011","text":"生群生技"},{"children":null,"cluster":0,"id":327,"count":1,"size":0.5,"amount":"50,000,000","no":"70559767","text":"國際厚生數位科技"},{"children":null,"cluster":0,"id":328,"count":2,"size":1.33,"amount":"133,000,000","text":"台灣新蛋","no":"13136368"},{"children":null,"cluster":0,"id":329,"count":1,"size":3.2,"amount":"320,000,000","no":"28059706","text":"榮民製藥"},{"children":null,"cluster":0,"id":330,"count":2,"size":0,"amount":null,"text":"行政院國軍退除役官兵輔導委員會","no":"0"},{"children":null,"cluster":0,"id":331,"count":1,"size":6,"amount":"600,000,000","no":"28432633","text":"敏盛資產管理"},{"children":null,"cluster":0,"id":332,"count":3,"size":0.6584077,"amount":"65,840,770","text":"博恩管理顧問","no":"80572992"},{"children":null,"cluster":0,"id":333,"count":3,"size":2.3898413,"amount":"238,984,130","text":"楊征投資","no":"24259416"},{"children":null,"cluster":0,"id":334,"count":3,"size":4.2,"amount":"420,000,000","text":"瑞安大藥廠","no":"23045916"},{"children":null,"cluster":0,"id":335,"count":3,"size":1.5,"amount":"150,000,000","text":"福林投資","no":"16477682"},{"children":null,"cluster":0,"id":336,"count":3,"size":8.6,"amount":"860,000,000","text":"高銀化學工業","no":"04397411"},{"children":null,"cluster":0,"id":337,"count":1,"size":19,"amount":"1,900,000,000","no":"97175440","text":"敏盛醫控"},{"children":null,"cluster":0,"id":338,"count":2,"size":0.837,"amount":"83,700,000","no":"04348186","text":"祐源"},{"children":null,"cluster":0,"id":339,"count":3,"size":0.6,"amount":"60,000,000","text":"永祐實業","no":"23604988"},{"children":null,"cluster":0,"id":340,"count":2,"size":0.1268,"amount":"12,680,000","text":"定吉實業","no":"27718006"},{"children":null,"cluster":0,"id":341,"count":2,"size":2,"amount":"200,000,000","text":"台灣創業投資","no":"22554052"},{"children":null,"cluster":0,"id":342,"count":1,"size":0.5,"amount":"50,000,000","no":"12876174","text":"彰銀人身保險代理人"},{"children":null,"cluster":0,"id":343,"count":5,"size":800,"amount":"80,000,000,000","text":"彰化商業銀行","no":"51811609"},{"children":null,"cluster":0,"id":344,"count":1,"size":0.08,"amount":"8,000,000","no":"80175776","text":"彰銀保險經紀人"},{"children":null,"cluster":0,"id":345,"count":1,"size":3.8,"amount":"380,000,000","no":"23221791","text":"七億建築經理"},{"children":null,"cluster":0,"id":346,"count":2,"size":0.05,"amount":"5,000,000","text":"長勝投資有限公司","no":"28627341"},{"children":null,"cluster":0,"id":347,"count":2,"size":0.1,"amount":"10,000,000","text":"帝信投資有限公司","no":"29041304"},{"children":null,"cluster":0,"id":348,"count":2,"size":31.9639281,"amount":"3,196,392,810","text":"海華建設","no":"20846081"},{"children":null,"cluster":0,"id":349,"count":1,"size":0.97,"amount":"97,000,000","no":"97290477","text":"聯安服務"},{"children":null,"cluster":0,"id":350,"count":2,"size":45,"amount":"4,500,000,000","text":"台灣新光保全","no":"12261768"},{"children":null,"cluster":0,"id":351,"count":2,"size":491.5752571,"amount":"49,157,525,710","text":"台新國際商業銀行","no":"86519539"},{"children":null,"cluster":0,"id":352,"count":2,"size":50,"amount":"5,000,000,000","text":"永豐創業投資","no":"80352673"},{"children":null,"cluster":0,"id":353,"count":2,"size":300,"amount":"30,000,000,000","text":"聯邦商業銀行","no":"86380802"},{"children":null,"cluster":0,"id":354,"count":2,"size":627.2,"amount":"62,720,000,000","text":"第一商業銀行","no":"05052322"},{"children":null,"cluster":0,"id":355,"count":2,"size":573.79,"amount":"57,379,000,000","text":"華南商業銀行","no":"03742301"},{"children":null,"cluster":0,"id":356,"count":2,"size":800,"amount":"80,000,000,000","text":"合作金庫商業銀行","no":"70799128"},{"children":null,"cluster":0,"id":357,"count":2,"size":476,"amount":"47,600,000,000","text":"安泰商業銀行","no":"86928561"},{"children":null,"cluster":0,"id":358,"count":2,"size":6,"amount":"600,000,000","text":"誼光保全","no":"89441178"},{"children":null,"cluster":0,"id":359,"count":2,"size":1200,"amount":"120,000,000,000","no":"80328055","text":"台新金融控股"},{"children":null,"cluster":0,"id":360,"count":2,"size":0.26,"amount":"26,000,000","text":"博瑞","no":"84129640"},{"children":null,"cluster":0,"id":361,"count":2,"size":1.3,"amount":"130,000,000","text":"東賢投資有限公司","no":"04278323"},{"children":null,"cluster":0,"id":362,"count":2,"size":2.3,"amount":"230,000,000","text":"台合實業投資","no":"22765198"},{"children":null,"cluster":0,"id":363,"count":2,"size":0.45,"amount":"45,000,000","text":"翔肇投資","no":"27555333"},{"children":null,"cluster":0,"id":364,"count":2,"size":0.5,"amount":"50,000,000","text":"朋城","no":"04499487"},{"children":null,"cluster":0,"id":365,"count":2,"size":0.45,"amount":"45,000,000","text":"名師企業管理顧問","no":"84133497"},{"children":null,"cluster":0,"id":366,"count":2,"size":6,"amount":"600,000,000","text":"台新國際投資開發","no":"16099838"},{"children":null,"cluster":0,"id":367,"count":2,"size":4,"amount":"400,000,000","text":"名皇國際物業","no":"16442740"},{"children":null,"cluster":0,"id":368,"count":1,"size":438.5499973,"amount":"43,854,999,730","no":"03787101","text":"臺灣菸酒"},{"children":null,"cluster":0,"id":369,"count":8,"size":0,"amount":null,"text":"財政部","no":"0"},{"children":null,"cluster":0,"id":370,"count":1,"size":900,"amount":"90,000,000,000","no":"28428379","text":"臺灣金融控股"},{"children":null,"cluster":0,"id":371,"count":1,"size":500,"amount":"50,000,000,000","no":"03700301","text":"臺灣土地銀行"},{"children":null,"cluster":0,"id":372,"count":1,"size":1000,"amount":"100,000,000,000","no":"80351999","text":"第一金融控股"},{"children":null,"cluster":0,"id":373,"count":2,"size":700,"amount":"70,000,000,000","text":"臺灣銀行","no":"03557311"},{"children":null,"cluster":0,"id":374,"count":2,"size":1,"amount":"100,000,000","text":"金園投資","no":"23221151"},{"children":null,"cluster":0,"id":375,"count":2,"size":0.57,"amount":"57,000,000","text":"全球通投資","no":"24309990"},{"children":null,"cluster":0,"id":376,"count":1,"size":600,"amount":"60,000,000,000","no":"03793407","text":"臺灣中小企業銀行"},{"children":null,"cluster":0,"id":377,"count":2,"size":0,"amount":null,"text":"臺灣銀行","no":"0"},{"children":null,"cluster":0,"id":378,"count":2,"size":0,"amount":null,"text":"台灣土地銀行","no":"0"},{"children":null,"cluster":0,"id":379,"count":2,"size":0,"amount":null,"text":"愛米斯機械工業","no":"0"},{"children":null,"cluster":0,"id":380,"count":2,"size":0,"amount":null,"text":"臺灣中小企業銀行企業工會","no":"0"},{"children":null,"cluster":0,"id":381,"count":1,"size":60,"amount":"6,000,000,000","no":"11081991","text":"中央再保險"},{"children":null,"cluster":0,"id":382,"count":2,"size":10,"amount":"1,000,000,000","text":"翔利投資","no":"70800315"},{"children":null,"cluster":0,"id":383,"count":2,"size":20,"amount":"2,000,000,000","text":"合興石化工業","no":"23531178"},{"children":null,"cluster":0,"id":384,"count":2,"size":0.68,"amount":"68,000,000","text":"凡登投資","no":"13107693"},{"children":null,"cluster":0,"id":385,"count":1,"size":130,"amount":"13,000,000,000","no":"70798839","text":"高雄捷運"},{"children":null,"cluster":0,"id":386,"count":2,"size":150,"amount":"15,000,000,000","text":"榮民工程","no":"16631762"},{"children":null,"cluster":0,"id":387,"count":2,"size":175,"amount":"17,500,000,000","text":"遠東百貨","no":"03521905"},{"children":null,"cluster":0,"id":388,"count":2,"size":150,"amount":"15,000,000,000","no":"79854797","text":"高雄銀行"},{"children":null,"cluster":0,"id":389,"count":2,"size":0,"amount":null,"text":"高雄市政府","no":"0"},{"children":null,"cluster":0,"id":390,"count":2,"size":4.5225,"amount":"452,250,000","text":"晉禾企業","no":"88680066"},{"children":null,"cluster":0,"id":391,"count":1,"size":9.5,"amount":"950,000,000","no":"22645531","text":"力新國際科技"},{"children":null,"cluster":0,"id":392,"count":4,"size":50,"amount":"5,000,000,000","text":"力信投資","no":"16447956"},{"children":null,"cluster":0,"id":393,"count":3,"size":8,"amount":"800,000,000","text":"智翔投資","no":"27250233"},{"children":null,"cluster":0,"id":394,"count":3,"size":40,"amount":"4,000,000,000","text":"世仁投資","no":"70816267"},{"children":null,"cluster":0,"id":395,"count":2,"size":4.8,"amount":"480,000,000","text":"力世創業投資","no":"16080009"},{"children":null,"cluster":0,"id":396,"count":2,"size":1.99,"amount":"199,000,000","text":"力元投資","no":"97163654"},{"children":null,"cluster":0,"id":397,"count":2,"size":8,"amount":"800,000,000","text":"利翔航太電子","no":"97324075"},{"children":null,"cluster":0,"id":398,"count":2,"size":1.98,"amount":"198,000,000","text":"力立企業","no":"20999396"},{"children":null,"cluster":0,"id":399,"count":2,"size":0,"amount":null,"text":"行政院國家科學技術發展基金","no":"0"},{"children":null,"cluster":0,"id":400,"count":2,"size":150,"amount":"15,000,000,000","no":"97160544","text":"漢翔航空工業"},{"children":null,"cluster":0,"id":401,"count":2,"size":0,"amount":null,"text":"經濟部","no":"0"},{"children":null,"cluster":0,"id":402,"count":2,"size":25,"amount":"2,500,000,000","no":"27558036","text":"智立投資"},{"children":null,"cluster":0,"id":403,"count":2,"size":15,"amount":"1,500,000,000","text":"智豐科技","no":"13117926"},{"children":null,"cluster":0,"id":404,"count":2,"size":5,"amount":"500,000,000","text":"智仁科技開發","no":"80688488"},{"children":null,"cluster":0,"id":405,"count":2,"size":15,"amount":"1,500,000,000","text":"世成科技","no":"80034994"},{"children":null,"cluster":0,"id":406,"count":2,"size":49,"amount":"4,900,000,000","no":"11547230","text":"高林實業"},{"children":null,"cluster":0,"id":407,"count":2,"size":1.1079999,"amount":"110,799,990","text":"憬興投資","no":"05634947"},{"children":null,"cluster":0,"id":408,"count":1,"size":4.65,"amount":"465,000,000","no":"28461658","text":"華航大飯店"},{"children":null,"cluster":0,"id":409,"count":17,"size":600,"amount":"60,000,000,000","text":"中華航空","no":"11145904"},{"children":null,"cluster":0,"id":410,"count":1,"size":0.5,"amount":"50,000,000","no":"23361835","text":"華夏"},{"children":null,"cluster":0,"id":411,"count":1,"size":40,"amount":"4,000,000,000","no":"23988865","text":"華信航空"},{"children":null,"cluster":0,"id":412,"count":1,"size":0.9,"amount":"90,000,000","no":"22188422","text":"華懋國際廣告"},{"children":null,"cluster":0,"id":413,"count":1,"size":0.16,"amount":"16,000,000","no":"12681826","text":"華旅網際旅行社"},{"children":null,"cluster":0,"id":414,"count":1,"size":15,"amount":"1,500,000,000","no":"28218351","text":"華航園區"},{"children":null,"cluster":0,"id":415,"count":1,"size":1.3861775,"amount":"138,617,750","no":"23827593","text":"先啟資訊系統"},{"children":null,"cluster":0,"id":416,"count":2,"size":0,"amount":null,"text":"新加坡商環亞旅遊資訊系統有限公司","no":"0"},{"children":null,"cluster":0,"id":417,"count":1,"size":0.1,"amount":"10,000,000","no":"84947584","text":"全球聯運"},{"children":null,"cluster":0,"id":418,"count":2,"size":0.25,"amount":"25,000,000","text":"立盟海空通運","no":"04399353"},{"children":null,"cluster":0,"id":419,"count":2,"size":1.2636,"amount":"126,360,000","text":"鴻霖航空貨運代理","no":"30436044"},{"children":null,"cluster":0,"id":420,"count":2,"size":4.356,"amount":"435,600,000","no":"20685304","text":"臺灣航勤"},{"children":null,"cluster":0,"id":421,"count":2,"size":0.75,"amount":"75,000,000","text":"日鑫資產管理","no":"53762858"},{"children":null,"cluster":0,"id":422,"count":2,"size":200,"amount":"20,000,000,000","text":"國產實業建設","no":"24060203"},{"children":null,"cluster":0,"id":423,"count":2,"size":13.583,"amount":"1,358,300,000","text":"勇誼","no":"04491653"},{"children":null,"cluster":0,"id":424,"count":1,"size":8.64,"amount":"864,000,000","no":"89282663","text":"華膳空廚"},{"children":null,"cluster":0,"id":425,"count":2,"size":0,"amount":null,"text":"香港商奧迪有限公司","no":"0"},{"children":null,"cluster":0,"id":426,"count":1,"size":7,"amount":"700,000,000","no":"20806736","text":"桃園航勤"},{"children":null,"cluster":0,"id":427,"count":2,"size":0,"amount":null,"text":"交通部","no":"0"},{"children":null,"cluster":0,"id":428,"count":2,"size":0,"amount":null,"text":"美商優比速航空","no":"89403619"},{"children":null,"cluster":0,"id":429,"count":1,"size":25,"amount":"2,500,000,000","no":"70759575","text":"華儲"},{"children":null,"cluster":0,"id":430,"count":2,"size":2.653,"amount":"265,300,000","text":"誼遠實業","no":"70354737"},{"children":null,"cluster":0,"id":431,"count":2,"size":0,"amount":null,"text":"美商優比速航空","no":"0"},{"children":null,"cluster":0,"id":432,"count":2,"size":12.6,"amount":"1,260,000,000","text":"欣楓","no":"97202782"},{"children":null,"cluster":0,"id":433,"count":2,"size":10,"amount":"1,000,000,000","text":"長春貨櫃儲運","no":"00655979"},{"children":null,"cluster":0,"id":434,"count":1,"size":5,"amount":"500,000,000","no":"70750455","text":"高雄空廚"},{"children":null,"cluster":0,"id":435,"count":2,"size":55,"amount":"5,500,000,000","text":"立榮航空","no":"22958771"},{"children":null,"cluster":0,"id":436,"count":2,"size":6.3618673,"amount":"636,186,730","text":"立捷國際","no":"89480262"},{"children":null,"cluster":0,"id":437,"count":1,"size":4.6666667,"amount":"466,666,670","no":"16130319","text":"科學城物流"},{"children":null,"cluster":0,"id":438,"count":2,"size":26,"amount":"2,600,000,000","text":"新竹物流","no":"46480100"},{"children":null,"cluster":0,"id":439,"count":2,"size":1,"amount":"100,000,000","text":"晉榮營造","no":"72032375"},{"children":null,"cluster":0,"id":440,"count":1,"size":5.26,"amount":"526,000,000","no":"89396976","text":"華普飛機引擎科技"},{"children":null,"cluster":0,"id":441,"count":2,"size":0,"amount":null,"text":"美商聯合工業科技國際公司","no":"0"},{"children":null,"cluster":0,"id":442,"count":2,"size":0,"amount":null,"text":"新加坡商新航工程私人有限公司","no":"0"},{"children":null,"cluster":0,"id":443,"count":1,"size":2,"amount":"200,000,000","no":"70764991","text":"中華快遞"},{"children":null,"cluster":0,"id":444,"count":2,"size":0,"amount":null,"text":"財團法人中華航空事業發展基金會","no":"0"},{"children":null,"cluster":0,"id":445,"count":2,"size":340,"amount":"34,000,000,000","no":"23218873","text":"錸德科技"},{"children":null,"cluster":0,"id":446,"count":2,"size":15.14434,"amount":"1,514,434,000","text":"中富投資","no":"16081160"},{"children":null,"cluster":0,"id":447,"count":3,"size":23.4,"amount":"2,340,000,000","text":"中原國際創業投資","no":"16441144"},{"children":null,"cluster":0,"id":448,"count":1,"size":100,"amount":"10,000,000,000","no":"70766576","text":"錸寶科技"},{"children":null,"cluster":0,"id":449,"count":1,"size":1.2,"amount":"120,000,000","no":"23870802","text":"統清"},{"children":null,"cluster":0,"id":450,"count":2,"size":0,"amount":null,"text":"日商日清奧利友集團株式會社","no":"0"},{"children":null,"cluster":0,"id":451,"count":1,"size":1,"amount":"100,000,000","no":"80521360","text":"統一東京小客車租賃"},{"children":null,"cluster":0,"id":452,"count":2,"size":2,"amount":"200,000,000","text":"統一東京","no":"16097233"},{"children":null,"cluster":0,"id":453,"count":2,"size":0,"amount":null,"text":"日商東京 株式會社(CENTURY TOKYO LEASING CORPORATION(日商東京世紀租賃株式會社)","no":"0"},{"children":null,"cluster":0,"id":454,"count":1,"size":54.08,"amount":"5,408,000,000","no":"89398334","text":"萬通票券金融"},{"children":null,"cluster":0,"id":455,"count":2,"size":800,"amount":"80,000,000,000","no":"03077208","text":"中國信託商業銀行"},{"children":null,"cluster":0,"id":456,"count":1,"size":1.3232868,"amount":"132,328,680","no":"55743723","text":"環球混凝土工業"},{"children":null,"cluster":0,"id":457,"count":12,"size":60.3891908,"amount":"6,038,919,080","text":"環球水泥","no":"07568009"},{"children":null,"cluster":0,"id":458,"count":3,"size":1.2,"amount":"120,000,000","text":"環泥投資","no":"23531445"},{"children":null,"cluster":0,"id":459,"count":1,"size":0.65,"amount":"65,000,000","no":"66608560","text":"嘉義混凝土工業"},{"children":null,"cluster":0,"id":460,"count":1,"size":0.3,"amount":"30,000,000","no":"69438597","text":"台南混凝土工業"},{"children":null,"cluster":0,"id":461,"count":2,"size":0.4,"amount":"40,000,000","text":"築美建設開發","no":"69297169"},{"children":null,"cluster":0,"id":462,"count":1,"size":2.5,"amount":"250,000,000","no":"86003245","text":"環中國際"},{"children":null,"cluster":0,"id":463,"count":2,"size":0,"amount":null,"text":"香港商 MOREHEAD COMPANY TED","no":"0"},{"children":null,"cluster":0,"id":464,"count":1,"size":0.5,"amount":"50,000,000","no":"54156486","text":"利永環球科技"},{"children":null,"cluster":0,"id":465,"count":1,"size":0.756,"amount":"75,600,000","no":"79363309","text":"高雄碼頭通運"},{"children":null,"cluster":0,"id":466,"count":1,"size":18.7425,"amount":"1,874,250,000","no":"44528635","text":"六和機械"},{"children":null,"cluster":0,"id":467,"count":4,"size":1.99,"amount":"199,000,000","text":"讓德投資","no":"04418247"},{"children":null,"cluster":0,"id":468,"count":2,"size":0,"amount":null,"text":"財團法人宗倬章先生教育基金會","no":"0"},{"children":null,"cluster":0,"id":469,"count":2,"size":11.698,"amount":"1,169,800,000","text":"仁記投資","no":"16089156"},{"children":null,"cluster":0,"id":470,"count":2,"size":3.392,"amount":"339,200,000","text":"六和紡織廠","no":"11113500"},{"children":null,"cluster":0,"id":471,"count":2,"size":1.7,"amount":"170,000,000","text":"延陵投資","no":"23639403"},{"children":null,"cluster":0,"id":472,"count":1,"size":11.394027,"amount":"1,139,402,700","no":"16773305","text":"嘉環東泥"},{"children":null,"cluster":0,"id":473,"count":3,"size":77.963905,"amount":"7,796,390,500","text":"嘉新水泥","no":"11892801"},{"children":null,"cluster":0,"id":474,"count":2,"size":0,"amount":null,"text":"環球水泥","no":"0"},{"children":null,"cluster":0,"id":475,"count":3,"size":80,"amount":"8,000,000,000","text":"東南水泥","no":"83078600"},{"children":null,"cluster":0,"id":476,"count":2,"size":31.45,"amount":"3,145,000,000","text":"港泥投資","no":"70483970"},{"children":null,"cluster":0,"id":477,"count":3,"size":9.69,"amount":"969,000,000","text":"欣欣水泥企業","no":"36513594"},{"children":null,"cluster":0,"id":478,"count":2,"size":4.2,"amount":"420,000,000","text":"台灣通運倉儲","no":"03634507"},{"children":null,"cluster":0,"id":479,"count":1,"size":0.2,"amount":"20,000,000","no":"89390918","text":"華東水泥"},{"children":null,"cluster":0,"id":480,"count":1,"size":30.24,"amount":"3,024,000,000","no":"86691030","text":"環泥建設開發"},{"children":null,"cluster":0,"id":481,"count":3,"size":7.7996902,"amount":"779,969,020","text":"坤慶國際開發","no":"11438401"},{"children":null,"cluster":0,"id":482,"count":3,"size":2.1824,"amount":"218,240,000","text":"新和興投資","no":"12314771"},{"children":null,"cluster":0,"id":483,"count":2,"size":6.5,"amount":"650,000,000","text":"裕邦投資","no":"22656831"},{"children":null,"cluster":0,"id":484,"count":1,"size":1,"amount":"100,000,000","no":"16118618","text":"高雄港裝卸"},{"children":null,"cluster":0,"id":485,"count":2,"size":1.6333165,"amount":"163,331,650","text":"高港鐵路承攬運輸","no":"79364004"},{"children":null,"cluster":0,"id":486,"count":2,"size":45,"amount":"4,500,000,000","text":"中鋼運通","no":"96973086"},{"children":null,"cluster":0,"id":487,"count":2,"size":6.587,"amount":"658,700,000","text":"台機船舶廠","no":"97173533"},{"children":null,"cluster":0,"id":488,"count":2,"size":150,"amount":"15,000,000,000","text":"東森國際","no":"04964250"},{"children":null,"cluster":0,"id":489,"count":2,"size":2.3,"amount":"230,000,000","text":"升元投資","no":"84703314"},{"children":null,"cluster":0,"id":490,"count":2,"size":0.05,"amount":"5,000,000","text":"雅寶興投資","no":"28776329"},{"children":null,"cluster":0,"id":491,"count":2,"size":0.08,"amount":"8,000,000","text":"諾貝爾國際貿易","no":"70664819"},{"children":null,"cluster":0,"id":492,"count":2,"size":0.03,"amount":"3,000,000","text":"宇聲投資有限公司","no":"29117113"},{"children":null,"cluster":0,"id":493,"count":2,"size":0.2,"amount":"20,000,000","text":"喬宏投資","no":"28344842"},{"children":null,"cluster":0,"id":494,"count":1,"size":7.82,"amount":"782,000,000","no":"73004186","text":"三新紡織"},{"children":null,"cluster":0,"id":495,"count":5,"size":1.412,"amount":"141,200,000","text":"永原投資","no":"22661406"},{"children":null,"cluster":0,"id":496,"count":1,"size":38.0030395,"amount":"3,800,303,950","no":"12209807","text":"南帝化學工業"},{"children":null,"cluster":0,"id":497,"count":2,"size":0,"amount":null,"text":"台南紡織","no":"0"},{"children":null,"cluster":0,"id":498,"count":2,"size":12.4,"amount":"1,240,000,000","text":"大成工程","no":"68026203"},{"children":null,"cluster":0,"id":499,"count":2,"size":0.46,"amount":"46,000,000","text":"唯新工業","no":"23255882"},{"children":null,"cluster":0,"id":500,"count":2,"size":3.8900194,"amount":"389,001,940","text":"東豐企業","no":"68455105"},{"children":null,"cluster":0,"id":501,"count":1,"size":0.299008,"amount":"29,900,800","no":"86724519","text":"兄弟象"},{"children":null,"cluster":0,"id":502,"count":3,"size":1.5,"amount":"150,000,000","text":"兄弟大飯店","no":"04274804"},{"children":null,"cluster":0,"id":503,"count":1,"size":0.6,"amount":"60,000,000","no":"23609506","text":"中華職棒事業"},{"children":null,"cluster":0,"id":504,"count":2,"size":7.8,"amount":"780,000,000","no":"23533909","text":"和業投資"},{"children":null,"cluster":0,"id":505,"count":2,"size":20.588,"amount":"2,058,800,000","text":"仲冠投資","no":"05129188"},{"children":null,"cluster":0,"id":506,"count":2,"size":4.51,"amount":"451,000,000","text":"松宏投資","no":"29614920"},{"children":null,"cluster":0,"id":507,"count":2,"size":0.8,"amount":"80,000,000","no":"96945569","text":"中信鯨育樂"},{"children":null,"cluster":0,"id":508,"count":1,"size":5,"amount":"500,000,000","no":"12678527","text":"三商美福家具"},{"children":null,"cluster":0,"id":509,"count":17,"size":70,"amount":"7,000,000,000","text":"三商行","no":"11052709"},{"children":null,"cluster":0,"id":510,"count":1,"size":6.91,"amount":"691,000,000","no":"23472403","text":"三商休閒產業"},{"children":null,"cluster":0,"id":511,"count":1,"size":0.03,"amount":"3,000,000","no":"24310574","text":"三商美邦保險代理人"},{"children":null,"cluster":0,"id":512,"count":1,"size":4.5,"amount":"450,000,000","no":"28454657","text":"三商烘焙食品"},{"children":null,"cluster":0,"id":513,"count":1,"size":0.9,"amount":"90,000,000","no":"23826449","text":"商禾"},{"children":null,"cluster":0,"id":514,"count":1,"size":20.66,"amount":"2,066,000,000","no":"31107415","text":"三商福寶"},{"children":null,"cluster":0,"id":515,"count":1,"size":0.1,"amount":"10,000,000","no":"53125129","text":"三商家醫"},{"children":null,"cluster":0,"id":516,"count":1,"size":4.995,"amount":"499,500,000","no":"97301707","text":"拿帕里"},{"children":null,"cluster":0,"id":517,"count":1,"size":29,"amount":"2,900,000,000","no":"31275691","text":"三商電腦"},{"children":null,"cluster":0,"id":518,"count":1,"size":0.483,"amount":"48,300,000","no":"23129990","text":"三商多媒體"},{"children":null,"cluster":0,"id":519,"count":2,"size":0,"amount":null,"text":"日商NHK ENTERPRISE, INC.","no":"0"},{"children":null,"cluster":0,"id":520,"count":1,"size":1,"amount":"100,000,000","no":"53925190","text":"三友藥妝"},{"children":null,"cluster":0,"id":521,"count":2,"size":0,"amount":null,"text":"住友商事株式會社","no":"0"},{"children":null,"cluster":0,"id":522,"count":1,"size":6,"amount":"600,000,000","no":"22662545","text":"旭富製藥科技"},{"children":null,"cluster":0,"id":523,"count":2,"size":0,"amount":null,"text":"瑞士商旭福","no":"0"},{"children":null,"cluster":0,"id":524,"count":1,"size":2,"amount":"200,000,000","no":"29058233","text":"三商朝日"},{"children":null,"cluster":0,"id":525,"count":2,"size":0,"amount":null,"text":"日商朝日集團控股株式會社","no":"0"},{"children":null,"cluster":0,"id":526,"count":1,"size":2,"amount":"200,000,000","no":"15983177","text":"河昌"},{"children":null,"cluster":0,"id":527,"count":2,"size":0,"amount":null,"text":"財團法人台灣武智紀念基金會","no":"0"},{"children":null,"cluster":0,"id":528,"count":1,"size":10,"amount":"1,000,000,000","no":"89406812","text":"漢友創業投資"},{"children":null,"cluster":0,"id":529,"count":2,"size":650,"amount":"65,000,000,000","text":"華新麗華","no":"35412204"},{"children":null,"cluster":0,"id":530,"count":2,"size":0.6,"amount":"60,000,000","text":"漢友投資顧問","no":"89477365"},{"children":null,"cluster":0,"id":531,"count":2,"size":0.05,"amount":"5,000,000","text":"建宏投資有限公司","no":"70394533"},{"children":null,"cluster":0,"id":532,"count":2,"size":1.95,"amount":"195,000,000","text":"商林投資","no":"31314420"},{"children":null,"cluster":0,"id":533,"count":2,"size":2.379,"amount":"237,900,000","text":"樹人投資","no":"31318875"},{"children":null,"cluster":0,"id":534,"count":1,"size":0.449,"amount":"44,900,000","no":"80288981","text":"王德興茶業"},{"children":null,"cluster":0,"id":535,"count":16,"size":60,"amount":"6,000,000,000","text":"味全食品工業","no":"11347802"},{"children":null,"cluster":0,"id":536,"count":1,"size":1,"amount":"100,000,000","no":"12360599","text":"中國青年商店"},{"children":null,"cluster":0,"id":537,"count":1,"size":0.6466258,"amount":"64,662,580","no":"12441191","text":"康全工程"},{"children":null,"cluster":0,"id":538,"count":1,"size":1,"amount":"100,000,000","no":"86820040","text":"利嘉營造有限公司"},{"children":null,"cluster":0,"id":539,"count":1,"size":0.6439435,"amount":"64,394,350","no":"04369267","text":"康合國際貿易"},{"children":null,"cluster":0,"id":540,"count":1,"size":8.65,"amount":"865,000,000","no":"12107371","text":"欣全實業"},{"children":null,"cluster":0,"id":541,"count":1,"size":0.35,"amount":"35,000,000","no":"22328970","text":"康國行銷"},{"children":null,"cluster":0,"id":542,"count":2,"size":0,"amount":null,"text":"國分株式會社","no":"0"},{"children":null,"cluster":0,"id":543,"count":1,"size":6,"amount":"600,000,000","no":"22318255","text":"松青商業"},{"children":null,"cluster":0,"id":544,"count":2,"size":0,"amount":null,"text":"日商株式會社 FRESSAY HOLDINGS CO., LTD","no":"0"},{"children":null,"cluster":0,"id":545,"count":1,"size":70,"amount":"7,000,000,000","no":"53090297","text":"頂率開發"},{"children":null,"cluster":0,"id":546,"count":2,"size":5,"amount":"500,000,000","text":"能率開發","no":"25115351"},{"children":null,"cluster":0,"id":547,"count":2,"size":30,"amount":"3,000,000,000","text":"頂禾開發","no":"25127764"},{"children":null,"cluster":0,"id":548,"count":1,"size":2.5,"amount":"250,000,000","no":"53924869","text":"台北卡樂比食品"},{"children":null,"cluster":0,"id":549,"count":2,"size":0,"amount":null,"text":"日商卡樂比株式會社","no":"0"},{"children":null,"cluster":0,"id":550,"count":1,"size":2,"amount":"200,000,000","no":"54097826","text":"福頂食品"},{"children":null,"cluster":0,"id":551,"count":2,"size":0.25,"amount":"25,000,000","text":"菁山企業","no":"35378780"},{"children":null,"cluster":0,"id":552,"count":1,"size":0.235,"amount":"23,500,000","no":"22662833","text":"優味企業"},{"children":null,"cluster":0,"id":553,"count":2,"size":0,"amount":null,"text":"日商上島珈琲株式會社","no":"0"},{"children":null,"cluster":0,"id":554,"count":3,"size":1.421992,"amount":"142,199,200","text":"台東興業","no":"03522518"},{"children":null,"cluster":0,"id":555,"count":1,"size":0.235,"amount":"23,500,000","no":"01187025","text":"優仕咖啡"},{"children":null,"cluster":0,"id":556,"count":2,"size":0,"amount":null,"text":"日商上島咖啡株式會社","no":"0"},{"children":null,"cluster":0,"id":557,"count":1,"size":0.828,"amount":"82,800,000","no":"22954487","text":"康聯投資"},{"children":null,"cluster":0,"id":558,"count":2,"size":0.65,"amount":"65,000,000","text":"太洋投資","no":"27330089"},{"children":null,"cluster":0,"id":559,"count":2,"size":4.63,"amount":"463,000,000","text":"明怡投資","no":"86691003"},{"children":null,"cluster":0,"id":560,"count":2,"size":4.2,"amount":"420,000,000","text":"中宇投資","no":"80330019"},{"children":null,"cluster":0,"id":561,"count":2,"size":3.6653,"amount":"366,530,000","no":"16481567","text":"康清"},{"children":null,"cluster":0,"id":562,"count":2,"size":0,"amount":null,"text":"英屬維京群島商瑋博","no":"0"},{"children":null,"cluster":0,"id":563,"count":2,"size":5.148,"amount":"514,800,000","text":"康發投資有限公司","no":"16327116"},{"children":null,"cluster":0,"id":564,"count":2,"size":1.48,"amount":"148,000,000","text":"康勝投資有限公司","no":"16481341"},{"children":null,"cluster":0,"id":565,"count":2,"size":0.8,"amount":"80,000,000","no":"23641386","text":"聚慶投資"},{"children":null,"cluster":0,"id":566,"count":2,"size":0.6875,"amount":"68,750,000","text":"孟裕實業","no":"04206530"},{"children":null,"cluster":0,"id":567,"count":2,"size":0.96,"amount":"96,000,000","no":"12693490","text":"康權"},{"children":null,"cluster":0,"id":568,"count":2,"size":0,"amount":null,"text":"英屬蓋曼群島商頂益︹開曼島︺控股公司","no":"0"},{"children":null,"cluster":0,"id":569,"count":2,"size":1.1,"amount":"110,000,000","text":"康俊","no":"12695791"},{"children":null,"cluster":0,"id":570,"count":2,"size":2,"amount":"200,000,000","no":"25094975","text":"義大文創產業"},{"children":null,"cluster":0,"id":571,"count":2,"size":200,"amount":"20,000,000,000","text":"燁輝企業","no":"75947936"},{"children":null,"cluster":0,"id":572,"count":2,"size":40,"amount":"4,000,000,000","text":"偉喬投資開發","no":"22267158"},{"children":null,"cluster":0,"id":573,"count":2,"size":50.2,"amount":"5,020,000,000","text":"義大開發","no":"84448481"},{"children":null,"cluster":0,"id":574,"count":2,"size":220.04136,"amount":"22,004,136,000","text":"燁聯鋼鐵","no":"23218395"},{"children":null,"cluster":0,"id":575,"count":2,"size":0.3129653,"amount":"31,296,530","no":"84251901","text":"義大職棒事業"},{"children":null,"cluster":0,"id":576,"count":2,"size":1.195,"amount":"119,500,000","text":"超志投資","no":"89948400"}],[[0,1,8.8888],[2,0,8.8888],[2,3,8.8888],[4,5,8.8888],[4,6,8.8888],[4,7,8.8888],[4,8,8.8888],[4,9,8.8888],[4,10,8.8888],[4,11,8.8888],[2,4,8.8888],[12,13,8.8888],[14,15,8.8888],[14,16,8.8888],[13,14,8.8888],[13,15,8.8888],[13,16,8.8888],[13,3,8.8888],[13,17,8.8888],[3,18,8.8888],[19,18,8.8888],[20,21,8.8888],[22,21,8.8888],[23,21,8.8888],[24,21,8.8888],[25,21,8.8888],[26,21,8.8888],[27,28,8.8888],[27,29,8.8888],[30,31,8.8888],[30,32,8.8888],[30,29,8.8888],[29,21,8.8888],[33,21,8.8888],[34,21,8.8888],[34,35,8.8888],[34,36,8.8888],[37,21,8.8888],[37,38,8.8888],[37,18,8.8888],[37,36,8.8888],[39,21,8.8888],[39,18,8.8888],[39,36,8.8888],[40,21,8.8888],[40,41,8.8888],[40,36,8.8888],[42,21,8.8888],[42,43,8.8888],[42,18,8.8888],[42,44,8.8888],[42,36,8.8888],[45,18,8.8888],[45,21,8.8888],[45,36,8.8888],[46,47,8.8888],[46,36,8.8888],[46,48,8.8888],[46,21,8.8888],[36,21,8.8888],[49,21,8.8888],[50,21,8.8888],[51,21,8.8888],[52,53,8.8888],[51,52,8.8888],[54,21,8.8888],[54,55,8.8888],[56,21,8.8888],[56,10,8.8888],[56,57,8.8888],[58,21,8.8888],[58,59,8.8888],[60,61,8.8888],[60,21,8.8888],[62,21,8.8888],[63,21,8.8888],[63,64,8.8888],[62,64,8.8888],[65,21,8.8888],[65,66,8.8888],[67,68,8.8888],[69,70,8.8888],[71,72,8.8888],[71,68,8.8888],[71,73,8.8888],[71,74,8.8888],[75,18,8.8888],[75,76,8.8888],[75,77,8.8888],[75,68,8.8888],[78,79,8.8888],[78,68,8.8888],[80,81,8.8888],[80,82,8.8888],[80,83,8.8888],[80,68,8.8888],[80,84,8.8888],[65,68,8.8888],[85,21,8.8888],[86,87,8.8888],[86,88,8.8888],[85,89,8.8888],[90,21,8.8888],[91,92,8.8888],[91,93,8.8888],[91,94,8.8888],[91,95,8.8888],[91,96,8.8888],[91,97,8.8888],[90,91,8.8888],[90,18,8.8888],[98,18,8.8888],[98,21,8.8888],[99,18,8.8888],[99,100,8.8888],[98,99,8.8888],[101,102,8.8888],[103,101,8.8888],[103,21,8.8888],[104,105,8.8888],[104,106,8.8888],[104,107,8.8888],[108,104,8.8888],[108,21,8.8888],[109,110,8.8888],[108,109,8.8888],[111,112,8.8888],[113,112,8.8888],[114,115,8.8888],[114,112,8.8888],[114,116,8.8888],[117,118,8.8888],[117,112,8.8888],[112,119,8.8888],[112,18,8.8888],[112,21,8.8888],[120,121,8.8888],[121,18,8.8888],[121,21,8.8888],[121,122,8.8888],[123,124,8.8888],[124,18,8.8888],[124,21,8.8888],[125,18,8.8888],[124,125,8.8888],[126,18,8.8888],[126,21,8.8888],[126,127,8.8888],[128,129,8.8888],[128,130,8.8888],[128,131,8.8888],[130,132,8.8888],[133,134,8.8888],[130,133,8.8888],[130,135,8.8888],[130,18,8.8888],[130,21,8.8888],[130,136,8.8888],[137,138,8.8888],[137,139,8.8888],[137,140,8.8888],[130,137,8.8888],[130,141,8.8888],[142,143,8.8888],[130,142,8.8888],[144,145,8.8888],[130,144,8.8888],[21,18,8.8888],[21,146,8.8888],[147,18,8.8888],[148,18,8.8888],[149,150,8.8888],[150,18,8.8888],[151,18,8.8888],[152,153,8.8888],[154,155,8.8888],[154,153,8.8888],[156,157,8.8888],[156,153,8.8888],[158,159,8.8888],[156,158,8.8888],[160,161,8.8888],[162,160,8.8888],[163,164,8.8888],[163,165,8.8888],[163,166,8.8888],[163,167,8.8888],[162,163,8.8888],[162,153,8.8888],[168,166,8.8888],[168,169,8.8888],[162,168,8.8888],[153,18,8.8888],[170,18,8.8888],[171,172,8.8888],[172,18,8.8888],[173,174,8.8888],[174,18,8.8888],[175,18,8.8888],[176,18,8.8888],[176,146,8.8888],[177,178,8.8888],[178,18,8.8888],[179,180,8.8888],[181,182,8.8888],[180,181,8.8888],[178,180,8.8888],[183,18,8.8888],[183,184,8.8888],[185,18,8.8888],[185,122,8.8888],[186,187,8.8888],[186,18,8.8888],[188,18,8.8888],[189,190,8.8888],[189,191,8.8888],[189,192,8.8888],[189,193,8.8888],[188,189,8.8888],[188,100,8.8888],[194,18,8.8888],[194,1,8.8888],[194,146,8.8888],[195,196,8.8888],[197,198,8.8888],[198,196,8.8888],[199,200,8.8888],[201,200,8.8888],[202,200,8.8888],[203,200,8.8888],[203,204,8.8888],[205,200,8.8888],[205,206,8.8888],[205,207,8.8888],[200,196,8.8888],[208,196,8.8888],[209,47,8.8888],[208,209,8.8888],[208,210,8.8888],[208,211,8.8888],[208,212,8.8888],[213,196,8.8888],[214,215,8.8888],[213,214,8.8888],[216,217,8.8888],[218,216,8.8888],[219,220,8.8888],[218,219,8.8888],[218,196,8.8888],[218,221,8.8888],[222,223,8.8888],[222,224,8.8888],[223,196,8.8888],[225,226,8.8888],[223,225,8.8888],[227,228,8.8888],[227,116,8.8888],[227,229,8.8888],[223,227,8.8888],[230,231,8.8888],[230,232,8.8888],[230,233,8.8888],[230,234,8.8888],[223,230,8.8888],[235,236,8.8888],[235,237,8.8888],[235,238,8.8888],[235,239,8.8888],[239,237,8.8888],[240,241,8.8888],[240,242,8.8888],[239,240,8.8888],[239,243,8.8888],[244,245,8.8888],[244,246,8.8888],[244,247,8.8888],[244,248,8.8888],[244,249,8.8888],[239,244,8.8888],[250,237,8.8888],[250,251,8.8888],[250,252,8.8888],[250,253,8.8888],[239,250,8.8888],[239,196,8.8888],[239,254,8.8888],[255,256,8.8888],[255,257,8.8888],[255,258,8.8888],[255,259,8.8888],[255,260,8.8888],[255,261,8.8888],[255,262,8.8888],[263,255,8.8888],[263,196,8.8888],[264,265,8.8888],[264,266,8.8888],[264,196,8.8888],[267,268,8.8888],[268,200,8.8888],[268,196,8.8888],[269,270,8.8888],[271,269,8.8888],[272,270,8.8888],[271,272,8.8888],[271,196,8.8888],[273,274,8.8888],[271,273,8.8888],[275,276,8.8888],[277,278,8.8888],[277,276,8.8888],[276,279,8.8888],[276,196,8.8888],[280,281,8.8888],[280,282,8.8888],[280,283,8.8888],[280,284,8.8888],[280,285,8.8888],[276,280,8.8888],[286,287,8.8888],[286,288,8.8888],[286,289,8.8888],[290,286,8.8888],[291,292,8.8888],[290,291,8.8888],[290,196,8.8888],[293,294,8.8888],[290,293,8.8888],[295,296,8.8888],[295,297,8.8888],[295,298,8.8888],[295,299,8.8888],[300,301,8.8888],[300,302,8.8888],[300,224,8.8888],[300,296,8.8888],[303,296,8.8888],[303,304,8.8888],[305,306,8.8888],[305,307,8.8888],[305,308,8.8888],[305,309,8.8888],[305,310,8.8888],[303,305,8.8888],[303,196,8.8888],[303,237,8.8888],[311,312,8.8888],[312,313,8.8888],[312,314,8.8888],[312,315,8.8888],[312,196,8.8888],[316,317,8.8888],[316,318,8.8888],[316,319,8.8888],[320,316,8.8888],[320,321,8.8888],[320,196,8.8888],[322,323,8.8888],[324,323,8.8888],[325,323,8.8888],[326,323,8.8888],[327,323,8.8888],[327,328,8.8888],[329,323,8.8888],[329,330,8.8888],[331,332,8.8888],[331,333,8.8888],[331,334,8.8888],[331,335,8.8888],[331,323,8.8888],[331,336,8.8888],[337,333,8.8888],[337,332,8.8888],[337,334,8.8888],[337,335,8.8888],[337,323,8.8888],[337,336,8.8888],[338,339,8.8888],[323,338,8.8888],[323,340,8.8888],[323,341,8.8888],[323,196,8.8888],[323,339,8.8888],[342,343,8.8888],[344,343,8.8888],[345,346,8.8888],[345,343,8.8888],[345,347,8.8888],[345,348,8.8888],[349,350,8.8888],[349,351,8.8888],[349,352,8.8888],[349,353,8.8888],[349,354,8.8888],[349,355,8.8888],[349,343,8.8888],[349,356,8.8888],[349,357,8.8888],[349,358,8.8888],[359,360,8.8888],[359,361,8.8888],[359,362,8.8888],[359,363,8.8888],[359,364,8.8888],[359,365,8.8888],[359,366,8.8888],[359,367,8.8888],[343,359,8.8888],[368,369,8.8888],[370,369,8.8888],[371,369,8.8888],[372,369,8.8888],[372,373,8.8888],[372,374,8.8888],[372,375,8.8888],[376,369,8.8888],[376,377,8.8888],[376,378,8.8888],[376,379,8.8888],[376,380,8.8888],[381,116,8.8888],[381,369,8.8888],[381,382,8.8888],[343,369,8.8888],[343,196,8.8888],[343,383,8.8888],[343,384,8.8888],[385,237,8.8888],[385,386,8.8888],[385,247,8.8888],[385,122,8.8888],[385,196,8.8888],[385,387,8.8888],[388,389,8.8888],[388,390,8.8888],[385,388,8.8888],[391,392,8.8888],[391,393,8.8888],[391,394,8.8888],[391,395,8.8888],[391,396,8.8888],[391,397,8.8888],[397,394,8.8888],[397,392,8.8888],[397,393,8.8888],[397,398,8.8888],[397,196,8.8888],[397,399,8.8888],[400,401,8.8888],[397,400,8.8888],[402,403,8.8888],[402,392,8.8888],[402,404,8.8888],[397,402,8.8888],[397,405,8.8888],[406,407,8.8888],[397,406,8.8888],[408,409,8.8888],[410,409,8.8888],[411,409,8.8888],[412,409,8.8888],[413,409,8.8888],[414,409,8.8888],[415,409,8.8888],[415,416,8.8888],[417,418,8.8888],[417,409,8.8888],[417,419,8.8888],[420,409,8.8888],[420,421,8.8888],[420,422,8.8888],[420,423,8.8888],[424,409,8.8888],[424,425,8.8888],[426,427,8.8888],[426,409,8.8888],[426,428,8.8888],[429,409,8.8888],[429,430,8.8888],[429,431,8.8888],[429,432,8.8888],[429,420,8.8888],[429,433,8.8888],[434,409,8.8888],[434,159,8.8888],[434,435,8.8888],[434,116,8.8888],[434,436,8.8888],[437,438,8.8888],[437,224,8.8888],[437,409,8.8888],[437,439,8.8888],[440,441,8.8888],[440,442,8.8888],[440,409,8.8888],[443,242,8.8888],[443,409,8.8888],[409,444,8.8888],[409,196,8.8888],[409,47,8.8888],[445,446,8.8888],[445,447,8.8888],[448,445,8.8888],[448,196,8.8888],[448,447,8.8888],[194,196,8.8888],[194,122,8.8888],[194,224,8.8888],[449,450,8.8888],[449,18,8.8888],[449,100,8.8888],[451,452,8.8888],[452,453,8.8888],[452,18,8.8888],[452,100,8.8888],[454,18,8.8888],[455,274,8.8888],[454,455,8.8888],[454,1,8.8888],[456,457,8.8888],[456,458,8.8888],[459,457,8.8888],[460,457,8.8888],[460,461,8.8888],[462,457,8.8888],[462,463,8.8888],[464,457,8.8888],[465,457,8.8888],[466,467,8.8888],[466,457,8.8888],[466,468,8.8888],[466,469,8.8888],[466,470,8.8888],[466,458,8.8888],[466,471,8.8888],[472,473,8.8888],[472,474,8.8888],[472,475,8.8888],[472,476,8.8888],[472,477,8.8888],[472,478,8.8888],[479,473,8.8888],[479,457,8.8888],[479,475,8.8888],[479,477,8.8888],[480,467,8.8888],[480,481,8.8888],[480,457,8.8888],[480,482,8.8888],[480,11,8.8888],[480,483,8.8888],[484,485,8.8888],[484,486,8.8888],[484,487,8.8888],[484,457,8.8888],[484,488,8.8888],[457,489,8.8888],[457,490,8.8888],[457,491,8.8888],[457,492,8.8888],[457,493,8.8888],[454,457,8.8888],[454,481,8.8888],[454,146,8.8888],[494,495,8.8888],[496,497,8.8888],[496,9,8.8888],[496,1,8.8888],[496,7,8.8888],[496,498,8.8888],[496,495,8.8888],[496,499,8.8888],[496,482,8.8888],[496,500,8.8888],[496,467,8.8888],[454,495,8.8888],[454,7,8.8888],[501,502,8.8888],[503,502,8.8888],[504,505,8.8888],[504,506,8.8888],[507,504,8.8888],[503,507,8.8888],[508,509,8.8888],[510,509,8.8888],[511,509,8.8888],[512,509,8.8888],[513,509,8.8888],[514,509,8.8888],[515,509,8.8888],[516,509,8.8888],[517,509,8.8888],[518,509,8.8888],[518,519,8.8888],[520,509,8.8888],[520,521,8.8888],[522,509,8.8888],[522,523,8.8888],[524,509,8.8888],[524,525,8.8888],[526,509,8.8888],[526,527,8.8888],[528,529,8.8888],[528,509,8.8888],[528,530,8.8888],[528,531,8.8888],[509,532,8.8888],[509,533,8.8888],[503,509,8.8888],[534,535,8.8888],[536,535,8.8888],[537,535,8.8888],[538,535,8.8888],[539,535,8.8888],[540,535,8.8888],[541,535,8.8888],[541,542,8.8888],[543,535,8.8888],[543,544,8.8888],[545,535,8.8888],[545,546,8.8888],[545,547,8.8888],[548,549,8.8888],[548,535,8.8888],[550,535,8.8888],[550,551,8.8888],[552,553,8.8888],[552,535,8.8888],[552,554,8.8888],[555,556,8.8888],[555,535,8.8888],[555,554,8.8888],[557,558,8.8888],[557,535,8.8888],[557,559,8.8888],[557,560,8.8888],[561,562,8.8888],[535,561,8.8888],[535,563,8.8888],[535,564,8.8888],[565,566,8.8888],[535,565,8.8888],[567,568,8.8888],[535,567,8.8888],[535,569,8.8888],[503,535,8.8888],[503,18,8.8888],[570,571,8.8888],[570,572,8.8888],[570,573,8.8888],[570,574,8.8888],[575,570,8.8888],[503,575,8.8888],[18,146,8.8888],[18,7,8.8888],[18,10,8.8888],[18,495,8.8888],[18,576,8.8888]]] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<title>Insights graph demo</title> | |
<link rel="stylesheet" href="build.css" /> | |
</head> | |
<body> | |
<div id="parent"></div> | |
<script src="build.js"></script> | |
<script> | |
!function() { | |
var d3 = require("ignacioola-d3/d3"), | |
InsightsGraph = require("insights"); | |
d3.json("data.json", function(data) { | |
var nodes = data[0], | |
links = data[1], | |
el = document.getElementById("parent"); | |
graph = new InsightsGraph(el, nodes, links, { | |
width: screen.width, | |
height: screen.height | |
}); | |
graph.tooltip("<div>word: {{text}}({{no}})</div><div>count: {{count}}</div> <div>資本額: {{amount}}</div>"); | |
}); | |
}(); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<title>Insights graph demo</title> | |
<link rel="stylesheet" href="build.css" /> | |
</head> | |
<body> | |
<div id="parent"></div> | |
<script src="build.js"></script> | |
<script> | |
!function() { | |
var d3 = require("ignacioola-d3/d3"), | |
InsightsGraph = require("insights"); | |
d3.json("data.json", function(data) { | |
var nodes = data[0], | |
links = data[1], | |
el = document.getElementById("parent"); | |
graph = new InsightsGraph(el, nodes, links, { | |
width: screen.width, | |
height: screen.height | |
}); | |
graph.tooltip("<div>word: {{text}}({{no}})</div><div>count: {{count}}</div> <div>資本額: {{amount}}</div>"); | |
}); | |
}(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment