|
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ |
|
/* |
|
|
|
This file needs to be compiled with Browserify to `bundle.js` in order that the visualisation can be displayed in the browser. |
|
|
|
*/ |
|
var d3 = require("d3") |
|
d3.sankey = require("d3-sankey").sankey |
|
d3.sankeyLinkHorizontal = require("d3-sankey").sankeyLinkHorizontal |
|
|
|
var margin = {top: 10, right: 10, bottom: 10, left: 10} |
|
var width = 960 - margin.left - margin.right |
|
var height = 1000 - margin.top - margin.bottom |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", `translate(${margin.left}, ${margin.top})`) |
|
|
|
var format = (d) => `${d} seats` |
|
var color = d3.scaleOrdinal(d3.schemeCategory10) |
|
|
|
sankey = d3.sankey() |
|
.nodeWidth(15) |
|
.nodePadding(10) |
|
.size([width, height]) |
|
|
|
d3.csv("raw.csv", function (error, data) { |
|
if (error) throw error |
|
|
|
var blocs = data.reduce((p, c) => { |
|
p[`${c["2015"]} (2015)`] = p[`${c["2015"]} (2015)`] + 1 || 1 |
|
p[`${c["2017"]} (2017)`] = p[`${c["2017"]} (2017)`] + 1 || 1 |
|
return p |
|
}, {}) |
|
|
|
var pairs = data.reduce((p, c) => { |
|
p[`${c["2015"]} (2015)|${c["2017"]} (2017)`] = p[`${c["2015"]} (2015)|${c["2017"]} (2017)`] + 1 || 1 |
|
return p |
|
}, {}) |
|
|
|
var diffs = Object.keys(pairs) |
|
.map(p => ({ |
|
source: p.replace(/\|.*/, ""), |
|
target: p.replace(/.*\|/, ""), |
|
value: pairs[p] |
|
})) |
|
|
|
var nodes = Object.keys(blocs) |
|
.map(k => ({ |
|
"name": k, |
|
"value": blocs[k] |
|
})) |
|
.sort((a, b) => b.value - a.value) |
|
|
|
graph = { |
|
"nodes" : nodes, |
|
"links" : diffs.map(d => ({ |
|
source: nodes.map(x => x.name).indexOf(d.source), |
|
target: nodes.map(x => x.name).indexOf(d.target), |
|
value: d.value |
|
})) |
|
} |
|
|
|
function dragmove(d) { |
|
d3.select(this) |
|
.attr("transform", `translate(${d.x0}, ${d.y0 = Math.max( |
|
0, Math.min(height - (d.y1 - d.y0), d.y0 + d3.event.dy))})`) |
|
sankey.update(graph) |
|
link.attr("d", path) |
|
} |
|
|
|
sankey(graph) |
|
var path = d3.sankeyLinkHorizontal() |
|
|
|
var link = svg.append("g").selectAll(".link") |
|
.data(graph.links) |
|
.enter().append("path") |
|
.attr("class", "link") |
|
.attr("fill", "none") |
|
.attr("stroke", "#000") |
|
.attr("stroke-opacity", 0.2) |
|
.attr("d", path) |
|
.attr("stroke-width", d => Math.max(1, d.width)) |
|
|
|
link.append("title") |
|
.text(d => `${d.source.name}, → ${d.target.name}\n${format(d.value)}`) |
|
|
|
var node = svg.append("g").selectAll(".node") |
|
.data(graph.nodes) |
|
.enter().append("g") |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", 10) |
|
.attr("class", "node") |
|
.attr("transform", d => `translate(${d.x0}, ${d.y0})`) |
|
.call(d3.drag() |
|
.subject(d => d) |
|
.on("drag", dragmove) |
|
) |
|
|
|
node.append("rect") |
|
.attr("height", d => d.y1 - d.y0) |
|
.attr("width", d => d.x1 - d.x0) |
|
.attr("fill", function(d) { |
|
return color(d.name.replace(/ .*/, "")) |
|
}) |
|
.attr("stroke", "#000") |
|
.append("title") |
|
.text(d => `${d.name}\n${format(d.value)}`) |
|
|
|
node.append("text") |
|
.attr("x", -6) |
|
.attr("y", d => (d.y1 - d.y0) / 2) |
|
.attr("dy", "0.35em") |
|
.attr("text-anchor", "end") |
|
.text(d => d.name) |
|
.filter(d => d.x0 < width / 2) |
|
.attr("x", d => 6 + sankey.nodeWidth()) |
|
.attr("text-anchor", "start") |
|
|
|
}) |
|
|
|
},{"d3":7,"d3-sankey":5}],2:[function(require,module,exports){ |
|
// https://d3js.org/d3-array/ Version 1.2.0. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
|
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
|
(factory((global.d3 = global.d3 || {}))); |
|
}(this, (function (exports) { 'use strict'; |
|
|
|
var ascending = function(a, b) { |
|
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; |
|
}; |
|
|
|
var bisector = function(compare) { |
|
if (compare.length === 1) compare = ascendingComparator(compare); |
|
return { |
|
left: function(a, x, lo, hi) { |
|
if (lo == null) lo = 0; |
|
if (hi == null) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (compare(a[mid], x) < 0) lo = mid + 1; |
|
else hi = mid; |
|
} |
|
return lo; |
|
}, |
|
right: function(a, x, lo, hi) { |
|
if (lo == null) lo = 0; |
|
if (hi == null) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (compare(a[mid], x) > 0) hi = mid; |
|
else lo = mid + 1; |
|
} |
|
return lo; |
|
} |
|
}; |
|
}; |
|
|
|
function ascendingComparator(f) { |
|
return function(d, x) { |
|
return ascending(f(d), x); |
|
}; |
|
} |
|
|
|
var ascendingBisect = bisector(ascending); |
|
var bisectRight = ascendingBisect.right; |
|
var bisectLeft = ascendingBisect.left; |
|
|
|
var pairs = function(array, f) { |
|
if (f == null) f = pair; |
|
var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); |
|
while (i < n) pairs[i] = f(p, p = array[++i]); |
|
return pairs; |
|
}; |
|
|
|
function pair(a, b) { |
|
return [a, b]; |
|
} |
|
|
|
var cross = function(values0, values1, reduce) { |
|
var n0 = values0.length, |
|
n1 = values1.length, |
|
values = new Array(n0 * n1), |
|
i0, |
|
i1, |
|
i, |
|
value0; |
|
|
|
if (reduce == null) reduce = pair; |
|
|
|
for (i0 = i = 0; i0 < n0; ++i0) { |
|
for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { |
|
values[i] = reduce(value0, values1[i1]); |
|
} |
|
} |
|
|
|
return values; |
|
}; |
|
|
|
var descending = function(a, b) { |
|
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; |
|
}; |
|
|
|
var number = function(x) { |
|
return x === null ? NaN : +x; |
|
}; |
|
|
|
var variance = function(values, valueof) { |
|
var n = values.length, |
|
m = 0, |
|
i = -1, |
|
mean = 0, |
|
value, |
|
delta, |
|
sum = 0; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { |
|
if (!isNaN(value = number(values[i]))) { |
|
delta = value - mean; |
|
mean += delta / ++m; |
|
sum += delta * (value - mean); |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { |
|
if (!isNaN(value = number(valueof(values[i], i, values)))) { |
|
delta = value - mean; |
|
mean += delta / ++m; |
|
sum += delta * (value - mean); |
|
} |
|
} |
|
} |
|
|
|
if (m > 1) return sum / (m - 1); |
|
}; |
|
|
|
var deviation = function(array, f) { |
|
var v = variance(array, f); |
|
return v ? Math.sqrt(v) : v; |
|
}; |
|
|
|
var extent = function(values, valueof) { |
|
var n = values.length, |
|
i = -1, |
|
value, |
|
min, |
|
max; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = values[i]) != null && value >= value) { |
|
min = max = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = values[i]) != null) { |
|
if (min > value) min = value; |
|
if (max < value) max = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = valueof(values[i], i, values)) != null && value >= value) { |
|
min = max = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = valueof(values[i], i, values)) != null) { |
|
if (min > value) min = value; |
|
if (max < value) max = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
return [min, max]; |
|
}; |
|
|
|
var array = Array.prototype; |
|
|
|
var slice = array.slice; |
|
var map = array.map; |
|
|
|
var constant = function(x) { |
|
return function() { |
|
return x; |
|
}; |
|
}; |
|
|
|
var identity = function(x) { |
|
return x; |
|
}; |
|
|
|
var range = function(start, stop, step) { |
|
start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; |
|
|
|
var i = -1, |
|
n = Math.max(0, Math.ceil((stop - start) / step)) | 0, |
|
range = new Array(n); |
|
|
|
while (++i < n) { |
|
range[i] = start + i * step; |
|
} |
|
|
|
return range; |
|
}; |
|
|
|
var e10 = Math.sqrt(50); |
|
var e5 = Math.sqrt(10); |
|
var e2 = Math.sqrt(2); |
|
|
|
var ticks = function(start, stop, count) { |
|
var reverse = stop < start, |
|
i = -1, |
|
n, |
|
ticks, |
|
step; |
|
|
|
if (reverse) n = start, start = stop, stop = n; |
|
|
|
if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; |
|
|
|
if (step > 0) { |
|
start = Math.ceil(start / step); |
|
stop = Math.floor(stop / step); |
|
ticks = new Array(n = Math.ceil(stop - start + 1)); |
|
while (++i < n) ticks[i] = (start + i) * step; |
|
} else { |
|
start = Math.floor(start * step); |
|
stop = Math.ceil(stop * step); |
|
ticks = new Array(n = Math.ceil(start - stop + 1)); |
|
while (++i < n) ticks[i] = (start - i) / step; |
|
} |
|
|
|
if (reverse) ticks.reverse(); |
|
|
|
return ticks; |
|
}; |
|
|
|
function tickIncrement(start, stop, count) { |
|
var step = (stop - start) / Math.max(0, count), |
|
power = Math.floor(Math.log(step) / Math.LN10), |
|
error = step / Math.pow(10, power); |
|
return power >= 0 |
|
? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) |
|
: -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); |
|
} |
|
|
|
function tickStep(start, stop, count) { |
|
var step0 = Math.abs(stop - start) / Math.max(0, count), |
|
step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), |
|
error = step0 / step1; |
|
if (error >= e10) step1 *= 10; |
|
else if (error >= e5) step1 *= 5; |
|
else if (error >= e2) step1 *= 2; |
|
return stop < start ? -step1 : step1; |
|
} |
|
|
|
var sturges = function(values) { |
|
return Math.ceil(Math.log(values.length) / Math.LN2) + 1; |
|
}; |
|
|
|
var histogram = function() { |
|
var value = identity, |
|
domain = extent, |
|
threshold = sturges; |
|
|
|
function histogram(data) { |
|
var i, |
|
n = data.length, |
|
x, |
|
values = new Array(n); |
|
|
|
for (i = 0; i < n; ++i) { |
|
values[i] = value(data[i], i, data); |
|
} |
|
|
|
var xz = domain(values), |
|
x0 = xz[0], |
|
x1 = xz[1], |
|
tz = threshold(values, x0, x1); |
|
|
|
// Convert number of thresholds into uniform thresholds. |
|
if (!Array.isArray(tz)) { |
|
tz = tickStep(x0, x1, tz); |
|
tz = range(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive |
|
} |
|
|
|
// Remove any thresholds outside the domain. |
|
var m = tz.length; |
|
while (tz[0] <= x0) tz.shift(), --m; |
|
while (tz[m - 1] > x1) tz.pop(), --m; |
|
|
|
var bins = new Array(m + 1), |
|
bin; |
|
|
|
// Initialize bins. |
|
for (i = 0; i <= m; ++i) { |
|
bin = bins[i] = []; |
|
bin.x0 = i > 0 ? tz[i - 1] : x0; |
|
bin.x1 = i < m ? tz[i] : x1; |
|
} |
|
|
|
// Assign data to bins by value, ignoring any outside the domain. |
|
for (i = 0; i < n; ++i) { |
|
x = values[i]; |
|
if (x0 <= x && x <= x1) { |
|
bins[bisectRight(tz, x, 0, m)].push(data[i]); |
|
} |
|
} |
|
|
|
return bins; |
|
} |
|
|
|
histogram.value = function(_) { |
|
return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; |
|
}; |
|
|
|
histogram.domain = function(_) { |
|
return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; |
|
}; |
|
|
|
histogram.thresholds = function(_) { |
|
return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; |
|
}; |
|
|
|
return histogram; |
|
}; |
|
|
|
var quantile = function(values, p, valueof) { |
|
if (valueof == null) valueof = number; |
|
if (!(n = values.length)) return; |
|
if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); |
|
if (p >= 1) return +valueof(values[n - 1], n - 1, values); |
|
var n, |
|
i = (n - 1) * p, |
|
i0 = Math.floor(i), |
|
value0 = +valueof(values[i0], i0, values), |
|
value1 = +valueof(values[i0 + 1], i0 + 1, values); |
|
return value0 + (value1 - value0) * (i - i0); |
|
}; |
|
|
|
var freedmanDiaconis = function(values, min, max) { |
|
values = map.call(values, number).sort(ascending); |
|
return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); |
|
}; |
|
|
|
var scott = function(values, min, max) { |
|
return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); |
|
}; |
|
|
|
var max = function(values, valueof) { |
|
var n = values.length, |
|
i = -1, |
|
value, |
|
max; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = values[i]) != null && value >= value) { |
|
max = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = values[i]) != null && value > max) { |
|
max = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = valueof(values[i], i, values)) != null && value >= value) { |
|
max = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = valueof(values[i], i, values)) != null && value > max) { |
|
max = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
return max; |
|
}; |
|
|
|
var mean = function(values, valueof) { |
|
var n = values.length, |
|
m = n, |
|
i = -1, |
|
value, |
|
sum = 0; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { |
|
if (!isNaN(value = number(values[i]))) sum += value; |
|
else --m; |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { |
|
if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; |
|
else --m; |
|
} |
|
} |
|
|
|
if (m) return sum / m; |
|
}; |
|
|
|
var median = function(values, valueof) { |
|
var n = values.length, |
|
i = -1, |
|
value, |
|
numbers = []; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { |
|
if (!isNaN(value = number(values[i]))) { |
|
numbers.push(value); |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { |
|
if (!isNaN(value = number(valueof(values[i], i, values)))) { |
|
numbers.push(value); |
|
} |
|
} |
|
} |
|
|
|
return quantile(numbers.sort(ascending), 0.5); |
|
}; |
|
|
|
var merge = function(arrays) { |
|
var n = arrays.length, |
|
m, |
|
i = -1, |
|
j = 0, |
|
merged, |
|
array; |
|
|
|
while (++i < n) j += arrays[i].length; |
|
merged = new Array(j); |
|
|
|
while (--n >= 0) { |
|
array = arrays[n]; |
|
m = array.length; |
|
while (--m >= 0) { |
|
merged[--j] = array[m]; |
|
} |
|
} |
|
|
|
return merged; |
|
}; |
|
|
|
var min = function(values, valueof) { |
|
var n = values.length, |
|
i = -1, |
|
value, |
|
min; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = values[i]) != null && value >= value) { |
|
min = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = values[i]) != null && min > value) { |
|
min = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { // Find the first comparable value. |
|
if ((value = valueof(values[i], i, values)) != null && value >= value) { |
|
min = value; |
|
while (++i < n) { // Compare the remaining values. |
|
if ((value = valueof(values[i], i, values)) != null && min > value) { |
|
min = value; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
return min; |
|
}; |
|
|
|
var permute = function(array, indexes) { |
|
var i = indexes.length, permutes = new Array(i); |
|
while (i--) permutes[i] = array[indexes[i]]; |
|
return permutes; |
|
}; |
|
|
|
var scan = function(values, compare) { |
|
if (!(n = values.length)) return; |
|
var n, |
|
i = 0, |
|
j = 0, |
|
xi, |
|
xj = values[j]; |
|
|
|
if (compare == null) compare = ascending; |
|
|
|
while (++i < n) { |
|
if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { |
|
xj = xi, j = i; |
|
} |
|
} |
|
|
|
if (compare(xj, xj) === 0) return j; |
|
}; |
|
|
|
var shuffle = function(array, i0, i1) { |
|
var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), |
|
t, |
|
i; |
|
|
|
while (m) { |
|
i = Math.random() * m-- | 0; |
|
t = array[m + i0]; |
|
array[m + i0] = array[i + i0]; |
|
array[i + i0] = t; |
|
} |
|
|
|
return array; |
|
}; |
|
|
|
var sum = function(values, valueof) { |
|
var n = values.length, |
|
i = -1, |
|
value, |
|
sum = 0; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { |
|
if (value = +values[i]) sum += value; // Note: zero and null are equivalent. |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { |
|
if (value = +valueof(values[i], i, values)) sum += value; |
|
} |
|
} |
|
|
|
return sum; |
|
}; |
|
|
|
var transpose = function(matrix) { |
|
if (!(n = matrix.length)) return []; |
|
for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { |
|
for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { |
|
row[j] = matrix[j][i]; |
|
} |
|
} |
|
return transpose; |
|
}; |
|
|
|
function length(d) { |
|
return d.length; |
|
} |
|
|
|
var zip = function() { |
|
return transpose(arguments); |
|
}; |
|
|
|
exports.bisect = bisectRight; |
|
exports.bisectRight = bisectRight; |
|
exports.bisectLeft = bisectLeft; |
|
exports.ascending = ascending; |
|
exports.bisector = bisector; |
|
exports.cross = cross; |
|
exports.descending = descending; |
|
exports.deviation = deviation; |
|
exports.extent = extent; |
|
exports.histogram = histogram; |
|
exports.thresholdFreedmanDiaconis = freedmanDiaconis; |
|
exports.thresholdScott = scott; |
|
exports.thresholdSturges = sturges; |
|
exports.max = max; |
|
exports.mean = mean; |
|
exports.median = median; |
|
exports.merge = merge; |
|
exports.min = min; |
|
exports.pairs = pairs; |
|
exports.permute = permute; |
|
exports.quantile = quantile; |
|
exports.range = range; |
|
exports.scan = scan; |
|
exports.shuffle = shuffle; |
|
exports.sum = sum; |
|
exports.ticks = ticks; |
|
exports.tickIncrement = tickIncrement; |
|
exports.tickStep = tickStep; |
|
exports.transpose = transpose; |
|
exports.variance = variance; |
|
exports.zip = zip; |
|
|
|
Object.defineProperty(exports, '__esModule', { value: true }); |
|
|
|
}))); |
|
|
|
},{}],3:[function(require,module,exports){ |
|
// https://d3js.org/d3-collection/ Version 1.0.3. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
|
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
|
(factory((global.d3 = global.d3 || {}))); |
|
}(this, (function (exports) { 'use strict'; |
|
|
|
var prefix = "$"; |
|
|
|
function Map() {} |
|
|
|
Map.prototype = map.prototype = { |
|
constructor: Map, |
|
has: function(key) { |
|
return (prefix + key) in this; |
|
}, |
|
get: function(key) { |
|
return this[prefix + key]; |
|
}, |
|
set: function(key, value) { |
|
this[prefix + key] = value; |
|
return this; |
|
}, |
|
remove: function(key) { |
|
var property = prefix + key; |
|
return property in this && delete this[property]; |
|
}, |
|
clear: function() { |
|
for (var property in this) if (property[0] === prefix) delete this[property]; |
|
}, |
|
keys: function() { |
|
var keys = []; |
|
for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); |
|
return keys; |
|
}, |
|
values: function() { |
|
var values = []; |
|
for (var property in this) if (property[0] === prefix) values.push(this[property]); |
|
return values; |
|
}, |
|
entries: function() { |
|
var entries = []; |
|
for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); |
|
return entries; |
|
}, |
|
size: function() { |
|
var size = 0; |
|
for (var property in this) if (property[0] === prefix) ++size; |
|
return size; |
|
}, |
|
empty: function() { |
|
for (var property in this) if (property[0] === prefix) return false; |
|
return true; |
|
}, |
|
each: function(f) { |
|
for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); |
|
} |
|
}; |
|
|
|
function map(object, f) { |
|
var map = new Map; |
|
|
|
// Copy constructor. |
|
if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); |
|
|
|
// Index array by numeric index or specified key function. |
|
else if (Array.isArray(object)) { |
|
var i = -1, |
|
n = object.length, |
|
o; |
|
|
|
if (f == null) while (++i < n) map.set(i, object[i]); |
|
else while (++i < n) map.set(f(o = object[i], i, object), o); |
|
} |
|
|
|
// Convert object to map. |
|
else if (object) for (var key in object) map.set(key, object[key]); |
|
|
|
return map; |
|
} |
|
|
|
var nest = function() { |
|
var keys = [], |
|
sortKeys = [], |
|
sortValues, |
|
rollup, |
|
nest; |
|
|
|
function apply(array, depth, createResult, setResult) { |
|
if (depth >= keys.length) return rollup != null |
|
? rollup(array) : (sortValues != null |
|
? array.sort(sortValues) |
|
: array); |
|
|
|
var i = -1, |
|
n = array.length, |
|
key = keys[depth++], |
|
keyValue, |
|
value, |
|
valuesByKey = map(), |
|
values, |
|
result = createResult(); |
|
|
|
while (++i < n) { |
|
if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { |
|
values.push(value); |
|
} else { |
|
valuesByKey.set(keyValue, [value]); |
|
} |
|
} |
|
|
|
valuesByKey.each(function(values, key) { |
|
setResult(result, key, apply(values, depth, createResult, setResult)); |
|
}); |
|
|
|
return result; |
|
} |
|
|
|
function entries(map$$1, depth) { |
|
if (++depth > keys.length) return map$$1; |
|
var array, sortKey = sortKeys[depth - 1]; |
|
if (rollup != null && depth >= keys.length) array = map$$1.entries(); |
|
else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); |
|
return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; |
|
} |
|
|
|
return nest = { |
|
object: function(array) { return apply(array, 0, createObject, setObject); }, |
|
map: function(array) { return apply(array, 0, createMap, setMap); }, |
|
entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, |
|
key: function(d) { keys.push(d); return nest; }, |
|
sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, |
|
sortValues: function(order) { sortValues = order; return nest; }, |
|
rollup: function(f) { rollup = f; return nest; } |
|
}; |
|
}; |
|
|
|
function createObject() { |
|
return {}; |
|
} |
|
|
|
function setObject(object, key, value) { |
|
object[key] = value; |
|
} |
|
|
|
function createMap() { |
|
return map(); |
|
} |
|
|
|
function setMap(map$$1, key, value) { |
|
map$$1.set(key, value); |
|
} |
|
|
|
function Set() {} |
|
|
|
var proto = map.prototype; |
|
|
|
Set.prototype = set.prototype = { |
|
constructor: Set, |
|
has: proto.has, |
|
add: function(value) { |
|
value += ""; |
|
this[prefix + value] = value; |
|
return this; |
|
}, |
|
remove: proto.remove, |
|
clear: proto.clear, |
|
values: proto.keys, |
|
size: proto.size, |
|
empty: proto.empty, |
|
each: proto.each |
|
}; |
|
|
|
function set(object, f) { |
|
var set = new Set; |
|
|
|
// Copy constructor. |
|
if (object instanceof Set) object.each(function(value) { set.add(value); }); |
|
|
|
// Otherwise, assume it’s an array. |
|
else if (object) { |
|
var i = -1, n = object.length; |
|
if (f == null) while (++i < n) set.add(object[i]); |
|
else while (++i < n) set.add(f(object[i], i, object)); |
|
} |
|
|
|
return set; |
|
} |
|
|
|
var keys = function(map) { |
|
var keys = []; |
|
for (var key in map) keys.push(key); |
|
return keys; |
|
}; |
|
|
|
var values = function(map) { |
|
var values = []; |
|
for (var key in map) values.push(map[key]); |
|
return values; |
|
}; |
|
|
|
var entries = function(map) { |
|
var entries = []; |
|
for (var key in map) entries.push({key: key, value: map[key]}); |
|
return entries; |
|
}; |
|
|
|
exports.nest = nest; |
|
exports.set = set; |
|
exports.map = map; |
|
exports.keys = keys; |
|
exports.values = values; |
|
exports.entries = entries; |
|
|
|
Object.defineProperty(exports, '__esModule', { value: true }); |
|
|
|
}))); |
|
|
|
},{}],4:[function(require,module,exports){ |
|
// https://d3js.org/d3-path/ Version 1.0.5. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
|
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
|
(factory((global.d3 = global.d3 || {}))); |
|
}(this, (function (exports) { 'use strict'; |
|
|
|
var pi = Math.PI; |
|
var tau = 2 * pi; |
|
var epsilon = 1e-6; |
|
var tauEpsilon = tau - epsilon; |
|
|
|
function Path() { |
|
this._x0 = this._y0 = // start of current subpath |
|
this._x1 = this._y1 = null; // end of current subpath |
|
this._ = ""; |
|
} |
|
|
|
function path() { |
|
return new Path; |
|
} |
|
|
|
Path.prototype = path.prototype = { |
|
constructor: Path, |
|
moveTo: function(x, y) { |
|
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); |
|
}, |
|
closePath: function() { |
|
if (this._x1 !== null) { |
|
this._x1 = this._x0, this._y1 = this._y0; |
|
this._ += "Z"; |
|
} |
|
}, |
|
lineTo: function(x, y) { |
|
this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); |
|
}, |
|
quadraticCurveTo: function(x1, y1, x, y) { |
|
this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); |
|
}, |
|
bezierCurveTo: function(x1, y1, x2, y2, x, y) { |
|
this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); |
|
}, |
|
arcTo: function(x1, y1, x2, y2, r) { |
|
x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; |
|
var x0 = this._x1, |
|
y0 = this._y1, |
|
x21 = x2 - x1, |
|
y21 = y2 - y1, |
|
x01 = x0 - x1, |
|
y01 = y0 - y1, |
|
l01_2 = x01 * x01 + y01 * y01; |
|
|
|
// Is the radius negative? Error. |
|
if (r < 0) throw new Error("negative radius: " + r); |
|
|
|
// Is this path empty? Move to (x1,y1). |
|
if (this._x1 === null) { |
|
this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); |
|
} |
|
|
|
// Or, is (x1,y1) coincident with (x0,y0)? Do nothing. |
|
else if (!(l01_2 > epsilon)) {} |
|
|
|
// Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? |
|
// Equivalently, is (x1,y1) coincident with (x2,y2)? |
|
// Or, is the radius zero? Line to (x1,y1). |
|
else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { |
|
this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); |
|
} |
|
|
|
// Otherwise, draw an arc! |
|
else { |
|
var x20 = x2 - x0, |
|
y20 = y2 - y0, |
|
l21_2 = x21 * x21 + y21 * y21, |
|
l20_2 = x20 * x20 + y20 * y20, |
|
l21 = Math.sqrt(l21_2), |
|
l01 = Math.sqrt(l01_2), |
|
l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), |
|
t01 = l / l01, |
|
t21 = l / l21; |
|
|
|
// If the start tangent is not coincident with (x0,y0), line to. |
|
if (Math.abs(t01 - 1) > epsilon) { |
|
this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); |
|
} |
|
|
|
this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); |
|
} |
|
}, |
|
arc: function(x, y, r, a0, a1, ccw) { |
|
x = +x, y = +y, r = +r; |
|
var dx = r * Math.cos(a0), |
|
dy = r * Math.sin(a0), |
|
x0 = x + dx, |
|
y0 = y + dy, |
|
cw = 1 ^ ccw, |
|
da = ccw ? a0 - a1 : a1 - a0; |
|
|
|
// Is the radius negative? Error. |
|
if (r < 0) throw new Error("negative radius: " + r); |
|
|
|
// Is this path empty? Move to (x0,y0). |
|
if (this._x1 === null) { |
|
this._ += "M" + x0 + "," + y0; |
|
} |
|
|
|
// Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). |
|
else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { |
|
this._ += "L" + x0 + "," + y0; |
|
} |
|
|
|
// Is this arc empty? We’re done. |
|
if (!r) return; |
|
|
|
// Does the angle go the wrong way? Flip the direction. |
|
if (da < 0) da = da % tau + tau; |
|
|
|
// Is this a complete circle? Draw two arcs to complete the circle. |
|
if (da > tauEpsilon) { |
|
this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); |
|
} |
|
|
|
// Is this arc non-empty? Draw an arc! |
|
else if (da > epsilon) { |
|
this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); |
|
} |
|
}, |
|
rect: function(x, y, w, h) { |
|
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; |
|
}, |
|
toString: function() { |
|
return this._; |
|
} |
|
}; |
|
|
|
exports.path = path; |
|
|
|
Object.defineProperty(exports, '__esModule', { value: true }); |
|
|
|
}))); |
|
|
|
},{}],5:[function(require,module,exports){ |
|
// https://github.com/d3/d3-sankey Version 0.6.0. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-collection'), require('d3-shape')) : |
|
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-collection', 'd3-shape'], factory) : |
|
(factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3)); |
|
}(this, (function (exports,d3Array,d3Collection,d3Shape) { 'use strict'; |
|
|
|
function constant(x) { |
|
return function() { |
|
return x; |
|
}; |
|
} |
|
|
|
function ascendingSourceBreadth(a, b) { |
|
return ascendingBreadth(a.source, b.source) || a.index - b.index; |
|
} |
|
|
|
function ascendingTargetBreadth(a, b) { |
|
return ascendingBreadth(a.target, b.target) || a.index - b.index; |
|
} |
|
|
|
function ascendingBreadth(a, b) { |
|
return a.y0 - b.y0; |
|
} |
|
|
|
function value(d) { |
|
return d.value; |
|
} |
|
|
|
function nodeCenter(node) { |
|
return (node.y0 + node.y1) / 2; |
|
} |
|
|
|
function weightedSource(link) { |
|
return nodeCenter(link.source) * link.value; |
|
} |
|
|
|
function weightedTarget(link) { |
|
return nodeCenter(link.target) * link.value; |
|
} |
|
|
|
function defaultNodes(graph) { |
|
return graph.nodes; |
|
} |
|
|
|
function defaultLinks(graph) { |
|
return graph.links; |
|
} |
|
|
|
var sankey = function() { |
|
var x0 = 0, y0 = 0, x1 = 1, y1 = 1, // extent |
|
dx = 24, // nodeWidth |
|
py = 8, // nodePadding |
|
nodes = defaultNodes, |
|
links = defaultLinks, |
|
iterations = 32; |
|
|
|
function sankey() { |
|
var graph = {nodes: nodes.apply(null, arguments), links: links.apply(null, arguments)}; |
|
computeNodeLinks(graph); |
|
computeNodeValues(graph); |
|
computeNodeDepths(graph); |
|
computeNodeBreadths(graph, iterations); |
|
computeLinkBreadths(graph); |
|
return graph; |
|
} |
|
|
|
sankey.update = function(graph) { |
|
computeLinkBreadths(graph); |
|
return graph; |
|
}; |
|
|
|
sankey.nodeWidth = function(_) { |
|
return arguments.length ? (dx = +_, sankey) : dx; |
|
}; |
|
|
|
sankey.nodePadding = function(_) { |
|
return arguments.length ? (py = +_, sankey) : py; |
|
}; |
|
|
|
sankey.nodes = function(_) { |
|
return arguments.length ? (nodes = typeof _ === "function" ? _ : constant(_), sankey) : nodes; |
|
}; |
|
|
|
sankey.links = function(_) { |
|
return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links; |
|
}; |
|
|
|
sankey.size = function(_) { |
|
return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], sankey) : [x1 - x0, y1 - y0]; |
|
}; |
|
|
|
sankey.extent = function(_) { |
|
return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], sankey) : [[x0, y0], [x1, y1]]; |
|
}; |
|
|
|
sankey.iterations = function(_) { |
|
return arguments.length ? (iterations = +_, sankey) : iterations; |
|
}; |
|
|
|
// Populate the sourceLinks and targetLinks for each node. |
|
// Also, if the source and target are not objects, assume they are indices. |
|
function computeNodeLinks(graph) { |
|
graph.nodes.forEach(function(node, i) { |
|
node.index = i; |
|
node.sourceLinks = []; |
|
node.targetLinks = []; |
|
}); |
|
graph.links.forEach(function(link, i) { |
|
var source = link.source, target = link.target; |
|
if (typeof source === "number") source = link.source = graph.nodes[link.source]; |
|
if (typeof target === "number") target = link.target = graph.nodes[link.target]; |
|
link.index = i; |
|
source.sourceLinks.push(link); |
|
target.targetLinks.push(link); |
|
}); |
|
} |
|
|
|
// Compute the value (size) of each node by summing the associated links. |
|
function computeNodeValues(graph) { |
|
graph.nodes.forEach(function(node) { |
|
node.value = Math.max( |
|
d3Array.sum(node.sourceLinks, value), |
|
d3Array.sum(node.targetLinks, value) |
|
); |
|
}); |
|
} |
|
|
|
// Iteratively assign the depth (x-position) for each node. |
|
// Nodes are assigned the maximum depth of incoming neighbors plus one; |
|
// nodes with no incoming links are assigned depth zero, while |
|
// nodes with no outgoing links are assigned the maximum depth. |
|
function computeNodeDepths(graph) { |
|
var remainingNodes = graph.nodes, |
|
nextNodes, |
|
depth = 0; |
|
|
|
while (remainingNodes.length) { |
|
nextNodes = []; |
|
remainingNodes.forEach(function(node) { |
|
node.depth = depth; |
|
node.sourceLinks.forEach(function(link) { |
|
if (nextNodes.indexOf(link.target) < 0) { |
|
nextNodes.push(link.target); |
|
} |
|
}); |
|
}); |
|
remainingNodes = nextNodes; |
|
++depth; |
|
} |
|
|
|
// |
|
moveSinksRight(graph, depth); |
|
scaleNodeDepths(graph, depth); |
|
} |
|
|
|
// function moveSourcesRight(graph) { |
|
// graph.nodes.forEach(function(node) { |
|
// if (!node.targetLinks.length) { |
|
// node.depth = min(node.sourceLinks, function(d) { return d.target.depth; }) - 1; |
|
// } |
|
// }); |
|
// } |
|
|
|
function moveSinksRight(graph, depth) { |
|
graph.nodes.forEach(function(node) { |
|
if (!node.sourceLinks.length) { |
|
node.depth = depth - 1; |
|
} |
|
}); |
|
} |
|
|
|
function scaleNodeDepths(graph, depth) { |
|
var kx = (x1 - x0 - dx) / (depth - 1); |
|
graph.nodes.forEach(function(node) { |
|
node.x1 = (node.x0 = x0 + node.depth * kx) + dx; |
|
}); |
|
} |
|
|
|
function computeNodeBreadths(graph) { |
|
var nodesByDepth = d3Collection.nest() |
|
.key(function(d) { return d.depth; }) |
|
.sortKeys(d3Array.ascending) |
|
.entries(graph.nodes) |
|
.map(function(d) { return d.values; }); |
|
|
|
// |
|
initializeNodeBreadth(); |
|
resolveCollisions(); |
|
for (var alpha = 1, n = iterations; n > 0; --n) { |
|
relaxRightToLeft(alpha *= 0.99); |
|
resolveCollisions(); |
|
relaxLeftToRight(alpha); |
|
resolveCollisions(); |
|
} |
|
|
|
function initializeNodeBreadth() { |
|
var ky = d3Array.min(nodesByDepth, function(nodes) { |
|
return (y1 - y0 - (nodes.length - 1) * py) / d3Array.sum(nodes, value); |
|
}); |
|
|
|
nodesByDepth.forEach(function(nodes) { |
|
nodes.forEach(function(node, i) { |
|
node.y1 = (node.y0 = i) + node.value * ky; |
|
}); |
|
}); |
|
|
|
graph.links.forEach(function(link) { |
|
link.width = link.value * ky; |
|
}); |
|
} |
|
|
|
function relaxLeftToRight(alpha) { |
|
nodesByDepth.forEach(function(nodes) { |
|
nodes.forEach(function(node) { |
|
if (node.targetLinks.length) { |
|
var dy = (d3Array.sum(node.targetLinks, weightedSource) / d3Array.sum(node.targetLinks, value) - nodeCenter(node)) * alpha; |
|
node.y0 += dy, node.y1 += dy; |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
function relaxRightToLeft(alpha) { |
|
nodesByDepth.slice().reverse().forEach(function(nodes) { |
|
nodes.forEach(function(node) { |
|
if (node.sourceLinks.length) { |
|
var dy = (d3Array.sum(node.sourceLinks, weightedTarget) / d3Array.sum(node.sourceLinks, value) - nodeCenter(node)) * alpha; |
|
node.y0 += dy, node.y1 += dy; |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
function resolveCollisions() { |
|
nodesByDepth.forEach(function(nodes) { |
|
var node, |
|
dy, |
|
y = y0, |
|
n = nodes.length, |
|
i; |
|
|
|
// Push any overlapping nodes down. |
|
nodes.sort(ascendingBreadth); |
|
for (i = 0; i < n; ++i) { |
|
node = nodes[i]; |
|
dy = y - node.y0; |
|
if (dy > 0) node.y0 += dy, node.y1 += dy; |
|
y = node.y1 + py; |
|
} |
|
|
|
// If the bottommost node goes outside the bounds, push it back up. |
|
dy = y - py - y1; |
|
if (dy > 0) { |
|
y = (node.y0 -= dy), node.y1 -= dy; |
|
|
|
// Push any overlapping nodes back up. |
|
for (i = n - 2; i >= 0; --i) { |
|
node = nodes[i]; |
|
dy = node.y1 + py - y; |
|
if (dy > 0) node.y0 -= dy, node.y1 -= dy; |
|
y = node.y0; |
|
} |
|
} |
|
}); |
|
} |
|
} |
|
|
|
function computeLinkBreadths(graph) { |
|
graph.nodes.forEach(function(node) { |
|
node.sourceLinks.sort(ascendingTargetBreadth); |
|
node.targetLinks.sort(ascendingSourceBreadth); |
|
}); |
|
graph.nodes.forEach(function(node) { |
|
var y0 = node.y0, y1 = y0; |
|
node.sourceLinks.forEach(function(link) { |
|
link.y0 = y0 + link.width / 2, y0 += link.width; |
|
}); |
|
node.targetLinks.forEach(function(link) { |
|
link.y1 = y1 + link.width / 2, y1 += link.width; |
|
}); |
|
}); |
|
} |
|
|
|
return sankey; |
|
}; |
|
|
|
function horizontalSource(d) { |
|
return [d.source.x1, d.y0]; |
|
} |
|
|
|
function horizontalTarget(d) { |
|
return [d.target.x0, d.y1]; |
|
} |
|
|
|
var sankeyLinkHorizontal = function() { |
|
return d3Shape.linkHorizontal() |
|
.source(horizontalSource) |
|
.target(horizontalTarget); |
|
}; |
|
|
|
exports.sankey = sankey; |
|
exports.sankeyLinkHorizontal = sankeyLinkHorizontal; |
|
|
|
Object.defineProperty(exports, '__esModule', { value: true }); |
|
|
|
}))); |
|
|
|
},{"d3-array":2,"d3-collection":3,"d3-shape":6}],6:[function(require,module,exports){ |
|
// https://d3js.org/d3-shape/ Version 1.2.0. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-path')) : |
|
typeof define === 'function' && define.amd ? define(['exports', 'd3-path'], factory) : |
|
(factory((global.d3 = global.d3 || {}),global.d3)); |
|
}(this, (function (exports,d3Path) { 'use strict'; |
|
|
|
var constant = function(x) { |
|
return function constant() { |
|
return x; |
|
}; |
|
}; |
|
|
|
var abs = Math.abs; |
|
var atan2 = Math.atan2; |
|
var cos = Math.cos; |
|
var max = Math.max; |
|
var min = Math.min; |
|
var sin = Math.sin; |
|
var sqrt = Math.sqrt; |
|
|
|
var epsilon = 1e-12; |
|
var pi = Math.PI; |
|
var halfPi = pi / 2; |
|
var tau = 2 * pi; |
|
|
|
function acos(x) { |
|
return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); |
|
} |
|
|
|
function asin(x) { |
|
return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); |
|
} |
|
|
|
function arcInnerRadius(d) { |
|
return d.innerRadius; |
|
} |
|
|
|
function arcOuterRadius(d) { |
|
return d.outerRadius; |
|
} |
|
|
|
function arcStartAngle(d) { |
|
return d.startAngle; |
|
} |
|
|
|
function arcEndAngle(d) { |
|
return d.endAngle; |
|
} |
|
|
|
function arcPadAngle(d) { |
|
return d && d.padAngle; // Note: optional! |
|
} |
|
|
|
function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { |
|
var x10 = x1 - x0, y10 = y1 - y0, |
|
x32 = x3 - x2, y32 = y3 - y2, |
|
t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); |
|
return [x0 + t * x10, y0 + t * y10]; |
|
} |
|
|
|
// Compute perpendicular offset line of length rc. |
|
// http://mathworld.wolfram.com/Circle-LineIntersection.html |
|
function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { |
|
var x01 = x0 - x1, |
|
y01 = y0 - y1, |
|
lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01), |
|
ox = lo * y01, |
|
oy = -lo * x01, |
|
x11 = x0 + ox, |
|
y11 = y0 + oy, |
|
x10 = x1 + ox, |
|
y10 = y1 + oy, |
|
x00 = (x11 + x10) / 2, |
|
y00 = (y11 + y10) / 2, |
|
dx = x10 - x11, |
|
dy = y10 - y11, |
|
d2 = dx * dx + dy * dy, |
|
r = r1 - rc, |
|
D = x11 * y10 - x10 * y11, |
|
d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)), |
|
cx0 = (D * dy - dx * d) / d2, |
|
cy0 = (-D * dx - dy * d) / d2, |
|
cx1 = (D * dy + dx * d) / d2, |
|
cy1 = (-D * dx + dy * d) / d2, |
|
dx0 = cx0 - x00, |
|
dy0 = cy0 - y00, |
|
dx1 = cx1 - x00, |
|
dy1 = cy1 - y00; |
|
|
|
// Pick the closer of the two intersection points. |
|
// TODO Is there a faster way to determine which intersection to use? |
|
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; |
|
|
|
return { |
|
cx: cx0, |
|
cy: cy0, |
|
x01: -ox, |
|
y01: -oy, |
|
x11: cx0 * (r1 / r - 1), |
|
y11: cy0 * (r1 / r - 1) |
|
}; |
|
} |
|
|
|
var arc = function() { |
|
var innerRadius = arcInnerRadius, |
|
outerRadius = arcOuterRadius, |
|
cornerRadius = constant(0), |
|
padRadius = null, |
|
startAngle = arcStartAngle, |
|
endAngle = arcEndAngle, |
|
padAngle = arcPadAngle, |
|
context = null; |
|
|
|
function arc() { |
|
var buffer, |
|
r, |
|
r0 = +innerRadius.apply(this, arguments), |
|
r1 = +outerRadius.apply(this, arguments), |
|
a0 = startAngle.apply(this, arguments) - halfPi, |
|
a1 = endAngle.apply(this, arguments) - halfPi, |
|
da = abs(a1 - a0), |
|
cw = a1 > a0; |
|
|
|
if (!context) context = buffer = d3Path.path(); |
|
|
|
// Ensure that the outer radius is always larger than the inner radius. |
|
if (r1 < r0) r = r1, r1 = r0, r0 = r; |
|
|
|
// Is it a point? |
|
if (!(r1 > epsilon)) context.moveTo(0, 0); |
|
|
|
// Or is it a circle or annulus? |
|
else if (da > tau - epsilon) { |
|
context.moveTo(r1 * cos(a0), r1 * sin(a0)); |
|
context.arc(0, 0, r1, a0, a1, !cw); |
|
if (r0 > epsilon) { |
|
context.moveTo(r0 * cos(a1), r0 * sin(a1)); |
|
context.arc(0, 0, r0, a1, a0, cw); |
|
} |
|
} |
|
|
|
// Or is it a circular or annular sector? |
|
else { |
|
var a01 = a0, |
|
a11 = a1, |
|
a00 = a0, |
|
a10 = a1, |
|
da0 = da, |
|
da1 = da, |
|
ap = padAngle.apply(this, arguments) / 2, |
|
rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)), |
|
rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), |
|
rc0 = rc, |
|
rc1 = rc, |
|
t0, |
|
t1; |
|
|
|
// Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. |
|
if (rp > epsilon) { |
|
var p0 = asin(rp / r0 * sin(ap)), |
|
p1 = asin(rp / r1 * sin(ap)); |
|
if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; |
|
else da0 = 0, a00 = a10 = (a0 + a1) / 2; |
|
if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; |
|
else da1 = 0, a01 = a11 = (a0 + a1) / 2; |
|
} |
|
|
|
var x01 = r1 * cos(a01), |
|
y01 = r1 * sin(a01), |
|
x10 = r0 * cos(a10), |
|
y10 = r0 * sin(a10); |
|
|
|
// Apply rounded corners? |
|
if (rc > epsilon) { |
|
var x11 = r1 * cos(a11), |
|
y11 = r1 * sin(a11), |
|
x00 = r0 * cos(a00), |
|
y00 = r0 * sin(a00); |
|
|
|
// Restrict the corner radius according to the sector angle. |
|
if (da < pi) { |
|
var oc = da0 > epsilon ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], |
|
ax = x01 - oc[0], |
|
ay = y01 - oc[1], |
|
bx = x11 - oc[0], |
|
by = y11 - oc[1], |
|
kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2), |
|
lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]); |
|
rc0 = min(rc, (r0 - lc) / (kc - 1)); |
|
rc1 = min(rc, (r1 - lc) / (kc + 1)); |
|
} |
|
} |
|
|
|
// Is the sector collapsed to a line? |
|
if (!(da1 > epsilon)) context.moveTo(x01, y01); |
|
|
|
// Does the sector’s outer ring have rounded corners? |
|
else if (rc1 > epsilon) { |
|
t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); |
|
t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); |
|
|
|
context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); |
|
|
|
// Have the corners merged? |
|
if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); |
|
|
|
// Otherwise, draw the two corners and the ring. |
|
else { |
|
context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); |
|
context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); |
|
context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); |
|
} |
|
} |
|
|
|
// Or is the outer ring just a circular arc? |
|
else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); |
|
|
|
// Is there no inner ring, and it’s a circular sector? |
|
// Or perhaps it’s an annular sector collapsed due to padding? |
|
if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10); |
|
|
|
// Does the sector’s inner ring (or point) have rounded corners? |
|
else if (rc0 > epsilon) { |
|
t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); |
|
t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); |
|
|
|
context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); |
|
|
|
// Have the corners merged? |
|
if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); |
|
|
|
// Otherwise, draw the two corners and the ring. |
|
else { |
|
context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); |
|
context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); |
|
context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); |
|
} |
|
} |
|
|
|
// Or is the inner ring just a circular arc? |
|
else context.arc(0, 0, r0, a10, a00, cw); |
|
} |
|
|
|
context.closePath(); |
|
|
|
if (buffer) return context = null, buffer + "" || null; |
|
} |
|
|
|
arc.centroid = function() { |
|
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, |
|
a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2; |
|
return [cos(a) * r, sin(a) * r]; |
|
}; |
|
|
|
arc.innerRadius = function(_) { |
|
return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius; |
|
}; |
|
|
|
arc.outerRadius = function(_) { |
|
return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius; |
|
}; |
|
|
|
arc.cornerRadius = function(_) { |
|
return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius; |
|
}; |
|
|
|
arc.padRadius = function(_) { |
|
return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius; |
|
}; |
|
|
|
arc.startAngle = function(_) { |
|
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle; |
|
}; |
|
|
|
arc.endAngle = function(_) { |
|
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle; |
|
}; |
|
|
|
arc.padAngle = function(_) { |
|
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle; |
|
}; |
|
|
|
arc.context = function(_) { |
|
return arguments.length ? ((context = _ == null ? null : _), arc) : context; |
|
}; |
|
|
|
return arc; |
|
}; |
|
|
|
function Linear(context) { |
|
this._context = context; |
|
} |
|
|
|
Linear.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; // proceed |
|
default: this._context.lineTo(x, y); break; |
|
} |
|
} |
|
}; |
|
|
|
var curveLinear = function(context) { |
|
return new Linear(context); |
|
}; |
|
|
|
function x(p) { |
|
return p[0]; |
|
} |
|
|
|
function y(p) { |
|
return p[1]; |
|
} |
|
|
|
var line = function() { |
|
var x$$1 = x, |
|
y$$1 = y, |
|
defined = constant(true), |
|
context = null, |
|
curve = curveLinear, |
|
output = null; |
|
|
|
function line(data) { |
|
var i, |
|
n = data.length, |
|
d, |
|
defined0 = false, |
|
buffer; |
|
|
|
if (context == null) output = curve(buffer = d3Path.path()); |
|
|
|
for (i = 0; i <= n; ++i) { |
|
if (!(i < n && defined(d = data[i], i, data)) === defined0) { |
|
if (defined0 = !defined0) output.lineStart(); |
|
else output.lineEnd(); |
|
} |
|
if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); |
|
} |
|
|
|
if (buffer) return output = null, buffer + "" || null; |
|
} |
|
|
|
line.x = function(_) { |
|
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), line) : x$$1; |
|
}; |
|
|
|
line.y = function(_) { |
|
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), line) : y$$1; |
|
}; |
|
|
|
line.defined = function(_) { |
|
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined; |
|
}; |
|
|
|
line.curve = function(_) { |
|
return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; |
|
}; |
|
|
|
line.context = function(_) { |
|
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; |
|
}; |
|
|
|
return line; |
|
}; |
|
|
|
var area = function() { |
|
var x0 = x, |
|
x1 = null, |
|
y0 = constant(0), |
|
y1 = y, |
|
defined = constant(true), |
|
context = null, |
|
curve = curveLinear, |
|
output = null; |
|
|
|
function area(data) { |
|
var i, |
|
j, |
|
k, |
|
n = data.length, |
|
d, |
|
defined0 = false, |
|
buffer, |
|
x0z = new Array(n), |
|
y0z = new Array(n); |
|
|
|
if (context == null) output = curve(buffer = d3Path.path()); |
|
|
|
for (i = 0; i <= n; ++i) { |
|
if (!(i < n && defined(d = data[i], i, data)) === defined0) { |
|
if (defined0 = !defined0) { |
|
j = i; |
|
output.areaStart(); |
|
output.lineStart(); |
|
} else { |
|
output.lineEnd(); |
|
output.lineStart(); |
|
for (k = i - 1; k >= j; --k) { |
|
output.point(x0z[k], y0z[k]); |
|
} |
|
output.lineEnd(); |
|
output.areaEnd(); |
|
} |
|
} |
|
if (defined0) { |
|
x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); |
|
output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); |
|
} |
|
} |
|
|
|
if (buffer) return output = null, buffer + "" || null; |
|
} |
|
|
|
function arealine() { |
|
return line().defined(defined).curve(curve).context(context); |
|
} |
|
|
|
area.x = function(_) { |
|
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0; |
|
}; |
|
|
|
area.x0 = function(_) { |
|
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0; |
|
}; |
|
|
|
area.x1 = function(_) { |
|
return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1; |
|
}; |
|
|
|
area.y = function(_) { |
|
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0; |
|
}; |
|
|
|
area.y0 = function(_) { |
|
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0; |
|
}; |
|
|
|
area.y1 = function(_) { |
|
return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1; |
|
}; |
|
|
|
area.lineX0 = |
|
area.lineY0 = function() { |
|
return arealine().x(x0).y(y0); |
|
}; |
|
|
|
area.lineY1 = function() { |
|
return arealine().x(x0).y(y1); |
|
}; |
|
|
|
area.lineX1 = function() { |
|
return arealine().x(x1).y(y0); |
|
}; |
|
|
|
area.defined = function(_) { |
|
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined; |
|
}; |
|
|
|
area.curve = function(_) { |
|
return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; |
|
}; |
|
|
|
area.context = function(_) { |
|
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; |
|
}; |
|
|
|
return area; |
|
}; |
|
|
|
var descending = function(a, b) { |
|
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; |
|
}; |
|
|
|
var identity = function(d) { |
|
return d; |
|
}; |
|
|
|
var pie = function() { |
|
var value = identity, |
|
sortValues = descending, |
|
sort = null, |
|
startAngle = constant(0), |
|
endAngle = constant(tau), |
|
padAngle = constant(0); |
|
|
|
function pie(data) { |
|
var i, |
|
n = data.length, |
|
j, |
|
k, |
|
sum = 0, |
|
index = new Array(n), |
|
arcs = new Array(n), |
|
a0 = +startAngle.apply(this, arguments), |
|
da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), |
|
a1, |
|
p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), |
|
pa = p * (da < 0 ? -1 : 1), |
|
v; |
|
|
|
for (i = 0; i < n; ++i) { |
|
if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { |
|
sum += v; |
|
} |
|
} |
|
|
|
// Optionally sort the arcs by previously-computed values or by data. |
|
if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); |
|
else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); |
|
|
|
// Compute the arcs! They are stored in the original data's order. |
|
for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { |
|
j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { |
|
data: data[j], |
|
index: i, |
|
value: v, |
|
startAngle: a0, |
|
endAngle: a1, |
|
padAngle: p |
|
}; |
|
} |
|
|
|
return arcs; |
|
} |
|
|
|
pie.value = function(_) { |
|
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value; |
|
}; |
|
|
|
pie.sortValues = function(_) { |
|
return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; |
|
}; |
|
|
|
pie.sort = function(_) { |
|
return arguments.length ? (sort = _, sortValues = null, pie) : sort; |
|
}; |
|
|
|
pie.startAngle = function(_) { |
|
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle; |
|
}; |
|
|
|
pie.endAngle = function(_) { |
|
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle; |
|
}; |
|
|
|
pie.padAngle = function(_) { |
|
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle; |
|
}; |
|
|
|
return pie; |
|
}; |
|
|
|
var curveRadialLinear = curveRadial(curveLinear); |
|
|
|
function Radial(curve) { |
|
this._curve = curve; |
|
} |
|
|
|
Radial.prototype = { |
|
areaStart: function() { |
|
this._curve.areaStart(); |
|
}, |
|
areaEnd: function() { |
|
this._curve.areaEnd(); |
|
}, |
|
lineStart: function() { |
|
this._curve.lineStart(); |
|
}, |
|
lineEnd: function() { |
|
this._curve.lineEnd(); |
|
}, |
|
point: function(a, r) { |
|
this._curve.point(r * Math.sin(a), r * -Math.cos(a)); |
|
} |
|
}; |
|
|
|
function curveRadial(curve) { |
|
|
|
function radial(context) { |
|
return new Radial(curve(context)); |
|
} |
|
|
|
radial._curve = curve; |
|
|
|
return radial; |
|
} |
|
|
|
function lineRadial(l) { |
|
var c = l.curve; |
|
|
|
l.angle = l.x, delete l.x; |
|
l.radius = l.y, delete l.y; |
|
|
|
l.curve = function(_) { |
|
return arguments.length ? c(curveRadial(_)) : c()._curve; |
|
}; |
|
|
|
return l; |
|
} |
|
|
|
var lineRadial$1 = function() { |
|
return lineRadial(line().curve(curveRadialLinear)); |
|
}; |
|
|
|
var areaRadial = function() { |
|
var a = area().curve(curveRadialLinear), |
|
c = a.curve, |
|
x0 = a.lineX0, |
|
x1 = a.lineX1, |
|
y0 = a.lineY0, |
|
y1 = a.lineY1; |
|
|
|
a.angle = a.x, delete a.x; |
|
a.startAngle = a.x0, delete a.x0; |
|
a.endAngle = a.x1, delete a.x1; |
|
a.radius = a.y, delete a.y; |
|
a.innerRadius = a.y0, delete a.y0; |
|
a.outerRadius = a.y1, delete a.y1; |
|
a.lineStartAngle = function() { return lineRadial(x0()); }, delete a.lineX0; |
|
a.lineEndAngle = function() { return lineRadial(x1()); }, delete a.lineX1; |
|
a.lineInnerRadius = function() { return lineRadial(y0()); }, delete a.lineY0; |
|
a.lineOuterRadius = function() { return lineRadial(y1()); }, delete a.lineY1; |
|
|
|
a.curve = function(_) { |
|
return arguments.length ? c(curveRadial(_)) : c()._curve; |
|
}; |
|
|
|
return a; |
|
}; |
|
|
|
var pointRadial = function(x, y) { |
|
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; |
|
}; |
|
|
|
var slice = Array.prototype.slice; |
|
|
|
function linkSource(d) { |
|
return d.source; |
|
} |
|
|
|
function linkTarget(d) { |
|
return d.target; |
|
} |
|
|
|
function link(curve) { |
|
var source = linkSource, |
|
target = linkTarget, |
|
x$$1 = x, |
|
y$$1 = y, |
|
context = null; |
|
|
|
function link() { |
|
var buffer, argv = slice.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); |
|
if (!context) context = buffer = d3Path.path(); |
|
curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); |
|
if (buffer) return context = null, buffer + "" || null; |
|
} |
|
|
|
link.source = function(_) { |
|
return arguments.length ? (source = _, link) : source; |
|
}; |
|
|
|
link.target = function(_) { |
|
return arguments.length ? (target = _, link) : target; |
|
}; |
|
|
|
link.x = function(_) { |
|
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), link) : x$$1; |
|
}; |
|
|
|
link.y = function(_) { |
|
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), link) : y$$1; |
|
}; |
|
|
|
link.context = function(_) { |
|
return arguments.length ? ((context = _ == null ? null : _), link) : context; |
|
}; |
|
|
|
return link; |
|
} |
|
|
|
function curveHorizontal(context, x0, y0, x1, y1) { |
|
context.moveTo(x0, y0); |
|
context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); |
|
} |
|
|
|
function curveVertical(context, x0, y0, x1, y1) { |
|
context.moveTo(x0, y0); |
|
context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); |
|
} |
|
|
|
function curveRadial$1(context, x0, y0, x1, y1) { |
|
var p0 = pointRadial(x0, y0), |
|
p1 = pointRadial(x0, y0 = (y0 + y1) / 2), |
|
p2 = pointRadial(x1, y0), |
|
p3 = pointRadial(x1, y1); |
|
context.moveTo(p0[0], p0[1]); |
|
context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); |
|
} |
|
|
|
function linkHorizontal() { |
|
return link(curveHorizontal); |
|
} |
|
|
|
function linkVertical() { |
|
return link(curveVertical); |
|
} |
|
|
|
function linkRadial() { |
|
var l = link(curveRadial$1); |
|
l.angle = l.x, delete l.x; |
|
l.radius = l.y, delete l.y; |
|
return l; |
|
} |
|
|
|
var circle = { |
|
draw: function(context, size) { |
|
var r = Math.sqrt(size / pi); |
|
context.moveTo(r, 0); |
|
context.arc(0, 0, r, 0, tau); |
|
} |
|
}; |
|
|
|
var cross = { |
|
draw: function(context, size) { |
|
var r = Math.sqrt(size / 5) / 2; |
|
context.moveTo(-3 * r, -r); |
|
context.lineTo(-r, -r); |
|
context.lineTo(-r, -3 * r); |
|
context.lineTo(r, -3 * r); |
|
context.lineTo(r, -r); |
|
context.lineTo(3 * r, -r); |
|
context.lineTo(3 * r, r); |
|
context.lineTo(r, r); |
|
context.lineTo(r, 3 * r); |
|
context.lineTo(-r, 3 * r); |
|
context.lineTo(-r, r); |
|
context.lineTo(-3 * r, r); |
|
context.closePath(); |
|
} |
|
}; |
|
|
|
var tan30 = Math.sqrt(1 / 3); |
|
var tan30_2 = tan30 * 2; |
|
|
|
var diamond = { |
|
draw: function(context, size) { |
|
var y = Math.sqrt(size / tan30_2), |
|
x = y * tan30; |
|
context.moveTo(0, -y); |
|
context.lineTo(x, 0); |
|
context.lineTo(0, y); |
|
context.lineTo(-x, 0); |
|
context.closePath(); |
|
} |
|
}; |
|
|
|
var ka = 0.89081309152928522810; |
|
var kr = Math.sin(pi / 10) / Math.sin(7 * pi / 10); |
|
var kx = Math.sin(tau / 10) * kr; |
|
var ky = -Math.cos(tau / 10) * kr; |
|
|
|
var star = { |
|
draw: function(context, size) { |
|
var r = Math.sqrt(size * ka), |
|
x = kx * r, |
|
y = ky * r; |
|
context.moveTo(0, -r); |
|
context.lineTo(x, y); |
|
for (var i = 1; i < 5; ++i) { |
|
var a = tau * i / 5, |
|
c = Math.cos(a), |
|
s = Math.sin(a); |
|
context.lineTo(s * r, -c * r); |
|
context.lineTo(c * x - s * y, s * x + c * y); |
|
} |
|
context.closePath(); |
|
} |
|
}; |
|
|
|
var square = { |
|
draw: function(context, size) { |
|
var w = Math.sqrt(size), |
|
x = -w / 2; |
|
context.rect(x, x, w, w); |
|
} |
|
}; |
|
|
|
var sqrt3 = Math.sqrt(3); |
|
|
|
var triangle = { |
|
draw: function(context, size) { |
|
var y = -Math.sqrt(size / (sqrt3 * 3)); |
|
context.moveTo(0, y * 2); |
|
context.lineTo(-sqrt3 * y, -y); |
|
context.lineTo(sqrt3 * y, -y); |
|
context.closePath(); |
|
} |
|
}; |
|
|
|
var c = -0.5; |
|
var s = Math.sqrt(3) / 2; |
|
var k = 1 / Math.sqrt(12); |
|
var a = (k / 2 + 1) * 3; |
|
|
|
var wye = { |
|
draw: function(context, size) { |
|
var r = Math.sqrt(size / a), |
|
x0 = r / 2, |
|
y0 = r * k, |
|
x1 = x0, |
|
y1 = r * k + r, |
|
x2 = -x1, |
|
y2 = y1; |
|
context.moveTo(x0, y0); |
|
context.lineTo(x1, y1); |
|
context.lineTo(x2, y2); |
|
context.lineTo(c * x0 - s * y0, s * x0 + c * y0); |
|
context.lineTo(c * x1 - s * y1, s * x1 + c * y1); |
|
context.lineTo(c * x2 - s * y2, s * x2 + c * y2); |
|
context.lineTo(c * x0 + s * y0, c * y0 - s * x0); |
|
context.lineTo(c * x1 + s * y1, c * y1 - s * x1); |
|
context.lineTo(c * x2 + s * y2, c * y2 - s * x2); |
|
context.closePath(); |
|
} |
|
}; |
|
|
|
var symbols = [ |
|
circle, |
|
cross, |
|
diamond, |
|
square, |
|
star, |
|
triangle, |
|
wye |
|
]; |
|
|
|
var symbol = function() { |
|
var type = constant(circle), |
|
size = constant(64), |
|
context = null; |
|
|
|
function symbol() { |
|
var buffer; |
|
if (!context) context = buffer = d3Path.path(); |
|
type.apply(this, arguments).draw(context, +size.apply(this, arguments)); |
|
if (buffer) return context = null, buffer + "" || null; |
|
} |
|
|
|
symbol.type = function(_) { |
|
return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type; |
|
}; |
|
|
|
symbol.size = function(_) { |
|
return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size; |
|
}; |
|
|
|
symbol.context = function(_) { |
|
return arguments.length ? (context = _ == null ? null : _, symbol) : context; |
|
}; |
|
|
|
return symbol; |
|
}; |
|
|
|
var noop = function() {}; |
|
|
|
function point(that, x, y) { |
|
that._context.bezierCurveTo( |
|
(2 * that._x0 + that._x1) / 3, |
|
(2 * that._y0 + that._y1) / 3, |
|
(that._x0 + 2 * that._x1) / 3, |
|
(that._y0 + 2 * that._y1) / 3, |
|
(that._x0 + 4 * that._x1 + x) / 6, |
|
(that._y0 + 4 * that._y1 + y) / 6 |
|
); |
|
} |
|
|
|
function Basis(context) { |
|
this._context = context; |
|
} |
|
|
|
Basis.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = |
|
this._y0 = this._y1 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 3: point(this, this._x1, this._y1); // proceed |
|
case 2: this._context.lineTo(this._x1, this._y1); break; |
|
} |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed |
|
default: point(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = x; |
|
this._y0 = this._y1, this._y1 = y; |
|
} |
|
}; |
|
|
|
var basis = function(context) { |
|
return new Basis(context); |
|
}; |
|
|
|
function BasisClosed(context) { |
|
this._context = context; |
|
} |
|
|
|
BasisClosed.prototype = { |
|
areaStart: noop, |
|
areaEnd: noop, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = |
|
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 1: { |
|
this._context.moveTo(this._x2, this._y2); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 2: { |
|
this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); |
|
this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 3: { |
|
this.point(this._x2, this._y2); |
|
this.point(this._x3, this._y3); |
|
this.point(this._x4, this._y4); |
|
break; |
|
} |
|
} |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._x2 = x, this._y2 = y; break; |
|
case 1: this._point = 2; this._x3 = x, this._y3 = y; break; |
|
case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; |
|
default: point(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = x; |
|
this._y0 = this._y1, this._y1 = y; |
|
} |
|
}; |
|
|
|
var basisClosed = function(context) { |
|
return new BasisClosed(context); |
|
}; |
|
|
|
function BasisOpen(context) { |
|
this._context = context; |
|
} |
|
|
|
BasisOpen.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = |
|
this._y0 = this._y1 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; |
|
case 3: this._point = 4; // proceed |
|
default: point(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = x; |
|
this._y0 = this._y1, this._y1 = y; |
|
} |
|
}; |
|
|
|
var basisOpen = function(context) { |
|
return new BasisOpen(context); |
|
}; |
|
|
|
function Bundle(context, beta) { |
|
this._basis = new Basis(context); |
|
this._beta = beta; |
|
} |
|
|
|
Bundle.prototype = { |
|
lineStart: function() { |
|
this._x = []; |
|
this._y = []; |
|
this._basis.lineStart(); |
|
}, |
|
lineEnd: function() { |
|
var x = this._x, |
|
y = this._y, |
|
j = x.length - 1; |
|
|
|
if (j > 0) { |
|
var x0 = x[0], |
|
y0 = y[0], |
|
dx = x[j] - x0, |
|
dy = y[j] - y0, |
|
i = -1, |
|
t; |
|
|
|
while (++i <= j) { |
|
t = i / j; |
|
this._basis.point( |
|
this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), |
|
this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) |
|
); |
|
} |
|
} |
|
|
|
this._x = this._y = null; |
|
this._basis.lineEnd(); |
|
}, |
|
point: function(x, y) { |
|
this._x.push(+x); |
|
this._y.push(+y); |
|
} |
|
}; |
|
|
|
var bundle = ((function custom(beta) { |
|
|
|
function bundle(context) { |
|
return beta === 1 ? new Basis(context) : new Bundle(context, beta); |
|
} |
|
|
|
bundle.beta = function(beta) { |
|
return custom(+beta); |
|
}; |
|
|
|
return bundle; |
|
}))(0.85); |
|
|
|
function point$1(that, x, y) { |
|
that._context.bezierCurveTo( |
|
that._x1 + that._k * (that._x2 - that._x0), |
|
that._y1 + that._k * (that._y2 - that._y0), |
|
that._x2 + that._k * (that._x1 - x), |
|
that._y2 + that._k * (that._y1 - y), |
|
that._x2, |
|
that._y2 |
|
); |
|
} |
|
|
|
function Cardinal(context, tension) { |
|
this._context = context; |
|
this._k = (1 - tension) / 6; |
|
} |
|
|
|
Cardinal.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = |
|
this._y0 = this._y1 = this._y2 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 2: this._context.lineTo(this._x2, this._y2); break; |
|
case 3: point$1(this, this._x1, this._y1); break; |
|
} |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; this._x1 = x, this._y1 = y; break; |
|
case 2: this._point = 3; // proceed |
|
default: point$1(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var cardinal = ((function custom(tension) { |
|
|
|
function cardinal(context) { |
|
return new Cardinal(context, tension); |
|
} |
|
|
|
cardinal.tension = function(tension) { |
|
return custom(+tension); |
|
}; |
|
|
|
return cardinal; |
|
}))(0); |
|
|
|
function CardinalClosed(context, tension) { |
|
this._context = context; |
|
this._k = (1 - tension) / 6; |
|
} |
|
|
|
CardinalClosed.prototype = { |
|
areaStart: noop, |
|
areaEnd: noop, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = |
|
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 1: { |
|
this._context.moveTo(this._x3, this._y3); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 2: { |
|
this._context.lineTo(this._x3, this._y3); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 3: { |
|
this.point(this._x3, this._y3); |
|
this.point(this._x4, this._y4); |
|
this.point(this._x5, this._y5); |
|
break; |
|
} |
|
} |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._x3 = x, this._y3 = y; break; |
|
case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; |
|
case 2: this._point = 3; this._x5 = x, this._y5 = y; break; |
|
default: point$1(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var cardinalClosed = ((function custom(tension) { |
|
|
|
function cardinal(context) { |
|
return new CardinalClosed(context, tension); |
|
} |
|
|
|
cardinal.tension = function(tension) { |
|
return custom(+tension); |
|
}; |
|
|
|
return cardinal; |
|
}))(0); |
|
|
|
function CardinalOpen(context, tension) { |
|
this._context = context; |
|
this._k = (1 - tension) / 6; |
|
} |
|
|
|
CardinalOpen.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = |
|
this._y0 = this._y1 = this._y2 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; |
|
case 3: this._point = 4; // proceed |
|
default: point$1(this, x, y); break; |
|
} |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var cardinalOpen = ((function custom(tension) { |
|
|
|
function cardinal(context) { |
|
return new CardinalOpen(context, tension); |
|
} |
|
|
|
cardinal.tension = function(tension) { |
|
return custom(+tension); |
|
}; |
|
|
|
return cardinal; |
|
}))(0); |
|
|
|
function point$2(that, x, y) { |
|
var x1 = that._x1, |
|
y1 = that._y1, |
|
x2 = that._x2, |
|
y2 = that._y2; |
|
|
|
if (that._l01_a > epsilon) { |
|
var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, |
|
n = 3 * that._l01_a * (that._l01_a + that._l12_a); |
|
x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; |
|
y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; |
|
} |
|
|
|
if (that._l23_a > epsilon) { |
|
var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, |
|
m = 3 * that._l23_a * (that._l23_a + that._l12_a); |
|
x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; |
|
y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; |
|
} |
|
|
|
that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); |
|
} |
|
|
|
function CatmullRom(context, alpha) { |
|
this._context = context; |
|
this._alpha = alpha; |
|
} |
|
|
|
CatmullRom.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = |
|
this._y0 = this._y1 = this._y2 = NaN; |
|
this._l01_a = this._l12_a = this._l23_a = |
|
this._l01_2a = this._l12_2a = this._l23_2a = |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 2: this._context.lineTo(this._x2, this._y2); break; |
|
case 3: this.point(this._x2, this._y2); break; |
|
} |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
|
|
if (this._point) { |
|
var x23 = this._x2 - x, |
|
y23 = this._y2 - y; |
|
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); |
|
} |
|
|
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; // proceed |
|
default: point$2(this, x, y); break; |
|
} |
|
|
|
this._l01_a = this._l12_a, this._l12_a = this._l23_a; |
|
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var catmullRom = ((function custom(alpha) { |
|
|
|
function catmullRom(context) { |
|
return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); |
|
} |
|
|
|
catmullRom.alpha = function(alpha) { |
|
return custom(+alpha); |
|
}; |
|
|
|
return catmullRom; |
|
}))(0.5); |
|
|
|
function CatmullRomClosed(context, alpha) { |
|
this._context = context; |
|
this._alpha = alpha; |
|
} |
|
|
|
CatmullRomClosed.prototype = { |
|
areaStart: noop, |
|
areaEnd: noop, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = |
|
this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; |
|
this._l01_a = this._l12_a = this._l23_a = |
|
this._l01_2a = this._l12_2a = this._l23_2a = |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 1: { |
|
this._context.moveTo(this._x3, this._y3); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 2: { |
|
this._context.lineTo(this._x3, this._y3); |
|
this._context.closePath(); |
|
break; |
|
} |
|
case 3: { |
|
this.point(this._x3, this._y3); |
|
this.point(this._x4, this._y4); |
|
this.point(this._x5, this._y5); |
|
break; |
|
} |
|
} |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
|
|
if (this._point) { |
|
var x23 = this._x2 - x, |
|
y23 = this._y2 - y; |
|
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); |
|
} |
|
|
|
switch (this._point) { |
|
case 0: this._point = 1; this._x3 = x, this._y3 = y; break; |
|
case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; |
|
case 2: this._point = 3; this._x5 = x, this._y5 = y; break; |
|
default: point$2(this, x, y); break; |
|
} |
|
|
|
this._l01_a = this._l12_a, this._l12_a = this._l23_a; |
|
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var catmullRomClosed = ((function custom(alpha) { |
|
|
|
function catmullRom(context) { |
|
return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); |
|
} |
|
|
|
catmullRom.alpha = function(alpha) { |
|
return custom(+alpha); |
|
}; |
|
|
|
return catmullRom; |
|
}))(0.5); |
|
|
|
function CatmullRomOpen(context, alpha) { |
|
this._context = context; |
|
this._alpha = alpha; |
|
} |
|
|
|
CatmullRomOpen.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = this._x2 = |
|
this._y0 = this._y1 = this._y2 = NaN; |
|
this._l01_a = this._l12_a = this._l23_a = |
|
this._l01_2a = this._l12_2a = this._l23_2a = |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
|
|
if (this._point) { |
|
var x23 = this._x2 - x, |
|
y23 = this._y2 - y; |
|
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); |
|
} |
|
|
|
switch (this._point) { |
|
case 0: this._point = 1; break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; |
|
case 3: this._point = 4; // proceed |
|
default: point$2(this, x, y); break; |
|
} |
|
|
|
this._l01_a = this._l12_a, this._l12_a = this._l23_a; |
|
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; |
|
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; |
|
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; |
|
} |
|
}; |
|
|
|
var catmullRomOpen = ((function custom(alpha) { |
|
|
|
function catmullRom(context) { |
|
return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); |
|
} |
|
|
|
catmullRom.alpha = function(alpha) { |
|
return custom(+alpha); |
|
}; |
|
|
|
return catmullRom; |
|
}))(0.5); |
|
|
|
function LinearClosed(context) { |
|
this._context = context; |
|
} |
|
|
|
LinearClosed.prototype = { |
|
areaStart: noop, |
|
areaEnd: noop, |
|
lineStart: function() { |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (this._point) this._context.closePath(); |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
if (this._point) this._context.lineTo(x, y); |
|
else this._point = 1, this._context.moveTo(x, y); |
|
} |
|
}; |
|
|
|
var linearClosed = function(context) { |
|
return new LinearClosed(context); |
|
}; |
|
|
|
function sign(x) { |
|
return x < 0 ? -1 : 1; |
|
} |
|
|
|
// Calculate the slopes of the tangents (Hermite-type interpolation) based on |
|
// the following paper: Steffen, M. 1990. A Simple Method for Monotonic |
|
// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. |
|
// NOV(II), P. 443, 1990. |
|
function slope3(that, x2, y2) { |
|
var h0 = that._x1 - that._x0, |
|
h1 = x2 - that._x1, |
|
s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), |
|
s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), |
|
p = (s0 * h1 + s1 * h0) / (h0 + h1); |
|
return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; |
|
} |
|
|
|
// Calculate a one-sided slope. |
|
function slope2(that, t) { |
|
var h = that._x1 - that._x0; |
|
return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; |
|
} |
|
|
|
// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations |
|
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves |
|
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". |
|
function point$3(that, t0, t1) { |
|
var x0 = that._x0, |
|
y0 = that._y0, |
|
x1 = that._x1, |
|
y1 = that._y1, |
|
dx = (x1 - x0) / 3; |
|
that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); |
|
} |
|
|
|
function MonotoneX(context) { |
|
this._context = context; |
|
} |
|
|
|
MonotoneX.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x0 = this._x1 = |
|
this._y0 = this._y1 = |
|
this._t0 = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
switch (this._point) { |
|
case 2: this._context.lineTo(this._x1, this._y1); break; |
|
case 3: point$3(this, this._t0, slope2(this, this._t0)); break; |
|
} |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
var t1 = NaN; |
|
|
|
x = +x, y = +y; |
|
if (x === this._x1 && y === this._y1) return; // Ignore coincident points. |
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; break; |
|
case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; |
|
default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; |
|
} |
|
|
|
this._x0 = this._x1, this._x1 = x; |
|
this._y0 = this._y1, this._y1 = y; |
|
this._t0 = t1; |
|
} |
|
}; |
|
|
|
function MonotoneY(context) { |
|
this._context = new ReflectContext(context); |
|
} |
|
|
|
(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { |
|
MonotoneX.prototype.point.call(this, y, x); |
|
}; |
|
|
|
function ReflectContext(context) { |
|
this._context = context; |
|
} |
|
|
|
ReflectContext.prototype = { |
|
moveTo: function(x, y) { this._context.moveTo(y, x); }, |
|
closePath: function() { this._context.closePath(); }, |
|
lineTo: function(x, y) { this._context.lineTo(y, x); }, |
|
bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } |
|
}; |
|
|
|
function monotoneX(context) { |
|
return new MonotoneX(context); |
|
} |
|
|
|
function monotoneY(context) { |
|
return new MonotoneY(context); |
|
} |
|
|
|
function Natural(context) { |
|
this._context = context; |
|
} |
|
|
|
Natural.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x = []; |
|
this._y = []; |
|
}, |
|
lineEnd: function() { |
|
var x = this._x, |
|
y = this._y, |
|
n = x.length; |
|
|
|
if (n) { |
|
this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); |
|
if (n === 2) { |
|
this._context.lineTo(x[1], y[1]); |
|
} else { |
|
var px = controlPoints(x), |
|
py = controlPoints(y); |
|
for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { |
|
this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); |
|
} |
|
} |
|
} |
|
|
|
if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); |
|
this._line = 1 - this._line; |
|
this._x = this._y = null; |
|
}, |
|
point: function(x, y) { |
|
this._x.push(+x); |
|
this._y.push(+y); |
|
} |
|
}; |
|
|
|
// See https://www.particleincell.com/2012/bezier-splines/ for derivation. |
|
function controlPoints(x) { |
|
var i, |
|
n = x.length - 1, |
|
m, |
|
a = new Array(n), |
|
b = new Array(n), |
|
r = new Array(n); |
|
a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; |
|
for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; |
|
a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; |
|
for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; |
|
a[n - 1] = r[n - 1] / b[n - 1]; |
|
for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; |
|
b[n - 1] = (x[n] + a[n - 1]) / 2; |
|
for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; |
|
return [a, b]; |
|
} |
|
|
|
var natural = function(context) { |
|
return new Natural(context); |
|
}; |
|
|
|
function Step(context, t) { |
|
this._context = context; |
|
this._t = t; |
|
} |
|
|
|
Step.prototype = { |
|
areaStart: function() { |
|
this._line = 0; |
|
}, |
|
areaEnd: function() { |
|
this._line = NaN; |
|
}, |
|
lineStart: function() { |
|
this._x = this._y = NaN; |
|
this._point = 0; |
|
}, |
|
lineEnd: function() { |
|
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); |
|
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); |
|
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; |
|
}, |
|
point: function(x, y) { |
|
x = +x, y = +y; |
|
switch (this._point) { |
|
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; |
|
case 1: this._point = 2; // proceed |
|
default: { |
|
if (this._t <= 0) { |
|
this._context.lineTo(this._x, y); |
|
this._context.lineTo(x, y); |
|
} else { |
|
var x1 = this._x * (1 - this._t) + x * this._t; |
|
this._context.lineTo(x1, this._y); |
|
this._context.lineTo(x1, y); |
|
} |
|
break; |
|
} |
|
} |
|
this._x = x, this._y = y; |
|
} |
|
}; |
|
|
|
var step = function(context) { |
|
return new Step(context, 0.5); |
|
}; |
|
|
|
function stepBefore(context) { |
|
return new Step(context, 0); |
|
} |
|
|
|
function stepAfter(context) { |
|
return new Step(context, 1); |
|
} |
|
|
|
var none = function(series, order) { |
|
if (!((n = series.length) > 1)) return; |
|
for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { |
|
s0 = s1, s1 = series[order[i]]; |
|
for (j = 0; j < m; ++j) { |
|
s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; |
|
} |
|
} |
|
}; |
|
|
|
var none$1 = function(series) { |
|
var n = series.length, o = new Array(n); |
|
while (--n >= 0) o[n] = n; |
|
return o; |
|
}; |
|
|
|
function stackValue(d, key) { |
|
return d[key]; |
|
} |
|
|
|
var stack = function() { |
|
var keys = constant([]), |
|
order = none$1, |
|
offset = none, |
|
value = stackValue; |
|
|
|
function stack(data) { |
|
var kz = keys.apply(this, arguments), |
|
i, |
|
m = data.length, |
|
n = kz.length, |
|
sz = new Array(n), |
|
oz; |
|
|
|
for (i = 0; i < n; ++i) { |
|
for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { |
|
si[j] = sij = [0, +value(data[j], ki, j, data)]; |
|
sij.data = data[j]; |
|
} |
|
si.key = ki; |
|
} |
|
|
|
for (i = 0, oz = order(sz); i < n; ++i) { |
|
sz[oz[i]].index = i; |
|
} |
|
|
|
offset(sz, oz); |
|
return sz; |
|
} |
|
|
|
stack.keys = function(_) { |
|
return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys; |
|
}; |
|
|
|
stack.value = function(_) { |
|
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value; |
|
}; |
|
|
|
stack.order = function(_) { |
|
return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order; |
|
}; |
|
|
|
stack.offset = function(_) { |
|
return arguments.length ? (offset = _ == null ? none : _, stack) : offset; |
|
}; |
|
|
|
return stack; |
|
}; |
|
|
|
var expand = function(series, order) { |
|
if (!((n = series.length) > 0)) return; |
|
for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { |
|
for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; |
|
if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; |
|
} |
|
none(series, order); |
|
}; |
|
|
|
var diverging = function(series, order) { |
|
if (!((n = series.length) > 1)) return; |
|
for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { |
|
for (yp = yn = 0, i = 0; i < n; ++i) { |
|
if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { |
|
d[0] = yp, d[1] = yp += dy; |
|
} else if (dy < 0) { |
|
d[1] = yn, d[0] = yn += dy; |
|
} else { |
|
d[0] = yp; |
|
} |
|
} |
|
} |
|
}; |
|
|
|
var silhouette = function(series, order) { |
|
if (!((n = series.length) > 0)) return; |
|
for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { |
|
for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; |
|
s0[j][1] += s0[j][0] = -y / 2; |
|
} |
|
none(series, order); |
|
}; |
|
|
|
var wiggle = function(series, order) { |
|
if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; |
|
for (var y = 0, j = 1, s0, m, n; j < m; ++j) { |
|
for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { |
|
var si = series[order[i]], |
|
sij0 = si[j][1] || 0, |
|
sij1 = si[j - 1][1] || 0, |
|
s3 = (sij0 - sij1) / 2; |
|
for (var k = 0; k < i; ++k) { |
|
var sk = series[order[k]], |
|
skj0 = sk[j][1] || 0, |
|
skj1 = sk[j - 1][1] || 0; |
|
s3 += skj0 - skj1; |
|
} |
|
s1 += sij0, s2 += s3 * sij0; |
|
} |
|
s0[j - 1][1] += s0[j - 1][0] = y; |
|
if (s1) y -= s2 / s1; |
|
} |
|
s0[j - 1][1] += s0[j - 1][0] = y; |
|
none(series, order); |
|
}; |
|
|
|
var ascending = function(series) { |
|
var sums = series.map(sum); |
|
return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); |
|
}; |
|
|
|
function sum(series) { |
|
var s = 0, i = -1, n = series.length, v; |
|
while (++i < n) if (v = +series[i][1]) s += v; |
|
return s; |
|
} |
|
|
|
var descending$1 = function(series) { |
|
return ascending(series).reverse(); |
|
}; |
|
|
|
var insideOut = function(series) { |
|
var n = series.length, |
|
i, |
|
j, |
|
sums = series.map(sum), |
|
order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }), |
|
top = 0, |
|
bottom = 0, |
|
tops = [], |
|
bottoms = []; |
|
|
|
for (i = 0; i < n; ++i) { |
|
j = order[i]; |
|
if (top < bottom) { |
|
top += sums[j]; |
|
tops.push(j); |
|
} else { |
|
bottom += sums[j]; |
|
bottoms.push(j); |
|
} |
|
} |
|
|
|
return bottoms.reverse().concat(tops); |
|
}; |
|
|
|
var reverse = function(series) { |
|
return none$1(series).reverse(); |
|
}; |
|
|
|
exports.arc = arc; |
|
exports.area = area; |
|
exports.line = line; |
|
exports.pie = pie; |
|
exports.areaRadial = areaRadial; |
|
exports.radialArea = areaRadial; |
|
exports.lineRadial = lineRadial$1; |
|
exports.radialLine = lineRadial$1; |
|
exports.pointRadial = pointRadial; |
|
exports.linkHorizontal = linkHorizontal; |
|
exports.linkVertical = linkVertical; |
|
exports.linkRadial = linkRadial; |
|
exports.symbol = symbol; |
|
exports.symbols = symbols; |
|
exports.symbolCircle = circle; |
|
exports.symbolCross = cross; |
|
exports.symbolDiamond = diamond; |
|
exports.symbolSquare = square; |
|
exports.symbolStar = star; |
|
exports.symbolTriangle = triangle; |
|
exports.symbolWye = wye; |
|
exports.curveBasisClosed = basisClosed; |
|
exports.curveBasisOpen = basisOpen; |
|
exports.curveBasis = basis; |
|
exports.curveBundle = bundle; |
|
exports.curveCardinalClosed = cardinalClosed; |
|
exports.curveCardinalOpen = cardinalOpen; |
|
exports.curveCardinal = cardinal; |
|
exports.curveCatmullRomClosed = catmullRomClosed; |
|
exports.curveCatmullRomOpen = catmullRomOpen; |
|
exports.curveCatmullRom = catmullRom; |
|
exports.curveLinearClosed = linearClosed; |
|
exports.curveLinear = curveLinear; |
|
exports.curveMonotoneX = monotoneX; |
|
exports.curveMonotoneY = monotoneY; |
|
exports.curveNatural = natural; |
|
exports.curveStep = step; |
|
exports.curveStepAfter = stepAfter; |
|
exports.curveStepBefore = stepBefore; |
|
exports.stack = stack; |
|
exports.stackOffsetExpand = expand; |
|
exports.stackOffsetDiverging = diverging; |
|
exports.stackOffsetNone = none; |
|
exports.stackOffsetSilhouette = silhouette; |
|
exports.stackOffsetWiggle = wiggle; |
|
exports.stackOrderAscending = ascending; |
|
exports.stackOrderDescending = descending$1; |
|
exports.stackOrderInsideOut = insideOut; |
|
exports.stackOrderNone = none$1; |
|
exports.stackOrderReverse = reverse; |
|
|
|
Object.defineProperty(exports, '__esModule', { value: true }); |
|
|
|
}))); |
|
|
|
},{"d3-path":4}],7:[function(require,module,exports){ |
|
// https://d3js.org Version 4.9.1. Copyright 2017 Mike Bostock. |
|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
|
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
|
(factory((global.d3 = global.d3 || {}))); |
|
}(this, (function (exports) { 'use strict'; |
|
|
|
var version = "4.9.1"; |
|
|
|
var ascending = function(a, b) { |
|
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; |
|
}; |
|
|
|
var bisector = function(compare) { |
|
if (compare.length === 1) compare = ascendingComparator(compare); |
|
return { |
|
left: function(a, x, lo, hi) { |
|
if (lo == null) lo = 0; |
|
if (hi == null) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (compare(a[mid], x) < 0) lo = mid + 1; |
|
else hi = mid; |
|
} |
|
return lo; |
|
}, |
|
right: function(a, x, lo, hi) { |
|
if (lo == null) lo = 0; |
|
if (hi == null) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (compare(a[mid], x) > 0) hi = mid; |
|
else lo = mid + 1; |
|
} |
|
return lo; |
|
} |
|
}; |
|
}; |
|
|
|
function ascendingComparator(f) { |
|
return function(d, x) { |
|
return ascending(f(d), x); |
|
}; |
|
} |
|
|
|
var ascendingBisect = bisector(ascending); |
|
var bisectRight = ascendingBisect.right; |
|
var bisectLeft = ascendingBisect.left; |
|
|
|
var pairs = function(array, f) { |
|
if (f == null) f = pair; |
|
var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); |
|
while (i < n) pairs[i] = f(p, p = array[++i]); |
|
return pairs; |
|
}; |
|
|
|
function pair(a, b) { |
|
return [a, b]; |
|
} |
|
|
|
var cross = function(values0, values1, reduce) { |
|
var n0 = values0.length, |
|
n1 = values1.length, |
|
values = new Array(n0 * n1), |
|
i0, |
|
i1, |
|
i, |
|
value0; |
|
|
|
if (reduce == null) reduce = pair; |
|
|
|
for (i0 = i = 0; i0 < n0; ++i0) { |
|
for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { |
|
values[i] = reduce(value0, values1[i1]); |
|
} |
|
} |
|
|
|
return values; |
|
}; |
|
|
|
var descending = function(a, b) { |
|
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; |
|
}; |
|
|
|
var number = function(x) { |
|
return x === null ? NaN : +x; |
|
}; |
|
|
|
var variance = function(values, valueof) { |
|
var n = values.length, |
|
m = 0, |
|
i = -1, |
|
mean = 0, |
|
value, |
|
delta, |
|
sum = 0; |
|
|
|
if (valueof == null) { |
|
while (++i < n) { |
|
if (!isNaN(value = number(values[i]))) { |
|
delta = value - mean; |
|
mean += delta / ++m; |
|
sum += delta * (value - mean); |
|
} |
|
} |
|
} |
|
|
|
else { |
|
while (++i < n) { |
|
if (!isNaN(value = number(valueof(values[i], i, values)))) { |
|