6378 lines
192 KiB
JavaScript
6378 lines
192 KiB
JavaScript
var a;
|
|
if (!Array.prototype.map) Array.prototype.map = function(b, c) {
|
|
for (var d = this.length, f = new Array(d), g = 0; g < d; g++)
|
|
if (g in this) f[g] = b.call(c, this[g], g, this);
|
|
return f
|
|
};
|
|
if (!Array.prototype.filter) Array.prototype.filter = function(b, c) {
|
|
for (var d = this.length, f = [], g = 0; g < d; g++)
|
|
if (g in this) {
|
|
var h = this[g];
|
|
b.call(c, h, g, this) && f.push(h)
|
|
} return f
|
|
};
|
|
if (!Array.prototype.forEach) Array.prototype.forEach = function(b, c) {
|
|
for (var d = this.length >>> 0, f = 0; f < d; f++) f in this && b.call(c, this[f], f, this)
|
|
};
|
|
if (!Array.prototype.reduce) Array.prototype.reduce = function(b, c) {
|
|
var d = this.length;
|
|
if (!d && arguments.length == 1) throw new Error("reduce: empty array, no initial value");
|
|
var f = 0;
|
|
if (arguments.length < 2)
|
|
for (;;) {
|
|
if (f in this) {
|
|
c = this[f++];
|
|
break
|
|
}
|
|
if (++f >= d) throw new Error("reduce: no values, no initial value");
|
|
}
|
|
for (; f < d; f++)
|
|
if (f in this) c = b(c, this[f], f, this);
|
|
return c
|
|
};
|
|
var pv = {};
|
|
pv.version = "3.3.1";
|
|
pv.identity = function(b) {
|
|
return b
|
|
};
|
|
pv.index = function() {
|
|
return this.index
|
|
};
|
|
pv.child = function() {
|
|
return this.childIndex
|
|
};
|
|
pv.parent = function() {
|
|
return this.parent.index
|
|
};
|
|
pv.extend = function(b) {
|
|
function c() {}
|
|
c.prototype = b.prototype || b;
|
|
return new c
|
|
};
|
|
try {
|
|
eval("pv.parse = function(x) x;")
|
|
} catch (e) {
|
|
pv.parse = function(b) {
|
|
for (var c = new RegExp("function\\s*(\\b\\w+)?\\s*\\([^)]*\\)\\s*", "mg"), d, f, g = 0, h = ""; d = c.exec(b);) {
|
|
d = d.index + d[0].length;
|
|
if (b.charAt(d) != "{") {
|
|
h += b.substring(g, d) + "{return ";
|
|
g = d;
|
|
for (var i = 0; i >= 0 && d < b.length; d++) {
|
|
var j = b.charAt(d);
|
|
switch (j) {
|
|
case '"':
|
|
case "'":
|
|
for (; ++d < b.length && (f = b.charAt(d)) != j;) f == "\\" && d++;
|
|
break;
|
|
case "[":
|
|
case "(":
|
|
i++;
|
|
break;
|
|
case "]":
|
|
case ")":
|
|
i--;
|
|
break;
|
|
case ";":
|
|
case ",":
|
|
i == 0 && i--;
|
|
break
|
|
}
|
|
}
|
|
h += pv.parse(b.substring(g, --d)) +
|
|
";}";
|
|
g = d
|
|
}
|
|
c.lastIndex = d
|
|
}
|
|
h += b.substring(g);
|
|
return h
|
|
}
|
|
}
|
|
pv.css = function(b, c) {
|
|
return window.getComputedStyle ? window.getComputedStyle(b, null).getPropertyValue(c) : b.currentStyle[c]
|
|
};
|
|
pv.error = function(b) {
|
|
typeof console == "undefined" ? alert(b) : console.error(b)
|
|
};
|
|
pv.listen = function(b, c, d) {
|
|
d = pv.listener(d);
|
|
return b.addEventListener ? b.addEventListener(c, d, false) : b.attachEvent("on" + c, d)
|
|
};
|
|
pv.listener = function(b) {
|
|
return b.$listener || (b.$listener = function(c) {
|
|
try {
|
|
pv.event = c;
|
|
return b.call(this, c)
|
|
} finally {
|
|
delete pv.event
|
|
}
|
|
})
|
|
};
|
|
pv.ancestor = function(b, c) {
|
|
for (; c;) {
|
|
if (c == b) return true;
|
|
c = c.parentNode
|
|
}
|
|
return false
|
|
};
|
|
pv.id = function() {
|
|
var b = 1;
|
|
return function() {
|
|
return b++
|
|
}
|
|
}();
|
|
pv.functor = function(b) {
|
|
return typeof b == "function" ? b : function() {
|
|
return b
|
|
}
|
|
};
|
|
pv.listen(window, "load", function() {
|
|
for (pv.$ = {
|
|
i: 0,
|
|
x: document.getElementsByTagName("script")
|
|
}; pv.$.i < pv.$.x.length; pv.$.i++) {
|
|
pv.$.s = pv.$.x[pv.$.i];
|
|
if (pv.$.s.type == "text/javascript+protovis") try {
|
|
window.eval(pv.parse(pv.$.s.text))
|
|
} catch (b) {
|
|
pv.error(b)
|
|
}
|
|
}
|
|
delete pv.$
|
|
});
|
|
pv.Format = {};
|
|
pv.Format.re = function(b) {
|
|
return b.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g, "\\$&")
|
|
};
|
|
pv.Format.pad = function(b, c, d) {
|
|
c = c - String(d).length;
|
|
return c < 1 ? d : (new Array(c + 1)).join(b) + d
|
|
};
|
|
pv.Format.date = function(b) {
|
|
function c(f) {
|
|
return b.replace(/%[a-zA-Z0-9]/g, function(g) {
|
|
switch (g) {
|
|
case "%a":
|
|
return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][f.getDay()];
|
|
case "%A":
|
|
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][f.getDay()];
|
|
case "%h":
|
|
case "%b":
|
|
return ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][f.getMonth()];
|
|
case "%B":
|
|
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][f.getMonth()];
|
|
case "%c":
|
|
return f.toLocaleString();
|
|
case "%C":
|
|
return d("0", 2, Math.floor(f.getFullYear() / 100) % 100);
|
|
case "%d":
|
|
return d("0", 2, f.getDate());
|
|
case "%x":
|
|
case "%D":
|
|
return d("0", 2, f.getMonth() + 1) + "/" + d("0", 2, f.getDate()) + "/" + d("0", 2, f.getFullYear() % 100);
|
|
case "%e":
|
|
return d(" ", 2, f.getDate());
|
|
case "%H":
|
|
return d("0", 2, f.getHours());
|
|
case "%I":
|
|
return (g = f.getHours() % 12) ? d("0", 2, g) : 12;
|
|
case "%m":
|
|
return d("0", 2, f.getMonth() + 1);
|
|
case "%M":
|
|
return d("0", 2, f.getMinutes());
|
|
case "%n":
|
|
return "\n";
|
|
case "%p":
|
|
return f.getHours() <
|
|
12 ? "AM" : "PM";
|
|
case "%T":
|
|
case "%X":
|
|
case "%r":
|
|
g = f.getHours() % 12;
|
|
return (g ? d("0", 2, g) : 12) + ":" + d("0", 2, f.getMinutes()) + ":" + d("0", 2, f.getSeconds()) + " " + (f.getHours() < 12 ? "AM" : "PM");
|
|
case "%R":
|
|
return d("0", 2, f.getHours()) + ":" + d("0", 2, f.getMinutes());
|
|
case "%S":
|
|
return d("0", 2, f.getSeconds());
|
|
case "%Q":
|
|
return d("0", 3, f.getMilliseconds());
|
|
case "%t":
|
|
return "\t";
|
|
case "%u":
|
|
return (g = f.getDay()) ? g : 1;
|
|
case "%w":
|
|
return f.getDay();
|
|
case "%y":
|
|
return d("0", 2, f.getFullYear() % 100);
|
|
case "%Y":
|
|
return f.getFullYear();
|
|
case "%%":
|
|
return "%"
|
|
}
|
|
return g
|
|
})
|
|
}
|
|
var d = pv.Format.pad;
|
|
c.format = c;
|
|
c.parse = function(f) {
|
|
var g = 1970,
|
|
h = 0,
|
|
i = 1,
|
|
j = 0,
|
|
k = 0,
|
|
l = 0,
|
|
q = [function() {}],
|
|
n = pv.Format.re(b).replace(/%[a-zA-Z0-9]/g, function(p) {
|
|
switch (p) {
|
|
case "%b":
|
|
q.push(function(m) {
|
|
h = {
|
|
Jan: 0,
|
|
Feb: 1,
|
|
Mar: 2,
|
|
Apr: 3,
|
|
May: 4,
|
|
Jun: 5,
|
|
Jul: 6,
|
|
Aug: 7,
|
|
Sep: 8,
|
|
Oct: 9,
|
|
Nov: 10,
|
|
Dec: 11
|
|
} [m]
|
|
});
|
|
return "([A-Za-z]+)";
|
|
case "%h":
|
|
case "%B":
|
|
q.push(function(m) {
|
|
h = {
|
|
January: 0,
|
|
February: 1,
|
|
March: 2,
|
|
April: 3,
|
|
May: 4,
|
|
June: 5,
|
|
July: 6,
|
|
August: 7,
|
|
September: 8,
|
|
October: 9,
|
|
November: 10,
|
|
December: 11
|
|
} [m]
|
|
});
|
|
return "([A-Za-z]+)";
|
|
case "%e":
|
|
case "%d":
|
|
q.push(function(m) {
|
|
i =
|
|
m
|
|
});
|
|
return "([0-9]+)";
|
|
case "%I":
|
|
case "%H":
|
|
q.push(function(m) {
|
|
j = m
|
|
});
|
|
return "([0-9]+)";
|
|
case "%m":
|
|
q.push(function(m) {
|
|
h = m - 1
|
|
});
|
|
return "([0-9]+)";
|
|
case "%M":
|
|
q.push(function(m) {
|
|
k = m
|
|
});
|
|
return "([0-9]+)";
|
|
case "%p":
|
|
q.push(function(m) {
|
|
if (j == 12) {
|
|
if (m == "am") j = 0
|
|
} else if (m == "pm") j = Number(j) + 12
|
|
});
|
|
return "(am|pm)";
|
|
case "%S":
|
|
q.push(function(m) {
|
|
l = m
|
|
});
|
|
return "([0-9]+)";
|
|
case "%y":
|
|
q.push(function(m) {
|
|
m = Number(m);
|
|
g = m + (0 <= m && m < 69 ? 2E3 : m >= 69 && m < 100 ? 1900 : 0)
|
|
});
|
|
return "([0-9]+)";
|
|
case "%Y":
|
|
q.push(function(m) {
|
|
g = m
|
|
});
|
|
return "([0-9]+)";
|
|
case "%%":
|
|
q.push(function() {});
|
|
return "%"
|
|
}
|
|
return p
|
|
});
|
|
(f = f.match(n)) && f.forEach(function(p, m) {
|
|
q[m](p)
|
|
});
|
|
return new Date(g, h, i, j, k, l)
|
|
};
|
|
return c
|
|
};
|
|
pv.Format.time = function(b) {
|
|
function c(f) {
|
|
f = Number(f);
|
|
switch (b) {
|
|
case "short":
|
|
if (f >= 31536E6) return (f / 31536E6).toFixed(1) + " years";
|
|
else if (f >= 6048E5) return (f / 6048E5).toFixed(1) + " weeks";
|
|
else if (f >= 864E5) return (f / 864E5).toFixed(1) + " days";
|
|
else if (f >= 36E5) return (f / 36E5).toFixed(1) + " hours";
|
|
else if (f >= 6E4) return (f / 6E4).toFixed(1) + " minutes";
|
|
return (f / 1E3).toFixed(1) + " seconds";
|
|
case "long":
|
|
var g = [],
|
|
h = f % 36E5 / 6E4 >> 0;
|
|
g.push(d("0", 2, f % 6E4 / 1E3 >> 0));
|
|
if (f >= 36E5) {
|
|
var i = f % 864E5 / 36E5 >> 0;
|
|
g.push(d("0", 2, h));
|
|
if (f >= 864E5) {
|
|
g.push(d("0",
|
|
2, i));
|
|
g.push(Math.floor(f / 864E5).toFixed())
|
|
} else g.push(i.toFixed())
|
|
} else g.push(h.toFixed());
|
|
return g.reverse().join(":")
|
|
}
|
|
}
|
|
var d = pv.Format.pad;
|
|
c.format = c;
|
|
c.parse = function(f) {
|
|
switch (b) {
|
|
case "short":
|
|
for (var g = /([0-9,.]+)\s*([a-z]+)/g, h, i = 0; h = g.exec(f);) {
|
|
var j = parseFloat(h[0].replace(",", "")),
|
|
k = 0;
|
|
switch (h[2].toLowerCase()) {
|
|
case "year":
|
|
case "years":
|
|
k = 31536E6;
|
|
break;
|
|
case "week":
|
|
case "weeks":
|
|
k = 6048E5;
|
|
break;
|
|
case "day":
|
|
case "days":
|
|
k = 864E5;
|
|
break;
|
|
case "hour":
|
|
case "hours":
|
|
k = 36E5;
|
|
break;
|
|
case "minute":
|
|
case "minutes":
|
|
k =
|
|
6E4;
|
|
break;
|
|
case "second":
|
|
case "seconds":
|
|
k = 1E3;
|
|
break
|
|
}
|
|
i += j * k
|
|
}
|
|
return i;
|
|
case "long":
|
|
h = f.replace(",", "").split(":").reverse();
|
|
i = 0;
|
|
if (h.length) i += parseFloat(h[0]) * 1E3;
|
|
if (h.length > 1) i += parseFloat(h[1]) * 6E4;
|
|
if (h.length > 2) i += parseFloat(h[2]) * 36E5;
|
|
if (h.length > 3) i += parseFloat(h[3]) * 864E5;
|
|
return i
|
|
}
|
|
};
|
|
return c
|
|
};
|
|
pv.Format.number = function() {
|
|
function b(r) {
|
|
if (Infinity > h) r = Math.round(r * i) / i;
|
|
var s = String(Math.abs(r)).split("."),
|
|
t = s[0];
|
|
if (t.length > d) t = t.substring(t.length - d);
|
|
if (l && t.length < c) t = (new Array(c - t.length + 1)).join(j) + t;
|
|
if (t.length > 3) t = t.replace(/\B(?=(?:\d{3})+(?!\d))/g, n);
|
|
if (!l && t.length < f) t = (new Array(f - t.length + 1)).join(j) + t;
|
|
s[0] = r < 0 ? p + t + m : t;
|
|
r = s[1] || "";
|
|
if (r.length < g) s[1] = r + (new Array(g - r.length + 1)).join(k);
|
|
return s.join(q)
|
|
}
|
|
var c = 0,
|
|
d = Infinity,
|
|
f = 0,
|
|
g = 0,
|
|
h = 0,
|
|
i = 1,
|
|
j = "0",
|
|
k = "0",
|
|
l = true,
|
|
q = ".",
|
|
n = ",",
|
|
p = "\u2212",
|
|
m = "";
|
|
b.format = b;
|
|
b.parse = function(r) {
|
|
var s = pv.Format.re;
|
|
r = String(r).replace(new RegExp("^(" + s(j) + ")*"), "").replace(new RegExp("(" + s(k) + ")*$"), "").split(q);
|
|
s = r[0].replace(new RegExp(s(n), "g"), "");
|
|
if (s.length > d) s = s.substring(s.length - d);
|
|
r = r[1] ? Number("0." + r[1]) : 0;
|
|
if (Infinity > h) r = Math.round(r * i) / i;
|
|
return Math.round(s) + r
|
|
};
|
|
b.integerDigits = function(r, s) {
|
|
if (arguments.length) {
|
|
c = Number(r);
|
|
d = arguments.length > 1 ? Number(s) : c;
|
|
f = c + Math.floor(c / 3) * n.length;
|
|
return this
|
|
}
|
|
return [c, d]
|
|
};
|
|
b.fractionDigits = function(r, s) {
|
|
if (arguments.length) {
|
|
g =
|
|
Number(r);
|
|
h = arguments.length > 1 ? Number(s) : g;
|
|
i = Math.pow(10, h);
|
|
return this
|
|
}
|
|
return [g, h]
|
|
};
|
|
b.integerPad = function(r) {
|
|
if (arguments.length) {
|
|
j = String(r);
|
|
l = /\d/.test(j);
|
|
return this
|
|
}
|
|
return j
|
|
};
|
|
b.fractionPad = function(r) {
|
|
if (arguments.length) {
|
|
k = String(r);
|
|
return this
|
|
}
|
|
return k
|
|
};
|
|
b.decimal = function(r) {
|
|
if (arguments.length) {
|
|
q = String(r);
|
|
return this
|
|
}
|
|
return q
|
|
};
|
|
b.group = function(r) {
|
|
if (arguments.length) {
|
|
n = r ? String(r) : "";
|
|
f = c + Math.floor(c / 3) * n.length;
|
|
return this
|
|
}
|
|
return n
|
|
};
|
|
b.negativeAffix = function(r, s) {
|
|
if (arguments.length) {
|
|
p = String(r ||
|
|
"");
|
|
m = String(s || "");
|
|
return this
|
|
}
|
|
return [p, m]
|
|
};
|
|
return b
|
|
};
|
|
pv.map = function(b, c) {
|
|
var d = {};
|
|
return c ? b.map(function(f, g) {
|
|
d.index = g;
|
|
return c.call(d, f)
|
|
}) : b.slice()
|
|
};
|
|
pv.repeat = function(b, c) {
|
|
if (arguments.length == 1) c = 2;
|
|
return pv.blend(pv.range(c).map(function() {
|
|
return b
|
|
}))
|
|
};
|
|
pv.cross = function(b, c) {
|
|
for (var d = [], f = 0, g = b.length, h = c.length; f < g; f++)
|
|
for (var i = 0, j = b[f]; i < h; i++) d.push([j, c[i]]);
|
|
return d
|
|
};
|
|
pv.blend = function(b) {
|
|
return Array.prototype.concat.apply([], b)
|
|
};
|
|
pv.transpose = function(b) {
|
|
var c = b.length,
|
|
d = pv.max(b, function(i) {
|
|
return i.length
|
|
});
|
|
if (d > c) {
|
|
b.length = d;
|
|
for (var f = c; f < d; f++) b[f] = new Array(c);
|
|
for (f = 0; f < c; f++)
|
|
for (var g = f + 1; g < d; g++) {
|
|
var h = b[f][g];
|
|
b[f][g] = b[g][f];
|
|
b[g][f] = h
|
|
}
|
|
} else {
|
|
for (f = 0; f < d; f++) b[f].length = c;
|
|
for (f = 0; f < c; f++)
|
|
for (g = 0; g < f; g++) {
|
|
h = b[f][g];
|
|
b[f][g] = b[g][f];
|
|
b[g][f] = h
|
|
}
|
|
}
|
|
b.length = d;
|
|
for (f = 0; f < d; f++) b[f].length = c;
|
|
return b
|
|
};
|
|
pv.normalize = function(b, c) {
|
|
b = pv.map(b, c);
|
|
c = pv.sum(b);
|
|
for (var d = 0; d < b.length; d++) b[d] /= c;
|
|
return b
|
|
};
|
|
pv.permute = function(b, c, d) {
|
|
if (!d) d = pv.identity;
|
|
var f = new Array(c.length),
|
|
g = {};
|
|
c.forEach(function(h, i) {
|
|
g.index = h;
|
|
f[i] = d.call(g, b[h])
|
|
});
|
|
return f
|
|
};
|
|
pv.numerate = function(b, c) {
|
|
if (!c) c = pv.identity;
|
|
var d = {},
|
|
f = {};
|
|
b.forEach(function(g, h) {
|
|
f.index = h;
|
|
d[c.call(f, g)] = h
|
|
});
|
|
return d
|
|
};
|
|
pv.uniq = function(b, c) {
|
|
if (!c) c = pv.identity;
|
|
var d = {},
|
|
f = [],
|
|
g = {},
|
|
h;
|
|
b.forEach(function(i, j) {
|
|
g.index = j;
|
|
h = c.call(g, i);
|
|
h in d || (d[h] = f.push(h))
|
|
});
|
|
return f
|
|
};
|
|
pv.naturalOrder = function(b, c) {
|
|
return b < c ? -1 : b > c ? 1 : 0
|
|
};
|
|
pv.reverseOrder = function(b, c) {
|
|
return c < b ? -1 : c > b ? 1 : 0
|
|
};
|
|
pv.search = function(b, c, d) {
|
|
if (!d) d = pv.identity;
|
|
for (var f = 0, g = b.length - 1; f <= g;) {
|
|
var h = f + g >> 1,
|
|
i = d(b[h]);
|
|
if (i < c) f = h + 1;
|
|
else if (i > c) g = h - 1;
|
|
else return h
|
|
}
|
|
return -f - 1
|
|
};
|
|
pv.search.index = function(b, c, d) {
|
|
b = pv.search(b, c, d);
|
|
return b < 0 ? -b - 1 : b
|
|
};
|
|
pv.range = function(b, c, d) {
|
|
if (arguments.length == 1) {
|
|
c = b;
|
|
b = 0
|
|
}
|
|
if (d == undefined) d = 1;
|
|
if ((c - b) / d == Infinity) throw new Error("range must be finite");
|
|
var f = [],
|
|
g = 0,
|
|
h;
|
|
c -= (c - b) * 1.0E-10;
|
|
if (d < 0)
|
|
for (;
|
|
(h = b + d * g++) > c;) f.push(h);
|
|
else
|
|
for (;
|
|
(h = b + d * g++) < c;) f.push(h);
|
|
return f
|
|
};
|
|
pv.random = function(b, c, d) {
|
|
if (arguments.length == 1) {
|
|
c = b;
|
|
b = 0
|
|
}
|
|
if (d == undefined) d = 1;
|
|
return d ? Math.floor(Math.random() * (c - b) / d) * d + b : Math.random() * (c - b) + b
|
|
};
|
|
pv.sum = function(b, c) {
|
|
var d = {};
|
|
return b.reduce(c ? function(f, g, h) {
|
|
d.index = h;
|
|
return f + c.call(d, g)
|
|
} : function(f, g) {
|
|
return f + g
|
|
}, 0)
|
|
};
|
|
pv.max = function(b, c) {
|
|
if (c == pv.index) return b.length - 1;
|
|
return Math.max.apply(null, c ? pv.map(b, c) : b)
|
|
};
|
|
pv.max.index = function(b, c) {
|
|
if (!b.length) return -1;
|
|
if (c == pv.index) return b.length - 1;
|
|
if (!c) c = pv.identity;
|
|
for (var d = 0, f = -Infinity, g = {}, h = 0; h < b.length; h++) {
|
|
g.index = h;
|
|
var i = c.call(g, b[h]);
|
|
if (i > f) {
|
|
f = i;
|
|
d = h
|
|
}
|
|
}
|
|
return d
|
|
};
|
|
pv.min = function(b, c) {
|
|
if (c == pv.index) return 0;
|
|
return Math.min.apply(null, c ? pv.map(b, c) : b)
|
|
};
|
|
pv.min.index = function(b, c) {
|
|
if (!b.length) return -1;
|
|
if (c == pv.index) return 0;
|
|
if (!c) c = pv.identity;
|
|
for (var d = 0, f = Infinity, g = {}, h = 0; h < b.length; h++) {
|
|
g.index = h;
|
|
var i = c.call(g, b[h]);
|
|
if (i < f) {
|
|
f = i;
|
|
d = h
|
|
}
|
|
}
|
|
return d
|
|
};
|
|
pv.mean = function(b, c) {
|
|
return pv.sum(b, c) / b.length
|
|
};
|
|
pv.median = function(b, c) {
|
|
if (c == pv.index) return (b.length - 1) / 2;
|
|
b = pv.map(b, c).sort(pv.naturalOrder);
|
|
if (b.length % 2) return b[Math.floor(b.length / 2)];
|
|
c = b.length / 2;
|
|
return (b[c - 1] + b[c]) / 2
|
|
};
|
|
pv.variance = function(b, c) {
|
|
if (b.length < 1) return NaN;
|
|
if (b.length == 1) return 0;
|
|
var d = pv.mean(b, c),
|
|
f = 0,
|
|
g = {};
|
|
if (!c) c = pv.identity;
|
|
for (var h = 0; h < b.length; h++) {
|
|
g.index = h;
|
|
var i = c.call(g, b[h]) - d;
|
|
f += i * i
|
|
}
|
|
return f
|
|
};
|
|
pv.deviation = function(b, c) {
|
|
return Math.sqrt(pv.variance(b, c) / (b.length - 1))
|
|
};
|
|
pv.log = function(b, c) {
|
|
return Math.log(b) / Math.log(c)
|
|
};
|
|
pv.logSymmetric = function(b, c) {
|
|
return b == 0 ? 0 : b < 0 ? -pv.log(-b, c) : pv.log(b, c)
|
|
};
|
|
pv.logAdjusted = function(b, c) {
|
|
if (!isFinite(b)) return b;
|
|
var d = b < 0;
|
|
if (b < c) b += (c - b) / c;
|
|
return d ? -pv.log(b, c) : pv.log(b, c)
|
|
};
|
|
pv.logFloor = function(b, c) {
|
|
return b > 0 ? Math.pow(c, Math.floor(pv.log(b, c))) : -Math.pow(c, -Math.floor(-pv.log(-b, c)))
|
|
};
|
|
pv.logCeil = function(b, c) {
|
|
return b > 0 ? Math.pow(c, Math.ceil(pv.log(b, c))) : -Math.pow(c, -Math.ceil(-pv.log(-b, c)))
|
|
};
|
|
(function() {
|
|
var b = Math.PI / 180,
|
|
c = 180 / Math.PI;
|
|
pv.radians = function(d) {
|
|
return b * d
|
|
};
|
|
pv.degrees = function(d) {
|
|
return c * d
|
|
}
|
|
})();
|
|
pv.keys = function(b) {
|
|
var c = [];
|
|
for (var d in b) c.push(d);
|
|
return c
|
|
};
|
|
pv.entries = function(b) {
|
|
var c = [];
|
|
for (var d in b) c.push({
|
|
key: d,
|
|
value: b[d]
|
|
});
|
|
return c
|
|
};
|
|
pv.values = function(b) {
|
|
var c = [];
|
|
for (var d in b) c.push(b[d]);
|
|
return c
|
|
};
|
|
pv.dict = function(b, c) {
|
|
for (var d = {}, f = {}, g = 0; g < b.length; g++)
|
|
if (g in b) {
|
|
var h = b[g];
|
|
f.index = g;
|
|
d[h] = c.call(f, h)
|
|
} return d
|
|
};
|
|
pv.dom = function(b) {
|
|
return new pv.Dom(b)
|
|
};
|
|
pv.Dom = function(b) {
|
|
this.$map = b
|
|
};
|
|
pv.Dom.prototype.$leaf = function(b) {
|
|
return typeof b != "object"
|
|
};
|
|
pv.Dom.prototype.leaf = function(b) {
|
|
if (arguments.length) {
|
|
this.$leaf = b;
|
|
return this
|
|
}
|
|
return this.$leaf
|
|
};
|
|
pv.Dom.prototype.root = function(b) {
|
|
function c(g) {
|
|
var h = new pv.Dom.Node;
|
|
for (var i in g) {
|
|
var j = g[i];
|
|
h.appendChild(d(j) ? new pv.Dom.Node(j) : c(j)).nodeName = i
|
|
}
|
|
return h
|
|
}
|
|
var d = this.$leaf,
|
|
f = c(this.$map);
|
|
f.nodeName = b;
|
|
return f
|
|
};
|
|
pv.Dom.prototype.nodes = function() {
|
|
return this.root().nodes()
|
|
};
|
|
pv.Dom.Node = function(b) {
|
|
this.nodeValue = b;
|
|
this.childNodes = []
|
|
};
|
|
a = pv.Dom.Node.prototype;
|
|
a.parentNode = null;
|
|
a.firstChild = null;
|
|
a.lastChild = null;
|
|
a.previousSibling = null;
|
|
a.nextSibling = null;
|
|
a.removeChild = function(b) {
|
|
var c = this.childNodes.indexOf(b);
|
|
if (c == -1) throw new Error("child not found");
|
|
this.childNodes.splice(c, 1);
|
|
if (b.previousSibling) b.previousSibling.nextSibling = b.nextSibling;
|
|
else this.firstChild = b.nextSibling;
|
|
if (b.nextSibling) b.nextSibling.previousSibling = b.previousSibling;
|
|
else this.lastChild = b.previousSibling;
|
|
delete b.nextSibling;
|
|
delete b.previousSibling;
|
|
delete b.parentNode;
|
|
return b
|
|
};
|
|
a.appendChild = function(b) {
|
|
b.parentNode && b.parentNode.removeChild(b);
|
|
b.parentNode = this;
|
|
if (b.previousSibling = this.lastChild) this.lastChild.nextSibling = b;
|
|
else this.firstChild = b;
|
|
this.lastChild = b;
|
|
this.childNodes.push(b);
|
|
return b
|
|
};
|
|
a.insertBefore = function(b, c) {
|
|
if (!c) return this.appendChild(b);
|
|
var d = this.childNodes.indexOf(c);
|
|
if (d == -1) throw new Error("child not found");
|
|
b.parentNode && b.parentNode.removeChild(b);
|
|
b.parentNode = this;
|
|
b.nextSibling = c;
|
|
if (b.previousSibling = c.previousSibling) c.previousSibling.nextSibling = b;
|
|
else {
|
|
if (c == this.lastChild) this.lastChild = b;
|
|
this.firstChild = b
|
|
}
|
|
this.childNodes.splice(d, 0, b);
|
|
return b
|
|
};
|
|
a.replaceChild = function(b, c) {
|
|
var d = this.childNodes.indexOf(c);
|
|
if (d == -1) throw new Error("child not found");
|
|
b.parentNode && b.parentNode.removeChild(b);
|
|
b.parentNode = this;
|
|
b.nextSibling = c.nextSibling;
|
|
if (b.previousSibling = c.previousSibling) c.previousSibling.nextSibling = b;
|
|
else this.firstChild = b;
|
|
if (c.nextSibling) c.nextSibling.previousSibling = b;
|
|
else this.lastChild = b;
|
|
this.childNodes[d] = b;
|
|
return c
|
|
};
|
|
a.visitBefore = function(b) {
|
|
function c(d, f) {
|
|
b(d, f);
|
|
for (d = d.firstChild; d; d = d.nextSibling) c(d, f + 1)
|
|
}
|
|
c(this, 0)
|
|
};
|
|
a.visitAfter = function(b) {
|
|
function c(d, f) {
|
|
for (var g = d.firstChild; g; g = g.nextSibling) c(g, f + 1);
|
|
b(d, f)
|
|
}
|
|
c(this, 0)
|
|
};
|
|
a.sort = function(b) {
|
|
if (this.firstChild) {
|
|
this.childNodes.sort(b);
|
|
var c = this.firstChild = this.childNodes[0],
|
|
d;
|
|
delete c.previousSibling;
|
|
for (var f = 1; f < this.childNodes.length; f++) {
|
|
c.sort(b);
|
|
d = this.childNodes[f];
|
|
d.previousSibling = c;
|
|
c = c.nextSibling = d
|
|
}
|
|
this.lastChild = c;
|
|
delete c.nextSibling;
|
|
c.sort(b)
|
|
}
|
|
return this
|
|
};
|
|
a.reverse = function() {
|
|
var b = [];
|
|
this.visitAfter(function(c) {
|
|
for (; c.lastChild;) b.push(c.removeChild(c.lastChild));
|
|
for (var d; d = b.pop();) c.insertBefore(d, c.firstChild)
|
|
});
|
|
return this
|
|
};
|
|
a.nodes = function() {
|
|
function b(d) {
|
|
c.push(d);
|
|
d.childNodes.forEach(b)
|
|
}
|
|
var c = [];
|
|
b(this, c);
|
|
return c
|
|
};
|
|
a.toggle = function(b) {
|
|
if (b) return this.toggled ? this.visitBefore(function(d) {
|
|
d.toggled && d.toggle()
|
|
}) : this.visitAfter(function(d) {
|
|
d.toggled || d.toggle()
|
|
});
|
|
b = this;
|
|
if (b.toggled) {
|
|
for (var c; c = b.toggled.pop();) b.appendChild(c);
|
|
delete b.toggled
|
|
} else if (b.lastChild)
|
|
for (b.toggled = []; b.lastChild;) b.toggled.push(b.removeChild(b.lastChild))
|
|
};
|
|
pv.nodes = function(b) {
|
|
for (var c = new pv.Dom.Node, d = 0; d < b.length; d++) c.appendChild(new pv.Dom.Node(b[d]));
|
|
return c.nodes()
|
|
};
|
|
pv.tree = function(b) {
|
|
return new pv.Tree(b)
|
|
};
|
|
pv.Tree = function(b) {
|
|
this.array = b
|
|
};
|
|
pv.Tree.prototype.keys = function(b) {
|
|
this.k = b;
|
|
return this
|
|
};
|
|
pv.Tree.prototype.value = function(b) {
|
|
this.v = b;
|
|
return this
|
|
};
|
|
pv.Tree.prototype.map = function() {
|
|
for (var b = {}, c = {}, d = 0; d < this.array.length; d++) {
|
|
c.index = d;
|
|
for (var f = this.array[d], g = this.k.call(c, f), h = b, i = 0; i < g.length - 1; i++) h = h[g[i]] || (h[g[i]] = {});
|
|
h[g[i]] = this.v ? this.v.call(c, f) : f
|
|
}
|
|
return b
|
|
};
|
|
pv.nest = function(b) {
|
|
return new pv.Nest(b)
|
|
};
|
|
pv.Nest = function(b) {
|
|
this.array = b;
|
|
this.keys = []
|
|
};
|
|
a = pv.Nest.prototype;
|
|
a.key = function(b) {
|
|
this.keys.push(b);
|
|
return this
|
|
};
|
|
a.sortKeys = function(b) {
|
|
this.keys[this.keys.length - 1].order = b || pv.naturalOrder;
|
|
return this
|
|
};
|
|
a.sortValues = function(b) {
|
|
this.order = b || pv.naturalOrder;
|
|
return this
|
|
};
|
|
a.map = function() {
|
|
for (var b = {}, c = [], d, f = 0; f < this.array.length; f++) {
|
|
var g = this.array[f],
|
|
h = b;
|
|
for (d = 0; d < this.keys.length - 1; d++) {
|
|
var i = this.keys[d](g);
|
|
h[i] || (h[i] = {});
|
|
h = h[i]
|
|
}
|
|
i = this.keys[d](g);
|
|
if (!h[i]) {
|
|
d = [];
|
|
c.push(d);
|
|
h[i] = d
|
|
}
|
|
h[i].push(g)
|
|
}
|
|
if (this.order)
|
|
for (d = 0; d < c.length; d++) c[d].sort(this.order);
|
|
return b
|
|
};
|
|
a.entries = function() {
|
|
function b(d) {
|
|
var f = [];
|
|
for (var g in d) {
|
|
var h = d[g];
|
|
f.push({
|
|
key: g,
|
|
values: h instanceof Array ? h : b(h)
|
|
})
|
|
}
|
|
return f
|
|
}
|
|
|
|
function c(d, f) {
|
|
var g = this.keys[f].order;
|
|
g && d.sort(function(i, j) {
|
|
return g(i.key, j.key)
|
|
});
|
|
if (++f < this.keys.length)
|
|
for (var h = 0; h < d.length; h++) c.call(this, d[h].values, f);
|
|
return d
|
|
}
|
|
return c.call(this, b(this.map()), 0)
|
|
};
|
|
a.rollup = function(b) {
|
|
function c(d) {
|
|
for (var f in d) {
|
|
var g = d[f];
|
|
if (g instanceof Array) d[f] = b(g);
|
|
else c(g)
|
|
}
|
|
return d
|
|
}
|
|
return c(this.map())
|
|
};
|
|
pv.flatten = function(b) {
|
|
return new pv.Flatten(b)
|
|
};
|
|
pv.Flatten = function(b) {
|
|
this.map = b;
|
|
this.keys = []
|
|
};
|
|
pv.Flatten.prototype.key = function(b, c) {
|
|
this.keys.push({
|
|
name: b,
|
|
value: c
|
|
});
|
|
delete this.$leaf;
|
|
return this
|
|
};
|
|
pv.Flatten.prototype.leaf = function(b) {
|
|
this.keys.length = 0;
|
|
this.$leaf = b;
|
|
return this
|
|
};
|
|
pv.Flatten.prototype.array = function() {
|
|
function b(i, j) {
|
|
if (j < f.length - 1)
|
|
for (var k in i) {
|
|
d.push(k);
|
|
b(i[k], j + 1);
|
|
d.pop()
|
|
} else c.push(d.concat(i))
|
|
}
|
|
var c = [],
|
|
d = [],
|
|
f = this.keys,
|
|
g = this.$leaf;
|
|
if (g) {
|
|
function h(i, j) {
|
|
if (g(i)) c.push({
|
|
keys: d.slice(),
|
|
value: i
|
|
});
|
|
else
|
|
for (var k in i) {
|
|
d.push(k);
|
|
h(i[k], j + 1);
|
|
d.pop()
|
|
}
|
|
}
|
|
h(this.map, 0);
|
|
return c
|
|
}
|
|
b(this.map, 0);
|
|
return c.map(function(i) {
|
|
for (var j = {}, k = 0; k < f.length; k++) {
|
|
var l = f[k],
|
|
q = i[k];
|
|
j[l.name] = l.value ? l.value.call(null, q) : q
|
|
}
|
|
return j
|
|
})
|
|
};
|
|
pv.vector = function(b, c) {
|
|
return new pv.Vector(b, c)
|
|
};
|
|
pv.Vector = function(b, c) {
|
|
this.x = b;
|
|
this.y = c
|
|
};
|
|
a = pv.Vector.prototype;
|
|
a.perp = function() {
|
|
return new pv.Vector(-this.y, this.x)
|
|
};
|
|
a.norm = function() {
|
|
var b = this.length();
|
|
return this.times(b ? 1 / b : 1)
|
|
};
|
|
a.length = function() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y)
|
|
};
|
|
a.times = function(b) {
|
|
return new pv.Vector(this.x * b, this.y * b)
|
|
};
|
|
a.plus = function(b, c) {
|
|
return arguments.length == 1 ? new pv.Vector(this.x + b.x, this.y + b.y) : new pv.Vector(this.x + b, this.y + c)
|
|
};
|
|
a.minus = function(b, c) {
|
|
return arguments.length == 1 ? new pv.Vector(this.x - b.x, this.y - b.y) : new pv.Vector(this.x - b, this.y - c)
|
|
};
|
|
a.dot = function(b, c) {
|
|
return arguments.length == 1 ? this.x * b.x + this.y * b.y : this.x * b + this.y * c
|
|
};
|
|
pv.Transform = function() {};
|
|
pv.Transform.prototype = {
|
|
k: 1,
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
pv.Transform.identity = new pv.Transform;
|
|
pv.Transform.prototype.translate = function(b, c) {
|
|
var d = new pv.Transform;
|
|
d.k = this.k;
|
|
d.x = this.k * b + this.x;
|
|
d.y = this.k * c + this.y;
|
|
return d
|
|
};
|
|
pv.Transform.prototype.scale = function(b) {
|
|
var c = new pv.Transform;
|
|
c.k = this.k * b;
|
|
c.x = this.x;
|
|
c.y = this.y;
|
|
return c
|
|
};
|
|
pv.Transform.prototype.invert = function() {
|
|
var b = new pv.Transform,
|
|
c = 1 / this.k;
|
|
b.k = c;
|
|
b.x = -this.x * c;
|
|
b.y = -this.y * c;
|
|
return b
|
|
};
|
|
pv.Transform.prototype.times = function(b) {
|
|
var c = new pv.Transform;
|
|
c.k = this.k * b.k;
|
|
c.x = this.k * b.x + this.x;
|
|
c.y = this.k * b.y + this.y;
|
|
return c
|
|
};
|
|
pv.Scale = function() {};
|
|
pv.Scale.interpolator = function(b, c) {
|
|
if (typeof b == "number") return function(d) {
|
|
return d * (c - b) + b
|
|
};
|
|
b = pv.color(b).rgb();
|
|
c = pv.color(c).rgb();
|
|
return function(d) {
|
|
var f = b.a * (1 - d) + c.a * d;
|
|
if (f < 1.0E-5) f = 0;
|
|
return b.a == 0 ? pv.rgb(c.r, c.g, c.b, f) : c.a == 0 ? pv.rgb(b.r, b.g, b.b, f) : pv.rgb(Math.round(b.r * (1 - d) + c.r * d), Math.round(b.g * (1 - d) + c.g * d), Math.round(b.b * (1 - d) + c.b * d), f)
|
|
}
|
|
};
|
|
pv.Scale.quantitative = function() {
|
|
function b(n) {
|
|
return new Date(n)
|
|
}
|
|
|
|
function c(n) {
|
|
var p = pv.search(d, n);
|
|
if (p < 0) p = -p - 2;
|
|
p = Math.max(0, Math.min(h.length - 1, p));
|
|
return h[p]((k(n) - f[p]) / (f[p + 1] - f[p]))
|
|
}
|
|
var d = [0, 1],
|
|
f = [0, 1],
|
|
g = [0, 1],
|
|
h = [pv.identity],
|
|
i = Number,
|
|
j = false,
|
|
k = pv.identity,
|
|
l = pv.identity,
|
|
q = String;
|
|
c.transform = function(n, p) {
|
|
k = function(m) {
|
|
return j ? -n(-m) : n(m)
|
|
};
|
|
l = function(m) {
|
|
return j ? -p(-m) : p(m)
|
|
};
|
|
f = d.map(k);
|
|
return this
|
|
};
|
|
c.domain = function(n, p, m) {
|
|
if (arguments.length) {
|
|
var r;
|
|
if (n instanceof Array) {
|
|
if (arguments.length <
|
|
2) p = pv.identity;
|
|
if (arguments.length < 3) m = p;
|
|
r = n.length && p(n[0]);
|
|
d = n.length ? [pv.min(n, p), pv.max(n, m)] : []
|
|
} else {
|
|
r = n;
|
|
d = Array.prototype.slice.call(arguments).map(Number)
|
|
}
|
|
if (d.length) {
|
|
if (d.length == 1) d = [d[0], d[0]]
|
|
} else d = [-Infinity, Infinity];
|
|
j = (d[0] || d[d.length - 1]) < 0;
|
|
f = d.map(k);
|
|
i = r instanceof Date ? b : Number;
|
|
return this
|
|
}
|
|
return d.map(i)
|
|
};
|
|
c.range = function() {
|
|
if (arguments.length) {
|
|
g = Array.prototype.slice.call(arguments);
|
|
if (g.length) {
|
|
if (g.length == 1) g = [g[0], g[0]]
|
|
} else g = [-Infinity, Infinity];
|
|
h = [];
|
|
for (var n = 0; n < g.length -
|
|
1; n++) h.push(pv.Scale.interpolator(g[n], g[n + 1]));
|
|
return this
|
|
}
|
|
return g
|
|
};
|
|
c.invert = function(n) {
|
|
var p = pv.search(g, n);
|
|
if (p < 0) p = -p - 2;
|
|
p = Math.max(0, Math.min(h.length - 1, p));
|
|
return i(l(f[p] + (n - g[p]) / (g[p + 1] - g[p]) * (f[p + 1] - f[p])))
|
|
};
|
|
c.ticks = function(n) {
|
|
var p = d[0],
|
|
m = d[d.length - 1],
|
|
r = m < p,
|
|
s = r ? m : p;
|
|
m = r ? p : m;
|
|
var t = m - s;
|
|
if (!t || !isFinite(t)) {
|
|
if (i == b) q = pv.Format.date("%x");
|
|
return [i(s)]
|
|
}
|
|
if (i == b) {
|
|
function x(w, y) {
|
|
switch (y) {
|
|
case 31536E6:
|
|
w.setMonth(0);
|
|
case 2592E6:
|
|
w.setDate(1);
|
|
case 6048E5:
|
|
y == 6048E5 && w.setDate(w.getDate() - w.getDay());
|
|
case 864E5:
|
|
w.setHours(0);
|
|
case 36E5:
|
|
w.setMinutes(0);
|
|
case 6E4:
|
|
w.setSeconds(0);
|
|
case 1E3:
|
|
w.setMilliseconds(0)
|
|
}
|
|
}
|
|
var u, o, v = 1;
|
|
if (t >= 94608E6) {
|
|
p = 31536E6;
|
|
u = "%Y";
|
|
o = function(w) {
|
|
w.setFullYear(w.getFullYear() + v)
|
|
}
|
|
} else if (t >= 7776E6) {
|
|
p = 2592E6;
|
|
u = "%m/%Y";
|
|
o = function(w) {
|
|
w.setMonth(w.getMonth() + v)
|
|
}
|
|
} else if (t >= 18144E5) {
|
|
p = 6048E5;
|
|
u = "%m/%d";
|
|
o = function(w) {
|
|
w.setDate(w.getDate() + 7 * v)
|
|
}
|
|
} else if (t >= 2592E5) {
|
|
p = 864E5;
|
|
u = "%m/%d";
|
|
o = function(w) {
|
|
w.setDate(w.getDate() + v)
|
|
}
|
|
} else if (t >= 108E5) {
|
|
p = 36E5;
|
|
u = "%I:%M %p";
|
|
o = function(w) {
|
|
w.setHours(w.getHours() +
|
|
v)
|
|
}
|
|
} else if (t >= 18E4) {
|
|
p = 6E4;
|
|
u = "%I:%M %p";
|
|
o = function(w) {
|
|
w.setMinutes(w.getMinutes() + v)
|
|
}
|
|
} else if (t >= 3E3) {
|
|
p = 1E3;
|
|
u = "%I:%M:%S";
|
|
o = function(w) {
|
|
w.setSeconds(w.getSeconds() + v)
|
|
}
|
|
} else {
|
|
p = 1;
|
|
u = "%S.%Qs";
|
|
o = function(w) {
|
|
w.setTime(w.getTime() + v)
|
|
}
|
|
}
|
|
q = pv.Format.date(u);
|
|
s = new Date(s);
|
|
u = [];
|
|
x(s, p);
|
|
t = t / p;
|
|
if (t > 10) switch (p) {
|
|
case 36E5:
|
|
v = t > 20 ? 6 : 3;
|
|
s.setHours(Math.floor(s.getHours() / v) * v);
|
|
break;
|
|
case 2592E6:
|
|
v = 3;
|
|
s.setMonth(Math.floor(s.getMonth() / v) * v);
|
|
break;
|
|
case 6E4:
|
|
v = t > 30 ? 15 : t > 15 ? 10 : 5;
|
|
s.setMinutes(Math.floor(s.getMinutes() / v) * v);
|
|
break;
|
|
case 1E3:
|
|
v = t > 90 ? 15 : t > 60 ? 10 : 5;
|
|
s.setSeconds(Math.floor(s.getSeconds() / v) * v);
|
|
break;
|
|
case 1:
|
|
v = t > 1E3 ? 250 : t > 200 ? 100 : t > 100 ? 50 : t > 50 ? 25 : 5;
|
|
s.setMilliseconds(Math.floor(s.getMilliseconds() / v) * v);
|
|
break;
|
|
default:
|
|
v = pv.logCeil(t / 15, 10);
|
|
if (t / v < 2) v /= 5;
|
|
else if (t / v < 5) v /= 2;
|
|
s.setFullYear(Math.floor(s.getFullYear() / v) * v);
|
|
break
|
|
}
|
|
for (;;) {
|
|
o(s);
|
|
if (s > m) break;
|
|
u.push(new Date(s))
|
|
}
|
|
return r ? u.reverse() : u
|
|
}
|
|
arguments.length || (n = 10);
|
|
v = pv.logFloor(t / n, 10);
|
|
p = n / (t / v);
|
|
if (p <= 0.15) v *= 10;
|
|
else if (p <= 0.35) v *= 5;
|
|
else if (p <= 0.75) v *= 2;
|
|
p = Math.ceil(s /
|
|
v) * v;
|
|
m = Math.floor(m / v) * v;
|
|
q = pv.Format.number().fractionDigits(Math.max(0, -Math.floor(pv.log(v, 10) + 0.01)));
|
|
m = pv.range(p, m + v, v);
|
|
return r ? m.reverse() : m
|
|
};
|
|
c.tickFormat = function(n) {
|
|
return q(n)
|
|
};
|
|
c.nice = function() {
|
|
if (d.length != 2) return this;
|
|
var n = d[0],
|
|
p = d[d.length - 1],
|
|
m = p < n,
|
|
r = m ? p : n;
|
|
n = m ? n : p;
|
|
p = n - r;
|
|
if (!p || !isFinite(p)) return this;
|
|
p = Math.pow(10, Math.round(Math.log(p) / Math.log(10)) - 1);
|
|
d = [Math.floor(r / p) * p, Math.ceil(n / p) * p];
|
|
m && d.reverse();
|
|
f = d.map(k);
|
|
return this
|
|
};
|
|
c.by = function(n) {
|
|
function p() {
|
|
return c(n.apply(this,
|
|
arguments))
|
|
}
|
|
for (var m in c) p[m] = c[m];
|
|
return p
|
|
};
|
|
c.domain.apply(c, arguments);
|
|
return c
|
|
};
|
|
pv.Scale.linear = function() {
|
|
var b = pv.Scale.quantitative();
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Scale.log = function() {
|
|
var b = pv.Scale.quantitative(1, 10),
|
|
c, d, f = function(h) {
|
|
return Math.log(h) / d
|
|
},
|
|
g = function(h) {
|
|
return Math.pow(c, h)
|
|
};
|
|
b.ticks = function() {
|
|
var h = b.domain(),
|
|
i = h[0] < 0,
|
|
j = Math.floor(i ? -f(-h[0]) : f(h[0])),
|
|
k = Math.ceil(i ? -f(-h[1]) : f(h[1])),
|
|
l = [];
|
|
if (i)
|
|
for (l.push(-g(-j)); j++ < k;)
|
|
for (i = c - 1; i > 0; i--) l.push(-g(-j) * i);
|
|
else {
|
|
for (; j < k; j++)
|
|
for (i = 1; i < c; i++) l.push(g(j) * i);
|
|
l.push(g(j))
|
|
}
|
|
for (j = 0; l[j] < h[0]; j++);
|
|
for (k = l.length; l[k - 1] > h[1]; k--);
|
|
return l.slice(j, k)
|
|
};
|
|
b.tickFormat = function(h) {
|
|
return h.toPrecision(1)
|
|
};
|
|
b.nice = function() {
|
|
var h = b.domain();
|
|
return b.domain(pv.logFloor(h[0], c), pv.logCeil(h[1], c))
|
|
};
|
|
b.base = function(h) {
|
|
if (arguments.length) {
|
|
c = Number(h);
|
|
d = Math.log(c);
|
|
b.transform(f, g);
|
|
return this
|
|
}
|
|
return c
|
|
};
|
|
b.domain.apply(b, arguments);
|
|
return b.base(10)
|
|
};
|
|
pv.Scale.root = function() {
|
|
var b = pv.Scale.quantitative();
|
|
b.power = function(c) {
|
|
if (arguments.length) {
|
|
var d = Number(c),
|
|
f = 1 / d;
|
|
b.transform(function(g) {
|
|
return Math.pow(g, f)
|
|
}, function(g) {
|
|
return Math.pow(g, d)
|
|
});
|
|
return this
|
|
}
|
|
return d
|
|
};
|
|
b.domain.apply(b, arguments);
|
|
return b.power(2)
|
|
};
|
|
pv.Scale.ordinal = function() {
|
|
function b(g) {
|
|
g in d || (d[g] = c.push(g) - 1);
|
|
return f[d[g] % f.length]
|
|
}
|
|
var c = [],
|
|
d = {},
|
|
f = [];
|
|
b.domain = function(g, h) {
|
|
if (arguments.length) {
|
|
g = g instanceof Array ? arguments.length > 1 ? pv.map(g, h) : g : Array.prototype.slice.call(arguments);
|
|
c = [];
|
|
for (var i = {}, j = 0; j < g.length; j++) {
|
|
var k = g[j];
|
|
if (!(k in i)) {
|
|
i[k] = true;
|
|
c.push(k)
|
|
}
|
|
}
|
|
d = pv.numerate(c);
|
|
return this
|
|
}
|
|
return c
|
|
};
|
|
b.range = function(g, h) {
|
|
if (arguments.length) {
|
|
f = g instanceof Array ? arguments.length > 1 ? pv.map(g, h) : g : Array.prototype.slice.call(arguments);
|
|
if (typeof f[0] == "string") f = f.map(pv.color);
|
|
return this
|
|
}
|
|
return f
|
|
};
|
|
b.split = function(g, h) {
|
|
var i = (h - g) / this.domain().length;
|
|
f = pv.range(g + i / 2, h, i);
|
|
return this
|
|
};
|
|
b.splitFlush = function(g, h) {
|
|
var i = this.domain().length,
|
|
j = (h - g) / (i - 1);
|
|
f = i == 1 ? [(g + h) / 2] : pv.range(g, h + j / 2, j);
|
|
return this
|
|
};
|
|
b.splitBanded = function(g, h, i) {
|
|
if (arguments.length < 3) i = 1;
|
|
if (i < 0) {
|
|
var j = this.domain().length;
|
|
j = (h - g - -i * j) / (j + 1);
|
|
f = pv.range(g + j, h, j - i);
|
|
f.band = -i
|
|
} else {
|
|
j = (h - g) / (this.domain().length + (1 - i));
|
|
f = pv.range(g + j * (1 - i), h, j);
|
|
f.band = j * i
|
|
}
|
|
return this
|
|
};
|
|
b.by = function(g) {
|
|
function h() {
|
|
return b(g.apply(this, arguments))
|
|
}
|
|
for (var i in b) h[i] = b[i];
|
|
return h
|
|
};
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Scale.quantile = function() {
|
|
function b(i) {
|
|
return h(Math.max(0, Math.min(d, pv.search.index(f, i) - 1)) / d)
|
|
}
|
|
var c = -1,
|
|
d = -1,
|
|
f = [],
|
|
g = [],
|
|
h = pv.Scale.linear();
|
|
b.quantiles = function(i) {
|
|
if (arguments.length) {
|
|
c = Number(i);
|
|
if (c < 0) {
|
|
f = [g[0]].concat(g);
|
|
d = g.length - 1
|
|
} else {
|
|
f = [];
|
|
f[0] = g[0];
|
|
for (var j = 1; j <= c; j++) f[j] = g[~~(j * (g.length - 1) / c)];
|
|
d = c - 1
|
|
}
|
|
return this
|
|
}
|
|
return f
|
|
};
|
|
b.domain = function(i, j) {
|
|
if (arguments.length) {
|
|
g = i instanceof Array ? pv.map(i, j) : Array.prototype.slice.call(arguments);
|
|
g.sort(pv.naturalOrder);
|
|
b.quantiles(c);
|
|
return this
|
|
}
|
|
return g
|
|
};
|
|
b.range = function() {
|
|
if (arguments.length) {
|
|
h.range.apply(h, arguments);
|
|
return this
|
|
}
|
|
return h.range()
|
|
};
|
|
b.by = function(i) {
|
|
function j() {
|
|
return b(i.apply(this, arguments))
|
|
}
|
|
for (var k in b) j[k] = b[k];
|
|
return j
|
|
};
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.histogram = function(b, c) {
|
|
var d = true;
|
|
return {
|
|
bins: function(f) {
|
|
var g = pv.map(b, c),
|
|
h = [];
|
|
arguments.length || (f = pv.Scale.linear(g).ticks());
|
|
for (var i = 0; i < f.length - 1; i++) {
|
|
var j = h[i] = [];
|
|
j.x = f[i];
|
|
j.dx = f[i + 1] - f[i];
|
|
j.y = 0
|
|
}
|
|
for (i = 0; i < g.length; i++) {
|
|
j = pv.search.index(f, g[i]) - 1;
|
|
j = h[Math.max(0, Math.min(h.length - 1, j))];
|
|
j.y++;
|
|
j.push(b[i])
|
|
}
|
|
if (!d)
|
|
for (i = 0; i < h.length; i++) h[i].y /= g.length;
|
|
return h
|
|
},
|
|
frequency: function(f) {
|
|
if (arguments.length) {
|
|
d = Boolean(f);
|
|
return this
|
|
}
|
|
return d
|
|
}
|
|
}
|
|
};
|
|
pv.color = function(b) {
|
|
if (b.rgb) return b.rgb();
|
|
var c = /([a-z]+)\((.*)\)/i.exec(b);
|
|
if (c) {
|
|
var d = c[2].split(","),
|
|
f = 1;
|
|
switch (c[1]) {
|
|
case "hsla":
|
|
case "rgba":
|
|
f = parseFloat(d[3]);
|
|
if (!f) return pv.Color.transparent;
|
|
break
|
|
}
|
|
switch (c[1]) {
|
|
case "hsla":
|
|
case "hsl":
|
|
b = parseFloat(d[0]);
|
|
var g = parseFloat(d[1]) / 100;
|
|
d = parseFloat(d[2]) / 100;
|
|
return (new pv.Color.Hsl(b, g, d, f)).rgb();
|
|
case "rgba":
|
|
case "rgb":
|
|
function h(k) {
|
|
var l = parseFloat(k);
|
|
return k[k.length - 1] == "%" ? Math.round(l * 2.55) : l
|
|
}
|
|
g = h(d[0]);
|
|
var i = h(d[1]),
|
|
j = h(d[2]);
|
|
return pv.rgb(g,
|
|
i, j, f)
|
|
}
|
|
}
|
|
if (f = pv.Color.names[b]) return f;
|
|
if (b.charAt(0) == "#") {
|
|
if (b.length == 4) {
|
|
g = b.charAt(1);
|
|
g += g;
|
|
i = b.charAt(2);
|
|
i += i;
|
|
j = b.charAt(3);
|
|
j += j
|
|
} else if (b.length == 7) {
|
|
g = b.substring(1, 3);
|
|
i = b.substring(3, 5);
|
|
j = b.substring(5, 7)
|
|
}
|
|
return pv.rgb(parseInt(g, 16), parseInt(i, 16), parseInt(j, 16), 1)
|
|
}
|
|
return new pv.Color(b, 1)
|
|
};
|
|
pv.Color = function(b, c) {
|
|
this.color = b;
|
|
this.opacity = c
|
|
};
|
|
pv.Color.prototype.brighter = function(b) {
|
|
return this.rgb().brighter(b)
|
|
};
|
|
pv.Color.prototype.darker = function(b) {
|
|
return this.rgb().darker(b)
|
|
};
|
|
pv.rgb = function(b, c, d, f) {
|
|
return new pv.Color.Rgb(b, c, d, arguments.length == 4 ? f : 1)
|
|
};
|
|
pv.Color.Rgb = function(b, c, d, f) {
|
|
pv.Color.call(this, f ? "rgb(" + b + "," + c + "," + d + ")" : "none", f);
|
|
this.r = b;
|
|
this.g = c;
|
|
this.b = d;
|
|
this.a = f
|
|
};
|
|
pv.Color.Rgb.prototype = pv.extend(pv.Color);
|
|
a = pv.Color.Rgb.prototype;
|
|
a.red = function(b) {
|
|
return pv.rgb(b, this.g, this.b, this.a)
|
|
};
|
|
a.green = function(b) {
|
|
return pv.rgb(this.r, b, this.b, this.a)
|
|
};
|
|
a.blue = function(b) {
|
|
return pv.rgb(this.r, this.g, b, this.a)
|
|
};
|
|
a.alpha = function(b) {
|
|
return pv.rgb(this.r, this.g, this.b, b)
|
|
};
|
|
a.rgb = function() {
|
|
return this
|
|
};
|
|
a.brighter = function(b) {
|
|
b = Math.pow(0.7, arguments.length ? b : 1);
|
|
var c = this.r,
|
|
d = this.g,
|
|
f = this.b;
|
|
if (!c && !d && !f) return pv.rgb(30, 30, 30, this.a);
|
|
if (c && c < 30) c = 30;
|
|
if (d && d < 30) d = 30;
|
|
if (f && f < 30) f = 30;
|
|
return pv.rgb(Math.min(255, Math.floor(c / b)), Math.min(255, Math.floor(d / b)), Math.min(255, Math.floor(f / b)), this.a)
|
|
};
|
|
a.darker = function(b) {
|
|
b = Math.pow(0.7, arguments.length ? b : 1);
|
|
return pv.rgb(Math.max(0, Math.floor(b * this.r)), Math.max(0, Math.floor(b * this.g)), Math.max(0, Math.floor(b * this.b)), this.a)
|
|
};
|
|
pv.hsl = function(b, c, d, f) {
|
|
return new pv.Color.Hsl(b, c, d, arguments.length == 4 ? f : 1)
|
|
};
|
|
pv.Color.Hsl = function(b, c, d, f) {
|
|
pv.Color.call(this, "hsl(" + b + "," + c * 100 + "%," + d * 100 + "%)", f);
|
|
this.h = b;
|
|
this.s = c;
|
|
this.l = d;
|
|
this.a = f
|
|
};
|
|
pv.Color.Hsl.prototype = pv.extend(pv.Color);
|
|
a = pv.Color.Hsl.prototype;
|
|
a.hue = function(b) {
|
|
return pv.hsl(b, this.s, this.l, this.a)
|
|
};
|
|
a.saturation = function(b) {
|
|
return pv.hsl(this.h, b, this.l, this.a)
|
|
};
|
|
a.lightness = function(b) {
|
|
return pv.hsl(this.h, this.s, b, this.a)
|
|
};
|
|
a.alpha = function(b) {
|
|
return pv.hsl(this.h, this.s, this.l, b)
|
|
};
|
|
a.rgb = function() {
|
|
function b(j) {
|
|
if (j > 360) j -= 360;
|
|
else if (j < 0) j += 360;
|
|
if (j < 60) return i + (h - i) * j / 60;
|
|
if (j < 180) return h;
|
|
if (j < 240) return i + (h - i) * (240 - j) / 60;
|
|
return i
|
|
}
|
|
|
|
function c(j) {
|
|
return Math.round(b(j) * 255)
|
|
}
|
|
var d = this.h,
|
|
f = this.s,
|
|
g = this.l;
|
|
d %= 360;
|
|
if (d < 0) d += 360;
|
|
f = Math.max(0, Math.min(f, 1));
|
|
g = Math.max(0, Math.min(g, 1));
|
|
var h = g <= 0.5 ? g * (1 + f) : g + f - g * f,
|
|
i = 2 * g - h;
|
|
return pv.rgb(c(d + 120), c(d), c(d - 120), this.a)
|
|
};
|
|
pv.Color.names = {
|
|
aliceblue: "#f0f8ff",
|
|
antiquewhite: "#faebd7",
|
|
aqua: "#00ffff",
|
|
aquamarine: "#7fffd4",
|
|
azure: "#f0ffff",
|
|
beige: "#f5f5dc",
|
|
bisque: "#ffe4c4",
|
|
black: "#000000",
|
|
blanchedalmond: "#ffebcd",
|
|
blue: "#0000ff",
|
|
blueviolet: "#8a2be2",
|
|
brown: "#a52a2a",
|
|
burlywood: "#deb887",
|
|
cadetblue: "#5f9ea0",
|
|
chartreuse: "#7fff00",
|
|
chocolate: "#d2691e",
|
|
coral: "#ff7f50",
|
|
cornflowerblue: "#6495ed",
|
|
cornsilk: "#fff8dc",
|
|
crimson: "#dc143c",
|
|
cyan: "#00ffff",
|
|
darkblue: "#00008b",
|
|
darkcyan: "#008b8b",
|
|
darkgoldenrod: "#b8860b",
|
|
darkgray: "#a9a9a9",
|
|
darkgreen: "#006400",
|
|
darkgrey: "#a9a9a9",
|
|
darkkhaki: "#bdb76b",
|
|
darkmagenta: "#8b008b",
|
|
darkolivegreen: "#556b2f",
|
|
darkorange: "#ff8c00",
|
|
darkorchid: "#9932cc",
|
|
darkred: "#8b0000",
|
|
darksalmon: "#e9967a",
|
|
darkseagreen: "#8fbc8f",
|
|
darkslateblue: "#483d8b",
|
|
darkslategray: "#2f4f4f",
|
|
darkslategrey: "#2f4f4f",
|
|
darkturquoise: "#00ced1",
|
|
darkviolet: "#9400d3",
|
|
deeppink: "#ff1493",
|
|
deepskyblue: "#00bfff",
|
|
dimgray: "#696969",
|
|
dimgrey: "#696969",
|
|
dodgerblue: "#1e90ff",
|
|
firebrick: "#b22222",
|
|
floralwhite: "#fffaf0",
|
|
forestgreen: "#228b22",
|
|
fuchsia: "#ff00ff",
|
|
gainsboro: "#dcdcdc",
|
|
ghostwhite: "#f8f8ff",
|
|
gold: "#ffd700",
|
|
goldenrod: "#daa520",
|
|
gray: "#808080",
|
|
green: "#008000",
|
|
greenyellow: "#adff2f",
|
|
grey: "#808080",
|
|
honeydew: "#f0fff0",
|
|
hotpink: "#ff69b4",
|
|
indianred: "#cd5c5c",
|
|
indigo: "#4b0082",
|
|
ivory: "#fffff0",
|
|
khaki: "#f0e68c",
|
|
lavender: "#e6e6fa",
|
|
lavenderblush: "#fff0f5",
|
|
lawngreen: "#7cfc00",
|
|
lemonchiffon: "#fffacd",
|
|
lightblue: "#add8e6",
|
|
lightcoral: "#f08080",
|
|
lightcyan: "#e0ffff",
|
|
lightgoldenrodyellow: "#fafad2",
|
|
lightgray: "#d3d3d3",
|
|
lightgreen: "#90ee90",
|
|
lightgrey: "#d3d3d3",
|
|
lightpink: "#ffb6c1",
|
|
lightsalmon: "#ffa07a",
|
|
lightseagreen: "#20b2aa",
|
|
lightskyblue: "#87cefa",
|
|
lightslategray: "#778899",
|
|
lightslategrey: "#778899",
|
|
lightsteelblue: "#b0c4de",
|
|
lightyellow: "#ffffe0",
|
|
lime: "#00ff00",
|
|
limegreen: "#32cd32",
|
|
linen: "#faf0e6",
|
|
magenta: "#ff00ff",
|
|
maroon: "#800000",
|
|
mediumaquamarine: "#66cdaa",
|
|
mediumblue: "#0000cd",
|
|
mediumorchid: "#ba55d3",
|
|
mediumpurple: "#9370db",
|
|
mediumseagreen: "#3cb371",
|
|
mediumslateblue: "#7b68ee",
|
|
mediumspringgreen: "#00fa9a",
|
|
mediumturquoise: "#48d1cc",
|
|
mediumvioletred: "#c71585",
|
|
midnightblue: "#191970",
|
|
mintcream: "#f5fffa",
|
|
mistyrose: "#ffe4e1",
|
|
moccasin: "#ffe4b5",
|
|
navajowhite: "#ffdead",
|
|
navy: "#000080",
|
|
oldlace: "#fdf5e6",
|
|
olive: "#808000",
|
|
olivedrab: "#6b8e23",
|
|
orange: "#ffa500",
|
|
orangered: "#ff4500",
|
|
orchid: "#da70d6",
|
|
palegoldenrod: "#eee8aa",
|
|
palegreen: "#98fb98",
|
|
paleturquoise: "#afeeee",
|
|
palevioletred: "#db7093",
|
|
papayawhip: "#ffefd5",
|
|
peachpuff: "#ffdab9",
|
|
peru: "#cd853f",
|
|
pink: "#ffc0cb",
|
|
plum: "#dda0dd",
|
|
powderblue: "#b0e0e6",
|
|
purple: "#800080",
|
|
red: "#ff0000",
|
|
rosybrown: "#bc8f8f",
|
|
royalblue: "#4169e1",
|
|
saddlebrown: "#8b4513",
|
|
salmon: "#fa8072",
|
|
sandybrown: "#f4a460",
|
|
seagreen: "#2e8b57",
|
|
seashell: "#fff5ee",
|
|
sienna: "#a0522d",
|
|
silver: "#c0c0c0",
|
|
skyblue: "#87ceeb",
|
|
slateblue: "#6a5acd",
|
|
slategray: "#708090",
|
|
slategrey: "#708090",
|
|
snow: "#fffafa",
|
|
springgreen: "#00ff7f",
|
|
steelblue: "#4682b4",
|
|
tan: "#d2b48c",
|
|
teal: "#008080",
|
|
thistle: "#d8bfd8",
|
|
tomato: "#ff6347",
|
|
turquoise: "#40e0d0",
|
|
violet: "#ee82ee",
|
|
wheat: "#f5deb3",
|
|
white: "#ffffff",
|
|
whitesmoke: "#f5f5f5",
|
|
yellow: "#ffff00",
|
|
yellowgreen: "#9acd32",
|
|
transparent: pv.Color.transparent = pv.rgb(0, 0, 0, 0)
|
|
};
|
|
(function() {
|
|
var b = pv.Color.names;
|
|
for (var c in b) b[c] = pv.color(b[c])
|
|
})();
|
|
pv.colors = function() {
|
|
var b = pv.Scale.ordinal();
|
|
b.range.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Colors = {};
|
|
pv.Colors.category10 = function() {
|
|
var b = pv.colors("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf");
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Colors.category20 = function() {
|
|
var b = pv.colors("#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5");
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Colors.category19 = function() {
|
|
var b = pv.colors("#9c9ede", "#7375b5", "#4a5584", "#cedb9c", "#b5cf6b", "#8ca252", "#637939", "#e7cb94", "#e7ba52", "#bd9e39", "#8c6d31", "#e7969c", "#d6616b", "#ad494a", "#843c39", "#de9ed6", "#ce6dbd", "#a55194", "#7b4173");
|
|
b.domain.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.ramp = function() {
|
|
var b = pv.Scale.linear();
|
|
b.range.apply(b, arguments);
|
|
return b
|
|
};
|
|
pv.Scene = pv.SvgScene = {
|
|
svg: "http://www.w3.org/2000/svg",
|
|
xmlns: "http://www.w3.org/2000/xmlns",
|
|
xlink: "http://www.w3.org/1999/xlink",
|
|
xhtml: "http://www.w3.org/1999/xhtml",
|
|
scale: 1,
|
|
events: ["DOMMouseScroll", "mousewheel", "mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "click", "dblclick"],
|
|
implicit: {
|
|
svg: {
|
|
"shape-rendering": "auto",
|
|
"pointer-events": "painted",
|
|
x: 0,
|
|
y: 0,
|
|
dy: 0,
|
|
"text-anchor": "start",
|
|
transform: "translate(0,0)",
|
|
fill: "none",
|
|
"fill-opacity": 1,
|
|
stroke: "none",
|
|
"stroke-opacity": 1,
|
|
"stroke-width": 1.5,
|
|
"stroke-linejoin": "miter"
|
|
},
|
|
css: {
|
|
font: "10px sans-serif"
|
|
}
|
|
}
|
|
};
|
|
pv.SvgScene.updateAll = function(b) {
|
|
if (b.length && b[0].reverse && b.type != "line" && b.type != "area") {
|
|
for (var c = pv.extend(b), d = 0, f = b.length - 1; f >= 0; d++, f--) c[d] = b[f];
|
|
b = c
|
|
}
|
|
this.removeSiblings(this[b.type](b))
|
|
};
|
|
pv.SvgScene.create = function(b) {
|
|
return document.createElementNS(this.svg, b)
|
|
};
|
|
pv.SvgScene.expect = function(b, c, d, f) {
|
|
if (b) {
|
|
if (b.tagName == "a") b = b.firstChild;
|
|
if (b.tagName != c) {
|
|
c = this.create(c);
|
|
b.parentNode.replaceChild(c, b);
|
|
b = c
|
|
}
|
|
} else b = this.create(c);
|
|
for (var g in d) {
|
|
c = d[g];
|
|
if (c == this.implicit.svg[g]) c = null;
|
|
c == null ? b.removeAttribute(g) : b.setAttribute(g, c)
|
|
}
|
|
for (g in f) {
|
|
c = f[g];
|
|
if (c == this.implicit.css[g]) c = null;
|
|
if (c == null) b.style.removeProperty(g);
|
|
else b.style[g] = c
|
|
}
|
|
return b
|
|
};
|
|
pv.SvgScene.append = function(b, c, d) {
|
|
b.$scene = {
|
|
scenes: c,
|
|
index: d
|
|
};
|
|
b = this.title(b, c[d]);
|
|
b.parentNode || c.$g.appendChild(b);
|
|
return b.nextSibling
|
|
};
|
|
pv.SvgScene.title = function(b, c) {
|
|
var d = b.parentNode;
|
|
if (d && d.tagName != "a") d = null;
|
|
if (c.title) {
|
|
if (!d) {
|
|
d = this.create("a");
|
|
b.parentNode && b.parentNode.replaceChild(d, b);
|
|
d.appendChild(b)
|
|
}
|
|
d.setAttributeNS(this.xlink, "title", c.title);
|
|
return d
|
|
}
|
|
d && d.parentNode.replaceChild(b, d);
|
|
return b
|
|
};
|
|
pv.SvgScene.dispatch = pv.listener(function(b) {
|
|
var c = b.target.$scene;
|
|
if (c) {
|
|
var d = b.type;
|
|
switch (d) {
|
|
case "DOMMouseScroll":
|
|
d = "mousewheel";
|
|
b.wheel = -480 * b.detail;
|
|
break;
|
|
case "mousewheel":
|
|
b.wheel = (window.opera ? 12 : 1) * b.wheelDelta;
|
|
break
|
|
}
|
|
pv.Mark.dispatch(d, c.scenes, c.index) && b.preventDefault()
|
|
}
|
|
});
|
|
pv.SvgScene.removeSiblings = function(b) {
|
|
for (; b;) {
|
|
var c = b.nextSibling;
|
|
b.parentNode.removeChild(b);
|
|
b = c
|
|
}
|
|
};
|
|
pv.SvgScene.undefined = function() {};
|
|
pv.SvgScene.pathBasis = function() {
|
|
function b(f, g, h, i, j) {
|
|
return {
|
|
x: f[0] * g.left + f[1] * h.left + f[2] * i.left + f[3] * j.left,
|
|
y: f[0] * g.top + f[1] * h.top + f[2] * i.top + f[3] * j.top
|
|
}
|
|
}
|
|
var c = [
|
|
[1 / 6, 2 / 3, 1 / 6, 0],
|
|
[0, 2 / 3, 1 / 3, 0],
|
|
[0, 1 / 3, 2 / 3, 0],
|
|
[0, 1 / 6, 2 / 3, 1 / 6]
|
|
],
|
|
d = function(f, g, h, i) {
|
|
var j = b(c[1], f, g, h, i),
|
|
k = b(c[2], f, g, h, i);
|
|
f = b(c[3], f, g, h, i);
|
|
return "C" + j.x + "," + j.y + "," + k.x + "," + k.y + "," + f.x + "," + f.y
|
|
};
|
|
d.segment = function(f, g, h, i) {
|
|
var j = b(c[0], f, g, h, i),
|
|
k = b(c[1], f, g, h, i),
|
|
l = b(c[2], f, g, h, i);
|
|
f = b(c[3], f, g, h, i);
|
|
return "M" + j.x + "," + j.y + "C" + k.x + "," + k.y +
|
|
"," + l.x + "," + l.y + "," + f.x + "," + f.y
|
|
};
|
|
return d
|
|
}();
|
|
pv.SvgScene.curveBasis = function(b) {
|
|
if (b.length <= 2) return "";
|
|
var c = "",
|
|
d = b[0],
|
|
f = d,
|
|
g = d,
|
|
h = b[1];
|
|
c += this.pathBasis(d, f, g, h);
|
|
for (var i = 2; i < b.length; i++) {
|
|
d = f;
|
|
f = g;
|
|
g = h;
|
|
h = b[i];
|
|
c += this.pathBasis(d, f, g, h)
|
|
}
|
|
c += this.pathBasis(f, g, h, h);
|
|
c += this.pathBasis(g, h, h, h);
|
|
return c
|
|
};
|
|
pv.SvgScene.curveBasisSegments = function(b) {
|
|
if (b.length <= 2) return "";
|
|
var c = [],
|
|
d = b[0],
|
|
f = d,
|
|
g = d,
|
|
h = b[1],
|
|
i = this.pathBasis.segment(d, f, g, h);
|
|
d = f;
|
|
f = g;
|
|
g = h;
|
|
h = b[2];
|
|
c.push(i + this.pathBasis(d, f, g, h));
|
|
for (i = 3; i < b.length; i++) {
|
|
d = f;
|
|
f = g;
|
|
g = h;
|
|
h = b[i];
|
|
c.push(this.pathBasis.segment(d, f, g, h))
|
|
}
|
|
c.push(this.pathBasis.segment(f, g, h, h) + this.pathBasis(g, h, h, h));
|
|
return c
|
|
};
|
|
pv.SvgScene.curveHermite = function(b, c) {
|
|
if (c.length < 1 || b.length != c.length && b.length != c.length + 2) return "";
|
|
var d = b.length != c.length,
|
|
f = "",
|
|
g = b[0],
|
|
h = b[1],
|
|
i = c[0],
|
|
j = i,
|
|
k = 1;
|
|
if (d) {
|
|
f += "Q" + (h.left - i.x * 2 / 3) + "," + (h.top - i.y * 2 / 3) + "," + h.left + "," + h.top;
|
|
g = b[1];
|
|
k = 2
|
|
}
|
|
if (c.length > 1) {
|
|
j = c[1];
|
|
h = b[k];
|
|
k++;
|
|
f += "C" + (g.left + i.x) + "," + (g.top + i.y) + "," + (h.left - j.x) + "," + (h.top - j.y) + "," + h.left + "," + h.top;
|
|
for (g = 2; g < c.length; g++, k++) {
|
|
h = b[k];
|
|
j = c[g];
|
|
f += "S" + (h.left - j.x) + "," + (h.top - j.y) + "," + h.left + "," + h.top
|
|
}
|
|
}
|
|
if (d) {
|
|
b = b[k];
|
|
f += "Q" + (h.left + j.x * 2 /
|
|
3) + "," + (h.top + j.y * 2 / 3) + "," + b.left + "," + b.top
|
|
}
|
|
return f
|
|
};
|
|
pv.SvgScene.curveHermiteSegments = function(b, c) {
|
|
if (c.length < 1 || b.length != c.length && b.length != c.length + 2) return [];
|
|
var d = b.length != c.length,
|
|
f = [],
|
|
g = b[0],
|
|
h = g,
|
|
i = c[0],
|
|
j = i,
|
|
k = 1;
|
|
if (d) {
|
|
h = b[1];
|
|
f.push("M" + g.left + "," + g.top + "Q" + (h.left - j.x * 2 / 3) + "," + (h.top - j.y * 2 / 3) + "," + h.left + "," + h.top);
|
|
k = 2
|
|
}
|
|
for (var l = 1; l < c.length; l++, k++) {
|
|
g = h;
|
|
i = j;
|
|
h = b[k];
|
|
j = c[l];
|
|
f.push("M" + g.left + "," + g.top + "C" + (g.left + i.x) + "," + (g.top + i.y) + "," + (h.left - j.x) + "," + (h.top - j.y) + "," + h.left + "," + h.top)
|
|
}
|
|
if (d) {
|
|
b = b[k];
|
|
f.push("M" + h.left + "," + h.top + "Q" + (h.left + j.x *
|
|
2 / 3) + "," + (h.top + j.y * 2 / 3) + "," + b.left + "," + b.top)
|
|
}
|
|
return f
|
|
};
|
|
pv.SvgScene.cardinalTangents = function(b, c) {
|
|
var d = [];
|
|
c = (1 - c) / 2;
|
|
for (var f = b[0], g = b[1], h = b[2], i = 3; i < b.length; i++) {
|
|
d.push({
|
|
x: c * (h.left - f.left),
|
|
y: c * (h.top - f.top)
|
|
});
|
|
f = g;
|
|
g = h;
|
|
h = b[i]
|
|
}
|
|
d.push({
|
|
x: c * (h.left - f.left),
|
|
y: c * (h.top - f.top)
|
|
});
|
|
return d
|
|
};
|
|
pv.SvgScene.curveCardinal = function(b, c) {
|
|
if (b.length <= 2) return "";
|
|
return this.curveHermite(b, this.cardinalTangents(b, c))
|
|
};
|
|
pv.SvgScene.curveCardinalSegments = function(b, c) {
|
|
if (b.length <= 2) return "";
|
|
return this.curveHermiteSegments(b, this.cardinalTangents(b, c))
|
|
};
|
|
pv.SvgScene.monotoneTangents = function(b) {
|
|
var c = [],
|
|
d = [],
|
|
f = [],
|
|
g = [],
|
|
h = 0;
|
|
for (h = 0; h < b.length - 1; h++) d[h] = (b[h + 1].top - b[h].top) / (b[h + 1].left - b[h].left);
|
|
f[0] = d[0];
|
|
g[0] = b[1].left - b[0].left;
|
|
for (h = 1; h < b.length - 1; h++) {
|
|
f[h] = (d[h - 1] + d[h]) / 2;
|
|
g[h] = (b[h + 1].left - b[h - 1].left) / 2
|
|
}
|
|
f[h] = d[h - 1];
|
|
g[h] = b[h].left - b[h - 1].left;
|
|
for (h = 0; h < b.length - 1; h++)
|
|
if (d[h] == 0) {
|
|
f[h] = 0;
|
|
f[h + 1] = 0
|
|
} for (h = 0; h < b.length - 1; h++)
|
|
if (!(Math.abs(f[h]) < 1.0E-5 || Math.abs(f[h + 1]) < 1.0E-5)) {
|
|
var i = f[h] / d[h],
|
|
j = f[h + 1] / d[h],
|
|
k = i * i + j * j;
|
|
if (k > 9) {
|
|
k = 3 / Math.sqrt(k);
|
|
f[h] =
|
|
k * i * d[h];
|
|
f[h + 1] = k * j * d[h]
|
|
}
|
|
} for (h = 0; h < b.length; h++) {
|
|
d = 1 + f[h] * f[h];
|
|
c.push({
|
|
x: g[h] / 3 / d,
|
|
y: f[h] * g[h] / 3 / d
|
|
})
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.curveMonotone = function(b) {
|
|
if (b.length <= 2) return "";
|
|
return this.curveHermite(b, this.monotoneTangents(b))
|
|
};
|
|
pv.SvgScene.curveMonotoneSegments = function(b) {
|
|
if (b.length <= 2) return "";
|
|
return this.curveHermiteSegments(b, this.monotoneTangents(b))
|
|
};
|
|
pv.SvgScene.area = function(b) {
|
|
function c(n, p) {
|
|
for (var m = [], r = [], s = p; n <= s; n++, p--) {
|
|
var t = b[n],
|
|
x = b[p];
|
|
t = t.left + "," + t.top;
|
|
x = x.left + x.width + "," + (x.top + x.height);
|
|
if (n < s) {
|
|
var u = b[n + 1],
|
|
o = b[p - 1];
|
|
switch (g.interpolate) {
|
|
case "step-before":
|
|
t += "V" + u.top;
|
|
x += "H" + (o.left + o.width);
|
|
break;
|
|
case "step-after":
|
|
t += "H" + u.left;
|
|
x += "V" + (o.top + o.height);
|
|
break
|
|
}
|
|
}
|
|
m.push(t);
|
|
r.push(x)
|
|
}
|
|
return m.concat(r).join("L")
|
|
}
|
|
|
|
function d(n, p) {
|
|
for (var m = [], r = [], s = p; n <= s; n++, p--) {
|
|
var t = b[p];
|
|
m.push(b[n]);
|
|
r.push({
|
|
left: t.left + t.width,
|
|
top: t.top + t.height
|
|
})
|
|
}
|
|
if (g.interpolate ==
|
|
"basis") {
|
|
n = pv.SvgScene.curveBasis(m);
|
|
p = pv.SvgScene.curveBasis(r)
|
|
} else if (g.interpolate == "cardinal") {
|
|
n = pv.SvgScene.curveCardinal(m, g.tension);
|
|
p = pv.SvgScene.curveCardinal(r, g.tension)
|
|
} else {
|
|
n = pv.SvgScene.curveMonotone(m);
|
|
p = pv.SvgScene.curveMonotone(r)
|
|
}
|
|
return m[0].left + "," + m[0].top + n + "L" + r[0].left + "," + r[0].top + p
|
|
}
|
|
var f = b.$g.firstChild;
|
|
if (!b.length) return f;
|
|
var g = b[0];
|
|
if (g.segmented) return this.areaSegment(b);
|
|
if (!g.visible) return f;
|
|
var h = g.fillStyle,
|
|
i = g.strokeStyle;
|
|
if (!h.opacity && !i.opacity) return f;
|
|
for (var j = [], k, l = 0; l < b.length; l++) {
|
|
k = b[l];
|
|
if (k.width || k.height) {
|
|
for (var q = l + 1; q < b.length; q++) {
|
|
k = b[q];
|
|
if (!k.width && !k.height) break
|
|
}
|
|
l && g.interpolate != "step-after" && l--;
|
|
q < b.length && g.interpolate != "step-before" && q++;
|
|
j.push((q - l > 2 && (g.interpolate == "basis" || g.interpolate == "cardinal" || g.interpolate == "monotone") ? d : c)(l, q - 1));
|
|
l = q - 1
|
|
}
|
|
}
|
|
if (!j.length) return f;
|
|
f = this.expect(f, "path", {
|
|
"shape-rendering": g.antialias ? null : "crispEdges",
|
|
"pointer-events": g.events,
|
|
cursor: g.cursor,
|
|
d: "M" + j.join("ZM") + "Z",
|
|
fill: h.color,
|
|
"fill-opacity": h.opacity ||
|
|
null,
|
|
stroke: i.color,
|
|
"stroke-opacity": i.opacity || null,
|
|
"stroke-width": i.opacity ? g.lineWidth / this.scale : null
|
|
});
|
|
return this.append(f, b, 0)
|
|
};
|
|
pv.SvgScene.areaSegment = function(b) {
|
|
var c = b.$g.firstChild,
|
|
d = b[0],
|
|
f, g;
|
|
if (d.interpolate == "basis" || d.interpolate == "cardinal" || d.interpolate == "monotone") {
|
|
f = [];
|
|
g = [];
|
|
for (var h = 0, i = b.length; h < i; h++) {
|
|
var j = b[i - h - 1];
|
|
f.push(b[h]);
|
|
g.push({
|
|
left: j.left + j.width,
|
|
top: j.top + j.height
|
|
})
|
|
}
|
|
if (d.interpolate == "basis") {
|
|
f = this.curveBasisSegments(f);
|
|
g = this.curveBasisSegments(g)
|
|
} else if (d.interpolate == "cardinal") {
|
|
f = this.curveCardinalSegments(f, d.tension);
|
|
g = this.curveCardinalSegments(g, d.tension)
|
|
} else {
|
|
f = this.curveMonotoneSegments(f);
|
|
g = this.curveMonotoneSegments(g)
|
|
}
|
|
}
|
|
h = 0;
|
|
for (i = b.length - 1; h < i; h++) {
|
|
d = b[h];
|
|
var k = b[h + 1];
|
|
if (d.visible && k.visible) {
|
|
var l = d.fillStyle,
|
|
q = d.strokeStyle;
|
|
if (l.opacity || q.opacity) {
|
|
if (f) {
|
|
j = f[h];
|
|
k = "L" + g[i - h - 1].substr(1);
|
|
j = j + k + "Z"
|
|
} else {
|
|
var n = d;
|
|
j = k;
|
|
switch (d.interpolate) {
|
|
case "step-before":
|
|
n = k;
|
|
break;
|
|
case "step-after":
|
|
j = d;
|
|
break
|
|
}
|
|
j = "M" + d.left + "," + n.top + "L" + k.left + "," + j.top + "L" + (k.left + k.width) + "," + (j.top + j.height) + "L" + (d.left + d.width) + "," + (n.top + n.height) + "Z"
|
|
}
|
|
c = this.expect(c, "path", {
|
|
"shape-rendering": d.antialias ? null : "crispEdges",
|
|
"pointer-events": d.events,
|
|
cursor: d.cursor,
|
|
d: j,
|
|
fill: l.color,
|
|
"fill-opacity": l.opacity || null,
|
|
stroke: q.color,
|
|
"stroke-opacity": q.opacity || null,
|
|
"stroke-width": q.opacity ? d.lineWidth / this.scale : null
|
|
});
|
|
c = this.append(c, b, h)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.bar = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
var g = f.fillStyle,
|
|
h = f.strokeStyle;
|
|
if (g.opacity || h.opacity) {
|
|
c = this.expect(c, "rect", {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
x: f.left,
|
|
y: f.top,
|
|
width: Math.max(1.0E-10, f.width),
|
|
height: Math.max(1.0E-10, f.height),
|
|
fill: g.color,
|
|
"fill-opacity": g.opacity || null,
|
|
stroke: h.color,
|
|
"stroke-opacity": h.opacity || null,
|
|
"stroke-width": h.opacity ? f.lineWidth / this.scale : null
|
|
});
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.dot = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
var g = f.fillStyle,
|
|
h = f.strokeStyle;
|
|
if (g.opacity || h.opacity) {
|
|
var i = f.radius,
|
|
j = null;
|
|
switch (f.shape) {
|
|
case "cross":
|
|
j = "M" + -i + "," + -i + "L" + i + "," + i + "M" + i + "," + -i + "L" + -i + "," + i;
|
|
break;
|
|
case "triangle":
|
|
j = i;
|
|
var k = i * 1.1547;
|
|
j = "M0," + j + "L" + k + "," + -j + " " + -k + "," + -j + "Z";
|
|
break;
|
|
case "diamond":
|
|
i *= Math.SQRT2;
|
|
j = "M0," + -i + "L" + i + ",0 0," + i + " " + -i + ",0Z";
|
|
break;
|
|
case "square":
|
|
j = "M" + -i + "," + -i + "L" + i + "," + -i + " " + i + "," + i + " " + -i + "," + i + "Z";
|
|
break;
|
|
case "tick":
|
|
j = "M0,0L0," + -f.size;
|
|
break;
|
|
case "bar":
|
|
j = "M0," + f.size / 2 + "L0," + -(f.size / 2);
|
|
break
|
|
}
|
|
g = {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
fill: g.color,
|
|
"fill-opacity": g.opacity || null,
|
|
stroke: h.color,
|
|
"stroke-opacity": h.opacity || null,
|
|
"stroke-width": h.opacity ? f.lineWidth / this.scale : null
|
|
};
|
|
if (j) {
|
|
g.transform = "translate(" + f.left + "," + f.top + ")";
|
|
if (f.angle) g.transform += " rotate(" + 180 * f.angle / Math.PI + ")";
|
|
g.d = j;
|
|
c = this.expect(c, "path", g)
|
|
} else {
|
|
g.cx = f.left;
|
|
g.cy = f.top;
|
|
g.r =
|
|
i;
|
|
c = this.expect(c, "circle", g)
|
|
}
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.image = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
c = this.fill(c, b, d);
|
|
if (f.image) {
|
|
c = this.expect(c, "foreignObject", {
|
|
cursor: f.cursor,
|
|
x: f.left,
|
|
y: f.top,
|
|
width: f.width,
|
|
height: f.height
|
|
});
|
|
var g = c.firstChild || c.appendChild(document.createElementNS(this.xhtml, "canvas"));
|
|
g.$scene = {
|
|
scenes: b,
|
|
index: d
|
|
};
|
|
g.style.width = f.width;
|
|
g.style.height = f.height;
|
|
g.width = f.imageWidth;
|
|
g.height = f.imageHeight;
|
|
g.getContext("2d").putImageData(f.image, 0, 0)
|
|
} else {
|
|
c = this.expect(c, "image", {
|
|
preserveAspectRatio: "none",
|
|
cursor: f.cursor,
|
|
x: f.left,
|
|
y: f.top,
|
|
width: f.width,
|
|
height: f.height
|
|
});
|
|
c.setAttributeNS(this.xlink, "href", f.url)
|
|
}
|
|
c = this.append(c, b, d);
|
|
c = this.stroke(c, b, d)
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.label = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
var g = f.textStyle;
|
|
if (g.opacity && f.text) {
|
|
var h = 0,
|
|
i = 0,
|
|
j = 0,
|
|
k = "start";
|
|
switch (f.textBaseline) {
|
|
case "middle":
|
|
j = ".35em";
|
|
break;
|
|
case "top":
|
|
j = ".71em";
|
|
i = f.textMargin;
|
|
break;
|
|
case "bottom":
|
|
i = "-" + f.textMargin;
|
|
break
|
|
}
|
|
switch (f.textAlign) {
|
|
case "right":
|
|
k = "end";
|
|
h = "-" + f.textMargin;
|
|
break;
|
|
case "center":
|
|
k = "middle";
|
|
break;
|
|
case "left":
|
|
h = f.textMargin;
|
|
break
|
|
}
|
|
c = this.expect(c, "text", {
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
x: h,
|
|
y: i,
|
|
dy: j,
|
|
transform: "translate(" + f.left + "," + f.top + ")" + (f.textAngle ? " rotate(" + 180 * f.textAngle / Math.PI + ")" : "") + (this.scale != 1 ? " scale(" + 1 / this.scale + ")" : ""),
|
|
fill: g.color,
|
|
"fill-opacity": g.opacity || null,
|
|
"text-anchor": k
|
|
}, {
|
|
font: f.font,
|
|
"text-shadow": f.textShadow,
|
|
"text-decoration": f.textDecoration
|
|
});
|
|
if (c.firstChild) c.firstChild.nodeValue = f.text;
|
|
else c.appendChild(document.createTextNode(f.text));
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.line = function(b) {
|
|
var c = b.$g.firstChild;
|
|
if (b.length < 2) return c;
|
|
var d = b[0];
|
|
if (d.segmented) return this.lineSegment(b);
|
|
if (!d.visible) return c;
|
|
var f = d.fillStyle,
|
|
g = d.strokeStyle;
|
|
if (!f.opacity && !g.opacity) return c;
|
|
var h = "M" + d.left + "," + d.top;
|
|
if (b.length > 2 && (d.interpolate == "basis" || d.interpolate == "cardinal" || d.interpolate == "monotone")) switch (d.interpolate) {
|
|
case "basis":
|
|
h += this.curveBasis(b);
|
|
break;
|
|
case "cardinal":
|
|
h += this.curveCardinal(b, d.tension);
|
|
break;
|
|
case "monotone":
|
|
h += this.curveMonotone(b);
|
|
break
|
|
} else
|
|
for (var i = 1; i < b.length; i++) h += this.pathSegment(b[i - 1], b[i]);
|
|
c = this.expect(c, "path", {
|
|
"shape-rendering": d.antialias ? null : "crispEdges",
|
|
"pointer-events": d.events,
|
|
cursor: d.cursor,
|
|
d: h,
|
|
fill: f.color,
|
|
"fill-opacity": f.opacity || null,
|
|
stroke: g.color,
|
|
"stroke-opacity": g.opacity || null,
|
|
"stroke-width": g.opacity ? d.lineWidth / this.scale : null,
|
|
"stroke-linejoin": d.lineJoin
|
|
});
|
|
return this.append(c, b, 0)
|
|
};
|
|
pv.SvgScene.lineSegment = function(b) {
|
|
var c = b.$g.firstChild,
|
|
d = b[0],
|
|
f;
|
|
switch (d.interpolate) {
|
|
case "basis":
|
|
f = this.curveBasisSegments(b);
|
|
break;
|
|
case "cardinal":
|
|
f = this.curveCardinalSegments(b, d.tension);
|
|
break;
|
|
case "monotone":
|
|
f = this.curveMonotoneSegments(b);
|
|
break
|
|
}
|
|
d = 0;
|
|
for (var g = b.length - 1; d < g; d++) {
|
|
var h = b[d],
|
|
i = b[d + 1];
|
|
if (h.visible && i.visible) {
|
|
var j = h.strokeStyle,
|
|
k = pv.Color.transparent;
|
|
if (j.opacity) {
|
|
if (h.interpolate == "linear" && h.lineJoin == "miter") {
|
|
k = j;
|
|
j = pv.Color.transparent;
|
|
i = this.pathJoin(b[d - 1], h, i, b[d + 2])
|
|
} else i =
|
|
f ? f[d] : "M" + h.left + "," + h.top + this.pathSegment(h, i);
|
|
c = this.expect(c, "path", {
|
|
"shape-rendering": h.antialias ? null : "crispEdges",
|
|
"pointer-events": h.events,
|
|
cursor: h.cursor,
|
|
d: i,
|
|
fill: k.color,
|
|
"fill-opacity": k.opacity || null,
|
|
stroke: j.color,
|
|
"stroke-opacity": j.opacity || null,
|
|
"stroke-width": j.opacity ? h.lineWidth / this.scale : null,
|
|
"stroke-linejoin": h.lineJoin
|
|
});
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.pathSegment = function(b, c) {
|
|
var d = 1;
|
|
switch (b.interpolate) {
|
|
case "polar-reverse":
|
|
d = 0;
|
|
case "polar":
|
|
var f = c.left - b.left,
|
|
g = c.top - b.top;
|
|
b = 1 - b.eccentricity;
|
|
f = Math.sqrt(f * f + g * g) / (2 * b);
|
|
if (b <= 0 || b > 1) break;
|
|
return "A" + f + "," + f + " 0 0," + d + " " + c.left + "," + c.top;
|
|
case "step-before":
|
|
return "V" + c.top + "H" + c.left;
|
|
case "step-after":
|
|
return "H" + c.left + "V" + c.top
|
|
}
|
|
return "L" + c.left + "," + c.top
|
|
};
|
|
pv.SvgScene.lineIntersect = function(b, c, d, f) {
|
|
return b.plus(c.times(d.minus(b).dot(f.perp()) / c.dot(f.perp())))
|
|
};
|
|
pv.SvgScene.pathJoin = function(b, c, d, f) {
|
|
var g = pv.vector(c.left, c.top);
|
|
d = pv.vector(d.left, d.top);
|
|
var h = d.minus(g),
|
|
i = h.perp().norm(),
|
|
j = i.times(c.lineWidth / (2 * this.scale));
|
|
c = g.plus(j);
|
|
var k = d.plus(j),
|
|
l = d.minus(j);
|
|
j = g.minus(j);
|
|
if (b && b.visible) {
|
|
b = g.minus(b.left, b.top).perp().norm().plus(i);
|
|
j = this.lineIntersect(g, b, j, h);
|
|
c = this.lineIntersect(g, b, c, h)
|
|
}
|
|
if (f && f.visible) {
|
|
f = pv.vector(f.left, f.top).minus(d).perp().norm().plus(i);
|
|
l = this.lineIntersect(d, f, l, h);
|
|
k = this.lineIntersect(d, f, k, h)
|
|
}
|
|
return "M" + c.x + "," + c.y +
|
|
"L" + k.x + "," + k.y + " " + l.x + "," + l.y + " " + j.x + "," + j.y
|
|
};
|
|
pv.SvgScene.panel = function(b) {
|
|
for (var c = b.$g, d = c && c.firstChild, f = 0; f < b.length; f++) {
|
|
var g = b[f];
|
|
if (g.visible) {
|
|
if (!b.parent) {
|
|
g.canvas.style.display = "inline-block";
|
|
if (c && c.parentNode != g.canvas) d = (c = g.canvas.firstChild) && c.firstChild;
|
|
if (!c) {
|
|
c = g.canvas.appendChild(this.create("svg"));
|
|
c.setAttribute("font-size", "10px");
|
|
c.setAttribute("font-family", "sans-serif");
|
|
c.setAttribute("fill", "none");
|
|
c.setAttribute("stroke", "none");
|
|
c.setAttribute("stroke-width", 1.5);
|
|
for (var h = 0; h < this.events.length; h++) c.addEventListener(this.events[h],
|
|
this.dispatch, false);
|
|
d = c.firstChild
|
|
}
|
|
b.$g = c;
|
|
c.setAttribute("width", g.width + g.left + g.right);
|
|
c.setAttribute("height", g.height + g.top + g.bottom)
|
|
}
|
|
if (g.overflow == "hidden") {
|
|
h = pv.id().toString(36);
|
|
var i = this.expect(d, "g", {
|
|
"clip-path": "url(#" + h + ")"
|
|
});
|
|
i.parentNode || c.appendChild(i);
|
|
b.$g = c = i;
|
|
d = i.firstChild;
|
|
d = this.expect(d, "clipPath", {
|
|
id: h
|
|
});
|
|
h = d.firstChild || d.appendChild(this.create("rect"));
|
|
h.setAttribute("x", g.left);
|
|
h.setAttribute("y", g.top);
|
|
h.setAttribute("width", g.width);
|
|
h.setAttribute("height", g.height);
|
|
d.parentNode ||
|
|
c.appendChild(d);
|
|
d = d.nextSibling
|
|
}
|
|
d = this.fill(d, b, f);
|
|
var j = this.scale,
|
|
k = g.transform,
|
|
l = g.left + k.x,
|
|
q = g.top + k.y;
|
|
this.scale *= k.k;
|
|
for (h = 0; h < g.children.length; h++) {
|
|
g.children[h].$g = d = this.expect(d, "g", {
|
|
transform: "translate(" + l + "," + q + ")" + (k.k != 1 ? " scale(" + k.k + ")" : "")
|
|
});
|
|
this.updateAll(g.children[h]);
|
|
d.parentNode || c.appendChild(d);
|
|
d = d.nextSibling
|
|
}
|
|
this.scale = j;
|
|
d = this.stroke(d, b, f);
|
|
if (g.overflow == "hidden") {
|
|
b.$g = c = i.parentNode;
|
|
d = i.nextSibling
|
|
}
|
|
}
|
|
}
|
|
return d
|
|
};
|
|
pv.SvgScene.fill = function(b, c, d) {
|
|
var f = c[d],
|
|
g = f.fillStyle;
|
|
if (g.opacity || f.events == "all") {
|
|
b = this.expect(b, "rect", {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
x: f.left,
|
|
y: f.top,
|
|
width: f.width,
|
|
height: f.height,
|
|
fill: g.color,
|
|
"fill-opacity": g.opacity,
|
|
stroke: null
|
|
});
|
|
b = this.append(b, c, d)
|
|
}
|
|
return b
|
|
};
|
|
pv.SvgScene.stroke = function(b, c, d) {
|
|
var f = c[d],
|
|
g = f.strokeStyle;
|
|
if (g.opacity || f.events == "all") {
|
|
b = this.expect(b, "rect", {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events == "all" ? "stroke" : f.events,
|
|
cursor: f.cursor,
|
|
x: f.left,
|
|
y: f.top,
|
|
width: Math.max(1.0E-10, f.width),
|
|
height: Math.max(1.0E-10, f.height),
|
|
fill: null,
|
|
stroke: g.color,
|
|
"stroke-opacity": g.opacity,
|
|
"stroke-width": f.lineWidth / this.scale
|
|
});
|
|
b = this.append(b, c, d)
|
|
}
|
|
return b
|
|
};
|
|
pv.SvgScene.rule = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
var g = f.strokeStyle;
|
|
if (g.opacity) {
|
|
c = this.expect(c, "line", {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
x1: f.left,
|
|
y1: f.top,
|
|
x2: f.left + f.width,
|
|
y2: f.top + f.height,
|
|
stroke: g.color,
|
|
"stroke-opacity": g.opacity,
|
|
"stroke-width": f.lineWidth / this.scale
|
|
});
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.SvgScene.wedge = function(b) {
|
|
for (var c = b.$g.firstChild, d = 0; d < b.length; d++) {
|
|
var f = b[d];
|
|
if (f.visible) {
|
|
var g = f.fillStyle,
|
|
h = f.strokeStyle;
|
|
if (g.opacity || h.opacity) {
|
|
var i = f.innerRadius,
|
|
j = f.outerRadius,
|
|
k = Math.abs(f.angle);
|
|
if (k >= 2 * Math.PI) i = i ? "M0," + j + "A" + j + "," + j + " 0 1,1 0," + -j + "A" + j + "," + j + " 0 1,1 0," + j + "M0," + i + "A" + i + "," + i + " 0 1,1 0," + -i + "A" + i + "," + i + " 0 1,1 0," + i + "Z" : "M0," + j + "A" + j + "," + j + " 0 1,1 0," + -j + "A" + j + "," + j + " 0 1,1 0," + j + "Z";
|
|
else {
|
|
var l = Math.min(f.startAngle, f.endAngle),
|
|
q = Math.max(f.startAngle, f.endAngle),
|
|
n = Math.cos(l),
|
|
p = Math.cos(q);
|
|
l = Math.sin(l);
|
|
q = Math.sin(q);
|
|
i = i ? "M" + j * n + "," + j * l + "A" + j + "," + j + " 0 " + (k < Math.PI ? "0" : "1") + ",1 " + j * p + "," + j * q + "L" + i * p + "," + i * q + "A" + i + "," + i + " 0 " + (k < Math.PI ? "0" : "1") + ",0 " + i * n + "," + i * l + "Z" : "M" + j * n + "," + j * l + "A" + j + "," + j + " 0 " + (k < Math.PI ? "0" : "1") + ",1 " + j * p + "," + j * q + "L0,0Z"
|
|
}
|
|
c = this.expect(c, "path", {
|
|
"shape-rendering": f.antialias ? null : "crispEdges",
|
|
"pointer-events": f.events,
|
|
cursor: f.cursor,
|
|
transform: "translate(" + f.left + "," + f.top + ")",
|
|
d: i,
|
|
fill: g.color,
|
|
"fill-rule": "evenodd",
|
|
"fill-opacity": g.opacity ||
|
|
null,
|
|
stroke: h.color,
|
|
"stroke-opacity": h.opacity || null,
|
|
"stroke-width": h.opacity ? f.lineWidth / this.scale : null
|
|
});
|
|
c = this.append(c, b, d)
|
|
}
|
|
}
|
|
}
|
|
return c
|
|
};
|
|
pv.Mark = function() {
|
|
this.$properties = [];
|
|
this.$handlers = {}
|
|
};
|
|
pv.Mark.prototype.properties = {};
|
|
pv.Mark.cast = {};
|
|
pv.Mark.prototype.property = function(b, c) {
|
|
if (!this.hasOwnProperty("properties")) this.properties = pv.extend(this.properties);
|
|
this.properties[b] = true;
|
|
pv.Mark.prototype.propertyMethod(b, false, pv.Mark.cast[b] = c);
|
|
return this
|
|
};
|
|
pv.Mark.prototype.propertyMethod = function(b, c, d) {
|
|
d || (d = pv.Mark.cast[b]);
|
|
this[b] = function(f) {
|
|
if (c && this.scene) {
|
|
var g = this.scene.defs;
|
|
if (arguments.length) {
|
|
g[b] = {
|
|
id: f == null ? 0 : pv.id(),
|
|
value: f != null && d ? d(f) : f
|
|
};
|
|
return this
|
|
}
|
|
return g[b] ? g[b].value : null
|
|
}
|
|
if (arguments.length) {
|
|
g = !c << 1 | typeof f == "function";
|
|
this.propertyValue(b, g & 1 && d ? function() {
|
|
var h = f.apply(this, arguments);
|
|
return h != null ? d(h) : null
|
|
} : f != null && d ? d(f) : f).type = g;
|
|
return this
|
|
}
|
|
return this.instance()[b]
|
|
}
|
|
};
|
|
pv.Mark.prototype.propertyValue = function(b, c) {
|
|
var d = this.$properties;
|
|
c = {
|
|
name: b,
|
|
id: pv.id(),
|
|
value: c
|
|
};
|
|
for (var f = 0; f < d.length; f++)
|
|
if (d[f].name == b) {
|
|
d.splice(f, 1);
|
|
break
|
|
} d.push(c);
|
|
return c
|
|
};
|
|
pv.Mark.prototype.property("data").property("visible", Boolean).property("left", Number).property("right", Number).property("top", Number).property("bottom", Number).property("cursor", String).property("title", String).property("reverse", Boolean).property("antialias", Boolean).property("events", String);
|
|
a = pv.Mark.prototype;
|
|
a.childIndex = -1;
|
|
a.index = -1;
|
|
a.scale = 1;
|
|
a.defaults = (new pv.Mark).data(function(b) {
|
|
return [b]
|
|
}).visible(true).antialias(true).events("painted");
|
|
a.extend = function(b) {
|
|
this.proto = b;
|
|
this.target = b.target;
|
|
return this
|
|
};
|
|
a.add = function(b) {
|
|
return this.parent.add(b).extend(this)
|
|
};
|
|
a.def = function(b, c) {
|
|
this.propertyMethod(b, true);
|
|
return this[b](arguments.length > 1 ? c : null)
|
|
};
|
|
a.anchor = function(b) {
|
|
b || (b = "center");
|
|
return (new pv.Anchor(this)).name(b).data(function() {
|
|
return this.scene.target.map(function(c) {
|
|
return c.data
|
|
})
|
|
}).visible(function() {
|
|
return this.scene.target[this.index].visible
|
|
}).left(function() {
|
|
var c = this.scene.target[this.index],
|
|
d = c.width || 0;
|
|
switch (this.name()) {
|
|
case "bottom":
|
|
case "top":
|
|
case "center":
|
|
return c.left + d / 2;
|
|
case "left":
|
|
return null
|
|
}
|
|
return c.left + d
|
|
}).top(function() {
|
|
var c = this.scene.target[this.index],
|
|
d = c.height || 0;
|
|
switch (this.name()) {
|
|
case "left":
|
|
case "right":
|
|
case "center":
|
|
return c.top +
|
|
d / 2;
|
|
case "top":
|
|
return null
|
|
}
|
|
return c.top + d
|
|
}).right(function() {
|
|
var c = this.scene.target[this.index];
|
|
return this.name() == "left" ? c.right + (c.width || 0) : null
|
|
}).bottom(function() {
|
|
var c = this.scene.target[this.index];
|
|
return this.name() == "top" ? c.bottom + (c.height || 0) : null
|
|
}).textAlign(function() {
|
|
switch (this.name()) {
|
|
case "bottom":
|
|
case "top":
|
|
case "center":
|
|
return "center";
|
|
case "right":
|
|
return "right"
|
|
}
|
|
return "left"
|
|
}).textBaseline(function() {
|
|
switch (this.name()) {
|
|
case "right":
|
|
case "left":
|
|
case "center":
|
|
return "middle";
|
|
case "top":
|
|
return "top"
|
|
}
|
|
return "bottom"
|
|
})
|
|
};
|
|
a.anchorTarget = function() {
|
|
return this.target
|
|
};
|
|
a.margin = function(b) {
|
|
return this.left(b).right(b).top(b).bottom(b)
|
|
};
|
|
a.instance = function(b) {
|
|
var c = this.scene || this.parent.instance(-1).children[this.childIndex],
|
|
d = !arguments.length || this.hasOwnProperty("index") ? this.index : b;
|
|
return c[d < 0 ? c.length - 1 : d]
|
|
};
|
|
a.instances = function(b) {
|
|
for (var c = this, d = [], f; !(f = c.scene);) {
|
|
b = b.parent;
|
|
d.push({
|
|
index: b.index,
|
|
childIndex: c.childIndex
|
|
});
|
|
c = c.parent
|
|
}
|
|
for (; d.length;) {
|
|
b = d.pop();
|
|
f = f[b.index].children[b.childIndex]
|
|
}
|
|
if (this.hasOwnProperty("index")) {
|
|
d = pv.extend(f[this.index]);
|
|
d.right = d.top = d.left = d.bottom = 0;
|
|
return [d]
|
|
}
|
|
return f
|
|
};
|
|
a.first = function() {
|
|
return this.scene[0]
|
|
};
|
|
a.last = function() {
|
|
return this.scene[this.scene.length - 1]
|
|
};
|
|
a.sibling = function() {
|
|
return this.index == 0 ? null : this.scene[this.index - 1]
|
|
};
|
|
a.cousin = function() {
|
|
var b = this.parent;
|
|
return (b = b && b.sibling()) && b.children ? b.children[this.childIndex][this.index] : null
|
|
};
|
|
a.render = function() {
|
|
function b(i, j, k) {
|
|
i.scale = k;
|
|
if (j < g.length) {
|
|
f.unshift(null);
|
|
if (i.hasOwnProperty("index")) c(i, j, k);
|
|
else {
|
|
for (var l = 0, q = i.scene.length; l < q; l++) {
|
|
i.index = l;
|
|
c(i, j, k)
|
|
}
|
|
delete i.index
|
|
}
|
|
f.shift()
|
|
} else {
|
|
i.build();
|
|
pv.Scene.scale = k;
|
|
pv.Scene.updateAll(i.scene)
|
|
}
|
|
delete i.scale
|
|
}
|
|
|
|
function c(i, j, k) {
|
|
var l = i.scene[i.index],
|
|
q;
|
|
if (l.visible) {
|
|
var n = g[j],
|
|
p = i.children[n];
|
|
for (q = 0; q < n; q++) i.children[q].scene = l.children[q];
|
|
f[0] = l.data;
|
|
if (p.scene) b(p, j + 1, k * l.transform.k);
|
|
else {
|
|
p.scene = l.children[n];
|
|
b(p, j + 1, k * l.transform.k);
|
|
delete p.scene
|
|
}
|
|
for (q = 0; q < n; q++) delete i.children[q].scene
|
|
}
|
|
}
|
|
var d = this.parent,
|
|
f = pv.Mark.stack;
|
|
if (d && !this.root.scene) this.root.render();
|
|
else {
|
|
for (var g = [], h = this; h.parent; h = h.parent) g.unshift(h.childIndex);
|
|
for (this.bind(); d && !d.hasOwnProperty("index");) d = d.parent;
|
|
this.context(d ? d.scene : undefined, d ? d.index : -1, function() {
|
|
b(this.root, 0, 1)
|
|
})
|
|
}
|
|
};
|
|
pv.Mark.stack = [];
|
|
a = pv.Mark.prototype;
|
|
a.bind = function() {
|
|
function b(j) {
|
|
do
|
|
for (var k = j.$properties, l = k.length - 1; l >= 0; l--) {
|
|
var q = k[l];
|
|
if (!(q.name in c)) {
|
|
c[q.name] = q;
|
|
switch (q.name) {
|
|
case "data":
|
|
f = q;
|
|
break;
|
|
case "visible":
|
|
g = q;
|
|
break;
|
|
default:
|
|
d[q.type].push(q);
|
|
break
|
|
}
|
|
}
|
|
}
|
|
while (j = j.proto)
|
|
}
|
|
var c = {},
|
|
d = [
|
|
[],
|
|
[],
|
|
[],
|
|
[]
|
|
],
|
|
f, g;
|
|
b(this);
|
|
b(this.defaults);
|
|
d[1].reverse();
|
|
d[3].reverse();
|
|
var h = this;
|
|
do
|
|
for (var i in h.properties) i in c || d[2].push(c[i] = {
|
|
name: i,
|
|
type: 2,
|
|
value: null
|
|
}); while (h = h.proto);
|
|
h = d[0].concat(d[1]);
|
|
for (i = 0; i < h.length; i++) this.propertyMethod(h[i].name,
|
|
true);
|
|
this.binds = {
|
|
properties: c,
|
|
data: f,
|
|
defs: h,
|
|
required: [g],
|
|
optional: pv.blend(d)
|
|
}
|
|
};
|
|
a.build = function() {
|
|
var b = this.scene,
|
|
c = pv.Mark.stack;
|
|
if (!b) {
|
|
b = this.scene = [];
|
|
b.mark = this;
|
|
b.type = this.type;
|
|
b.childIndex = this.childIndex;
|
|
if (this.parent) {
|
|
b.parent = this.parent.scene;
|
|
b.parentIndex = this.parent.index
|
|
}
|
|
}
|
|
if (this.target) b.target = this.target.instances(b);
|
|
if (this.binds.defs.length) {
|
|
var d = b.defs;
|
|
if (!d) b.defs = d = {};
|
|
for (var f = 0; f < this.binds.defs.length; f++) {
|
|
var g = this.binds.defs[f],
|
|
h = d[g.name];
|
|
if (!h || g.id > h.id) d[g.name] = {
|
|
id: 0,
|
|
value: g.type & 1 ? g.value.apply(this, c) : g.value
|
|
}
|
|
}
|
|
}
|
|
d = this.binds.data;
|
|
d = d.type &
|
|
1 ? d.value.apply(this, c) : d.value;
|
|
c.unshift(null);
|
|
b.length = d.length;
|
|
for (f = 0; f < d.length; f++) {
|
|
pv.Mark.prototype.index = this.index = f;
|
|
(g = b[f]) || (b[f] = g = {});
|
|
g.data = c[0] = d[f];
|
|
this.buildInstance(g)
|
|
}
|
|
pv.Mark.prototype.index = -1;
|
|
delete this.index;
|
|
c.shift();
|
|
return this
|
|
};
|
|
a.buildProperties = function(b, c) {
|
|
for (var d = 0, f = c.length; d < f; d++) {
|
|
var g = c[d],
|
|
h = g.value;
|
|
switch (g.type) {
|
|
case 0:
|
|
case 1:
|
|
h = this.scene.defs[g.name].value;
|
|
break;
|
|
case 3:
|
|
h = h.apply(this, pv.Mark.stack);
|
|
break
|
|
}
|
|
b[g.name] = h
|
|
}
|
|
};
|
|
a.buildInstance = function(b) {
|
|
this.buildProperties(b, this.binds.required);
|
|
if (b.visible) {
|
|
this.buildProperties(b, this.binds.optional);
|
|
this.buildImplied(b)
|
|
}
|
|
};
|
|
a.buildImplied = function(b) {
|
|
var c = b.left,
|
|
d = b.right,
|
|
f = b.top,
|
|
g = b.bottom,
|
|
h = this.properties,
|
|
i = h.width ? b.width : 0,
|
|
j = h.height ? b.height : 0,
|
|
k = this.parent ? this.parent.width() : i + c + d;
|
|
if (i == null) i = k - (d = d || 0) - (c = c || 0);
|
|
else if (d == null)
|
|
if (c == null) c = d = (k - i) / 2;
|
|
else d = k - i - (c = c || 0);
|
|
else if (c == null) c = k - i - d;
|
|
k = this.parent ? this.parent.height() : j + f + g;
|
|
if (j == null) j = k - (f = f || 0) - (g = g || 0);
|
|
else if (g == null) g = f == null ? (f = (k - j) / 2) : k - j - (f = f || 0);
|
|
else if (f == null) f = k - j - g;
|
|
b.left = c;
|
|
b.right = d;
|
|
b.top = f;
|
|
b.bottom = g;
|
|
if (h.width) b.width = i;
|
|
if (h.height) b.height =
|
|
j;
|
|
if (h.textStyle && !b.textStyle) b.textStyle = pv.Color.transparent;
|
|
if (h.fillStyle && !b.fillStyle) b.fillStyle = pv.Color.transparent;
|
|
if (h.strokeStyle && !b.strokeStyle) b.strokeStyle = pv.Color.transparent
|
|
};
|
|
a.mouse = function() {
|
|
var b = pv.event.pageX || 0,
|
|
c = pv.event.pageY || 0,
|
|
d = this.root.canvas();
|
|
do {
|
|
b -= d.offsetLeft;
|
|
c -= d.offsetTop
|
|
} while (d = d.offsetParent);
|
|
d = pv.Transform.identity;
|
|
var f = this.properties.transform ? this : this.parent,
|
|
g = [];
|
|
do g.push(f); while (f = f.parent);
|
|
for (; f = g.pop();) d = d.translate(f.left(), f.top()).times(f.transform());
|
|
d = d.invert();
|
|
return pv.vector(b * d.k + d.x, c * d.k + d.y)
|
|
};
|
|
a.event = function(b, c) {
|
|
this.$handlers[b] = pv.functor(c);
|
|
return this
|
|
};
|
|
a.context = function(b, c, d) {
|
|
function f(l, q) {
|
|
pv.Mark.scene = l;
|
|
h.index = q;
|
|
if (l) {
|
|
var n = l.mark,
|
|
p = n,
|
|
m = [];
|
|
do {
|
|
m.push(p);
|
|
i.push(l[q].data);
|
|
p.index = q;
|
|
p.scene = l;
|
|
q = l.parentIndex;
|
|
l = l.parent
|
|
} while (p = p.parent);
|
|
l = m.length - 1;
|
|
for (q = 1; l > 0; l--) {
|
|
p = m[l];
|
|
p.scale = q;
|
|
q *= p.scene[p.index].transform.k
|
|
}
|
|
if (n.children) {
|
|
l = 0;
|
|
for (m = n.children.length; l < m; l++) {
|
|
p = n.children[l];
|
|
p.scene = n.scene[n.index].children[l];
|
|
p.scale = q
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function g(l) {
|
|
if (l) {
|
|
l = l.mark;
|
|
var q;
|
|
if (l.children)
|
|
for (var n = 0, p = l.children.length; n < p; n++) {
|
|
q = l.children[n];
|
|
delete q.scene;
|
|
delete q.scale
|
|
}
|
|
q = l;
|
|
do {
|
|
i.pop();
|
|
if (q.parent) {
|
|
delete q.scene;
|
|
delete q.scale
|
|
}
|
|
delete q.index
|
|
} while (q = q.parent)
|
|
}
|
|
}
|
|
var h = pv.Mark.prototype,
|
|
i = pv.Mark.stack,
|
|
j = pv.Mark.scene,
|
|
k = h.index;
|
|
g(j, k);
|
|
f(b, c);
|
|
try {
|
|
d.apply(this, i)
|
|
} finally {
|
|
g(b, c);
|
|
f(j, k)
|
|
}
|
|
};
|
|
pv.Mark.dispatch = function(b, c, d) {
|
|
var f = c.mark,
|
|
g = c.parent,
|
|
h = f.$handlers[b];
|
|
if (!h) return g && pv.Mark.dispatch(b, g, c.parentIndex);
|
|
f.context(c, d, function() {
|
|
(f = h.apply(f, pv.Mark.stack)) && f.render && f.render()
|
|
});
|
|
return true
|
|
};
|
|
pv.Anchor = function(b) {
|
|
pv.Mark.call(this);
|
|
this.target = b;
|
|
this.parent = b.parent
|
|
};
|
|
pv.Anchor.prototype = pv.extend(pv.Mark).property("name", String);
|
|
pv.Anchor.prototype.extend = function(b) {
|
|
this.proto = b;
|
|
return this
|
|
};
|
|
pv.Area = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Area.prototype = pv.extend(pv.Mark).property("width", Number).property("height", Number).property("lineWidth", Number).property("strokeStyle", pv.color).property("fillStyle", pv.color).property("segmented", Boolean).property("interpolate", String).property("tension", Number);
|
|
pv.Area.prototype.type = "area";
|
|
pv.Area.prototype.defaults = (new pv.Area).extend(pv.Mark.prototype.defaults).lineWidth(1.5).fillStyle(pv.Colors.category20().by(pv.parent)).interpolate("linear").tension(0.7);
|
|
pv.Area.prototype.buildImplied = function(b) {
|
|
if (b.height == null) b.height = 0;
|
|
if (b.width == null) b.width = 0;
|
|
pv.Mark.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.Area.fixed = {
|
|
lineWidth: 1,
|
|
lineJoin: 1,
|
|
strokeStyle: 1,
|
|
fillStyle: 1,
|
|
segmented: 1,
|
|
interpolate: 1,
|
|
tension: 1
|
|
};
|
|
pv.Area.prototype.bind = function() {
|
|
pv.Mark.prototype.bind.call(this);
|
|
var b = this.binds,
|
|
c = b.required;
|
|
b = b.optional;
|
|
for (var d = 0, f = b.length; d < f; d++) {
|
|
var g = b[d];
|
|
g.fixed = g.name in pv.Area.fixed;
|
|
if (g.name == "segmented") {
|
|
c.push(g);
|
|
b.splice(d, 1);
|
|
d--;
|
|
f--
|
|
}
|
|
}
|
|
this.binds.$required = c;
|
|
this.binds.$optional = b
|
|
};
|
|
pv.Area.prototype.buildInstance = function(b) {
|
|
var c = this.binds;
|
|
if (this.index) {
|
|
var d = c.fixed;
|
|
if (!d) {
|
|
d = c.fixed = [];
|
|
|
|
function f(i) {
|
|
return !i.fixed || (d.push(i), false)
|
|
}
|
|
c.required = c.required.filter(f);
|
|
if (!this.scene[0].segmented) c.optional = c.optional.filter(f)
|
|
}
|
|
c = 0;
|
|
for (var g = d.length; c < g; c++) {
|
|
var h = d[c].name;
|
|
b[h] = this.scene[0][h]
|
|
}
|
|
} else {
|
|
c.required = c.$required;
|
|
c.optional = c.$optional;
|
|
c.fixed = null
|
|
}
|
|
pv.Mark.prototype.buildInstance.call(this, b)
|
|
};
|
|
pv.Area.prototype.anchor = function(b) {
|
|
return pv.Mark.prototype.anchor.call(this, b).interpolate(function() {
|
|
return this.scene.target[this.index].interpolate
|
|
}).eccentricity(function() {
|
|
return this.scene.target[this.index].eccentricity
|
|
}).tension(function() {
|
|
return this.scene.target[this.index].tension
|
|
})
|
|
};
|
|
pv.Bar = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Bar.prototype = pv.extend(pv.Mark).property("width", Number).property("height", Number).property("lineWidth", Number).property("strokeStyle", pv.color).property("fillStyle", pv.color);
|
|
pv.Bar.prototype.type = "bar";
|
|
pv.Bar.prototype.defaults = (new pv.Bar).extend(pv.Mark.prototype.defaults).lineWidth(1.5).fillStyle(pv.Colors.category20().by(pv.parent));
|
|
pv.Dot = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Dot.prototype = pv.extend(pv.Mark).property("size", Number).property("radius", Number).property("shape", String).property("angle", Number).property("lineWidth", Number).property("strokeStyle", pv.color).property("fillStyle", pv.color);
|
|
pv.Dot.prototype.type = "dot";
|
|
pv.Dot.prototype.defaults = (new pv.Dot).extend(pv.Mark.prototype.defaults).size(20).shape("circle").lineWidth(1.5).strokeStyle(pv.Colors.category10().by(pv.parent));
|
|
pv.Dot.prototype.anchor = function(b) {
|
|
return pv.Mark.prototype.anchor.call(this, b).left(function() {
|
|
var c = this.scene.target[this.index];
|
|
switch (this.name()) {
|
|
case "bottom":
|
|
case "top":
|
|
case "center":
|
|
return c.left;
|
|
case "left":
|
|
return null
|
|
}
|
|
return c.left + c.radius
|
|
}).right(function() {
|
|
var c = this.scene.target[this.index];
|
|
return this.name() == "left" ? c.right + c.radius : null
|
|
}).top(function() {
|
|
var c = this.scene.target[this.index];
|
|
switch (this.name()) {
|
|
case "left":
|
|
case "right":
|
|
case "center":
|
|
return c.top;
|
|
case "top":
|
|
return null
|
|
}
|
|
return c.top +
|
|
c.radius
|
|
}).bottom(function() {
|
|
var c = this.scene.target[this.index];
|
|
return this.name() == "top" ? c.bottom + c.radius : null
|
|
}).textAlign(function() {
|
|
switch (this.name()) {
|
|
case "left":
|
|
return "right";
|
|
case "bottom":
|
|
case "top":
|
|
case "center":
|
|
return "center"
|
|
}
|
|
return "left"
|
|
}).textBaseline(function() {
|
|
switch (this.name()) {
|
|
case "right":
|
|
case "left":
|
|
case "center":
|
|
return "middle";
|
|
case "bottom":
|
|
return "top"
|
|
}
|
|
return "bottom"
|
|
})
|
|
};
|
|
pv.Dot.prototype.buildImplied = function(b) {
|
|
if (b.radius == null) b.radius = Math.sqrt(b.size);
|
|
else if (b.size == null) b.size = b.radius * b.radius;
|
|
pv.Mark.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.Label = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Label.prototype = pv.extend(pv.Mark).property("text", String).property("font", String).property("textAngle", Number).property("textStyle", pv.color).property("textAlign", String).property("textBaseline", String).property("textMargin", Number).property("textDecoration", String).property("textShadow", String);
|
|
pv.Label.prototype.type = "label";
|
|
pv.Label.prototype.defaults = (new pv.Label).extend(pv.Mark.prototype.defaults).events("none").text(pv.identity).font("10px sans-serif").textAngle(0).textStyle("black").textAlign("left").textBaseline("bottom").textMargin(3);
|
|
pv.Line = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Line.prototype = pv.extend(pv.Mark).property("lineWidth", Number).property("lineJoin", String).property("strokeStyle", pv.color).property("fillStyle", pv.color).property("segmented", Boolean).property("interpolate", String).property("eccentricity", Number).property("tension", Number);
|
|
a = pv.Line.prototype;
|
|
a.type = "line";
|
|
a.defaults = (new pv.Line).extend(pv.Mark.prototype.defaults).lineJoin("miter").lineWidth(1.5).strokeStyle(pv.Colors.category10().by(pv.parent)).interpolate("linear").eccentricity(0).tension(0.7);
|
|
a.bind = pv.Area.prototype.bind;
|
|
a.buildInstance = pv.Area.prototype.buildInstance;
|
|
a.anchor = function(b) {
|
|
return pv.Area.prototype.anchor.call(this, b).textAlign(function() {
|
|
switch (this.name()) {
|
|
case "left":
|
|
return "right";
|
|
case "bottom":
|
|
case "top":
|
|
case "center":
|
|
return "center";
|
|
case "right":
|
|
return "left"
|
|
}
|
|
}).textBaseline(function() {
|
|
switch (this.name()) {
|
|
case "right":
|
|
case "left":
|
|
case "center":
|
|
return "middle";
|
|
case "top":
|
|
return "bottom";
|
|
case "bottom":
|
|
return "top"
|
|
}
|
|
})
|
|
};
|
|
pv.Rule = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Rule.prototype = pv.extend(pv.Mark).property("width", Number).property("height", Number).property("lineWidth", Number).property("strokeStyle", pv.color);
|
|
pv.Rule.prototype.type = "rule";
|
|
pv.Rule.prototype.defaults = (new pv.Rule).extend(pv.Mark.prototype.defaults).lineWidth(1).strokeStyle("black").antialias(false);
|
|
pv.Rule.prototype.anchor = pv.Line.prototype.anchor;
|
|
pv.Rule.prototype.buildImplied = function(b) {
|
|
var c = b.left,
|
|
d = b.right;
|
|
if (b.width != null || c == null && d == null || d != null && c != null) b.height = 0;
|
|
else b.width = 0;
|
|
pv.Mark.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.Panel = function() {
|
|
pv.Bar.call(this);
|
|
this.children = [];
|
|
this.root = this;
|
|
this.$dom = pv.$ && pv.$.s
|
|
};
|
|
pv.Panel.prototype = pv.extend(pv.Bar).property("transform").property("overflow", String).property("canvas", function(b) {
|
|
return typeof b == "string" ? document.getElementById(b) : b
|
|
});
|
|
a = pv.Panel.prototype;
|
|
a.type = "panel";
|
|
a.defaults = (new pv.Panel).extend(pv.Bar.prototype.defaults).fillStyle(null).overflow("visible");
|
|
a.anchor = function(b) {
|
|
b = pv.Bar.prototype.anchor.call(this, b);
|
|
b.parent = this;
|
|
return b
|
|
};
|
|
a.add = function(b) {
|
|
b = new b;
|
|
b.parent = this;
|
|
b.root = this.root;
|
|
b.childIndex = this.children.length;
|
|
this.children.push(b);
|
|
return b
|
|
};
|
|
a.bind = function() {
|
|
pv.Mark.prototype.bind.call(this);
|
|
for (var b = 0; b < this.children.length; b++) this.children[b].bind()
|
|
};
|
|
a.buildInstance = function(b) {
|
|
pv.Bar.prototype.buildInstance.call(this, b);
|
|
if (b.visible) {
|
|
if (!b.children) b.children = [];
|
|
var c = this.scale * b.transform.k,
|
|
d, f = this.children.length;
|
|
pv.Mark.prototype.index = -1;
|
|
for (var g = 0; g < f; g++) {
|
|
d = this.children[g];
|
|
d.scene = b.children[g];
|
|
d.scale = c;
|
|
d.build()
|
|
}
|
|
for (g = 0; g < f; g++) {
|
|
d = this.children[g];
|
|
b.children[g] = d.scene;
|
|
delete d.scene;
|
|
delete d.scale
|
|
}
|
|
b.children.length = f
|
|
}
|
|
};
|
|
a.buildImplied = function(b) {
|
|
if (!this.parent) {
|
|
var c = b.canvas;
|
|
if (c) {
|
|
if (c.$panel != this)
|
|
for (c.$panel = this; c.lastChild;) c.removeChild(c.lastChild);
|
|
var d;
|
|
if (b.width == null) {
|
|
d = parseFloat(pv.css(c, "width"));
|
|
b.width = d - b.left - b.right
|
|
}
|
|
if (b.height == null) {
|
|
d = parseFloat(pv.css(c, "height"));
|
|
b.height = d - b.top - b.bottom
|
|
}
|
|
} else {
|
|
d = this.$canvas || (this.$canvas = []);
|
|
if (!(c = d[this.index])) {
|
|
c = d[this.index] = document.createElement("span");
|
|
if (this.$dom) this.$dom.parentNode.insertBefore(c, this.$dom);
|
|
else {
|
|
for (d = document.body; d.lastChild &&
|
|
d.lastChild.tagName;) d = d.lastChild;
|
|
if (d != document.body) d = d.parentNode;
|
|
d.appendChild(c)
|
|
}
|
|
}
|
|
}
|
|
b.canvas = c
|
|
}
|
|
if (!b.transform) b.transform = pv.Transform.identity;
|
|
pv.Mark.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.Image = function() {
|
|
pv.Bar.call(this)
|
|
};
|
|
pv.Image.prototype = pv.extend(pv.Bar).property("url", String).property("imageWidth", Number).property("imageHeight", Number);
|
|
a = pv.Image.prototype;
|
|
a.type = "image";
|
|
a.defaults = (new pv.Image).extend(pv.Bar.prototype.defaults).fillStyle(null);
|
|
a.image = function(b) {
|
|
this.$image = function() {
|
|
var c = b.apply(this, arguments);
|
|
return c == null ? pv.Color.transparent : typeof c == "string" ? pv.color(c) : c
|
|
};
|
|
return this
|
|
};
|
|
a.bind = function() {
|
|
pv.Bar.prototype.bind.call(this);
|
|
var b = this.binds,
|
|
c = this;
|
|
do b.image = c.$image; while (!b.image && (c = c.proto))
|
|
};
|
|
a.buildImplied = function(b) {
|
|
pv.Bar.prototype.buildImplied.call(this, b);
|
|
if (b.visible) {
|
|
if (b.imageWidth == null) b.imageWidth = b.width;
|
|
if (b.imageHeight == null) b.imageHeight = b.height;
|
|
if (b.url == null && this.binds.image) {
|
|
var c = this.$canvas || (this.$canvas = document.createElement("canvas")),
|
|
d = c.getContext("2d"),
|
|
f = b.imageWidth,
|
|
g = b.imageHeight,
|
|
h = pv.Mark.stack;
|
|
c.width = f;
|
|
c.height = g;
|
|
b = (b.image = d.createImageData(f, g)).data;
|
|
h.unshift(null, null);
|
|
for (d = c = 0; c < g; c++) {
|
|
h[1] = c;
|
|
for (var i = 0; i < f; i++) {
|
|
h[0] = i;
|
|
var j = this.binds.image.apply(this,
|
|
h);
|
|
b[d++] = j.r;
|
|
b[d++] = j.g;
|
|
b[d++] = j.b;
|
|
b[d++] = 255 * j.a
|
|
}
|
|
}
|
|
h.splice(0, 2)
|
|
}
|
|
}
|
|
};
|
|
pv.Wedge = function() {
|
|
pv.Mark.call(this)
|
|
};
|
|
pv.Wedge.prototype = pv.extend(pv.Mark).property("startAngle", Number).property("endAngle", Number).property("angle", Number).property("innerRadius", Number).property("outerRadius", Number).property("lineWidth", Number).property("strokeStyle", pv.color).property("fillStyle", pv.color);
|
|
a = pv.Wedge.prototype;
|
|
a.type = "wedge";
|
|
a.defaults = (new pv.Wedge).extend(pv.Mark.prototype.defaults).startAngle(function() {
|
|
var b = this.sibling();
|
|
return b ? b.endAngle : -Math.PI / 2
|
|
}).innerRadius(0).lineWidth(1.5).strokeStyle(null).fillStyle(pv.Colors.category20().by(pv.index));
|
|
a.midRadius = function() {
|
|
return (this.innerRadius() + this.outerRadius()) / 2
|
|
};
|
|
a.midAngle = function() {
|
|
return (this.startAngle() + this.endAngle()) / 2
|
|
};
|
|
a.anchor = function(b) {
|
|
function c(g) {
|
|
return g.innerRadius || g.angle < 2 * Math.PI
|
|
}
|
|
|
|
function d(g) {
|
|
return (g.innerRadius + g.outerRadius) / 2
|
|
}
|
|
|
|
function f(g) {
|
|
return (g.startAngle + g.endAngle) / 2
|
|
}
|
|
return pv.Mark.prototype.anchor.call(this, b).left(function() {
|
|
var g = this.scene.target[this.index];
|
|
if (c(g)) switch (this.name()) {
|
|
case "outer":
|
|
return g.left + g.outerRadius * Math.cos(f(g));
|
|
case "inner":
|
|
return g.left + g.innerRadius * Math.cos(f(g));
|
|
case "start":
|
|
return g.left + d(g) * Math.cos(g.startAngle);
|
|
case "center":
|
|
return g.left + d(g) * Math.cos(f(g));
|
|
case "end":
|
|
return g.left + d(g) * Math.cos(g.endAngle)
|
|
}
|
|
return g.left
|
|
}).top(function() {
|
|
var g = this.scene.target[this.index];
|
|
if (c(g)) switch (this.name()) {
|
|
case "outer":
|
|
return g.top + g.outerRadius * Math.sin(f(g));
|
|
case "inner":
|
|
return g.top + g.innerRadius * Math.sin(f(g));
|
|
case "start":
|
|
return g.top + d(g) * Math.sin(g.startAngle);
|
|
case "center":
|
|
return g.top + d(g) * Math.sin(f(g));
|
|
case "end":
|
|
return g.top + d(g) * Math.sin(g.endAngle)
|
|
}
|
|
return g.top
|
|
}).textAlign(function() {
|
|
var g = this.scene.target[this.index];
|
|
if (c(g)) switch (this.name()) {
|
|
case "outer":
|
|
return pv.Wedge.upright(f(g)) ?
|
|
"right" : "left";
|
|
case "inner":
|
|
return pv.Wedge.upright(f(g)) ? "left" : "right"
|
|
}
|
|
return "center"
|
|
}).textBaseline(function() {
|
|
var g = this.scene.target[this.index];
|
|
if (c(g)) switch (this.name()) {
|
|
case "start":
|
|
return pv.Wedge.upright(g.startAngle) ? "top" : "bottom";
|
|
case "end":
|
|
return pv.Wedge.upright(g.endAngle) ? "bottom" : "top"
|
|
}
|
|
return "middle"
|
|
}).textAngle(function() {
|
|
var g = this.scene.target[this.index],
|
|
h = 0;
|
|
if (c(g)) switch (this.name()) {
|
|
case "center":
|
|
case "inner":
|
|
case "outer":
|
|
h = f(g);
|
|
break;
|
|
case "start":
|
|
h = g.startAngle;
|
|
break;
|
|
case "end":
|
|
h =
|
|
g.endAngle;
|
|
break
|
|
}
|
|
return pv.Wedge.upright(h) ? h : h + Math.PI
|
|
})
|
|
};
|
|
pv.Wedge.upright = function(b) {
|
|
b %= 2 * Math.PI;
|
|
b = b < 0 ? 2 * Math.PI + b : b;
|
|
return b < Math.PI / 2 || b >= 3 * Math.PI / 2
|
|
};
|
|
pv.Wedge.prototype.buildImplied = function(b) {
|
|
if (b.angle == null) b.angle = b.endAngle - b.startAngle;
|
|
else if (b.endAngle == null) b.endAngle = b.startAngle + b.angle;
|
|
pv.Mark.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.simulation = function(b) {
|
|
return new pv.Simulation(b)
|
|
};
|
|
pv.Simulation = function(b) {
|
|
for (var c = 0; c < b.length; c++) this.particle(b[c])
|
|
};
|
|
a = pv.Simulation.prototype;
|
|
a.particle = function(b) {
|
|
b.next = this.particles;
|
|
if (isNaN(b.px)) b.px = b.x;
|
|
if (isNaN(b.py)) b.py = b.y;
|
|
if (isNaN(b.fx)) b.fx = 0;
|
|
if (isNaN(b.fy)) b.fy = 0;
|
|
this.particles = b;
|
|
return this
|
|
};
|
|
a.force = function(b) {
|
|
b.next = this.forces;
|
|
this.forces = b;
|
|
return this
|
|
};
|
|
a.constraint = function(b) {
|
|
b.next = this.constraints;
|
|
this.constraints = b;
|
|
return this
|
|
};
|
|
a.stabilize = function(b) {
|
|
var c;
|
|
arguments.length || (b = 3);
|
|
for (var d = 0; d < b; d++) {
|
|
var f = new pv.Quadtree(this.particles);
|
|
for (c = this.constraints; c; c = c.next) c.apply(this.particles, f)
|
|
}
|
|
for (c = this.particles; c; c = c.next) {
|
|
c.px = c.x;
|
|
c.py = c.y
|
|
}
|
|
return this
|
|
};
|
|
a.step = function() {
|
|
var b;
|
|
for (b = this.particles; b; b = b.next) {
|
|
var c = b.px,
|
|
d = b.py;
|
|
b.px = b.x;
|
|
b.py = b.y;
|
|
b.x += b.vx = b.x - c + b.fx;
|
|
b.y += b.vy = b.y - d + b.fy
|
|
}
|
|
c = new pv.Quadtree(this.particles);
|
|
for (b = this.constraints; b; b = b.next) b.apply(this.particles, c);
|
|
for (b = this.particles; b; b = b.next) b.fx = b.fy = 0;
|
|
for (b = this.forces; b; b = b.next) b.apply(this.particles, c)
|
|
};
|
|
pv.Quadtree = function(b) {
|
|
function c(l, q, n, p, m, r) {
|
|
if (!(isNaN(q.x) || isNaN(q.y)))
|
|
if (l.leaf)
|
|
if (l.p) {
|
|
if (!(Math.abs(l.p.x - q.x) + Math.abs(l.p.y - q.y) < 0.01)) {
|
|
var s = l.p;
|
|
l.p = null;
|
|
d(l, s, n, p, m, r)
|
|
}
|
|
d(l, q, n, p, m, r)
|
|
} else l.p = q;
|
|
else d(l, q, n, p, m, r)
|
|
}
|
|
|
|
function d(l, q, n, p, m, r) {
|
|
var s = (n + m) * 0.5,
|
|
t = (p + r) * 0.5,
|
|
x = q.x >= s,
|
|
u = q.y >= t;
|
|
l.leaf = false;
|
|
switch ((u << 1) + x) {
|
|
case 0:
|
|
l = l.c1 || (l.c1 = new pv.Quadtree.Node);
|
|
break;
|
|
case 1:
|
|
l = l.c2 || (l.c2 = new pv.Quadtree.Node);
|
|
break;
|
|
case 2:
|
|
l = l.c3 || (l.c3 = new pv.Quadtree.Node);
|
|
break;
|
|
case 3:
|
|
l = l.c4 || (l.c4 = new pv.Quadtree.Node);
|
|
break
|
|
}
|
|
if (x) n = s;
|
|
else m = s;
|
|
if (u) p = t;
|
|
else r = t;
|
|
c(l, q, n, p, m, r)
|
|
}
|
|
var f, g = Number.POSITIVE_INFINITY,
|
|
h = g,
|
|
i = Number.NEGATIVE_INFINITY,
|
|
j = i;
|
|
for (f = b; f; f = f.next) {
|
|
if (f.x < g) g = f.x;
|
|
if (f.y < h) h = f.y;
|
|
if (f.x > i) i = f.x;
|
|
if (f.y > j) j = f.y
|
|
}
|
|
f = i - g;
|
|
var k = j - h;
|
|
if (f > k) j = h + f;
|
|
else i = g + k;
|
|
this.xMin = g;
|
|
this.yMin = h;
|
|
this.xMax = i;
|
|
this.yMax = j;
|
|
this.root = new pv.Quadtree.Node;
|
|
for (f = b; f; f = f.next) c(this.root, f, g, h, i, j)
|
|
};
|
|
pv.Quadtree.Node = function() {
|
|
this.leaf = true;
|
|
this.p = this.c4 = this.c3 = this.c2 = this.c1 = null
|
|
};
|
|
pv.Force = {};
|
|
pv.Force.charge = function(b) {
|
|
function c(l) {
|
|
function q(m) {
|
|
c(m);
|
|
l.cn += m.cn;
|
|
n += m.cn * m.cx;
|
|
p += m.cn * m.cy
|
|
}
|
|
var n = 0,
|
|
p = 0;
|
|
l.cn = 0;
|
|
if (!l.leaf) {
|
|
l.c1 && q(l.c1);
|
|
l.c2 && q(l.c2);
|
|
l.c3 && q(l.c3);
|
|
l.c4 && q(l.c4)
|
|
}
|
|
if (l.p) {
|
|
l.cn += b;
|
|
n += b * l.p.x;
|
|
p += b * l.p.y
|
|
}
|
|
l.cx = n / l.cn;
|
|
l.cy = p / l.cn
|
|
}
|
|
|
|
function d(l, q, n, p, m, r) {
|
|
var s = l.cx - q.x,
|
|
t = l.cy - q.y,
|
|
x = 1 / Math.sqrt(s * s + t * t);
|
|
if (l.leaf && l.p != q || (m - n) * x < j) {
|
|
if (!(x < i)) {
|
|
if (x > g) x = g;
|
|
l = l.cn * x * x * x;
|
|
s = s * l;
|
|
t = t * l;
|
|
q.fx += s;
|
|
q.fy += t
|
|
}
|
|
} else if (!l.leaf) {
|
|
var u = (n + m) * 0.5,
|
|
o = (p + r) * 0.5;
|
|
l.c1 && d(l.c1, q, n, p, u, o);
|
|
l.c2 && d(l.c2, q, u, p,
|
|
m, o);
|
|
l.c3 && d(l.c3, q, n, o, u, r);
|
|
l.c4 && d(l.c4, q, u, o, m, r);
|
|
if (!(x < i)) {
|
|
if (x > g) x = g;
|
|
if (l.p && l.p != q) {
|
|
l = b * x * x * x;
|
|
s = s * l;
|
|
t = t * l;
|
|
q.fx += s;
|
|
q.fy += t
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var f = 2,
|
|
g = 1 / f,
|
|
h = 500,
|
|
i = 1 / h,
|
|
j = 0.9,
|
|
k = {};
|
|
arguments.length || (b = -40);
|
|
k.constant = function(l) {
|
|
if (arguments.length) {
|
|
b = Number(l);
|
|
return k
|
|
}
|
|
return b
|
|
};
|
|
k.domain = function(l, q) {
|
|
if (arguments.length) {
|
|
f = Number(l);
|
|
g = 1 / f;
|
|
h = Number(q);
|
|
i = 1 / h;
|
|
return k
|
|
}
|
|
return [f, h]
|
|
};
|
|
k.theta = function(l) {
|
|
if (arguments.length) {
|
|
j = Number(l);
|
|
return k
|
|
}
|
|
return j
|
|
};
|
|
k.apply = function(l, q) {
|
|
c(q.root);
|
|
for (l = l; l; l = l.next) d(q.root,
|
|
l, q.xMin, q.yMin, q.xMax, q.yMax)
|
|
};
|
|
return k
|
|
};
|
|
pv.Force.drag = function(b) {
|
|
var c = {};
|
|
arguments.length || (b = 0.1);
|
|
c.constant = function(d) {
|
|
if (arguments.length) {
|
|
b = d;
|
|
return c
|
|
}
|
|
return b
|
|
};
|
|
c.apply = function(d) {
|
|
if (b)
|
|
for (d = d; d; d = d.next) {
|
|
d.fx -= b * d.vx;
|
|
d.fy -= b * d.vy
|
|
}
|
|
};
|
|
return c
|
|
};
|
|
pv.Force.spring = function(b) {
|
|
var c = 0.1,
|
|
d = 20,
|
|
f, g, h = {};
|
|
arguments.length || (b = 0.1);
|
|
h.links = function(i) {
|
|
if (arguments.length) {
|
|
f = i;
|
|
g = i.map(function(j) {
|
|
return 1 / Math.sqrt(Math.max(j.sourceNode.linkDegree, j.targetNode.linkDegree))
|
|
});
|
|
return h
|
|
}
|
|
return f
|
|
};
|
|
h.constant = function(i) {
|
|
if (arguments.length) {
|
|
b = Number(i);
|
|
return h
|
|
}
|
|
return b
|
|
};
|
|
h.damping = function(i) {
|
|
if (arguments.length) {
|
|
c = Number(i);
|
|
return h
|
|
}
|
|
return c
|
|
};
|
|
h.length = function(i) {
|
|
if (arguments.length) {
|
|
d = Number(i);
|
|
return h
|
|
}
|
|
return d
|
|
};
|
|
h.apply = function() {
|
|
for (var i = 0; i < f.length; i++) {
|
|
var j =
|
|
f[i].sourceNode,
|
|
k = f[i].targetNode,
|
|
l = j.x - k.x,
|
|
q = j.y - k.y,
|
|
n = Math.sqrt(l * l + q * q),
|
|
p = n ? 1 / n : 1;
|
|
p = (b * g[i] * (n - d) + c * g[i] * (l * (j.vx - k.vx) + q * (j.vy - k.vy)) * p) * p;
|
|
l = -p * (n ? l : 0.01 * (0.5 - Math.random()));
|
|
q = -p * (n ? q : 0.01 * (0.5 - Math.random()));
|
|
j.fx += l;
|
|
j.fy += q;
|
|
k.fx -= l;
|
|
k.fy -= q
|
|
}
|
|
};
|
|
return h
|
|
};
|
|
pv.Constraint = {};
|
|
pv.Constraint.collision = function(b) {
|
|
function c(l, q, n, p, m, r) {
|
|
if (!l.leaf) {
|
|
var s = (n + m) * 0.5,
|
|
t = (p + r) * 0.5,
|
|
x = t < j,
|
|
u = s > g,
|
|
o = s < i;
|
|
if (t > h) {
|
|
l.c1 && u && c(l.c1, q, n, p, s, t);
|
|
l.c2 && o && c(l.c2, q, s, p, m, t)
|
|
}
|
|
if (x) {
|
|
l.c3 && u && c(l.c3, q, n, t, s, r);
|
|
l.c4 && o && c(l.c4, q, s, t, m, r)
|
|
}
|
|
}
|
|
if (l.p && l.p != q) {
|
|
n = q.x - l.p.x;
|
|
p = q.y - l.p.y;
|
|
m = Math.sqrt(n * n + p * p);
|
|
r = f + b(l.p);
|
|
if (m < r) {
|
|
m = (m - r) / m * 0.5;
|
|
n *= m;
|
|
p *= m;
|
|
q.x -= n;
|
|
q.y -= p;
|
|
l.p.x += n;
|
|
l.p.y += p
|
|
}
|
|
}
|
|
}
|
|
var d = 1,
|
|
f, g, h, i, j, k = {};
|
|
arguments.length || (f = 10);
|
|
k.repeat = function(l) {
|
|
if (arguments.length) {
|
|
d = Number(l);
|
|
return k
|
|
}
|
|
return d
|
|
};
|
|
k.apply =
|
|
function(l, q) {
|
|
var n, p, m = -Infinity;
|
|
for (n = l; n; n = n.next) {
|
|
p = b(n);
|
|
if (p > m) m = p
|
|
}
|
|
for (var r = 0; r < d; r++)
|
|
for (n = l; n; n = n.next) {
|
|
p = (f = b(n)) + m;
|
|
g = n.x - p;
|
|
i = n.x + p;
|
|
h = n.y - p;
|
|
j = n.y + p;
|
|
c(q.root, n, q.xMin, q.yMin, q.xMax, q.yMax)
|
|
}
|
|
};
|
|
return k
|
|
};
|
|
pv.Constraint.position = function(b) {
|
|
var c = 1,
|
|
d = {};
|
|
arguments.length || (b = function(f) {
|
|
return f.fix
|
|
});
|
|
d.alpha = function(f) {
|
|
if (arguments.length) {
|
|
c = Number(f);
|
|
return d
|
|
}
|
|
return c
|
|
};
|
|
d.apply = function(f) {
|
|
for (f = f; f; f = f.next) {
|
|
var g = b(f);
|
|
if (g) {
|
|
f.x += (g.x - f.x) * c;
|
|
f.y += (g.y - f.y) * c;
|
|
f.fx = f.fy = f.vx = f.vy = 0
|
|
}
|
|
}
|
|
};
|
|
return d
|
|
};
|
|
pv.Constraint.bound = function() {
|
|
var b = {},
|
|
c, d;
|
|
b.x = function(f, g) {
|
|
if (arguments.length) {
|
|
c = {
|
|
min: Math.min(f, g),
|
|
max: Math.max(f, g)
|
|
};
|
|
return this
|
|
}
|
|
return c
|
|
};
|
|
b.y = function(f, g) {
|
|
if (arguments.length) {
|
|
d = {
|
|
min: Math.min(f, g),
|
|
max: Math.max(f, g)
|
|
};
|
|
return this
|
|
}
|
|
return d
|
|
};
|
|
b.apply = function(f) {
|
|
if (c)
|
|
for (var g = f; g; g = g.next) g.x = g.x < c.min ? c.min : g.x > c.max ? c.max : g.x;
|
|
if (d)
|
|
for (g = f; g; g = g.next) g.y = g.y < d.min ? d.min : g.y > d.max ? d.max : g.y
|
|
};
|
|
return b
|
|
};
|
|
pv.Layout = function() {
|
|
pv.Panel.call(this)
|
|
};
|
|
pv.Layout.prototype = pv.extend(pv.Panel);
|
|
pv.Layout.prototype.property = function(b, c) {
|
|
if (!this.hasOwnProperty("properties")) this.properties = pv.extend(this.properties);
|
|
this.properties[b] = true;
|
|
this.propertyMethod(b, false, pv.Mark.cast[b] = c);
|
|
return this
|
|
};
|
|
pv.Layout.Network = function() {
|
|
pv.Layout.call(this);
|
|
var b = this;
|
|
this.$id = pv.id();
|
|
(this.node = (new pv.Mark).data(function() {
|
|
return b.nodes()
|
|
}).strokeStyle("#1f77b4").fillStyle("#fff").left(function(c) {
|
|
return c.x
|
|
}).top(function(c) {
|
|
return c.y
|
|
})).parent = this;
|
|
this.link = (new pv.Mark).extend(this.node).data(function(c) {
|
|
return [c.sourceNode, c.targetNode]
|
|
}).fillStyle(null).lineWidth(function(c, d) {
|
|
return d.linkValue * 1.5
|
|
}).strokeStyle("rgba(0,0,0,.2)");
|
|
this.link.add = function(c) {
|
|
return b.add(pv.Panel).data(function() {
|
|
return b.links()
|
|
}).add(c).extend(this)
|
|
};
|
|
(this.label = (new pv.Mark).extend(this.node).textMargin(7).textBaseline("middle").text(function(c) {
|
|
return c.nodeName || c.nodeValue
|
|
}).textAngle(function(c) {
|
|
c = c.midAngle;
|
|
return pv.Wedge.upright(c) ? c : c + Math.PI
|
|
}).textAlign(function(c) {
|
|
return pv.Wedge.upright(c.midAngle) ? "left" : "right"
|
|
})).parent = this
|
|
};
|
|
pv.Layout.Network.prototype = pv.extend(pv.Layout).property("nodes", function(b) {
|
|
return b.map(function(c, d) {
|
|
if (typeof c != "object") c = {
|
|
nodeValue: c
|
|
};
|
|
c.index = d;
|
|
return c
|
|
})
|
|
}).property("links", function(b) {
|
|
return b.map(function(c) {
|
|
if (isNaN(c.linkValue)) c.linkValue = isNaN(c.value) ? 1 : c.value;
|
|
return c
|
|
})
|
|
});
|
|
pv.Layout.Network.prototype.reset = function() {
|
|
this.$id = pv.id();
|
|
return this
|
|
};
|
|
pv.Layout.Network.prototype.buildProperties = function(b, c) {
|
|
if ((b.$id || 0) < this.$id) pv.Layout.prototype.buildProperties.call(this, b, c)
|
|
};
|
|
pv.Layout.Network.prototype.buildImplied = function(b) {
|
|
pv.Layout.prototype.buildImplied.call(this, b);
|
|
if (b.$id >= this.$id) return true;
|
|
b.$id = this.$id;
|
|
b.nodes.forEach(function(c) {
|
|
c.linkDegree = 0
|
|
});
|
|
b.links.forEach(function(c) {
|
|
var d = c.linkValue;
|
|
(c.sourceNode || (c.sourceNode = b.nodes[c.source])).linkDegree += d;
|
|
(c.targetNode || (c.targetNode = b.nodes[c.target])).linkDegree += d
|
|
})
|
|
};
|
|
pv.Layout.Hierarchy = function() {
|
|
pv.Layout.Network.call(this);
|
|
this.link.strokeStyle("#ccc")
|
|
};
|
|
pv.Layout.Hierarchy.prototype = pv.extend(pv.Layout.Network);
|
|
pv.Layout.Hierarchy.prototype.buildImplied = function(b) {
|
|
if (!b.links) b.links = pv.Layout.Hierarchy.links.call(this);
|
|
pv.Layout.Network.prototype.buildImplied.call(this, b)
|
|
};
|
|
pv.Layout.Hierarchy.links = function() {
|
|
return this.nodes().filter(function(b) {
|
|
return b.parentNode
|
|
}).map(function(b) {
|
|
return {
|
|
sourceNode: b,
|
|
targetNode: b.parentNode,
|
|
linkValue: 1
|
|
}
|
|
})
|
|
};
|
|
pv.Layout.Hierarchy.NodeLink = {
|
|
buildImplied: function(b) {
|
|
function c(m) {
|
|
return m.parentNode ? m.depth * (n - q) + q : 0
|
|
}
|
|
|
|
function d(m) {
|
|
return m.parentNode ? (m.breadth - 0.25) * 2 * Math.PI : 0
|
|
}
|
|
|
|
function f(m) {
|
|
switch (i) {
|
|
case "left":
|
|
return m.depth * k;
|
|
case "right":
|
|
return k - m.depth * k;
|
|
case "top":
|
|
return m.breadth * k;
|
|
case "bottom":
|
|
return k - m.breadth * k;
|
|
case "radial":
|
|
return k / 2 + c(m) * Math.cos(m.midAngle)
|
|
}
|
|
}
|
|
|
|
function g(m) {
|
|
switch (i) {
|
|
case "left":
|
|
return m.breadth * l;
|
|
case "right":
|
|
return l - m.breadth * l;
|
|
case "top":
|
|
return m.depth * l;
|
|
case "bottom":
|
|
return l -
|
|
m.depth * l;
|
|
case "radial":
|
|
return l / 2 + c(m) * Math.sin(m.midAngle)
|
|
}
|
|
}
|
|
var h = b.nodes,
|
|
i = b.orient,
|
|
j = /^(top|bottom)$/.test(i),
|
|
k = b.width,
|
|
l = b.height;
|
|
if (i == "radial") {
|
|
var q = b.innerRadius,
|
|
n = b.outerRadius;
|
|
if (q == null) q = 0;
|
|
if (n == null) n = Math.min(k, l) / 2
|
|
}
|
|
for (b = 0; b < h.length; b++) {
|
|
var p = h[b];
|
|
p.midAngle = i == "radial" ? d(p) : j ? Math.PI / 2 : 0;
|
|
p.x = f(p);
|
|
p.y = g(p);
|
|
if (p.firstChild) p.midAngle += Math.PI
|
|
}
|
|
}
|
|
};
|
|
pv.Layout.Hierarchy.Fill = {
|
|
constructor: function() {
|
|
this.node.strokeStyle("#fff").fillStyle("#ccc").width(function(b) {
|
|
return b.dx
|
|
}).height(function(b) {
|
|
return b.dy
|
|
}).innerRadius(function(b) {
|
|
return b.innerRadius
|
|
}).outerRadius(function(b) {
|
|
return b.outerRadius
|
|
}).startAngle(function(b) {
|
|
return b.startAngle
|
|
}).angle(function(b) {
|
|
return b.angle
|
|
});
|
|
this.label.textAlign("center").left(function(b) {
|
|
return b.x + b.dx / 2
|
|
}).top(function(b) {
|
|
return b.y + b.dy / 2
|
|
});
|
|
delete this.link
|
|
},
|
|
buildImplied: function(b) {
|
|
function c(o, v) {
|
|
return (o +
|
|
v) / (1 + v)
|
|
}
|
|
|
|
function d(o) {
|
|
switch (n) {
|
|
case "left":
|
|
return c(o.minDepth, s) * m;
|
|
case "right":
|
|
return (1 - c(o.maxDepth, s)) * m;
|
|
case "top":
|
|
return o.minBreadth * m;
|
|
case "bottom":
|
|
return (1 - o.maxBreadth) * m;
|
|
case "radial":
|
|
return m / 2
|
|
}
|
|
}
|
|
|
|
function f(o) {
|
|
switch (n) {
|
|
case "left":
|
|
return o.minBreadth * r;
|
|
case "right":
|
|
return (1 - o.maxBreadth) * r;
|
|
case "top":
|
|
return c(o.minDepth, s) * r;
|
|
case "bottom":
|
|
return (1 - c(o.maxDepth, s)) * r;
|
|
case "radial":
|
|
return r / 2
|
|
}
|
|
}
|
|
|
|
function g(o) {
|
|
switch (n) {
|
|
case "left":
|
|
case "right":
|
|
return (o.maxDepth - o.minDepth) / (1 + s) * m;
|
|
case "top":
|
|
case "bottom":
|
|
return (o.maxBreadth -
|
|
o.minBreadth) * m;
|
|
case "radial":
|
|
return o.parentNode ? (o.innerRadius + o.outerRadius) * Math.cos(o.midAngle) : 0
|
|
}
|
|
}
|
|
|
|
function h(o) {
|
|
switch (n) {
|
|
case "left":
|
|
case "right":
|
|
return (o.maxBreadth - o.minBreadth) * r;
|
|
case "top":
|
|
case "bottom":
|
|
return (o.maxDepth - o.minDepth) / (1 + s) * r;
|
|
case "radial":
|
|
return o.parentNode ? (o.innerRadius + o.outerRadius) * Math.sin(o.midAngle) : 0
|
|
}
|
|
}
|
|
|
|
function i(o) {
|
|
return Math.max(0, c(o.minDepth, s / 2)) * (x - t) + t
|
|
}
|
|
|
|
function j(o) {
|
|
return c(o.maxDepth, s / 2) * (x - t) + t
|
|
}
|
|
|
|
function k(o) {
|
|
return (o.parentNode ? o.minBreadth - 0.25 : 0) *
|
|
2 * Math.PI
|
|
}
|
|
|
|
function l(o) {
|
|
return (o.parentNode ? o.maxBreadth - o.minBreadth : 1) * 2 * Math.PI
|
|
}
|
|
var q = b.nodes,
|
|
n = b.orient,
|
|
p = /^(top|bottom)$/.test(n),
|
|
m = b.width,
|
|
r = b.height,
|
|
s = -q[0].minDepth;
|
|
if (n == "radial") {
|
|
var t = b.innerRadius,
|
|
x = b.outerRadius;
|
|
if (t == null) t = 0;
|
|
if (t) s *= 2;
|
|
if (x == null) x = Math.min(m, r) / 2
|
|
}
|
|
for (b = 0; b < q.length; b++) {
|
|
var u = q[b];
|
|
u.x = d(u);
|
|
u.y = f(u);
|
|
if (n == "radial") {
|
|
u.innerRadius = i(u);
|
|
u.outerRadius = j(u);
|
|
u.startAngle = k(u);
|
|
u.angle = l(u);
|
|
u.midAngle = u.startAngle + u.angle / 2
|
|
} else u.midAngle = p ? -Math.PI / 2 : 0;
|
|
u.dx = g(u);
|
|
u.dy = h(u)
|
|
}
|
|
}
|
|
};
|
|
pv.Layout.Grid = function() {
|
|
pv.Layout.call(this);
|
|
var b = this;
|
|
(this.cell = (new pv.Mark).data(function() {
|
|
return b.scene[b.index].$grid
|
|
}).width(function() {
|
|
return b.width() / b.cols()
|
|
}).height(function() {
|
|
return b.height() / b.rows()
|
|
}).left(function() {
|
|
return this.width() * (this.index % b.cols())
|
|
}).top(function() {
|
|
return this.height() * Math.floor(this.index / b.cols())
|
|
})).parent = this
|
|
};
|
|
pv.Layout.Grid.prototype = pv.extend(pv.Layout).property("rows").property("cols");
|
|
pv.Layout.Grid.prototype.defaults = (new pv.Layout.Grid).extend(pv.Layout.prototype.defaults).rows(1).cols(1);
|
|
pv.Layout.Grid.prototype.buildImplied = function(b) {
|
|
pv.Layout.prototype.buildImplied.call(this, b);
|
|
var c = b.rows,
|
|
d = b.cols;
|
|
if (typeof d == "object") c = pv.transpose(d);
|
|
if (typeof c == "object") {
|
|
b.$grid = pv.blend(c);
|
|
b.rows = c.length;
|
|
b.cols = c[0] ? c[0].length : 0
|
|
} else b.$grid = pv.repeat([b.data], c * d)
|
|
};
|
|
pv.Layout.Stack = function() {
|
|
function b(i) {
|
|
return function() {
|
|
return f[i](this.parent.index, this.index)
|
|
}
|
|
}
|
|
pv.Layout.call(this);
|
|
var c = this,
|
|
d = function() {
|
|
return null
|
|
},
|
|
f = {
|
|
t: d,
|
|
l: d,
|
|
r: d,
|
|
b: d,
|
|
w: d,
|
|
h: d
|
|
},
|
|
g, h = c.buildImplied;
|
|
this.buildImplied = function(i) {
|
|
h.call(this, i);
|
|
var j = i.layers,
|
|
k = j.length,
|
|
l, q = i.orient,
|
|
n = /^(top|bottom)\b/.test(q),
|
|
p = this.parent[n ? "height" : "width"](),
|
|
m = [],
|
|
r = [],
|
|
s = [],
|
|
t = pv.Mark.stack,
|
|
x = {
|
|
parent: {
|
|
parent: this
|
|
}
|
|
};
|
|
t.unshift(null);
|
|
g = [];
|
|
for (var u = 0; u < k; u++) {
|
|
s[u] = [];
|
|
r[u] = [];
|
|
x.parent.index = u;
|
|
t[0] = j[u];
|
|
g[u] =
|
|
this.$values.apply(x.parent, t);
|
|
if (!u) l = g[u].length;
|
|
t.unshift(null);
|
|
for (var o = 0; o < l; o++) {
|
|
t[0] = g[u][o];
|
|
x.index = o;
|
|
u || (m[o] = this.$x.apply(x, t));
|
|
s[u][o] = this.$y.apply(x, t)
|
|
}
|
|
t.shift()
|
|
}
|
|
t.shift();
|
|
switch (i.order) {
|
|
case "inside-out":
|
|
var v = s.map(function(A) {
|
|
return pv.max.index(A)
|
|
});
|
|
x = pv.range(k).sort(function(A, D) {
|
|
return v[A] - v[D]
|
|
});
|
|
j = s.map(function(A) {
|
|
return pv.sum(A)
|
|
});
|
|
var w = t = 0,
|
|
y = [],
|
|
z = [];
|
|
for (u = 0; u < k; u++) {
|
|
o = x[u];
|
|
if (t < w) {
|
|
t += j[o];
|
|
y.push(o)
|
|
} else {
|
|
w += j[o];
|
|
z.push(o)
|
|
}
|
|
}
|
|
j = z.reverse().concat(y);
|
|
break;
|
|
case "reverse":
|
|
j =
|
|
pv.range(k - 1, -1, -1);
|
|
break;
|
|
default:
|
|
j = pv.range(k);
|
|
break
|
|
}
|
|
switch (i.offset) {
|
|
case "silohouette":
|
|
for (o = 0; o < l; o++) {
|
|
for (u = x = 0; u < k; u++) x += s[u][o];
|
|
r[j[0]][o] = (p - x) / 2
|
|
}
|
|
break;
|
|
case "wiggle":
|
|
for (u = x = 0; u < k; u++) x += s[u][0];
|
|
r[j[0]][0] = x = (p - x) / 2;
|
|
for (o = 1; o < l; o++) {
|
|
t = p = 0;
|
|
w = m[o] - m[o - 1];
|
|
for (u = 0; u < k; u++) p += s[u][o];
|
|
for (u = 0; u < k; u++) {
|
|
y = (s[j[u]][o] - s[j[u]][o - 1]) / (2 * w);
|
|
for (i = 0; i < u; i++) y += (s[j[i]][o] - s[j[i]][o - 1]) / w;
|
|
t += y * s[j[u]][o]
|
|
}
|
|
r[j[0]][o] = x -= p ? t / p * w : 0
|
|
}
|
|
break;
|
|
case "expand":
|
|
for (o = 0; o < l; o++) {
|
|
for (u = i = r[j[0]][o] = 0; u < k; u++) i += s[u][o];
|
|
if (i) {
|
|
i = p / i;
|
|
for (u = 0; u < k; u++) s[u][o] *= i
|
|
} else {
|
|
i = p / k;
|
|
for (u = 0; u < k; u++) s[u][o] = i
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
for (o = 0; o < l; o++) r[j[0]][o] = 0;
|
|
break
|
|
}
|
|
for (o = 0; o < l; o++) {
|
|
x = r[j[0]][o];
|
|
for (u = 1; u < k; u++) {
|
|
x += s[j[u - 1]][o];
|
|
r[j[u]][o] = x
|
|
}
|
|
}
|
|
u = q.indexOf("-");
|
|
k = n ? "h" : "w";
|
|
n = u < 0 ? n ? "l" : "b" : q.charAt(u + 1);
|
|
q = q.charAt(0);
|
|
for (var C in f) f[C] = d;
|
|
f[n] = function(A, D) {
|
|
return m[D]
|
|
};
|
|
f[q] = function(A, D) {
|
|
return r[A][D]
|
|
};
|
|
f[k] = function(A, D) {
|
|
return s[A][D]
|
|
}
|
|
};
|
|
this.layer = (new pv.Mark).data(function() {
|
|
return g[this.parent.index]
|
|
}).top(b("t")).left(b("l")).right(b("r")).bottom(b("b")).width(b("w")).height(b("h"));
|
|
this.layer.add = function(i) {
|
|
return c.add(pv.Panel).data(function() {
|
|
return c.layers()
|
|
}).add(i).extend(this)
|
|
}
|
|
};
|
|
pv.Layout.Stack.prototype = pv.extend(pv.Layout).property("orient", String).property("offset", String).property("order", String).property("layers");
|
|
a = pv.Layout.Stack.prototype;
|
|
a.defaults = (new pv.Layout.Stack).extend(pv.Layout.prototype.defaults).orient("bottom-left").offset("zero").layers([
|
|
[]
|
|
]);
|
|
a.$x = pv.Layout.Stack.prototype.$y = function() {
|
|
return 0
|
|
};
|
|
a.x = function(b) {
|
|
this.$x = pv.functor(b);
|
|
return this
|
|
};
|
|
a.y = function(b) {
|
|
this.$y = pv.functor(b);
|
|
return this
|
|
};
|
|
a.$values = pv.identity;
|
|
a.values = function(b) {
|
|
this.$values = pv.functor(b);
|
|
return this
|
|
};
|
|
pv.Layout.Treemap = function() {
|
|
pv.Layout.Hierarchy.call(this);
|
|
this.node.strokeStyle("#fff").fillStyle("rgba(31, 119, 180, .25)").width(function(b) {
|
|
return b.dx
|
|
}).height(function(b) {
|
|
return b.dy
|
|
});
|
|
this.label.visible(function(b) {
|
|
return !b.firstChild
|
|
}).left(function(b) {
|
|
return b.x + b.dx / 2
|
|
}).top(function(b) {
|
|
return b.y + b.dy / 2
|
|
}).textAlign("center").textAngle(function(b) {
|
|
return b.dx > b.dy ? 0 : -Math.PI / 2
|
|
});
|
|
(this.leaf = (new pv.Mark).extend(this.node).fillStyle(null).strokeStyle(null).visible(function(b) {
|
|
return !b.firstChild
|
|
})).parent =
|
|
this;
|
|
delete this.link
|
|
};
|
|
pv.Layout.Treemap.prototype = pv.extend(pv.Layout.Hierarchy).property("round", Boolean).property("paddingLeft", Number).property("paddingRight", Number).property("paddingTop", Number).property("paddingBottom", Number).property("mode", String).property("order", String);
|
|
a = pv.Layout.Treemap.prototype;
|
|
a.defaults = (new pv.Layout.Treemap).extend(pv.Layout.Hierarchy.prototype.defaults).mode("squarify").order("ascending");
|
|
a.padding = function(b) {
|
|
return this.paddingLeft(b).paddingRight(b).paddingTop(b).paddingBottom(b)
|
|
};
|
|
a.$size = function(b) {
|
|
return Number(b.nodeValue)
|
|
};
|
|
a.size = function(b) {
|
|
this.$size = pv.functor(b);
|
|
return this
|
|
};
|
|
a.buildImplied = function(b) {
|
|
function c(r, s, t, x, u, o, v) {
|
|
for (var w = 0, y = 0; w < r.length; w++) {
|
|
var z = r[w];
|
|
if (t) {
|
|
z.x = x + y;
|
|
z.y = u;
|
|
y += z.dx = p(o * z.size / s);
|
|
z.dy = v
|
|
} else {
|
|
z.x = x;
|
|
z.y = u + y;
|
|
z.dx = o;
|
|
y += z.dy = p(v * z.size / s)
|
|
}
|
|
}
|
|
if (z)
|
|
if (t) z.dx += o - y;
|
|
else z.dy += v - y
|
|
}
|
|
|
|
function d(r, s) {
|
|
for (var t = -Infinity, x = Infinity, u = 0, o = 0; o < r.length; o++) {
|
|
var v = r[o].size;
|
|
if (v < x) x = v;
|
|
if (v > t) t = v;
|
|
u += v
|
|
}
|
|
u *= u;
|
|
s *= s;
|
|
return Math.max(s * t / u, u / (s * x))
|
|
}
|
|
|
|
function f(r, s) {
|
|
function t(A) {
|
|
var D = o == y,
|
|
G = pv.sum(A, n),
|
|
E = y ? p(G / y) : 0;
|
|
c(A, G, D, x, u, D ? o : E, D ? E : v);
|
|
if (D) {
|
|
u += E;
|
|
v -= E
|
|
} else {
|
|
x +=
|
|
E;
|
|
o -= E
|
|
}
|
|
y = Math.min(o, v);
|
|
return D
|
|
}
|
|
var x = r.x + j,
|
|
u = r.y + l,
|
|
o = r.dx - j - k,
|
|
v = r.dy - l - q;
|
|
if (m != "squarify") c(r.childNodes, r.size, m == "slice" ? true : m == "dice" ? false : s & 1, x, u, o, v);
|
|
else {
|
|
var w = [];
|
|
s = Infinity;
|
|
var y = Math.min(o, v),
|
|
z = o * v / r.size;
|
|
if (!(r.size <= 0)) {
|
|
r.visitBefore(function(A) {
|
|
A.size *= z
|
|
});
|
|
for (r = r.childNodes.slice(); r.length;) {
|
|
var C = r[r.length - 1];
|
|
if (C.size) {
|
|
w.push(C);
|
|
z = d(w, y);
|
|
if (z <= s) {
|
|
r.pop();
|
|
s = z
|
|
} else {
|
|
w.pop();
|
|
t(w);
|
|
w.length = 0;
|
|
s = Infinity
|
|
}
|
|
} else r.pop()
|
|
}
|
|
if (t(w))
|
|
for (s = 0; s < w.length; s++) w[s].dy += v;
|
|
else
|
|
for (s = 0; s < w.length; s++) w[s].dx +=
|
|
o
|
|
}
|
|
}
|
|
}
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var g = this,
|
|
h = b.nodes[0],
|
|
i = pv.Mark.stack,
|
|
j = b.paddingLeft,
|
|
k = b.paddingRight,
|
|
l = b.paddingTop,
|
|
q = b.paddingBottom,
|
|
n = function(r) {
|
|
return r.size
|
|
},
|
|
p = b.round ? Math.round : Number,
|
|
m = b.mode;
|
|
i.unshift(null);
|
|
h.visitAfter(function(r, s) {
|
|
r.depth = s;
|
|
r.x = r.y = r.dx = r.dy = 0;
|
|
r.size = r.firstChild ? pv.sum(r.childNodes, function(t) {
|
|
return t.size
|
|
}) : g.$size.apply(g, (i[0] = r, i))
|
|
});
|
|
i.shift();
|
|
switch (b.order) {
|
|
case "ascending":
|
|
h.sort(function(r, s) {
|
|
return r.size - s.size
|
|
});
|
|
break;
|
|
case "descending":
|
|
h.sort(function(r, s) {
|
|
return s.size - r.size
|
|
});
|
|
break;
|
|
case "reverse":
|
|
h.reverse();
|
|
break
|
|
}
|
|
h.x = 0;
|
|
h.y = 0;
|
|
h.dx = b.width;
|
|
h.dy = b.height;
|
|
h.visitBefore(f)
|
|
}
|
|
};
|
|
pv.Layout.Tree = function() {
|
|
pv.Layout.Hierarchy.call(this)
|
|
};
|
|
pv.Layout.Tree.prototype = pv.extend(pv.Layout.Hierarchy).property("group", Number).property("breadth", Number).property("depth", Number).property("orient", String);
|
|
pv.Layout.Tree.prototype.defaults = (new pv.Layout.Tree).extend(pv.Layout.Hierarchy.prototype.defaults).group(1).breadth(15).depth(60).orient("top");
|
|
pv.Layout.Tree.prototype.buildImplied = function(b) {
|
|
function c(o) {
|
|
var v, w, y;
|
|
if (o.firstChild) {
|
|
v = o.firstChild;
|
|
w = o.lastChild;
|
|
for (var z = y = v; z; z = z.nextSibling) {
|
|
c(z);
|
|
y = f(z, y)
|
|
}
|
|
j(o);
|
|
w = 0.5 * (v.prelim + w.prelim);
|
|
if (v = o.previousSibling) {
|
|
o.prelim = v.prelim + l(o.depth, true);
|
|
o.mod = o.prelim - w
|
|
} else o.prelim = w
|
|
} else if (v = o.previousSibling) o.prelim = v.prelim + l(o.depth, true)
|
|
}
|
|
|
|
function d(o, v, w) {
|
|
o.breadth = o.prelim + v;
|
|
v += o.mod;
|
|
for (o = o.firstChild; o; o = o.nextSibling) d(o, v, w)
|
|
}
|
|
|
|
function f(o, v) {
|
|
var w = o.previousSibling;
|
|
if (w) {
|
|
var y = o,
|
|
z =
|
|
o,
|
|
C = w;
|
|
w = o.parentNode.firstChild;
|
|
var A = y.mod,
|
|
D = z.mod,
|
|
G = C.mod,
|
|
E = w.mod;
|
|
C = h(C);
|
|
for (y = g(y); C && y;) {
|
|
C = C;
|
|
y = y;
|
|
w = g(w);
|
|
z = h(z);
|
|
z.ancestor = o;
|
|
var B = C.prelim + G - (y.prelim + A) + l(C.depth, false);
|
|
if (B > 0) {
|
|
i(k(C, o, v), o, B);
|
|
A += B;
|
|
D += B
|
|
}
|
|
G += C.mod;
|
|
A += y.mod;
|
|
E += w.mod;
|
|
D += z.mod;
|
|
C = h(C);
|
|
y = g(y)
|
|
}
|
|
if (C && !h(z)) {
|
|
z.thread = C;
|
|
z.mod += G - D
|
|
}
|
|
if (y && !g(w)) {
|
|
w.thread = y;
|
|
w.mod += A - E;
|
|
v = o
|
|
}
|
|
}
|
|
return v
|
|
}
|
|
|
|
function g(o) {
|
|
return o.firstChild || o.thread
|
|
}
|
|
|
|
function h(o) {
|
|
return o.lastChild || o.thread
|
|
}
|
|
|
|
function i(o, v, w) {
|
|
var y = v.number - o.number;
|
|
v.change -= w / y;
|
|
v.shift += w;
|
|
o.change +=
|
|
w / y;
|
|
v.prelim += w;
|
|
v.mod += w
|
|
}
|
|
|
|
function j(o) {
|
|
var v = 0,
|
|
w = 0;
|
|
for (o = o.lastChild; o; o = o.previousSibling) {
|
|
o.prelim += v;
|
|
o.mod += v;
|
|
w += o.change;
|
|
v += o.shift + w
|
|
}
|
|
}
|
|
|
|
function k(o, v, w) {
|
|
return o.ancestor.parentNode == v.parentNode ? o.ancestor : w
|
|
}
|
|
|
|
function l(o, v) {
|
|
return (v ? 1 : t + 1) / (m == "radial" ? o : 1)
|
|
}
|
|
|
|
function q(o) {
|
|
return m == "radial" ? o.breadth / r : 0
|
|
}
|
|
|
|
function n(o) {
|
|
switch (m) {
|
|
case "left":
|
|
return o.depth;
|
|
case "right":
|
|
return x - o.depth;
|
|
case "top":
|
|
case "bottom":
|
|
return o.breadth + x / 2;
|
|
case "radial":
|
|
return x / 2 + o.depth * Math.cos(q(o))
|
|
}
|
|
}
|
|
|
|
function p(o) {
|
|
switch (m) {
|
|
case "left":
|
|
case "right":
|
|
return o.breadth +
|
|
u / 2;
|
|
case "top":
|
|
return o.depth;
|
|
case "bottom":
|
|
return u - o.depth;
|
|
case "radial":
|
|
return u / 2 + o.depth * Math.sin(q(o))
|
|
}
|
|
}
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var m = b.orient,
|
|
r = b.depth,
|
|
s = b.breadth,
|
|
t = b.group,
|
|
x = b.width,
|
|
u = b.height;
|
|
b = b.nodes[0];
|
|
b.visitAfter(function(o, v) {
|
|
o.ancestor = o;
|
|
o.prelim = 0;
|
|
o.mod = 0;
|
|
o.change = 0;
|
|
o.shift = 0;
|
|
o.number = o.previousSibling ? o.previousSibling.number + 1 : 0;
|
|
o.depth = v
|
|
});
|
|
c(b);
|
|
d(b, -b.prelim, 0);
|
|
b.visitAfter(function(o) {
|
|
o.breadth *= s;
|
|
o.depth *= r;
|
|
o.midAngle = q(o);
|
|
o.x = n(o);
|
|
o.y = p(o);
|
|
if (o.firstChild) o.midAngle += Math.PI;
|
|
delete o.breadth;
|
|
delete o.depth;
|
|
delete o.ancestor;
|
|
delete o.prelim;
|
|
delete o.mod;
|
|
delete o.change;
|
|
delete o.shift;
|
|
delete o.number;
|
|
delete o.thread
|
|
})
|
|
}
|
|
};
|
|
pv.Layout.Indent = function() {
|
|
pv.Layout.Hierarchy.call(this);
|
|
this.link.interpolate("step-after")
|
|
};
|
|
pv.Layout.Indent.prototype = pv.extend(pv.Layout.Hierarchy).property("depth", Number).property("breadth", Number);
|
|
pv.Layout.Indent.prototype.defaults = (new pv.Layout.Indent).extend(pv.Layout.Hierarchy.prototype.defaults).depth(15).breadth(15);
|
|
pv.Layout.Indent.prototype.buildImplied = function(b) {
|
|
function c(i, j, k) {
|
|
i.x = g + k++ * f;
|
|
i.y = h + j++ * d;
|
|
i.midAngle = 0;
|
|
for (i = i.firstChild; i; i = i.nextSibling) j = c(i, j, k);
|
|
return j
|
|
}
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var d = b.breadth,
|
|
f = b.depth,
|
|
g = 0,
|
|
h = 0;
|
|
c(b.nodes[0], 1, 1)
|
|
}
|
|
};
|
|
pv.Layout.Pack = function() {
|
|
pv.Layout.Hierarchy.call(this);
|
|
this.node.radius(function(b) {
|
|
return b.radius
|
|
}).strokeStyle("rgb(31, 119, 180)").fillStyle("rgba(31, 119, 180, .25)");
|
|
this.label.textAlign("center");
|
|
delete this.link
|
|
};
|
|
pv.Layout.Pack.prototype = pv.extend(pv.Layout.Hierarchy).property("spacing", Number).property("order", String);
|
|
pv.Layout.Pack.prototype.defaults = (new pv.Layout.Pack).extend(pv.Layout.Hierarchy.prototype.defaults).spacing(1).order("ascending");
|
|
pv.Layout.Pack.prototype.$radius = function() {
|
|
return 1
|
|
};
|
|
pv.Layout.Pack.prototype.size = function(b) {
|
|
this.$radius = typeof b == "function" ? function() {
|
|
return Math.sqrt(b.apply(this, arguments))
|
|
} : (b = Math.sqrt(b), function() {
|
|
return b
|
|
});
|
|
return this
|
|
};
|
|
pv.Layout.Pack.prototype.buildImplied = function(b) {
|
|
function c(n) {
|
|
var p = pv.Mark.stack;
|
|
p.unshift(null);
|
|
for (var m = 0, r = n.length; m < r; m++) {
|
|
var s = n[m];
|
|
if (!s.firstChild) s.radius = i.$radius.apply(i, (p[0] = s, p))
|
|
}
|
|
p.shift()
|
|
}
|
|
|
|
function d(n) {
|
|
var p = [];
|
|
for (n = n.firstChild; n; n = n.nextSibling) {
|
|
if (n.firstChild) n.radius = d(n);
|
|
n.n = n.p = n;
|
|
p.push(n)
|
|
}
|
|
switch (b.order) {
|
|
case "ascending":
|
|
p.sort(function(m, r) {
|
|
return m.radius - r.radius
|
|
});
|
|
break;
|
|
case "descending":
|
|
p.sort(function(m, r) {
|
|
return r.radius - m.radius
|
|
});
|
|
break;
|
|
case "reverse":
|
|
p.reverse();
|
|
break
|
|
}
|
|
return f(p)
|
|
}
|
|
|
|
function f(n) {
|
|
function p(B) {
|
|
t = Math.min(B.x - B.radius, t);
|
|
x = Math.max(B.x + B.radius, x);
|
|
u = Math.min(B.y - B.radius, u);
|
|
o = Math.max(B.y + B.radius, o)
|
|
}
|
|
|
|
function m(B, F) {
|
|
var H = B.n;
|
|
B.n = F;
|
|
F.p = B;
|
|
F.n = H;
|
|
H.p = F
|
|
}
|
|
|
|
function r(B, F) {
|
|
B.n = F;
|
|
F.p = B
|
|
}
|
|
|
|
function s(B, F) {
|
|
var H = F.x - B.x,
|
|
I = F.y - B.y;
|
|
B = B.radius + F.radius;
|
|
return B * B - H * H - I * I > 0.0010
|
|
}
|
|
var t = Infinity,
|
|
x = -Infinity,
|
|
u = Infinity,
|
|
o = -Infinity,
|
|
v, w, y, z, C;
|
|
v = n[0];
|
|
v.x = -v.radius;
|
|
v.y = 0;
|
|
p(v);
|
|
if (n.length > 1) {
|
|
w = n[1];
|
|
w.x = w.radius;
|
|
w.y = 0;
|
|
p(w);
|
|
if (n.length > 2) {
|
|
y = n[2];
|
|
g(v, w, y);
|
|
p(y);
|
|
m(v, y);
|
|
v.p =
|
|
y;
|
|
m(y, w);
|
|
w = v.n;
|
|
for (var A = 3; A < n.length; A++) {
|
|
g(v, w, y = n[A]);
|
|
var D = 0,
|
|
G = 1,
|
|
E = 1;
|
|
for (z = w.n; z != w; z = z.n, G++)
|
|
if (s(z, y)) {
|
|
D = 1;
|
|
break
|
|
} if (D == 1)
|
|
for (C = v.p; C != z.p; C = C.p, E++)
|
|
if (s(C, y)) {
|
|
if (E < G) {
|
|
D = -1;
|
|
z = C
|
|
}
|
|
break
|
|
} if (D == 0) {
|
|
m(v, y);
|
|
w = y;
|
|
p(y)
|
|
} else if (D > 0) {
|
|
r(v, z);
|
|
w = z;
|
|
A--
|
|
} else if (D < 0) {
|
|
r(z, w);
|
|
v = z;
|
|
A--
|
|
}
|
|
}
|
|
}
|
|
}
|
|
v = (t + x) / 2;
|
|
w = (u + o) / 2;
|
|
for (A = y = 0; A < n.length; A++) {
|
|
z = n[A];
|
|
z.x -= v;
|
|
z.y -= w;
|
|
y = Math.max(y, z.radius + Math.sqrt(z.x * z.x + z.y * z.y))
|
|
}
|
|
return y + b.spacing
|
|
}
|
|
|
|
function g(n, p, m) {
|
|
var r = p.radius + m.radius,
|
|
s = n.radius + m.radius,
|
|
t = p.x - n.x;
|
|
p = p.y - n.y;
|
|
var x = Math.sqrt(t *
|
|
t + p * p),
|
|
u = (s * s + x * x - r * r) / (2 * s * x);
|
|
r = Math.acos(u);
|
|
u = u * s;
|
|
s = Math.sin(r) * s;
|
|
t /= x;
|
|
p /= x;
|
|
m.x = n.x + u * t + s * p;
|
|
m.y = n.y + u * p - s * t
|
|
}
|
|
|
|
function h(n, p, m, r) {
|
|
for (var s = n.firstChild; s; s = s.nextSibling) {
|
|
s.x += n.x;
|
|
s.y += n.y;
|
|
h(s, p, m, r)
|
|
}
|
|
n.x = p + r * n.x;
|
|
n.y = m + r * n.y;
|
|
n.radius *= r
|
|
}
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var i = this,
|
|
j = b.nodes,
|
|
k = j[0];
|
|
c(j);
|
|
k.x = 0;
|
|
k.y = 0;
|
|
k.radius = d(k);
|
|
j = this.width();
|
|
var l = this.height(),
|
|
q = 1 / Math.max(2 * k.radius / j, 2 * k.radius / l);
|
|
h(k, j / 2, l / 2, q)
|
|
}
|
|
};
|
|
pv.Layout.Force = function() {
|
|
pv.Layout.Network.call(this);
|
|
this.link.lineWidth(function(b, c) {
|
|
return Math.sqrt(c.linkValue) * 1.5
|
|
});
|
|
this.label.textAlign("center")
|
|
};
|
|
pv.Layout.Force.prototype = pv.extend(pv.Layout.Network).property("bound", Boolean).property("iterations", Number).property("dragConstant", Number).property("chargeConstant", Number).property("chargeMinDistance", Number).property("chargeMaxDistance", Number).property("chargeTheta", Number).property("springConstant", Number).property("springDamping", Number).property("springLength", Number);
|
|
pv.Layout.Force.prototype.defaults = (new pv.Layout.Force).extend(pv.Layout.Network.prototype.defaults).dragConstant(0.1).chargeConstant(-40).chargeMinDistance(2).chargeMaxDistance(500).chargeTheta(0.9).springConstant(0.1).springDamping(0.3).springLength(20);
|
|
pv.Layout.Force.prototype.buildImplied = function(b) {
|
|
function c(q) {
|
|
return q.fix ? 1 : q.vx * q.vx + q.vy * q.vy
|
|
}
|
|
if (pv.Layout.Network.prototype.buildImplied.call(this, b)) {
|
|
if (b = b.$force) {
|
|
b.next = this.binds.$force;
|
|
this.binds.$force = b
|
|
}
|
|
} else {
|
|
for (var d = this, f = b.nodes, g = b.links, h = b.iterations, i = b.width, j = b.height, k = 0, l; k < f.length; k++) {
|
|
l = f[k];
|
|
if (isNaN(l.x)) l.x = i / 2 + 40 * Math.random() - 20;
|
|
if (isNaN(l.y)) l.y = j / 2 + 40 * Math.random() - 20
|
|
}
|
|
l = pv.simulation(f);
|
|
l.force(pv.Force.drag(b.dragConstant));
|
|
l.force(pv.Force.charge(b.chargeConstant).domain(b.chargeMinDistance,
|
|
b.chargeMaxDistance).theta(b.chargeTheta));
|
|
l.force(pv.Force.spring(b.springConstant).damping(b.springDamping).length(b.springLength).links(g));
|
|
l.constraint(pv.Constraint.position());
|
|
b.bound && l.constraint(pv.Constraint.bound().x(6, i - 6).y(6, j - 6));
|
|
if (h == null) {
|
|
l.step();
|
|
l.step();
|
|
b.$force = this.binds.$force = {
|
|
next: this.binds.$force,
|
|
nodes: f,
|
|
min: 1.0E-4 * (g.length + 1),
|
|
sim: l
|
|
};
|
|
if (!this.$timer) this.$timer = setInterval(function() {
|
|
for (var q = false, n = d.binds.$force; n; n = n.next)
|
|
if (pv.max(n.nodes, c) > n.min) {
|
|
n.sim.step();
|
|
q = true
|
|
} q && d.render()
|
|
}, 42)
|
|
} else
|
|
for (k = 0; k < h; k++) l.step()
|
|
}
|
|
};
|
|
pv.Layout.Cluster = function() {
|
|
pv.Layout.Hierarchy.call(this);
|
|
var b, c = this.buildImplied;
|
|
this.buildImplied = function(d) {
|
|
c.call(this, d);
|
|
b = /^(top|bottom)$/.test(d.orient) ? "step-before" : /^(left|right)$/.test(d.orient) ? "step-after" : "linear"
|
|
};
|
|
this.link.interpolate(function() {
|
|
return b
|
|
})
|
|
};
|
|
pv.Layout.Cluster.prototype = pv.extend(pv.Layout.Hierarchy).property("group", Number).property("orient", String).property("innerRadius", Number).property("outerRadius", Number);
|
|
pv.Layout.Cluster.prototype.defaults = (new pv.Layout.Cluster).extend(pv.Layout.Hierarchy.prototype.defaults).group(0).orient("top");
|
|
pv.Layout.Cluster.prototype.buildImplied = function(b) {
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var c = b.nodes[0],
|
|
d = b.group,
|
|
f, g, h = 0,
|
|
i = 0.5 - d / 2,
|
|
j = undefined;
|
|
c.visitAfter(function(k) {
|
|
if (k.firstChild) k.depth = 1 + pv.max(k.childNodes, function(l) {
|
|
return l.depth
|
|
});
|
|
else {
|
|
if (d && j != k.parentNode) {
|
|
j = k.parentNode;
|
|
h += d
|
|
}
|
|
h++;
|
|
k.depth = 0
|
|
}
|
|
});
|
|
f = 1 / h;
|
|
g = 1 / c.depth;
|
|
j = undefined;
|
|
c.visitAfter(function(k) {
|
|
if (k.firstChild) k.breadth = pv.mean(k.childNodes, function(l) {
|
|
return l.breadth
|
|
});
|
|
else {
|
|
if (d && j != k.parentNode) {
|
|
j = k.parentNode;
|
|
i += d
|
|
}
|
|
k.breadth = f * i++
|
|
}
|
|
k.depth = 1 - k.depth * g
|
|
});
|
|
c.visitAfter(function(k) {
|
|
k.minBreadth = k.firstChild ? k.firstChild.minBreadth : k.breadth - f / 2;
|
|
k.maxBreadth = k.firstChild ? k.lastChild.maxBreadth : k.breadth + f / 2
|
|
});
|
|
c.visitBefore(function(k) {
|
|
k.minDepth = k.parentNode ? k.parentNode.maxDepth : 0;
|
|
k.maxDepth = k.parentNode ? k.depth + c.depth : k.minDepth + 2 * c.depth
|
|
});
|
|
c.minDepth = -g;
|
|
pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, b)
|
|
}
|
|
};
|
|
pv.Layout.Cluster.Fill = function() {
|
|
pv.Layout.Cluster.call(this);
|
|
pv.Layout.Hierarchy.Fill.constructor.call(this)
|
|
};
|
|
pv.Layout.Cluster.Fill.prototype = pv.extend(pv.Layout.Cluster);
|
|
pv.Layout.Cluster.Fill.prototype.buildImplied = function(b) {
|
|
pv.Layout.Cluster.prototype.buildImplied.call(this, b) || pv.Layout.Hierarchy.Fill.buildImplied.call(this, b)
|
|
};
|
|
pv.Layout.Partition = function() {
|
|
pv.Layout.Hierarchy.call(this)
|
|
};
|
|
pv.Layout.Partition.prototype = pv.extend(pv.Layout.Hierarchy).property("order", String).property("orient", String).property("innerRadius", Number).property("outerRadius", Number);
|
|
pv.Layout.Partition.prototype.defaults = (new pv.Layout.Partition).extend(pv.Layout.Hierarchy.prototype.defaults).orient("top");
|
|
pv.Layout.Partition.prototype.$size = function() {
|
|
return 1
|
|
};
|
|
pv.Layout.Partition.prototype.size = function(b) {
|
|
this.$size = b;
|
|
return this
|
|
};
|
|
pv.Layout.Partition.prototype.buildImplied = function(b) {
|
|
if (!pv.Layout.Hierarchy.prototype.buildImplied.call(this, b)) {
|
|
var c = this,
|
|
d = b.nodes[0],
|
|
f = pv.Mark.stack,
|
|
g = 0;
|
|
f.unshift(null);
|
|
d.visitAfter(function(i, j) {
|
|
if (j > g) g = j;
|
|
i.size = i.firstChild ? pv.sum(i.childNodes, function(k) {
|
|
return k.size
|
|
}) : c.$size.apply(c, (f[0] = i, f))
|
|
});
|
|
f.shift();
|
|
switch (b.order) {
|
|
case "ascending":
|
|
d.sort(function(i, j) {
|
|
return i.size - j.size
|
|
});
|
|
break;
|
|
case "descending":
|
|
d.sort(function(i, j) {
|
|
return j.size - i.size
|
|
});
|
|
break
|
|
}
|
|
var h = 1 / g;
|
|
d.minBreadth = 0;
|
|
d.breadth =
|
|
0.5;
|
|
d.maxBreadth = 1;
|
|
d.visitBefore(function(i) {
|
|
for (var j = i.minBreadth, k = i.maxBreadth - j, l = i.firstChild; l; l = l.nextSibling) {
|
|
l.minBreadth = j;
|
|
l.maxBreadth = j += l.size / i.size * k;
|
|
l.breadth = (j + l.minBreadth) / 2
|
|
}
|
|
});
|
|
d.visitAfter(function(i, j) {
|
|
i.minDepth = (j - 1) * h;
|
|
i.maxDepth = i.depth = j * h
|
|
});
|
|
pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, b)
|
|
}
|
|
};
|
|
pv.Layout.Partition.Fill = function() {
|
|
pv.Layout.Partition.call(this);
|
|
pv.Layout.Hierarchy.Fill.constructor.call(this)
|
|
};
|
|
pv.Layout.Partition.Fill.prototype = pv.extend(pv.Layout.Partition);
|
|
pv.Layout.Partition.Fill.prototype.buildImplied = function(b) {
|
|
pv.Layout.Partition.prototype.buildImplied.call(this, b) || pv.Layout.Hierarchy.Fill.buildImplied.call(this, b)
|
|
};
|
|
pv.Layout.Arc = function() {
|
|
pv.Layout.Network.call(this);
|
|
var b, c, d, f = this.buildImplied;
|
|
this.buildImplied = function(g) {
|
|
f.call(this, g);
|
|
c = g.directed;
|
|
b = g.orient == "radial" ? "linear" : "polar";
|
|
d = g.orient == "right" || g.orient == "top"
|
|
};
|
|
this.link.data(function(g) {
|
|
var h = g.sourceNode;
|
|
g = g.targetNode;
|
|
return d != (c || h.breadth < g.breadth) ? [h, g] : [g, h]
|
|
}).interpolate(function() {
|
|
return b
|
|
})
|
|
};
|
|
pv.Layout.Arc.prototype = pv.extend(pv.Layout.Network).property("orient", String).property("directed", Boolean);
|
|
pv.Layout.Arc.prototype.defaults = (new pv.Layout.Arc).extend(pv.Layout.Network.prototype.defaults).orient("bottom");
|
|
pv.Layout.Arc.prototype.sort = function(b) {
|
|
this.$sort = b;
|
|
return this
|
|
};
|
|
pv.Layout.Arc.prototype.buildImplied = function(b) {
|
|
function c(m) {
|
|
switch (h) {
|
|
case "top":
|
|
return -Math.PI / 2;
|
|
case "bottom":
|
|
return Math.PI / 2;
|
|
case "left":
|
|
return Math.PI;
|
|
case "right":
|
|
return 0;
|
|
case "radial":
|
|
return (m - 0.25) * 2 * Math.PI
|
|
}
|
|
}
|
|
|
|
function d(m) {
|
|
switch (h) {
|
|
case "top":
|
|
case "bottom":
|
|
return m * k;
|
|
case "left":
|
|
return 0;
|
|
case "right":
|
|
return k;
|
|
case "radial":
|
|
return k / 2 + q * Math.cos(c(m))
|
|
}
|
|
}
|
|
|
|
function f(m) {
|
|
switch (h) {
|
|
case "top":
|
|
return 0;
|
|
case "bottom":
|
|
return l;
|
|
case "left":
|
|
case "right":
|
|
return m * l;
|
|
case "radial":
|
|
return l / 2 + q * Math.sin(c(m))
|
|
}
|
|
}
|
|
if (!pv.Layout.Network.prototype.buildImplied.call(this, b)) {
|
|
var g = b.nodes,
|
|
h = b.orient,
|
|
i = this.$sort,
|
|
j = pv.range(g.length),
|
|
k = b.width,
|
|
l = b.height,
|
|
q = Math.min(k, l) / 2;
|
|
i && j.sort(function(m, r) {
|
|
return i(g[m], g[r])
|
|
});
|
|
for (b = 0; b < g.length; b++) {
|
|
var n = g[j[b]],
|
|
p = n.breadth = (b + 0.5) / g.length;
|
|
n.x = d(p);
|
|
n.y = f(p);
|
|
n.midAngle = c(p)
|
|
}
|
|
}
|
|
};
|
|
pv.Layout.Horizon = function() {
|
|
pv.Layout.call(this);
|
|
var b = this,
|
|
c, d, f, g, h, i, j = this.buildImplied;
|
|
this.buildImplied = function(k) {
|
|
j.call(this, k);
|
|
c = k.bands;
|
|
d = k.mode;
|
|
f = Math.round((d == "color" ? 0.5 : 1) * k.height);
|
|
g = k.backgroundStyle;
|
|
h = pv.ramp(g, k.negativeStyle).domain(0, c);
|
|
i = pv.ramp(g, k.positiveStyle).domain(0, c)
|
|
};
|
|
c = (new pv.Panel).data(function() {
|
|
return pv.range(c * 2)
|
|
}).overflow("hidden").height(function() {
|
|
return f
|
|
}).top(function(k) {
|
|
return d == "color" ? (k & 1) * f : 0
|
|
}).fillStyle(function(k) {
|
|
return k ? null : g
|
|
});
|
|
this.band =
|
|
(new pv.Mark).top(function(k, l) {
|
|
return d == "mirror" && l & 1 ? (l + 1 >> 1) * f : null
|
|
}).bottom(function(k, l) {
|
|
return d == "mirror" ? l & 1 ? null : (l + 1 >> 1) * -f : (l & 1 || -1) * (l + 1 >> 1) * f
|
|
}).fillStyle(function(k, l) {
|
|
return (l & 1 ? h : i)((l >> 1) + 1)
|
|
});
|
|
this.band.add = function(k) {
|
|
return b.add(pv.Panel).extend(c).add(k).extend(this)
|
|
}
|
|
};
|
|
pv.Layout.Horizon.prototype = pv.extend(pv.Layout).property("bands", Number).property("mode", String).property("backgroundStyle", pv.color).property("positiveStyle", pv.color).property("negativeStyle", pv.color);
|
|
pv.Layout.Horizon.prototype.defaults = (new pv.Layout.Horizon).extend(pv.Layout.prototype.defaults).bands(2).mode("offset").backgroundStyle("white").positiveStyle("#1f77b4").negativeStyle("#d62728");
|
|
pv.Layout.Rollup = function() {
|
|
pv.Layout.Network.call(this);
|
|
var b = this,
|
|
c, d, f = b.buildImplied;
|
|
this.buildImplied = function(g) {
|
|
f.call(this, g);
|
|
c = g.$rollup.nodes;
|
|
d = g.$rollup.links
|
|
};
|
|
this.node.data(function() {
|
|
return c
|
|
}).size(function(g) {
|
|
return g.nodes.length * 20
|
|
});
|
|
this.link.interpolate("polar").eccentricity(0.8);
|
|
this.link.add = function(g) {
|
|
return b.add(pv.Panel).data(function() {
|
|
return d
|
|
}).add(g).extend(this)
|
|
}
|
|
};
|
|
pv.Layout.Rollup.prototype = pv.extend(pv.Layout.Network).property("directed", Boolean);
|
|
pv.Layout.Rollup.prototype.x = function(b) {
|
|
this.$x = pv.functor(b);
|
|
return this
|
|
};
|
|
pv.Layout.Rollup.prototype.y = function(b) {
|
|
this.$y = pv.functor(b);
|
|
return this
|
|
};
|
|
pv.Layout.Rollup.prototype.buildImplied = function(b) {
|
|
function c(r) {
|
|
return i[r] + "," + j[r]
|
|
}
|
|
if (!pv.Layout.Network.prototype.buildImplied.call(this, b)) {
|
|
var d = b.nodes,
|
|
f = b.links,
|
|
g = b.directed,
|
|
h = d.length,
|
|
i = [],
|
|
j = [],
|
|
k = 0,
|
|
l = {},
|
|
q = {},
|
|
n = pv.Mark.stack,
|
|
p = {
|
|
parent: this
|
|
};
|
|
n.unshift(null);
|
|
for (var m = 0; m < h; m++) {
|
|
p.index = m;
|
|
n[0] = d[m];
|
|
i[m] = this.$x.apply(p, n);
|
|
j[m] = this.$y.apply(p, n)
|
|
}
|
|
n.shift();
|
|
for (m = 0; m < d.length; m++) {
|
|
h = c(m);
|
|
n = l[h];
|
|
if (!n) {
|
|
n = l[h] = pv.extend(d[m]);
|
|
n.index = k++;
|
|
n.x = i[m];
|
|
n.y = j[m];
|
|
n.nodes = []
|
|
}
|
|
n.nodes.push(d[m])
|
|
}
|
|
for (m = 0; m <
|
|
f.length; m++) {
|
|
k = f[m].targetNode;
|
|
d = l[c(f[m].sourceNode.index)];
|
|
k = l[c(k.index)];
|
|
h = !g && d.index > k.index ? k.index + "," + d.index : d.index + "," + k.index;
|
|
(n = q[h]) || (n = q[h] = {
|
|
sourceNode: d,
|
|
targetNode: k,
|
|
linkValue: 0,
|
|
links: []
|
|
});
|
|
n.links.push(f[m]);
|
|
n.linkValue += f[m].linkValue
|
|
}
|
|
b.$rollup = {
|
|
nodes: pv.values(l),
|
|
links: pv.values(q)
|
|
}
|
|
}
|
|
};
|
|
pv.Layout.Matrix = function() {
|
|
pv.Layout.Network.call(this);
|
|
var b, c, d, f, g, h = this.buildImplied;
|
|
this.buildImplied = function(i) {
|
|
h.call(this, i);
|
|
b = i.nodes.length;
|
|
c = i.width / b;
|
|
d = i.height / b;
|
|
f = i.$matrix.labels;
|
|
g = i.$matrix.pairs
|
|
};
|
|
this.link.data(function() {
|
|
return g
|
|
}).left(function() {
|
|
return c * (this.index % b)
|
|
}).top(function() {
|
|
return d * Math.floor(this.index / b)
|
|
}).width(function() {
|
|
return c
|
|
}).height(function() {
|
|
return d
|
|
}).lineWidth(1.5).strokeStyle("#fff").fillStyle(function(i) {
|
|
return i.linkValue ? "#555" : "#eee"
|
|
}).parent =
|
|
this;
|
|
delete this.link.add;
|
|
this.label.data(function() {
|
|
return f
|
|
}).left(function() {
|
|
return this.index & 1 ? c * ((this.index >> 1) + 0.5) : 0
|
|
}).top(function() {
|
|
return this.index & 1 ? 0 : d * ((this.index >> 1) + 0.5)
|
|
}).textMargin(4).textAlign(function() {
|
|
return this.index & 1 ? "left" : "right"
|
|
}).textAngle(function() {
|
|
return this.index & 1 ? -Math.PI / 2 : 0
|
|
});
|
|
delete this.node
|
|
};
|
|
pv.Layout.Matrix.prototype = pv.extend(pv.Layout.Network).property("directed", Boolean);
|
|
pv.Layout.Matrix.prototype.sort = function(b) {
|
|
this.$sort = b;
|
|
return this
|
|
};
|
|
pv.Layout.Matrix.prototype.buildImplied = function(b) {
|
|
if (!pv.Layout.Network.prototype.buildImplied.call(this, b)) {
|
|
var c = b.nodes,
|
|
d = b.links,
|
|
f = this.$sort,
|
|
g = c.length,
|
|
h = pv.range(g),
|
|
i = [],
|
|
j = [],
|
|
k = {};
|
|
b.$matrix = {
|
|
labels: i,
|
|
pairs: j
|
|
};
|
|
f && h.sort(function(m, r) {
|
|
return f(c[m], c[r])
|
|
});
|
|
for (var l = 0; l < g; l++)
|
|
for (var q = 0; q < g; q++) {
|
|
var n = h[l],
|
|
p = h[q];
|
|
j.push(k[n + "." + p] = {
|
|
row: l,
|
|
col: q,
|
|
sourceNode: c[n],
|
|
targetNode: c[p],
|
|
linkValue: 0
|
|
})
|
|
}
|
|
for (l = 0; l < g; l++) {
|
|
n = h[l];
|
|
i.push(c[n], c[n])
|
|
}
|
|
for (l = 0; l < d.length; l++) {
|
|
i = d[l];
|
|
g = i.sourceNode.index;
|
|
h = i.targetNode.index;
|
|
i = i.linkValue;
|
|
k[g + "." + h].linkValue += i;
|
|
b.directed || (k[h + "." + g].linkValue += i)
|
|
}
|
|
}
|
|
};
|
|
pv.Layout.Bullet = function() {
|
|
pv.Layout.call(this);
|
|
var b = this,
|
|
c = b.buildImplied,
|
|
d = b.x = pv.Scale.linear(),
|
|
f, g, h, i, j;
|
|
this.buildImplied = function(k) {
|
|
c.call(this, j = k);
|
|
f = k.orient;
|
|
g = /^left|right$/.test(f);
|
|
h = pv.ramp("#bbb", "#eee").domain(0, Math.max(1, j.ranges.length - 1));
|
|
i = pv.ramp("steelblue", "lightsteelblue").domain(0, Math.max(1, j.measures.length - 1))
|
|
};
|
|
(this.range = new pv.Mark).data(function() {
|
|
return j.ranges
|
|
}).reverse(true).left(function() {
|
|
return f == "left" ? 0 : null
|
|
}).top(function() {
|
|
return f == "top" ? 0 : null
|
|
}).right(function() {
|
|
return f ==
|
|
"right" ? 0 : null
|
|
}).bottom(function() {
|
|
return f == "bottom" ? 0 : null
|
|
}).width(function(k) {
|
|
return g ? d(k) : null
|
|
}).height(function(k) {
|
|
return g ? null : d(k)
|
|
}).fillStyle(function() {
|
|
return h(this.index)
|
|
}).antialias(false).parent = b;
|
|
(this.measure = new pv.Mark).extend(this.range).data(function() {
|
|
return j.measures
|
|
}).left(function() {
|
|
return f == "left" ? 0 : g ? null : this.parent.width() / 3.25
|
|
}).top(function() {
|
|
return f == "top" ? 0 : g ? this.parent.height() / 3.25 : null
|
|
}).right(function() {
|
|
return f == "right" ? 0 : g ? null : this.parent.width() / 3.25
|
|
}).bottom(function() {
|
|
return f ==
|
|
"bottom" ? 0 : g ? this.parent.height() / 3.25 : null
|
|
}).fillStyle(function() {
|
|
return i(this.index)
|
|
}).parent = b;
|
|
(this.marker = new pv.Mark).data(function() {
|
|
return j.markers
|
|
}).left(function(k) {
|
|
return f == "left" ? d(k) : g ? null : this.parent.width() / 2
|
|
}).top(function(k) {
|
|
return f == "top" ? d(k) : g ? this.parent.height() / 2 : null
|
|
}).right(function(k) {
|
|
return f == "right" ? d(k) : null
|
|
}).bottom(function(k) {
|
|
return f == "bottom" ? d(k) : null
|
|
}).strokeStyle("black").shape("bar").angle(function() {
|
|
return g ? 0 : Math.PI / 2
|
|
}).parent = b;
|
|
(this.tick = new pv.Mark).data(function() {
|
|
return d.ticks(7)
|
|
}).left(function(k) {
|
|
return f ==
|
|
"left" ? d(k) : null
|
|
}).top(function(k) {
|
|
return f == "top" ? d(k) : null
|
|
}).right(function(k) {
|
|
return f == "right" ? d(k) : g ? null : -6
|
|
}).bottom(function(k) {
|
|
return f == "bottom" ? d(k) : g ? -8 : null
|
|
}).height(function() {
|
|
return g ? 6 : null
|
|
}).width(function() {
|
|
return g ? null : 6
|
|
}).parent = b
|
|
};
|
|
pv.Layout.Bullet.prototype = pv.extend(pv.Layout).property("orient", String).property("ranges").property("markers").property("measures").property("maximum", Number);
|
|
pv.Layout.Bullet.prototype.defaults = (new pv.Layout.Bullet).extend(pv.Layout.prototype.defaults).orient("left").ranges([]).markers([]).measures([]);
|
|
pv.Layout.Bullet.prototype.buildImplied = function(b) {
|
|
pv.Layout.prototype.buildImplied.call(this, b);
|
|
var c = this.parent[/^left|right$/.test(b.orient) ? "width" : "height"]();
|
|
b.maximum = b.maximum || pv.max([].concat(b.ranges, b.markers, b.measures));
|
|
this.x.domain(0, b.maximum).range(0, c)
|
|
};
|
|
pv.Behavior = {};
|
|
pv.Behavior.drag = function() {
|
|
function b(k) {
|
|
g = this.index;
|
|
f = this.scene;
|
|
var l = this.mouse();
|
|
i = ((h = k).fix = pv.vector(k.x, k.y)).minus(l);
|
|
j = {
|
|
x: this.parent.width() - (k.dx || 0),
|
|
y: this.parent.height() - (k.dy || 0)
|
|
};
|
|
f.mark.context(f, g, function() {
|
|
this.render()
|
|
});
|
|
pv.Mark.dispatch("dragstart", f, g)
|
|
}
|
|
|
|
function c() {
|
|
if (f) {
|
|
f.mark.context(f, g, function() {
|
|
var k = this.mouse();
|
|
h.x = h.fix.x = Math.max(0, Math.min(i.x + k.x, j.x));
|
|
h.y = h.fix.y = Math.max(0, Math.min(i.y + k.y, j.y));
|
|
this.render()
|
|
});
|
|
pv.Mark.dispatch("drag", f, g)
|
|
}
|
|
}
|
|
|
|
function d() {
|
|
if (f) {
|
|
h.fix =
|
|
null;
|
|
f.mark.context(f, g, function() {
|
|
this.render()
|
|
});
|
|
pv.Mark.dispatch("dragend", f, g);
|
|
f = null
|
|
}
|
|
}
|
|
var f, g, h, i, j;
|
|
pv.listen(window, "mousemove", c);
|
|
pv.listen(window, "mouseup", d);
|
|
return b
|
|
};
|
|
pv.Behavior.point = function(b) {
|
|
function c(l, q) {
|
|
l = l[q];
|
|
q = {
|
|
cost: Infinity
|
|
};
|
|
for (var n = 0, p = l.visible && l.children.length; n < p; n++) {
|
|
var m = l.children[n],
|
|
r = m.mark,
|
|
s;
|
|
if (r.type == "panel") {
|
|
r.scene = m;
|
|
for (var t = 0, x = m.length; t < x; t++) {
|
|
r.index = t;
|
|
s = c(m, t);
|
|
if (s.cost < q.cost) q = s
|
|
}
|
|
delete r.scene;
|
|
delete r.index
|
|
} else if (r.$handlers.point) {
|
|
r = r.mouse();
|
|
t = 0;
|
|
for (x = m.length; t < x; t++) {
|
|
var u = m[t];
|
|
s = r.x - u.left - (u.width || 0) / 2;
|
|
u = r.y - u.top - (u.height || 0) / 2;
|
|
var o = i * s * s + j * u * u;
|
|
if (o < q.cost) {
|
|
q.distance = s * s + u * u;
|
|
q.cost = o;
|
|
q.scene = m;
|
|
q.index = t
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return q
|
|
}
|
|
|
|
function d() {
|
|
var l = c(this.scene, this.index);
|
|
if (l.cost == Infinity || l.distance > k) l = null;
|
|
if (g) {
|
|
if (l && g.scene == l.scene && g.index == l.index) return;
|
|
pv.Mark.dispatch("unpoint", g.scene, g.index)
|
|
}
|
|
if (g = l) {
|
|
pv.Mark.dispatch("point", l.scene, l.index);
|
|
pv.listen(this.root.canvas(), "mouseout", f)
|
|
}
|
|
}
|
|
|
|
function f(l) {
|
|
if (g && !pv.ancestor(this, l.relatedTarget)) {
|
|
pv.Mark.dispatch("unpoint", g.scene, g.index);
|
|
g = null
|
|
}
|
|
}
|
|
var g, h = null,
|
|
i = 1,
|
|
j = 1,
|
|
k = arguments.length ? b * b : 900;
|
|
d.collapse = function(l) {
|
|
if (arguments.length) {
|
|
h = String(l);
|
|
switch (h) {
|
|
case "y":
|
|
i =
|
|
1;
|
|
j = 0;
|
|
break;
|
|
case "x":
|
|
i = 0;
|
|
j = 1;
|
|
break;
|
|
default:
|
|
j = i = 1;
|
|
break
|
|
}
|
|
return d
|
|
}
|
|
return h
|
|
};
|
|
return d
|
|
};
|
|
pv.Behavior.select = function() {
|
|
function b(j) {
|
|
g = this.index;
|
|
f = this.scene;
|
|
i = this.mouse();
|
|
h = j;
|
|
h.x = i.x;
|
|
h.y = i.y;
|
|
h.dx = h.dy = 0;
|
|
pv.Mark.dispatch("selectstart", f, g)
|
|
}
|
|
|
|
function c() {
|
|
if (f) {
|
|
f.mark.context(f, g, function() {
|
|
var j = this.mouse();
|
|
h.x = Math.max(0, Math.min(i.x, j.x));
|
|
h.y = Math.max(0, Math.min(i.y, j.y));
|
|
h.dx = Math.min(this.width(), Math.max(j.x, i.x)) - h.x;
|
|
h.dy = Math.min(this.height(), Math.max(j.y, i.y)) - h.y;
|
|
this.render()
|
|
});
|
|
pv.Mark.dispatch("select", f, g)
|
|
}
|
|
}
|
|
|
|
function d() {
|
|
if (f) {
|
|
pv.Mark.dispatch("selectend", f, g);
|
|
f = null
|
|
}
|
|
}
|
|
var f,
|
|
g, h, i;
|
|
pv.listen(window, "mousemove", c);
|
|
pv.listen(window, "mouseup", d);
|
|
return b
|
|
};
|
|
pv.Behavior.resize = function(b) {
|
|
function c(k) {
|
|
h = this.index;
|
|
g = this.scene;
|
|
j = this.mouse();
|
|
i = k;
|
|
switch (b) {
|
|
case "left":
|
|
j.x = i.x + i.dx;
|
|
break;
|
|
case "right":
|
|
j.x = i.x;
|
|
break;
|
|
case "top":
|
|
j.y = i.y + i.dy;
|
|
break;
|
|
case "bottom":
|
|
j.y = i.y;
|
|
break
|
|
}
|
|
pv.Mark.dispatch("resizestart", g, h)
|
|
}
|
|
|
|
function d() {
|
|
if (g) {
|
|
g.mark.context(g, h, function() {
|
|
var k = this.mouse();
|
|
i.x = Math.max(0, Math.min(j.x, k.x));
|
|
i.y = Math.max(0, Math.min(j.y, k.y));
|
|
i.dx = Math.min(this.parent.width(), Math.max(k.x, j.x)) - i.x;
|
|
i.dy = Math.min(this.parent.height(), Math.max(k.y, j.y)) - i.y;
|
|
this.render()
|
|
});
|
|
pv.Mark.dispatch("resize", g, h)
|
|
}
|
|
}
|
|
|
|
function f() {
|
|
if (g) {
|
|
pv.Mark.dispatch("resizeend", g, h);
|
|
g = null
|
|
}
|
|
}
|
|
var g, h, i, j;
|
|
pv.listen(window, "mousemove", d);
|
|
pv.listen(window, "mouseup", f);
|
|
return c
|
|
};
|
|
pv.Behavior.pan = function() {
|
|
function b() {
|
|
g = this.index;
|
|
f = this.scene;
|
|
i = pv.vector(pv.event.pageX, pv.event.pageY);
|
|
h = this.transform();
|
|
j = 1 / (h.k * this.scale);
|
|
if (k) k = {
|
|
x: (1 - h.k) * this.width(),
|
|
y: (1 - h.k) * this.height()
|
|
}
|
|
}
|
|
|
|
function c() {
|
|
if (f) {
|
|
f.mark.context(f, g, function() {
|
|
var l = h.translate((pv.event.pageX - i.x) * j, (pv.event.pageY - i.y) * j);
|
|
if (k) {
|
|
l.x = Math.max(k.x, Math.min(0, l.x));
|
|
l.y = Math.max(k.y, Math.min(0, l.y))
|
|
}
|
|
this.transform(l).render()
|
|
});
|
|
pv.Mark.dispatch("pan", f, g)
|
|
}
|
|
}
|
|
|
|
function d() {
|
|
f = null
|
|
}
|
|
var f, g, h, i, j, k;
|
|
b.bound = function(l) {
|
|
if (arguments.length) {
|
|
k =
|
|
Boolean(l);
|
|
return this
|
|
}
|
|
return Boolean(k)
|
|
};
|
|
pv.listen(window, "mousemove", c);
|
|
pv.listen(window, "mouseup", d);
|
|
return b
|
|
};
|
|
pv.Behavior.zoom = function(b) {
|
|
function c() {
|
|
var f = this.mouse(),
|
|
g = pv.event.wheel * b;
|
|
f = this.transform().translate(f.x, f.y).scale(g < 0 ? 1E3 / (1E3 - g) : (1E3 + g) / 1E3).translate(-f.x, -f.y);
|
|
if (d) {
|
|
f.k = Math.max(1, f.k);
|
|
f.x = Math.max((1 - f.k) * this.width(), Math.min(0, f.x));
|
|
f.y = Math.max((1 - f.k) * this.height(), Math.min(0, f.y))
|
|
}
|
|
this.transform(f).render();
|
|
pv.Mark.dispatch("zoom", this.scene, this.index)
|
|
}
|
|
var d;
|
|
arguments.length || (b = 1 / 48);
|
|
c.bound = function(f) {
|
|
if (arguments.length) {
|
|
d = Boolean(f);
|
|
return this
|
|
}
|
|
return Boolean(d)
|
|
};
|
|
return c
|
|
};
|
|
pv.Geo = function() {};
|
|
pv.Geo.projections = {
|
|
mercator: {
|
|
project: function(b) {
|
|
return {
|
|
x: b.lng / 180,
|
|
y: b.lat > 85 ? 1 : b.lat < -85 ? -1 : Math.log(Math.tan(Math.PI / 4 + pv.radians(b.lat) / 2)) / Math.PI
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
return {
|
|
lng: b.x * 180,
|
|
lat: pv.degrees(2 * Math.atan(Math.exp(b.y * Math.PI)) - Math.PI / 2)
|
|
}
|
|
}
|
|
},
|
|
"gall-peters": {
|
|
project: function(b) {
|
|
return {
|
|
x: b.lng / 180,
|
|
y: Math.sin(pv.radians(b.lat))
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
return {
|
|
lng: b.x * 180,
|
|
lat: pv.degrees(Math.asin(b.y))
|
|
}
|
|
}
|
|
},
|
|
sinusoidal: {
|
|
project: function(b) {
|
|
return {
|
|
x: pv.radians(b.lng) * Math.cos(pv.radians(b.lat)) / Math.PI,
|
|
y: b.lat / 90
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
return {
|
|
lng: pv.degrees(b.x * Math.PI / Math.cos(b.y * Math.PI / 2)),
|
|
lat: b.y * 90
|
|
}
|
|
}
|
|
},
|
|
aitoff: {
|
|
project: function(b) {
|
|
var c = pv.radians(b.lng);
|
|
b = pv.radians(b.lat);
|
|
var d = Math.acos(Math.cos(b) * Math.cos(c / 2));
|
|
return {
|
|
x: 2 * (d ? Math.cos(b) * Math.sin(c / 2) * d / Math.sin(d) : 0) / Math.PI,
|
|
y: 2 * (d ? Math.sin(b) * d / Math.sin(d) : 0) / Math.PI
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
var c = b.y * Math.PI / 2;
|
|
return {
|
|
lng: pv.degrees(b.x * Math.PI / 2 / Math.cos(c)),
|
|
lat: pv.degrees(c)
|
|
}
|
|
}
|
|
},
|
|
hammer: {
|
|
project: function(b) {
|
|
var c = pv.radians(b.lng);
|
|
b = pv.radians(b.lat);
|
|
var d = Math.sqrt(1 + Math.cos(b) * Math.cos(c / 2));
|
|
return {
|
|
x: 2 * Math.SQRT2 * Math.cos(b) * Math.sin(c / 2) / d / 3,
|
|
y: Math.SQRT2 * Math.sin(b) / d / 1.5
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
var c = b.x * 3;
|
|
b = b.y * 1.5;
|
|
var d = Math.sqrt(1 - c * c / 16 - b * b / 4);
|
|
return {
|
|
lng: pv.degrees(2 * Math.atan2(d * c, 2 * (2 * d * d - 1))),
|
|
lat: pv.degrees(Math.asin(d * b))
|
|
}
|
|
}
|
|
},
|
|
identity: {
|
|
project: function(b) {
|
|
return {
|
|
x: b.lng / 180,
|
|
y: b.lat / 90
|
|
}
|
|
},
|
|
invert: function(b) {
|
|
return {
|
|
lng: b.x * 180,
|
|
lat: b.y * 90
|
|
}
|
|
}
|
|
}
|
|
};
|
|
pv.Geo.scale = function(b) {
|
|
function c(m) {
|
|
if (!n || m.lng != n.lng || m.lat != n.lat) {
|
|
n = m;
|
|
m = d(m);
|
|
p = {
|
|
x: k(m.x),
|
|
y: l(m.y)
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
function d(m) {
|
|
return j.project({
|
|
lng: m.lng - q.lng,
|
|
lat: m.lat
|
|
})
|
|
}
|
|
|
|
function f(m) {
|
|
m = j.invert(m);
|
|
m.lng += q.lng;
|
|
return m
|
|
}
|
|
var g = {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
h = {
|
|
x: 1,
|
|
y: 1
|
|
},
|
|
i = [],
|
|
j = pv.Geo.projections.identity,
|
|
k = pv.Scale.linear(-1, 1).range(0, 1),
|
|
l = pv.Scale.linear(-1, 1).range(1, 0),
|
|
q = {
|
|
lng: 0,
|
|
lat: 0
|
|
},
|
|
n, p;
|
|
c.x = function(m) {
|
|
return c(m).x
|
|
};
|
|
c.y = function(m) {
|
|
return c(m).y
|
|
};
|
|
c.ticks = {
|
|
lng: function(m) {
|
|
var r;
|
|
if (i.length > 1) {
|
|
var s = pv.Scale.linear();
|
|
if (m == undefined) m = 10;
|
|
r = s.domain(i, function(t) {
|
|
return t.lat
|
|
}).ticks(m);
|
|
m = s.domain(i, function(t) {
|
|
return t.lng
|
|
}).ticks(m)
|
|
} else {
|
|
r = pv.range(-80, 81, 10);
|
|
m = pv.range(-180, 181, 10)
|
|
}
|
|
return m.map(function(t) {
|
|
return r.map(function(x) {
|
|
return {
|
|
lat: x,
|
|
lng: t
|
|
}
|
|
})
|
|
})
|
|
},
|
|
lat: function(m) {
|
|
return pv.transpose(c.ticks.lng(m))
|
|
}
|
|
};
|
|
c.invert = function(m) {
|
|
return f({
|
|
x: k.invert(m.x),
|
|
y: l.invert(m.y)
|
|
})
|
|
};
|
|
c.domain = function(m, r) {
|
|
if (arguments.length) {
|
|
i = m instanceof Array ? arguments.length > 1 ? pv.map(m, r) : m : Array.prototype.slice.call(arguments);
|
|
if (i.length > 1) {
|
|
var s = i.map(function(x) {
|
|
return x.lng
|
|
}),
|
|
t = i.map(function(x) {
|
|
return x.lat
|
|
});
|
|
q = {
|
|
lng: (pv.max(s) + pv.min(s)) / 2,
|
|
lat: (pv.max(t) + pv.min(t)) / 2
|
|
};
|
|
s = i.map(d);
|
|
k.domain(s, function(x) {
|
|
return x.x
|
|
});
|
|
l.domain(s, function(x) {
|
|
return x.y
|
|
})
|
|
} else {
|
|
q = {
|
|
lng: 0,
|
|
lat: 0
|
|
};
|
|
k.domain(-1, 1);
|
|
l.domain(-1, 1)
|
|
}
|
|
n = null;
|
|
return this
|
|
}
|
|
return i
|
|
};
|
|
c.range = function(m, r) {
|
|
if (arguments.length) {
|
|
if (typeof m == "object") {
|
|
g = {
|
|
x: Number(m.x),
|
|
y: Number(m.y)
|
|
};
|
|
h = {
|
|
x: Number(r.x),
|
|
y: Number(r.y)
|
|
}
|
|
} else {
|
|
g = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
h = {
|
|
x: Number(m),
|
|
y: Number(r)
|
|
}
|
|
}
|
|
k.range(g.x, h.x);
|
|
l.range(h.y, g.y);
|
|
n = null;
|
|
return this
|
|
}
|
|
return [g, h]
|
|
};
|
|
c.projection = function(m) {
|
|
if (arguments.length) {
|
|
j = typeof m == "string" ? pv.Geo.projections[m] || pv.Geo.projections.identity : m;
|
|
return this.domain(i)
|
|
}
|
|
return m
|
|
};
|
|
c.by = function(m) {
|
|
function r() {
|
|
return c(m.apply(this, arguments))
|
|
}
|
|
for (var s in c) r[s] = c[s];
|
|
return r
|
|
};
|
|
arguments.length && c.projection(b);
|
|
return c
|
|
}; |