|
d3 = function() { |
|
var d3 = { |
|
version: "3.1.7" |
|
}; |
|
if (!Date.now) Date.now = function() { |
|
return +new Date(); |
|
}; |
|
var d3_document = document, d3_window = window; |
|
try { |
|
d3_document.createElement("div").style.setProperty("opacity", 0, ""); |
|
} catch (error) { |
|
var d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; |
|
d3_style_prototype.setProperty = function(name, value, priority) { |
|
d3_style_setProperty.call(this, name, value + "", priority); |
|
}; |
|
} |
|
d3.ascending = function(a, b) { |
|
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; |
|
}; |
|
d3.descending = function(a, b) { |
|
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; |
|
}; |
|
d3.min = function(array, f) { |
|
var i = -1, n = array.length, a, b; |
|
if (arguments.length === 1) { |
|
while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; |
|
while (++i < n) if ((b = array[i]) != null && a > b) a = b; |
|
} else { |
|
while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; |
|
} |
|
return a; |
|
}; |
|
d3.max = function(array, f) { |
|
var i = -1, n = array.length, a, b; |
|
if (arguments.length === 1) { |
|
while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; |
|
while (++i < n) if ((b = array[i]) != null && b > a) a = b; |
|
} else { |
|
while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; |
|
} |
|
return a; |
|
}; |
|
d3.extent = function(array, f) { |
|
var i = -1, n = array.length, a, b, c; |
|
if (arguments.length === 1) { |
|
while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined; |
|
while (++i < n) if ((b = array[i]) != null) { |
|
if (a > b) a = b; |
|
if (c < b) c = b; |
|
} |
|
} else { |
|
while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
while (++i < n) if ((b = f.call(array, array[i], i)) != null) { |
|
if (a > b) a = b; |
|
if (c < b) c = b; |
|
} |
|
} |
|
return [ a, c ]; |
|
}; |
|
d3.sum = function(array, f) { |
|
var s = 0, n = array.length, a, i = -1; |
|
if (arguments.length === 1) { |
|
while (++i < n) if (!isNaN(a = +array[i])) s += a; |
|
} else { |
|
while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; |
|
} |
|
return s; |
|
}; |
|
function d3_number(x) { |
|
return x != null && !isNaN(x); |
|
} |
|
d3.mean = function(array, f) { |
|
var n = array.length, a, m = 0, i = -1, j = 0; |
|
if (arguments.length === 1) { |
|
while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; |
|
} else { |
|
while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; |
|
} |
|
return j ? m : undefined; |
|
}; |
|
d3.quantile = function(values, p) { |
|
var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; |
|
return e ? v + e * (values[h] - v) : v; |
|
}; |
|
d3.median = function(array, f) { |
|
if (arguments.length > 1) array = array.map(f); |
|
array = array.filter(d3_number); |
|
return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; |
|
}; |
|
d3.bisector = function(f) { |
|
return { |
|
left: function(a, x, lo, hi) { |
|
if (arguments.length < 3) lo = 0; |
|
if (arguments.length < 4) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid; |
|
} |
|
return lo; |
|
}, |
|
right: function(a, x, lo, hi) { |
|
if (arguments.length < 3) lo = 0; |
|
if (arguments.length < 4) hi = a.length; |
|
while (lo < hi) { |
|
var mid = lo + hi >>> 1; |
|
if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1; |
|
} |
|
return lo; |
|
} |
|
}; |
|
}; |
|
var d3_bisector = d3.bisector(function(d) { |
|
return d; |
|
}); |
|
d3.bisectLeft = d3_bisector.left; |
|
d3.bisect = d3.bisectRight = d3_bisector.right; |
|
d3.shuffle = function(array) { |
|
var m = array.length, t, i; |
|
while (m) { |
|
i = Math.random() * m-- | 0; |
|
t = array[m], array[m] = array[i], array[i] = t; |
|
} |
|
return array; |
|
}; |
|
d3.permute = function(array, indexes) { |
|
var permutes = [], i = -1, n = indexes.length; |
|
while (++i < n) permutes[i] = array[indexes[i]]; |
|
return permutes; |
|
}; |
|
d3.zip = function() { |
|
if (!(n = arguments.length)) return []; |
|
for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { |
|
for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { |
|
zip[j] = arguments[j][i]; |
|
} |
|
} |
|
return zips; |
|
}; |
|
function d3_zipLength(d) { |
|
return d.length; |
|
} |
|
d3.transpose = function(matrix) { |
|
return d3.zip.apply(d3, matrix); |
|
}; |
|
d3.keys = function(map) { |
|
var keys = []; |
|
for (var key in map) keys.push(key); |
|
return keys; |
|
}; |
|
d3.values = function(map) { |
|
var values = []; |
|
for (var key in map) values.push(map[key]); |
|
return values; |
|
}; |
|
d3.entries = function(map) { |
|
var entries = []; |
|
for (var key in map) entries.push({ |
|
key: key, |
|
value: map[key] |
|
}); |
|
return entries; |
|
}; |
|
d3.merge = function(arrays) { |
|
return Array.prototype.concat.apply([], arrays); |
|
}; |
|
d3.range = function(start, stop, step) { |
|
if (arguments.length < 3) { |
|
step = 1; |
|
if (arguments.length < 2) { |
|
stop = start; |
|
start = 0; |
|
} |
|
} |
|
if ((stop - start) / step === Infinity) throw new Error("infinite range"); |
|
var range = [], k = d3_range_integerScale(Math.abs(step)), i = -1, j; |
|
start *= k, stop *= k, step *= k; |
|
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); |
|
return range; |
|
}; |
|
function d3_range_integerScale(x) { |
|
var k = 1; |
|
while (x * k % 1) k *= 10; |
|
return k; |
|
} |
|
function d3_class(ctor, properties) { |
|
try { |
|
for (var key in properties) { |
|
Object.defineProperty(ctor.prototype, key, { |
|
value: properties[key], |
|
enumerable: false |
|
}); |
|
} |
|
} catch (e) { |
|
ctor.prototype = properties; |
|
} |
|
} |
|
d3.map = function(object) { |
|
var map = new d3_Map(); |
|
for (var key in object) map.set(key, object[key]); |
|
return map; |
|
}; |
|
function d3_Map() {} |
|
d3_class(d3_Map, { |
|
has: function(key) { |
|
return d3_map_prefix + key in this; |
|
}, |
|
get: function(key) { |
|
return this[d3_map_prefix + key]; |
|
}, |
|
set: function(key, value) { |
|
return this[d3_map_prefix + key] = value; |
|
}, |
|
remove: function(key) { |
|
key = d3_map_prefix + key; |
|
return key in this && delete this[key]; |
|
}, |
|
keys: function() { |
|
var keys = []; |
|
this.forEach(function(key) { |
|
keys.push(key); |
|
}); |
|
return keys; |
|
}, |
|
values: function() { |
|
var values = []; |
|
this.forEach(function(key, value) { |
|
values.push(value); |
|
}); |
|
return values; |
|
}, |
|
entries: function() { |
|
var entries = []; |
|
this.forEach(function(key, value) { |
|
entries.push({ |
|
key: key, |
|
value: value |
|
}); |
|
}); |
|
return entries; |
|
}, |
|
forEach: function(f) { |
|
for (var key in this) { |
|
if (key.charCodeAt(0) === d3_map_prefixCode) { |
|
f.call(this, key.substring(1), this[key]); |
|
} |
|
} |
|
} |
|
}); |
|
var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0); |
|
d3.nest = function() { |
|
var nest = {}, keys = [], sortKeys = [], sortValues, rollup; |
|
function map(mapType, array, depth) { |
|
if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; |
|
var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; |
|
while (++i < n) { |
|
if (values = valuesByKey.get(keyValue = key(object = array[i]))) { |
|
values.push(object); |
|
} else { |
|
valuesByKey.set(keyValue, [ object ]); |
|
} |
|
} |
|
if (mapType) { |
|
object = mapType(); |
|
setter = function(keyValue, values) { |
|
object.set(keyValue, map(mapType, values, depth)); |
|
}; |
|
} else { |
|
object = {}; |
|
setter = function(keyValue, values) { |
|
object[keyValue] = map(mapType, values, depth); |
|
}; |
|
} |
|
valuesByKey.forEach(setter); |
|
return object; |
|
} |
|
function entries(map, depth) { |
|
if (depth >= keys.length) return map; |
|
var array = [], sortKey = sortKeys[depth++]; |
|
map.forEach(function(key, keyMap) { |
|
array.push({ |
|
key: key, |
|
values: entries(keyMap, depth) |
|
}); |
|
}); |
|
return sortKey ? array.sort(function(a, b) { |
|
return sortKey(a.key, b.key); |
|
}) : array; |
|
} |
|
nest.map = function(array, mapType) { |
|
return map(mapType, array, 0); |
|
}; |
|
nest.entries = function(array) { |
|
return entries(map(d3.map, array, 0), 0); |
|
}; |
|
nest.key = function(d) { |
|
keys.push(d); |
|
return nest; |
|
}; |
|
nest.sortKeys = function(order) { |
|
sortKeys[keys.length - 1] = order; |
|
return nest; |
|
}; |
|
nest.sortValues = function(order) { |
|
sortValues = order; |
|
return nest; |
|
}; |
|
nest.rollup = function(f) { |
|
rollup = f; |
|
return nest; |
|
}; |
|
return nest; |
|
}; |
|
d3.set = function(array) { |
|
var set = new d3_Set(); |
|
if (array) for (var i = 0; i < array.length; i++) set.add(array[i]); |
|
return set; |
|
}; |
|
function d3_Set() {} |
|
d3_class(d3_Set, { |
|
has: function(value) { |
|
return d3_map_prefix + value in this; |
|
}, |
|
add: function(value) { |
|
this[d3_map_prefix + value] = true; |
|
return value; |
|
}, |
|
remove: function(value) { |
|
value = d3_map_prefix + value; |
|
return value in this && delete this[value]; |
|
}, |
|
values: function() { |
|
var values = []; |
|
this.forEach(function(value) { |
|
values.push(value); |
|
}); |
|
return values; |
|
}, |
|
forEach: function(f) { |
|
for (var value in this) { |
|
if (value.charCodeAt(0) === d3_map_prefixCode) { |
|
f.call(this, value.substring(1)); |
|
} |
|
} |
|
} |
|
}); |
|
d3.behavior = {}; |
|
d3.rebind = function(target, source) { |
|
var i = 1, n = arguments.length, method; |
|
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); |
|
return target; |
|
}; |
|
function d3_rebind(target, source, method) { |
|
return function() { |
|
var value = method.apply(source, arguments); |
|
return value === source ? target : value; |
|
}; |
|
} |
|
d3.dispatch = function() { |
|
var dispatch = new d3_dispatch(), i = -1, n = arguments.length; |
|
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); |
|
return dispatch; |
|
}; |
|
function d3_dispatch() {} |
|
d3_dispatch.prototype.on = function(type, listener) { |
|
var i = type.indexOf("."), name = ""; |
|
if (i >= 0) { |
|
name = type.substring(i + 1); |
|
type = type.substring(0, i); |
|
} |
|
if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); |
|
if (arguments.length === 2) { |
|
if (listener == null) for (type in this) { |
|
if (this.hasOwnProperty(type)) this[type].on(name, null); |
|
} |
|
return this; |
|
} |
|
}; |
|
function d3_dispatch_event(dispatch) { |
|
var listeners = [], listenerByName = new d3_Map(); |
|
function event() { |
|
var z = listeners, i = -1, n = z.length, l; |
|
while (++i < n) if (l = z[i].on) l.apply(this, arguments); |
|
return dispatch; |
|
} |
|
event.on = function(name, listener) { |
|
var l = listenerByName.get(name), i; |
|
if (arguments.length < 2) return l && l.on; |
|
if (l) { |
|
l.on = null; |
|
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); |
|
listenerByName.remove(name); |
|
} |
|
if (listener) listeners.push(listenerByName.set(name, { |
|
on: listener |
|
})); |
|
return dispatch; |
|
}; |
|
return event; |
|
} |
|
d3.event = null; |
|
function d3_eventCancel() { |
|
d3.event.stopPropagation(); |
|
d3.event.preventDefault(); |
|
} |
|
function d3_eventSource() { |
|
var e = d3.event, s; |
|
while (s = e.sourceEvent) e = s; |
|
return e; |
|
} |
|
function d3_eventSuppress(target, type) { |
|
function off() { |
|
target.on(type, null); |
|
} |
|
target.on(type, function() { |
|
d3_eventCancel(); |
|
off(); |
|
}, true); |
|
setTimeout(off, 0); |
|
} |
|
function d3_eventDispatch(target) { |
|
var dispatch = new d3_dispatch(), i = 0, n = arguments.length; |
|
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); |
|
dispatch.of = function(thiz, argumentz) { |
|
return function(e1) { |
|
try { |
|
var e0 = e1.sourceEvent = d3.event; |
|
e1.target = target; |
|
d3.event = e1; |
|
dispatch[e1.type].apply(thiz, argumentz); |
|
} finally { |
|
d3.event = e0; |
|
} |
|
}; |
|
}; |
|
return dispatch; |
|
} |
|
d3.mouse = function(container) { |
|
return d3_mousePoint(container, d3_eventSource()); |
|
}; |
|
var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; |
|
function d3_mousePoint(container, e) { |
|
var svg = container.ownerSVGElement || container; |
|
if (svg.createSVGPoint) { |
|
var point = svg.createSVGPoint(); |
|
if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { |
|
svg = d3.select(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0); |
|
var ctm = svg[0][0].getScreenCTM(); |
|
d3_mouse_bug44083 = !(ctm.f || ctm.e); |
|
svg.remove(); |
|
} |
|
if (d3_mouse_bug44083) { |
|
point.x = e.pageX; |
|
point.y = e.pageY; |
|
} else { |
|
point.x = e.clientX; |
|
point.y = e.clientY; |
|
} |
|
point = point.matrixTransform(container.getScreenCTM().inverse()); |
|
return [ point.x, point.y ]; |
|
} |
|
var rect = container.getBoundingClientRect(); |
|
return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; |
|
} |
|
var d3_array = d3_arraySlice; |
|
function d3_arrayCopy(pseudoarray) { |
|
var i = -1, n = pseudoarray.length, array = []; |
|
while (++i < n) array.push(pseudoarray[i]); |
|
return array; |
|
} |
|
function d3_arraySlice(pseudoarray) { |
|
return Array.prototype.slice.call(pseudoarray); |
|
} |
|
try { |
|
d3_array(d3_document.documentElement.childNodes)[0].nodeType; |
|
} catch (e) { |
|
d3_array = d3_arrayCopy; |
|
} |
|
var d3_arraySubclass = [].__proto__ ? function(array, prototype) { |
|
array.__proto__ = prototype; |
|
} : function(array, prototype) { |
|
for (var property in prototype) array[property] = prototype[property]; |
|
}; |
|
d3.touches = function(container, touches) { |
|
if (arguments.length < 2) touches = d3_eventSource().touches; |
|
return touches ? d3_array(touches).map(function(touch) { |
|
var point = d3_mousePoint(container, touch); |
|
point.identifier = touch.identifier; |
|
return point; |
|
}) : []; |
|
}; |
|
d3.behavior.drag = function() { |
|
var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null; |
|
function drag() { |
|
this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown); |
|
} |
|
function mousedown() { |
|
var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0; |
|
var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true); |
|
if (origin) { |
|
offset = origin.apply(target, arguments); |
|
offset = [ offset.x - origin_[0], offset.y - origin_[1] ]; |
|
} else { |
|
offset = [ 0, 0 ]; |
|
} |
|
if (touchId == null) d3_eventCancel(); |
|
event_({ |
|
type: "dragstart" |
|
}); |
|
function point() { |
|
var p = target.parentNode; |
|
return touchId != null ? d3.touches(p).filter(function(p) { |
|
return p.identifier === touchId; |
|
})[0] : d3.mouse(p); |
|
} |
|
function dragmove() { |
|
if (!target.parentNode) return dragend(); |
|
var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1]; |
|
moved |= dx | dy; |
|
origin_ = p; |
|
d3_eventCancel(); |
|
event_({ |
|
type: "drag", |
|
x: p[0] + offset[0], |
|
y: p[1] + offset[1], |
|
dx: dx, |
|
dy: dy |
|
}); |
|
} |
|
function dragend() { |
|
event_({ |
|
type: "dragend" |
|
}); |
|
if (moved) { |
|
d3_eventCancel(); |
|
if (d3.event.target === eventTarget) d3_eventSuppress(w, "click"); |
|
} |
|
w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null); |
|
} |
|
} |
|
drag.origin = function(x) { |
|
if (!arguments.length) return origin; |
|
origin = x; |
|
return drag; |
|
}; |
|
return d3.rebind(drag, event, "on"); |
|
}; |
|
function d3_selection(groups) { |
|
d3_arraySubclass(groups, d3_selectionPrototype); |
|
return groups; |
|
} |
|
var d3_select = function(s, n) { |
|
return n.querySelector(s); |
|
}, d3_selectAll = function(s, n) { |
|
return n.querySelectorAll(s); |
|
}, d3_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) { |
|
return d3_selectMatcher.call(n, s); |
|
}; |
|
if (typeof Sizzle === "function") { |
|
d3_select = function(s, n) { |
|
return Sizzle(s, n)[0] || null; |
|
}; |
|
d3_selectAll = function(s, n) { |
|
return Sizzle.uniqueSort(Sizzle(s, n)); |
|
}; |
|
d3_selectMatches = Sizzle.matchesSelector; |
|
} |
|
d3.selection = function() { |
|
return d3_selectionRoot; |
|
}; |
|
var d3_selectionPrototype = d3.selection.prototype = []; |
|
d3_selectionPrototype.select = function(selector) { |
|
var subgroups = [], subgroup, subnode, group, node; |
|
if (typeof selector !== "function") selector = d3_selection_selector(selector); |
|
for (var j = -1, m = this.length; ++j < m; ) { |
|
subgroups.push(subgroup = []); |
|
subgroup.parentNode = (group = this[j]).parentNode; |
|
for (var i = -1, n = group.length; ++i < n; ) { |
|
if (node = group[i]) { |
|
subgroup.push(subnode = selector.call(node, node.__data__, i)); |
|
if (subnode && "__data__" in node) subnode.__data__ = node.__data__; |
|
} else { |
|
subgroup.push(null); |
|
} |
|
} |
|
} |
|
return d3_selection(subgroups); |
|
}; |
|
function d3_selection_selector(selector) { |
|
return function() { |
|
return d3_select(selector, this); |
|
}; |
|
} |
|
d3_selectionPrototype.selectAll = function(selector) { |
|
var subgroups = [], subgroup, node; |
|
if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); |
|
for (var j = -1, m = this.length; ++j < m; ) { |
|
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { |
|
if (node = group[i]) { |
|
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i))); |
|
subgroup.parentNode = node; |
|
} |
|
} |
|
} |
|
return d3_selection(subgroups); |
|
}; |
|
function d3_selection_selectorAll(selector) { |
|
return function() { |
|
return d3_selectAll(selector, this); |
|
}; |
|
} |
|
var d3_nsPrefix = { |
|
svg: "http://www.w3.org/2000/svg", |
|
xhtml: "http://www.w3.org/1999/xhtml", |
|
xlink: "http://www.w3.org/1999/xlink", |
|
xml: "http://www.w3.org/XML/1998/namespace", |
|
xmlns: "http://www.w3.org/2000/xmlns/" |
|
}; |
|
d3.ns = { |
|
prefix: d3_nsPrefix, |
|
qualify: function(name) { |
|
var i = name.indexOf(":"), prefix = name; |
|
if (i >= 0) { |
|
prefix = name.substring(0, i); |
|
name = name.substring(i + 1); |
|
} |
|
return d3_nsPrefix.hasOwnProperty(prefix) ? { |
|
space: d3_nsPrefix[prefix], |
|
local: name |
|
} : name; |
|
} |
|
}; |
|
d3_selectionPrototype.attr = function(name, value) { |
|
if (arguments.length < 2) { |
|
if (typeof name === "string") { |
|
var node = this.node(); |
|
name = d3.ns.qualify(name); |
|
return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); |
|
} |
|
for (value in name) this.each(d3_selection_attr(value, name[value])); |
|
return this; |
|
} |
|
return this.each(d3_selection_attr(name, value)); |
|
}; |
|
function d3_selection_attr(name, value) { |
|
name = d3.ns.qualify(name); |
|
function attrNull() { |
|
this.removeAttribute(name); |
|
} |
|
function attrNullNS() { |
|
this.removeAttributeNS(name.space, name.local); |
|
} |
|
function attrConstant() { |
|
this.setAttribute(name, value); |
|
} |
|
function attrConstantNS() { |
|
this.setAttributeNS(name.space, name.local, value); |
|
} |
|
function attrFunction() { |
|
var x = value.apply(this, arguments); |
|
if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); |
|
} |
|
function attrFunctionNS() { |
|
var x = value.apply(this, arguments); |
|
if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); |
|
} |
|
return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; |
|
} |
|
function d3_collapse(s) { |
|
return s.trim().replace(/\s+/g, " "); |
|
} |
|
d3.requote = function(s) { |
|
return s.replace(d3_requote_re, "\\$&"); |
|
}; |
|
var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; |
|
d3_selectionPrototype.classed = function(name, value) { |
|
if (arguments.length < 2) { |
|
if (typeof name === "string") { |
|
var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1; |
|
if (value = node.classList) { |
|
while (++i < n) if (!value.contains(name[i])) return false; |
|
} else { |
|
value = node.getAttribute("class"); |
|
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; |
|
} |
|
return true; |
|
} |
|
for (value in name) this.each(d3_selection_classed(value, name[value])); |
|
return this; |
|
} |
|
return this.each(d3_selection_classed(name, value)); |
|
}; |
|
function d3_selection_classedRe(name) { |
|
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); |
|
} |
|
function d3_selection_classed(name, value) { |
|
name = name.trim().split(/\s+/).map(d3_selection_classedName); |
|
var n = name.length; |
|
function classedConstant() { |
|
var i = -1; |
|
while (++i < n) name[i](this, value); |
|
} |
|
function classedFunction() { |
|
var i = -1, x = value.apply(this, arguments); |
|
while (++i < n) name[i](this, x); |
|
} |
|
return typeof value === "function" ? classedFunction : classedConstant; |
|
} |
|
function d3_selection_classedName(name) { |
|
var re = d3_selection_classedRe(name); |
|
return function(node, value) { |
|
if (c = node.classList) return value ? c.add(name) : c.remove(name); |
|
var c = node.getAttribute("class") || ""; |
|
if (value) { |
|
re.lastIndex = 0; |
|
if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); |
|
} else { |
|
node.setAttribute("class", d3_collapse(c.replace(re, " "))); |
|
} |
|
}; |
|
} |
|
d3_selectionPrototype.style = function(name, value, priority) { |
|
var n = arguments.length; |
|
if (n < 3) { |
|
if (typeof name !== "string") { |
|
if (n < 2) value = ""; |
|
for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); |
|
return this; |
|
} |
|
if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name); |
|
priority = ""; |
|
} |
|
return this.each(d3_selection_style(name, value, priority)); |
|
}; |
|
function d3_selection_style(name, value, priority) { |
|
function styleNull() { |
|
this.style.removeProperty(name); |
|
} |
|
function styleConstant() { |
|
this.style.setProperty(name, value, priority); |
|
} |
|
function styleFunction() { |
|
var x = value.apply(this, arguments); |
|
if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); |
|
} |
|
return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; |
|
} |
|
d3_selectionPrototype.property = function(name, value) { |
|
if (arguments.length < 2) { |
|
if (typeof name === "string") return this.node()[name]; |
|
for (value in name) this.each(d3_selection_property(value, name[value])); |
|
return this; |
|
} |
|
return this.each(d3_selection_property(name, value)); |
|
}; |
|
function d3_selection_property(name, value) { |
|
function propertyNull() { |
|
delete this[name]; |
|
} |
|
function propertyConstant() { |
|
this[name] = value; |
|
} |
|
function propertyFunction() { |
|
var x = value.apply(this, arguments); |
|
if (x == null) delete this[name]; else this[name] = x; |
|
} |
|
return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; |
|
} |
|
d3_selectionPrototype.text = function(value) { |
|
return arguments.length ? this.each(typeof value === "function" ? function() { |
|
var v = value.apply(this, arguments); |
|
this.textContent = v == null ? "" : v; |
|
} : value == null ? function() { |
|
this.textContent = ""; |
|
} : function() { |
|
this.textContent = value; |
|
}) : this.node().textContent; |
|
}; |
|
d3_selectionPrototype.html = function(value) { |
|
return arguments.length ? this.each(typeof value === "function" ? function() { |
|
var v = value.apply(this, arguments); |
|
this.innerHTML = v == null ? "" : v; |
|
} : value == null ? function() { |
|
this.innerHTML = ""; |
|
} : function() { |
|
this.innerHTML = value; |
|
}) : this.node().innerHTML; |
|
}; |
|
d3_selectionPrototype.append = function(name) { |
|
name = d3.ns.qualify(name); |
|
function append() { |
|
return this.appendChild(d3_document.createElementNS(this.namespaceURI, name)); |
|
} |
|
function appendNS() { |
|
return this.appendChild(d3_document.createElementNS(name.space, name.local)); |
|
} |
|
return this.select(name.local ? appendNS : append); |
|
}; |
|
d3_selectionPrototype.insert = function(name, before) { |
|
name = d3.ns.qualify(name); |
|
if (typeof before !== "function") before = d3_selection_selector(before); |
|
function insert(d, i) { |
|
return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), before.call(this, d, i)); |
|
} |
|
function insertNS(d, i) { |
|
return this.insertBefore(d3_document.createElementNS(name.space, name.local), before.call(this, d, i)); |
|
} |
|
return this.select(name.local ? insertNS : insert); |
|
}; |
|
d3_selectionPrototype.remove = function() { |
|
return this.each(function() { |
|
var parent = this.parentNode; |
|
if (parent) parent.removeChild(this); |
|
}); |
|
}; |
|
d3_selectionPrototype.data = function(value, key) { |
|
var i = -1, n = this.length, group, node; |
|
if (!arguments.length) { |
|
value = new Array(n = (group = this[0]).length); |
|
while (++i < n) { |
|
if (node = group[i]) { |
|
value[i] = node.__data__; |
|
} |
|
} |
|
return value; |
|
} |
|
function bind(group, groupData) { |
|
var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; |
|
if (key) { |
|
var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue; |
|
for (i = -1; ++i < n; ) { |
|
keyValue = key.call(node = group[i], node.__data__, i); |
|
if (nodeByKeyValue.has(keyValue)) { |
|
exitNodes[i] = node; |
|
} else { |
|
nodeByKeyValue.set(keyValue, node); |
|
} |
|
keyValues.push(keyValue); |
|
} |
|
for (i = -1; ++i < m; ) { |
|
keyValue = key.call(groupData, nodeData = groupData[i], i); |
|
if (node = nodeByKeyValue.get(keyValue)) { |
|
updateNodes[i] = node; |
|
node.__data__ = nodeData; |
|
} else if (!dataByKeyValue.has(keyValue)) { |
|
enterNodes[i] = d3_selection_dataNode(nodeData); |
|
} |
|
dataByKeyValue.set(keyValue, nodeData); |
|
nodeByKeyValue.remove(keyValue); |
|
} |
|
for (i = -1; ++i < n; ) { |
|
if (nodeByKeyValue.has(keyValues[i])) { |
|
exitNodes[i] = group[i]; |
|
} |
|
} |
|
} else { |
|
for (i = -1; ++i < n0; ) { |
|
node = group[i]; |
|
nodeData = groupData[i]; |
|
if (node) { |
|
node.__data__ = nodeData; |
|
updateNodes[i] = node; |
|
} else { |
|
enterNodes[i] = d3_selection_dataNode(nodeData); |
|
} |
|
} |
|
for (;i < m; ++i) { |
|
enterNodes[i] = d3_selection_dataNode(groupData[i]); |
|
} |
|
for (;i < n; ++i) { |
|
exitNodes[i] = group[i]; |
|
} |
|
} |
|
enterNodes.update = updateNodes; |
|
enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; |
|
enter.push(enterNodes); |
|
update.push(updateNodes); |
|
exit.push(exitNodes); |
|
} |
|
var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); |
|
if (typeof value === "function") { |
|
while (++i < n) { |
|
bind(group = this[i], value.call(group, group.parentNode.__data__, i)); |
|
} |
|
} else { |
|
while (++i < n) { |
|
bind(group = this[i], value); |
|
} |
|
} |
|
update.enter = function() { |
|
return enter; |
|
}; |
|
update.exit = function() { |
|
return exit; |
|
}; |
|
return update; |
|
}; |
|
function d3_selection_dataNode(data) { |
|
return { |
|
__data__: data |
|
}; |
|
} |
|
d3_selectionPrototype.datum = function(value) { |
|
return arguments.length ? this.property("__data__", value) : this.property("__data__"); |
|
}; |
|
d3_selectionPrototype.filter = function(filter) { |
|
var subgroups = [], subgroup, group, node; |
|
if (typeof filter !== "function") filter = d3_selection_filter(filter); |
|
for (var j = 0, m = this.length; j < m; j++) { |
|
subgroups.push(subgroup = []); |
|
subgroup.parentNode = (group = this[j]).parentNode; |
|
for (var i = 0, n = group.length; i < n; i++) { |
|
if ((node = group[i]) && filter.call(node, node.__data__, i)) { |
|
subgroup.push(node); |
|
} |
|
} |
|
} |
|
return d3_selection(subgroups); |
|
}; |
|
function d3_selection_filter(selector) { |
|
return function() { |
|
return d3_selectMatches(this, selector); |
|
}; |
|
} |
|
d3_selectionPrototype.order = function() { |
|
for (var j = -1, m = this.length; ++j < m; ) { |
|
for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { |
|
if (node = group[i]) { |
|
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); |
|
next = node; |
|
} |
|
} |
|
} |
|
return this; |
|
}; |
|
d3_selectionPrototype.sort = function(comparator) { |
|
comparator = d3_selection_sortComparator.apply(this, arguments); |
|
for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); |
|
return this.order(); |
|
}; |
|
function d3_selection_sortComparator(comparator) { |
|
if (!arguments.length) comparator = d3.ascending; |
|
return function(a, b) { |
|
return !a - !b || comparator(a.__data__, b.__data__); |
|
}; |
|
} |
|
function d3_noop() {} |
|
d3_selectionPrototype.on = function(type, listener, capture) { |
|
var n = arguments.length; |
|
if (n < 3) { |
|
if (typeof type !== "string") { |
|
if (n < 2) listener = false; |
|
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); |
|
return this; |
|
} |
|
if (n < 2) return (n = this.node()["__on" + type]) && n._; |
|
capture = false; |
|
} |
|
return this.each(d3_selection_on(type, listener, capture)); |
|
}; |
|
function d3_selection_on(type, listener, capture) { |
|
var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; |
|
if (i > 0) type = type.substring(0, i); |
|
var filter = d3_selection_onFilters.get(type); |
|
if (filter) type = filter, wrap = d3_selection_onFilter; |
|
function onRemove() { |
|
var l = this[name]; |
|
if (l) { |
|
this.removeEventListener(type, l, l.$); |
|
delete this[name]; |
|
} |
|
} |
|
function onAdd() { |
|
var l = wrap(listener, d3_array(arguments)); |
|
onRemove.call(this); |
|
this.addEventListener(type, this[name] = l, l.$ = capture); |
|
l._ = listener; |
|
} |
|
function removeAll() { |
|
var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; |
|
for (var name in this) { |
|
if (match = name.match(re)) { |
|
var l = this[name]; |
|
this.removeEventListener(match[1], l, l.$); |
|
delete this[name]; |
|
} |
|
} |
|
} |
|
return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; |
|
} |
|
var d3_selection_onFilters = d3.map({ |
|
mouseenter: "mouseover", |
|
mouseleave: "mouseout" |
|
}); |
|
d3_selection_onFilters.forEach(function(k) { |
|
if ("on" + k in d3_document) d3_selection_onFilters.remove(k); |
|
}); |
|
function d3_selection_onListener(listener, argumentz) { |
|
return function(e) { |
|
var o = d3.event; |
|
d3.event = e; |
|
argumentz[0] = this.__data__; |
|
try { |
|
listener.apply(this, argumentz); |
|
} finally { |
|
d3.event = o; |
|
} |
|
}; |
|
} |
|
function d3_selection_onFilter(listener, argumentz) { |
|
var l = d3_selection_onListener(listener, argumentz); |
|
return function(e) { |
|
var target = this, related = e.relatedTarget; |
|
if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { |
|
l.call(target, e); |
|
} |
|
}; |
|
} |
|
d3_selectionPrototype.each = function(callback) { |
|
return d3_selection_each(this, function(node, i, j) { |
|
callback.call(node, node.__data__, i, j); |
|
}); |
|
}; |
|
function d3_selection_each(groups, callback) { |
|
for (var j = 0, m = groups.length; j < m; j++) { |
|
for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { |
|
if (node = group[i]) callback(node, i, j); |
|
} |
|
} |
|
return groups; |
|
} |
|
d3_selectionPrototype.call = function(callback) { |
|
var args = d3_array(arguments); |
|
callback.apply(args[0] = this, args); |
|
return this; |
|
}; |
|
d3_selectionPrototype.empty = function() { |
|
return !this.node(); |
|
}; |
|
d3_selectionPrototype.node = function() { |
|
for (var j = 0, m = this.length; j < m; j++) { |
|
for (var group = this[j], i = 0, n = group.length; i < n; i++) { |
|
var node = group[i]; |
|
if (node) return node; |
|
} |
|
} |
|
return null; |
|
}; |
|
function d3_selection_enter(selection) { |
|
d3_arraySubclass(selection, d3_selection_enterPrototype); |
|
return selection; |
|
} |
|
var d3_selection_enterPrototype = []; |
|
d3.selection.enter = d3_selection_enter; |
|
d3.selection.enter.prototype = d3_selection_enterPrototype; |
|
d3_selection_enterPrototype.append = d3_selectionPrototype.append; |
|
d3_selection_enterPrototype.insert = d3_selectionPrototype.insert; |
|
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; |
|
d3_selection_enterPrototype.node = d3_selectionPrototype.node; |
|
d3_selection_enterPrototype.select = function(selector) { |
|
var subgroups = [], subgroup, subnode, upgroup, group, node; |
|
for (var j = -1, m = this.length; ++j < m; ) { |
|
upgroup = (group = this[j]).update; |
|
subgroups.push(subgroup = []); |
|
subgroup.parentNode = group.parentNode; |
|
for (var i = -1, n = group.length; ++i < n; ) { |
|
if (node = group[i]) { |
|
subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i)); |
|
subnode.__data__ = node.__data__; |
|
} else { |
|
subgroup.push(null); |
|
} |
|
} |
|
} |
|
return d3_selection(subgroups); |
|
}; |
|
d3_selectionPrototype.transition = function() { |
|
var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit); |
|
transition.time = Date.now(); |
|
for (var j = -1, m = this.length; ++j < m; ) { |
|
subgroups.push(subgroup = []); |
|
for (var group = this[j], i = -1, n = group.length; ++i < n; ) { |
|
if (node = group[i]) d3_transitionNode(node, i, id, transition); |
|
subgroup.push(node); |
|
} |
|
} |
|
return d3_transition(subgroups, id); |
|
}; |
|
d3.select = function(node) { |
|
var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ]; |
|
group.parentNode = d3_selectRoot; |
|
return d3_selection([ group ]); |
|
}; |
|
d3.selectAll = function(nodes) { |
|
var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes); |
|
group.parentNode = d3_selectRoot; |
|
return d3_selection([ group ]); |
|
}; |
|
var d3_selectionRoot = d3.select(d3_selectRoot); |
|
d3.behavior.zoom = function() { |
|
var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime; |
|
function zoom() { |
|
this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart); |
|
} |
|
zoom.translate = function(x) { |
|
if (!arguments.length) return translate; |
|
translate = x.map(Number); |
|
rescale(); |
|
return zoom; |
|
}; |
|
zoom.scale = function(x) { |
|
if (!arguments.length) return scale; |
|
scale = +x; |
|
rescale(); |
|
return zoom; |
|
}; |
|
zoom.scaleExtent = function(x) { |
|
if (!arguments.length) return scaleExtent; |
|
scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number); |
|
return zoom; |
|
}; |
|
zoom.x = function(z) { |
|
if (!arguments.length) return x1; |
|
x1 = z; |
|
x0 = z.copy(); |
|
translate = [ 0, 0 ]; |
|
scale = 1; |
|
return zoom; |
|
}; |
|
zoom.y = function(z) { |
|
if (!arguments.length) return y1; |
|
y1 = z; |
|
y0 = z.copy(); |
|
translate = [ 0, 0 ]; |
|
scale = 1; |
|
return zoom; |
|
}; |
|
function location(p) { |
|
return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ]; |
|
} |
|
function point(l) { |
|
return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ]; |
|
} |
|
function scaleTo(s) { |
|
scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); |
|
} |
|
function translateTo(p, l) { |
|
l = point(l); |
|
translate[0] += p[0] - l[0]; |
|
translate[1] += p[1] - l[1]; |
|
} |
|
function rescale() { |
|
if (x1) x1.domain(x0.range().map(function(x) { |
|
return (x - translate[0]) / scale; |
|
}).map(x0.invert)); |
|
if (y1) y1.domain(y0.range().map(function(y) { |
|
return (y - translate[1]) / scale; |
|
}).map(y0.invert)); |
|
} |
|
function dispatch(event) { |
|
rescale(); |
|
d3.event.preventDefault(); |
|
event({ |
|
type: "zoom", |
|
scale: scale, |
|
translate: translate |
|
}); |
|
} |
|
function mousedown() { |
|
var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target)); |
|
d3_window.focus(); |
|
d3_eventCancel(); |
|
function mousemove() { |
|
moved = 1; |
|
translateTo(d3.mouse(target), l); |
|
dispatch(event_); |
|
} |
|
function mouseup() { |
|
if (moved) d3_eventCancel(); |
|
w.on("mousemove.zoom", null).on("mouseup.zoom", null); |
|
if (moved && d3.event.target === eventTarget) d3_eventSuppress(w, "click.zoom"); |
|
} |
|
} |
|
function mousewheel() { |
|
if (!translate0) translate0 = location(d3.mouse(this)); |
|
scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale); |
|
translateTo(d3.mouse(this), translate0); |
|
dispatch(event.of(this, arguments)); |
|
} |
|
function mousemove() { |
|
translate0 = null; |
|
} |
|
function dblclick() { |
|
var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2; |
|
scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); |
|
translateTo(p, l); |
|
dispatch(event.of(this, arguments)); |
|
} |
|
function touchstart() { |
|
var touches = d3.touches(this), now = Date.now(); |
|
scale0 = scale; |
|
translate0 = {}; |
|
touches.forEach(function(t) { |
|
translate0[t.identifier] = location(t); |
|
}); |
|
d3_eventCancel(); |
|
if (touches.length === 1) { |
|
if (now - touchtime < 500) { |
|
var p = touches[0], l = location(touches[0]); |
|
scaleTo(scale * 2); |
|
translateTo(p, l); |
|
dispatch(event.of(this, arguments)); |
|
} |
|
touchtime = now; |
|
} |
|
} |
|
function touchmove() { |
|
var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier]; |
|
if (p1 = touches[1]) { |
|
var p1, l1 = translate0[p1.identifier]; |
|
p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; |
|
l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; |
|
scaleTo(d3.event.scale * scale0); |
|
} |
|
translateTo(p0, l0); |
|
touchtime = null; |
|
dispatch(event.of(this, arguments)); |
|
} |
|
return d3.rebind(zoom, event, "on"); |
|
}; |
|
var d3_behavior_zoomInfinity = [ 0, Infinity ]; |
|
var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { |
|
return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); |
|
}, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { |
|
return d3.event.wheelDelta; |
|
}, "mousewheel") : (d3_behavior_zoomDelta = function() { |
|
return -d3.event.detail; |
|
}, "MozMousePixelScroll"); |
|
function d3_Color() {} |
|
d3_Color.prototype.toString = function() { |
|
return this.rgb() + ""; |
|
}; |
|
d3.hsl = function(h, s, l) { |
|
return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l); |
|
}; |
|
function d3_hsl(h, s, l) { |
|
return new d3_Hsl(h, s, l); |
|
} |
|
function d3_Hsl(h, s, l) { |
|
this.h = h; |
|
this.s = s; |
|
this.l = l; |
|
} |
|
var d3_hslPrototype = d3_Hsl.prototype = new d3_Color(); |
|
d3_hslPrototype.brighter = function(k) { |
|
k = Math.pow(.7, arguments.length ? k : 1); |
|
return d3_hsl(this.h, this.s, this.l / k); |
|
}; |
|
d3_hslPrototype.darker = function(k) { |
|
k = Math.pow(.7, arguments.length ? k : 1); |
|
return d3_hsl(this.h, this.s, k * this.l); |
|
}; |
|
d3_hslPrototype.rgb = function() { |
|
return d3_hsl_rgb(this.h, this.s, this.l); |
|
}; |
|
function d3_hsl_rgb(h, s, l) { |
|
var m1, m2; |
|
h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; |
|
s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; |
|
l = l < 0 ? 0 : l > 1 ? 1 : l; |
|
m2 = l <= .5 ? l * (1 + s) : l + s - l * s; |
|
m1 = 2 * l - m2; |
|
function v(h) { |
|
if (h > 360) h -= 360; else if (h < 0) h += 360; |
|
if (h < 60) return m1 + (m2 - m1) * h / 60; |
|
if (h < 180) return m2; |
|
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; |
|
return m1; |
|
} |
|
function vv(h) { |
|
return Math.round(v(h) * 255); |
|
} |
|
return d3_rgb(vv(h + 120), vv(h), vv(h - 120)); |
|
} |
|
var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π; |
|
function d3_sgn(x) { |
|
return x > 0 ? 1 : x < 0 ? -1 : 0; |
|
} |
|
function d3_acos(x) { |
|
return Math.acos(Math.max(-1, Math.min(1, x))); |
|
} |
|
function d3_asin(x) { |
|
return x > 1 ? π / 2 : x < -1 ? -π / 2 : Math.asin(x); |
|
} |
|
function d3_sinh(x) { |
|
return (Math.exp(x) - Math.exp(-x)) / 2; |
|
} |
|
function d3_cosh(x) { |
|
return (Math.exp(x) + Math.exp(-x)) / 2; |
|
} |
|
function d3_haversin(x) { |
|
return (x = Math.sin(x / 2)) * x; |
|
} |
|
d3.hcl = function(h, c, l) { |
|
return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l); |
|
}; |
|
function d3_hcl(h, c, l) { |
|
return new d3_Hcl(h, c, l); |
|
} |
|
function d3_Hcl(h, c, l) { |
|
this.h = h; |
|
this.c = c; |
|
this.l = l; |
|
} |
|
var d3_hclPrototype = d3_Hcl.prototype = new d3_Color(); |
|
d3_hclPrototype.brighter = function(k) { |
|
return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); |
|
}; |
|
d3_hclPrototype.darker = function(k) { |
|
return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); |
|
}; |
|
d3_hclPrototype.rgb = function() { |
|
return d3_hcl_lab(this.h, this.c, this.l).rgb(); |
|
}; |
|
function d3_hcl_lab(h, c, l) { |
|
if (isNaN(h)) h = 0; |
|
if (isNaN(c)) c = 0; |
|
return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); |
|
} |
|
d3.lab = function(l, a, b) { |
|
return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b); |
|
}; |
|
function d3_lab(l, a, b) { |
|
return new d3_Lab(l, a, b); |
|
} |
|
function d3_Lab(l, a, b) { |
|
this.l = l; |
|
this.a = a; |
|
this.b = b; |
|
} |
|
var d3_lab_K = 18; |
|
var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; |
|
var d3_labPrototype = d3_Lab.prototype = new d3_Color(); |
|
d3_labPrototype.brighter = function(k) { |
|
return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); |
|
}; |
|
d3_labPrototype.darker = function(k) { |
|
return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); |
|
}; |
|
d3_labPrototype.rgb = function() { |
|
return d3_lab_rgb(this.l, this.a, this.b); |
|
}; |
|
function d3_lab_rgb(l, a, b) { |
|
var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; |
|
x = d3_lab_xyz(x) * d3_lab_X; |
|
y = d3_lab_xyz(y) * d3_lab_Y; |
|
z = d3_lab_xyz(z) * d3_lab_Z; |
|
return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); |
|
} |
|
function d3_lab_hcl(l, a, b) { |
|
return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l); |
|
} |
|
function d3_lab_xyz(x) { |
|
return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; |
|
} |
|
function d3_xyz_lab(x) { |
|
return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; |
|
} |
|
function d3_xyz_rgb(r) { |
|
return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); |
|
} |
|
d3.rgb = function(r, g, b) { |
|
return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b); |
|
}; |
|
function d3_rgb(r, g, b) { |
|
return new d3_Rgb(r, g, b); |
|
} |
|
function d3_Rgb(r, g, b) { |
|
this.r = r; |
|
this.g = g; |
|
this.b = b; |
|
} |
|
var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color(); |
|
d3_rgbPrototype.brighter = function(k) { |
|
k = Math.pow(.7, arguments.length ? k : 1); |
|
var r = this.r, g = this.g, b = this.b, i = 30; |
|
if (!r && !g && !b) return d3_rgb(i, i, i); |
|
if (r && r < i) r = i; |
|
if (g && g < i) g = i; |
|
if (b && b < i) b = i; |
|
return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k))); |
|
}; |
|
d3_rgbPrototype.darker = function(k) { |
|
k = Math.pow(.7, arguments.length ? k : 1); |
|
return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b)); |
|
}; |
|
d3_rgbPrototype.hsl = function() { |
|
return d3_rgb_hsl(this.r, this.g, this.b); |
|
}; |
|
d3_rgbPrototype.toString = function() { |
|
return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); |
|
}; |
|
function d3_rgb_hex(v) { |
|
return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); |
|
} |
|
function d3_rgb_parse(format, rgb, hsl) { |
|
var r = 0, g = 0, b = 0, m1, m2, name; |
|
m1 = /([a-z]+)\((.*)\)/i.exec(format); |
|
if (m1) { |
|
m2 = m1[2].split(","); |
|
switch (m1[1]) { |
|
case "hsl": |
|
{ |
|
return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); |
|
} |
|
|
|
case "rgb": |
|
{ |
|
return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); |
|
} |
|
} |
|
} |
|
if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b); |
|
if (format != null && format.charAt(0) === "#") { |
|
if (format.length === 4) { |
|
r = format.charAt(1); |
|
r += r; |
|
g = format.charAt(2); |
|
g += g; |
|
b = format.charAt(3); |
|
b += b; |
|
} else if (format.length === 7) { |
|
r = format.substring(1, 3); |
|
g = format.substring(3, 5); |
|
b = format.substring(5, 7); |
|
} |
|
r = parseInt(r, 16); |
|
g = parseInt(g, 16); |
|
b = parseInt(b, 16); |
|
} |
|
return rgb(r, g, b); |
|
} |
|
function d3_rgb_hsl(r, g, b) { |
|
var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; |
|
if (d) { |
|
s = l < .5 ? d / (max + min) : d / (2 - max - min); |
|
if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; |
|
h *= 60; |
|
} else { |
|
h = NaN; |
|
s = l > 0 && l < 1 ? 0 : h; |
|
} |
|
return d3_hsl(h, s, l); |
|
} |
|
function d3_rgb_lab(r, g, b) { |
|
r = d3_rgb_xyz(r); |
|
g = d3_rgb_xyz(g); |
|
b = d3_rgb_xyz(b); |
|
var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); |
|
return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); |
|
} |
|
function d3_rgb_xyz(r) { |
|
return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); |
|
} |
|
function d3_rgb_parseNumber(c) { |
|
var f = parseFloat(c); |
|
return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; |
|
} |
|
var d3_rgb_names = d3.map({ |
|
aliceblue: "#f0f8ff", |
|
antiquewhite: "#faebd7", |
|
aqua: "#00ffff", |
|
aquamarine: "#7fffd4", |
|
azure: "#f0ffff", |
|
beige: "#f5f5dc", |
|
bisque: "#ffe4c4", |
|
black: "#000000", |
|
blanchedalmond: "#ffebcd", |
|
blue: "#0000ff", |
|
blueviolet: "#8a2be2", |
|
brown: "#a52a2a", |
|
burlywood: "#deb887", |
|
cadetblue: "#5f9ea0", |
|
chartreuse: "#7fff00", |
|
chocolate: "#d2691e", |
|
coral: "#ff7f50", |
|
cornflowerblue: "#6495ed", |
|
cornsilk: "#fff8dc", |
|
crimson: "#dc143c", |
|
cyan: "#00ffff", |
|
darkblue: "#00008b", |
|
darkcyan: "#008b8b", |
|
darkgoldenrod: "#b8860b", |
|
darkgray: "#a9a9a9", |
|
darkgreen: "#006400", |
|
darkgrey: "#a9a9a9", |
|
darkkhaki: "#bdb76b", |
|
darkmagenta: "#8b008b", |
|
darkolivegreen: "#556b2f", |
|
darkorange: "#ff8c00", |
|
darkorchid: "#9932cc", |
|
darkred: "#8b0000", |
|
darksalmon: "#e9967a", |
|
darkseagreen: "#8fbc8f", |
|
darkslateblue: "#483d8b", |
|
darkslategray: "#2f4f4f", |
|
darkslategrey: "#2f4f4f", |
|
darkturquoise: "#00ced1", |
|
darkviolet: "#9400d3", |
|
deeppink: "#ff1493", |
|
deepskyblue: "#00bfff", |
|
dimgray: "#696969", |
|
dimgrey: "#696969", |
|
dodgerblue: "#1e90ff", |
|
firebrick: "#b22222", |
|
floralwhite: "#fffaf0", |
|
forestgreen: "#228b22", |
|
fuchsia: "#ff00ff", |
|
gainsboro: "#dcdcdc", |
|
ghostwhite: "#f8f8ff", |
|
gold: "#ffd700", |
|
goldenrod: "#daa520", |
|
gray: "#808080", |
|
green: "#008000", |
|
greenyellow: "#adff2f", |
|
grey: "#808080", |
|
honeydew: "#f0fff0", |
|
hotpink: "#ff69b4", |
|
indianred: "#cd5c5c", |
|
indigo: "#4b0082", |
|
ivory: "#fffff0", |
|
khaki: "#f0e68c", |
|
lavender: "#e6e6fa", |
|
lavenderblush: "#fff0f5", |
|
lawngreen: "#7cfc00", |
|
lemonchiffon: "#fffacd", |
|
lightblue: "#add8e6", |
|
lightcoral: "#f08080", |
|
lightcyan: "#e0ffff", |
|
lightgoldenrodyellow: "#fafad2", |
|
lightgray: "#d3d3d3", |
|
lightgreen: "#90ee90", |
|
lightgrey: "#d3d3d3", |
|
lightpink: "#ffb6c1", |
|
lightsalmon: "#ffa07a", |
|
lightseagreen: "#20b2aa", |
|
lightskyblue: "#87cefa", |
|
lightslategray: "#778899", |
|
lightslategrey: "#778899", |
|
lightsteelblue: "#b0c4de", |
|
lightyellow: "#ffffe0", |
|
lime: "#00ff00", |
|
limegreen: "#32cd32", |
|
linen: "#faf0e6", |
|
magenta: "#ff00ff", |
|
maroon: "#800000", |
|
mediumaquamarine: "#66cdaa", |
|
mediumblue: "#0000cd", |
|
mediumorchid: "#ba55d3", |
|
mediumpurple: "#9370db", |
|
mediumseagreen: "#3cb371", |
|
mediumslateblue: "#7b68ee", |
|
mediumspringgreen: "#00fa9a", |
|
mediumturquoise: "#48d1cc", |
|
mediumvioletred: "#c71585", |
|
midnightblue: "#191970", |
|
mintcream: "#f5fffa", |
|
mistyrose: "#ffe4e1", |
|
moccasin: "#ffe4b5", |
|
navajowhite: "#ffdead", |
|
navy: "#000080", |
|
oldlace: "#fdf5e6", |
|
olive: "#808000", |
|
olivedrab: "#6b8e23", |
|
orange: "#ffa500", |
|
orangered: "#ff4500", |
|
orchid: "#da70d6", |
|
palegoldenrod: "#eee8aa", |
|
palegreen: "#98fb98", |
|
paleturquoise: "#afeeee", |
|
palevioletred: "#db7093", |
|
papayawhip: "#ffefd5", |
|
peachpuff: "#ffdab9", |
|
peru: "#cd853f", |
|
pink: "#ffc0cb", |
|
plum: "#dda0dd", |
|
powderblue: "#b0e0e6", |
|
purple: "#800080", |
|
red: "#ff0000", |
|
rosybrown: "#bc8f8f", |
|
royalblue: "#4169e1", |
|
saddlebrown: "#8b4513", |
|
salmon: "#fa8072", |
|
sandybrown: "#f4a460", |
|
seagreen: "#2e8b57", |
|
seashell: "#fff5ee", |
|
sienna: "#a0522d", |
|
silver: "#c0c0c0", |
|
skyblue: "#87ceeb", |
|
slateblue: "#6a5acd", |
|
slategray: "#708090", |
|
slategrey: "#708090", |
|
snow: "#fffafa", |
|
springgreen: "#00ff7f", |
|
steelblue: "#4682b4", |
|
tan: "#d2b48c", |
|
teal: "#008080", |
|
thistle: "#d8bfd8", |
|
tomato: "#ff6347", |
|
turquoise: "#40e0d0", |
|
violet: "#ee82ee", |
|
wheat: "#f5deb3", |
|
white: "#ffffff", |
|
whitesmoke: "#f5f5f5", |
|
yellow: "#ffff00", |
|
yellowgreen: "#9acd32" |
|
}); |
|
d3_rgb_names.forEach(function(key, value) { |
|
d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb)); |
|
}); |
|
function d3_functor(v) { |
|
return typeof v === "function" ? v : function() { |
|
return v; |
|
}; |
|
} |
|
d3.functor = d3_functor; |
|
function d3_identity(d) { |
|
return d; |
|
} |
|
d3.xhr = function(url, mimeType, callback) { |
|
var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, response = d3_identity, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)(); |
|
"onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { |
|
request.readyState > 3 && respond(); |
|
}; |
|
function respond() { |
|
var s = request.status; |
|
!s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request); |
|
} |
|
request.onprogress = function(event) { |
|
var o = d3.event; |
|
d3.event = event; |
|
try { |
|
dispatch.progress.call(xhr, request); |
|
} finally { |
|
d3.event = o; |
|
} |
|
}; |
|
xhr.header = function(name, value) { |
|
name = (name + "").toLowerCase(); |
|
if (arguments.length < 2) return headers[name]; |
|
if (value == null) delete headers[name]; else headers[name] = value + ""; |
|
return xhr; |
|
}; |
|
xhr.mimeType = function(value) { |
|
if (!arguments.length) return mimeType; |
|
mimeType = value == null ? null : value + ""; |
|
return xhr; |
|
}; |
|
xhr.response = function(value) { |
|
response = value; |
|
return xhr; |
|
}; |
|
[ "get", "post" ].forEach(function(method) { |
|
xhr[method] = function() { |
|
return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); |
|
}; |
|
}); |
|
xhr.send = function(method, data, callback) { |
|
if (arguments.length === 2 && typeof data === "function") callback = data, data = null; |
|
request.open(method, url, true); |
|
if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; |
|
if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); |
|
if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); |
|
if (callback != null) xhr.on("error", callback).on("load", function(request) { |
|
callback(null, request); |
|
}); |
|
request.send(data == null ? null : data); |
|
return xhr; |
|
}; |
|
xhr.abort = function() { |
|
request.abort(); |
|
return xhr; |
|
}; |
|
d3.rebind(xhr, dispatch, "on"); |
|
if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, |
|
mimeType = null; |
|
return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); |
|
}; |
|
function d3_xhr_fixCallback(callback) { |
|
return callback.length === 1 ? function(error, request) { |
|
callback(error == null ? request : null); |
|
} : callback; |
|
} |
|
function d3_dsv(delimiter, mimeType) { |
|
var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); |
|
function dsv(url, row, callback) { |
|
if (arguments.length < 3) callback = row, row = null; |
|
var xhr = d3.xhr(url, mimeType, callback); |
|
xhr.row = function(_) { |
|
return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; |
|
}; |
|
return xhr.row(row); |
|
} |
|
function response(request) { |
|
return dsv.parse(request.responseText); |
|
} |
|
function typedResponse(f) { |
|
return function(request) { |
|
return dsv.parse(request.responseText, f); |
|
}; |
|
} |
|
dsv.parse = function(text, f) { |
|
var o; |
|
return dsv.parseRows(text, function(row, i) { |
|
if (o) return o(row, i - 1); |
|
var a = new Function("d", "return {" + row.map(function(name, i) { |
|
return JSON.stringify(name) + ": d[" + i + "]"; |
|
}).join(",") + "}"); |
|
o = f ? function(row, i) { |
|
return f(a(row), i); |
|
} : a; |
|
}); |
|
}; |
|
dsv.parseRows = function(text, f) { |
|
var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; |
|
function token() { |
|
if (I >= N) return EOF; |
|
if (eol) return eol = false, EOL; |
|
var j = I; |
|
if (text.charCodeAt(j) === 34) { |
|
var i = j; |
|
while (i++ < N) { |
|
if (text.charCodeAt(i) === 34) { |
|
if (text.charCodeAt(i + 1) !== 34) break; |
|
++i; |
|
} |
|
} |
|
I = i + 2; |
|
var c = text.charCodeAt(i + 1); |
|
if (c === 13) { |
|
eol = true; |
|
if (text.charCodeAt(i + 2) === 10) ++I; |
|
} else if (c === 10) { |
|
eol = true; |
|
} |
|
return text.substring(j + 1, i).replace(/""/g, '"'); |
|
} |
|
while (I < N) { |
|
var c = text.charCodeAt(I++), k = 1; |
|
if (c === 10) eol = true; else if (c === 13) { |
|
eol = true; |
|
if (text.charCodeAt(I) === 10) ++I, ++k; |
|
} else if (c !== delimiterCode) continue; |
|
return text.substring(j, I - k); |
|
} |
|
return text.substring(j); |
|
} |
|
while ((t = token()) !== EOF) { |
|
var a = []; |
|
while (t !== EOL && t !== EOF) { |
|
a.push(t); |
|
t = token(); |
|
} |
|
if (f && !(a = f(a, n++))) continue; |
|
rows.push(a); |
|
} |
|
return rows; |
|
}; |
|
dsv.format = function(rows) { |
|
if (Array.isArray(rows[0])) return dsv.formatRows(rows); |
|
var fieldSet = new d3_Set(), fields = []; |
|
rows.forEach(function(row) { |
|
for (var field in row) { |
|
if (!fieldSet.has(field)) { |
|
fields.push(fieldSet.add(field)); |
|
} |
|
} |
|
}); |
|
return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { |
|
return fields.map(function(field) { |
|
return formatValue(row[field]); |
|
}).join(delimiter); |
|
})).join("\n"); |
|
}; |
|
dsv.formatRows = function(rows) { |
|
return rows.map(formatRow).join("\n"); |
|
}; |
|
function formatRow(row) { |
|
return row.map(formatValue).join(delimiter); |
|
} |
|
function formatValue(text) { |
|
return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; |
|
} |
|
return dsv; |
|
} |
|
d3.csv = d3_dsv(",", "text/csv"); |
|
d3.tsv = d3_dsv(" ", "text/tab-separated-values"); |
|
var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout; |
|
d3.timer = function(callback, delay, then) { |
|
if (arguments.length < 3) { |
|
if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return; |
|
then = Date.now(); |
|
} |
|
var timer = d3_timer_byId[callback.id]; |
|
if (timer && timer.callback === callback) { |
|
timer.then = then; |
|
timer.delay = delay; |
|
} else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = { |
|
callback: callback, |
|
then: then, |
|
delay: delay, |
|
next: d3_timer_queue |
|
}; |
|
if (!d3_timer_interval) { |
|
d3_timer_timeout = clearTimeout(d3_timer_timeout); |
|
d3_timer_interval = 1; |
|
d3_timer_frame(d3_timer_step); |
|
} |
|
}; |
|
function d3_timer_step() { |
|
var elapsed, now = Date.now(), t1 = d3_timer_queue; |
|
while (t1) { |
|
elapsed = now - t1.then; |
|
if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed); |
|
t1 = t1.next; |
|
} |
|
var delay = d3_timer_flush() - now; |
|
if (delay > 24) { |
|
if (isFinite(delay)) { |
|
clearTimeout(d3_timer_timeout); |
|
d3_timer_timeout = setTimeout(d3_timer_step, delay); |
|
} |
|
d3_timer_interval = 0; |
|
} else { |
|
d3_timer_interval = 1; |
|
d3_timer_frame(d3_timer_step); |
|
} |
|
} |
|
d3.timer.flush = function() { |
|
var elapsed, now = Date.now(), t1 = d3_timer_queue; |
|
while (t1) { |
|
elapsed = now - t1.then; |
|
if (!t1.delay) t1.flush = t1.callback(elapsed); |
|
t1 = t1.next; |
|
} |
|
d3_timer_flush(); |
|
}; |
|
function d3_timer_flush() { |
|
var t0 = null, t1 = d3_timer_queue, then = Infinity; |
|
while (t1) { |
|
if (t1.flush) { |
|
delete d3_timer_byId[t1.callback.id]; |
|
t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next; |
|
} else { |
|
then = Math.min(then, t1.then + t1.delay); |
|
t1 = (t0 = t1).next; |
|
} |
|
} |
|
return then; |
|
} |
|
var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) { |
|
setTimeout(callback, 17); |
|
}; |
|
var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ]; |
|
var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); |
|
d3.formatPrefix = function(value, precision) { |
|
var i = 0; |
|
if (value) { |
|
if (value < 0) value *= -1; |
|
if (precision) value = d3.round(value, d3_format_precision(value, precision)); |
|
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); |
|
i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); |
|
} |
|
return d3_formatPrefixes[8 + i / 3]; |
|
}; |
|
function d3_formatPrefix(d, i) { |
|
var k = Math.pow(10, Math.abs(8 - i) * 3); |
|
return { |
|
scale: i > 8 ? function(d) { |
|
return d / k; |
|
} : function(d) { |
|
return d * k; |
|
}, |
|
symbol: d |
|
}; |
|
} |
|
d3.round = function(x, n) { |
|
return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); |
|
}; |
|
d3.format = function(specifier) { |
|
var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false; |
|
if (precision) precision = +precision.substring(1); |
|
if (zfill || fill === "0" && align === "=") { |
|
zfill = fill = "0"; |
|
align = "="; |
|
if (comma) width -= Math.floor((width - 1) / 4); |
|
} |
|
switch (type) { |
|
case "n": |
|
comma = true; |
|
type = "g"; |
|
break; |
|
|
|
case "%": |
|
scale = 100; |
|
suffix = "%"; |
|
type = "f"; |
|
break; |
|
|
|
case "p": |
|
scale = 100; |
|
suffix = "%"; |
|
type = "r"; |
|
break; |
|
|
|
case "b": |
|
case "o": |
|
case "x": |
|
case "X": |
|
if (basePrefix) basePrefix = "0" + type.toLowerCase(); |
|
|
|
case "c": |
|
case "d": |
|
integer = true; |
|
precision = 0; |
|
break; |
|
|
|
case "s": |
|
scale = -1; |
|
type = "r"; |
|
break; |
|
} |
|
if (basePrefix === "#") basePrefix = ""; |
|
if (type == "r" && !precision) type = "g"; |
|
if (precision != null) { |
|
if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); |
|
} |
|
type = d3_format_types.get(type) || d3_format_typeDefault; |
|
var zcomma = zfill && comma; |
|
return function(value) { |
|
if (integer && value % 1) return ""; |
|
var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign; |
|
if (scale < 0) { |
|
var prefix = d3.formatPrefix(value, precision); |
|
value = prefix.scale(value); |
|
suffix = prefix.symbol; |
|
} else { |
|
value *= scale; |
|
} |
|
value = type(value, precision); |
|
if (!zfill && comma) value = d3_format_group(value); |
|
var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; |
|
if (zcomma) value = d3_format_group(padding + value); |
|
if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint); |
|
negative += basePrefix; |
|
return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix; |
|
}; |
|
}; |
|
var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; |
|
var d3_format_types = d3.map({ |
|
b: function(x) { |
|
return x.toString(2); |
|
}, |
|
c: function(x) { |
|
return String.fromCharCode(x); |
|
}, |
|
o: function(x) { |
|
return x.toString(8); |
|
}, |
|
x: function(x) { |
|
return x.toString(16); |
|
}, |
|
X: function(x) { |
|
return x.toString(16).toUpperCase(); |
|
}, |
|
g: function(x, p) { |
|
return x.toPrecision(p); |
|
}, |
|
e: function(x, p) { |
|
return x.toExponential(p); |
|
}, |
|
f: function(x, p) { |
|
return x.toFixed(p); |
|
}, |
|
r: function(x, p) { |
|
return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); |
|
} |
|
}); |
|
function d3_format_precision(x, p) { |
|
return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); |
|
} |
|
function d3_format_typeDefault(x) { |
|
return x + ""; |
|
} |
|
var d3_format_group = d3_identity; |
|
if (d3_format_grouping) { |
|
var d3_format_groupingLength = d3_format_grouping.length; |
|
d3_format_group = function(value) { |
|
var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length, |
|
""), t = [], j = 0, g = d3_format_grouping[0]; |
|
while (i > 0 && g > 0) { |
|
t.push(value.substring(i -= g, i + g)); |
|
g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength]; |
|
} |
|
return t.reverse().join(d3_format_thousandsSeparator || "") + f; |
|
}; |
|
} |
|
d3.geo = {}; |
|
d3.geo.stream = function(object, listener) { |
|
if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { |
|
d3_geo_streamObjectType[object.type](object, listener); |
|
} else { |
|
d3_geo_streamGeometry(object, listener); |
|
} |
|
}; |
|
function d3_geo_streamGeometry(geometry, listener) { |
|
if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { |
|
d3_geo_streamGeometryType[geometry.type](geometry, listener); |
|
} |
|
} |
|
var d3_geo_streamObjectType = { |
|
Feature: function(feature, listener) { |
|
d3_geo_streamGeometry(feature.geometry, listener); |
|
}, |
|
FeatureCollection: function(object, listener) { |
|
var features = object.features, i = -1, n = features.length; |
|
while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); |
|
} |
|
}; |
|
var d3_geo_streamGeometryType = { |
|
Sphere: function(object, listener) { |
|
listener.sphere(); |
|
}, |
|
Point: function(object, listener) { |
|
var coordinate = object.coordinates; |
|
listener.point(coordinate[0], coordinate[1]); |
|
}, |
|
MultiPoint: function(object, listener) { |
|
var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate; |
|
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]); |
|
}, |
|
LineString: function(object, listener) { |
|
d3_geo_streamLine(object.coordinates, listener, 0); |
|
}, |
|
MultiLineString: function(object, listener) { |
|
var coordinates = object.coordinates, i = -1, n = coordinates.length; |
|
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); |
|
}, |
|
Polygon: function(object, listener) { |
|
d3_geo_streamPolygon(object.coordinates, listener); |
|
}, |
|
MultiPolygon: function(object, listener) { |
|
var coordinates = object.coordinates, i = -1, n = coordinates.length; |
|
while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); |
|
}, |
|
GeometryCollection: function(object, listener) { |
|
var geometries = object.geometries, i = -1, n = geometries.length; |
|
while (++i < n) d3_geo_streamGeometry(geometries[i], listener); |
|
} |
|
}; |
|
function d3_geo_streamLine(coordinates, listener, closed) { |
|
var i = -1, n = coordinates.length - closed, coordinate; |
|
listener.lineStart(); |
|
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]); |
|
listener.lineEnd(); |
|
} |
|
function d3_geo_streamPolygon(coordinates, listener) { |
|
var i = -1, n = coordinates.length; |
|
listener.polygonStart(); |
|
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); |
|
listener.polygonEnd(); |
|
} |
|
d3.geo.area = function(object) { |
|
d3_geo_areaSum = 0; |
|
d3.geo.stream(object, d3_geo_area); |
|
return d3_geo_areaSum; |
|
}; |
|
var d3_geo_areaSum, d3_geo_areaRingSum; |
|
var d3_geo_area = { |
|
sphere: function() { |
|
d3_geo_areaSum += 4 * π; |
|
}, |
|
point: d3_noop, |
|
lineStart: d3_noop, |
|
lineEnd: d3_noop, |
|
polygonStart: function() { |
|
d3_geo_areaRingSum = 0; |
|
d3_geo_area.lineStart = d3_geo_areaRingStart; |
|
}, |
|
polygonEnd: function() { |
|
var area = 2 * d3_geo_areaRingSum; |
|
d3_geo_areaSum += area < 0 ? 4 * π + area : area; |
|
d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; |
|
} |
|
}; |
|
function d3_geo_areaRingStart() { |
|
var λ00, φ00, λ0, cosφ0, sinφ0; |
|
d3_geo_area.point = function(λ, φ) { |
|
d3_geo_area.point = nextPoint; |
|
λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), |
|
sinφ0 = Math.sin(φ); |
|
}; |
|
function nextPoint(λ, φ) { |
|
λ *= d3_radians; |
|
φ = φ * d3_radians / 2 + π / 4; |
|
var dλ = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ); |
|
d3_geo_areaRingSum += Math.atan2(v, u); |
|
λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; |
|
} |
|
d3_geo_area.lineEnd = function() { |
|
nextPoint(λ00, φ00); |
|
}; |
|
} |
|
function d3_geo_cartesian(spherical) { |
|
var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); |
|
return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; |
|
} |
|
function d3_geo_cartesianDot(a, b) { |
|
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; |
|
} |
|
function d3_geo_cartesianCross(a, b) { |
|
return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; |
|
} |
|
function d3_geo_cartesianAdd(a, b) { |
|
a[0] += b[0]; |
|
a[1] += b[1]; |
|
a[2] += b[2]; |
|
} |
|
function d3_geo_cartesianScale(vector, k) { |
|
return [ vector[0] * k, vector[1] * k, vector[2] * k ]; |
|
} |
|
function d3_geo_cartesianNormalize(d) { |
|
var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); |
|
d[0] /= l; |
|
d[1] /= l; |
|
d[2] /= l; |
|
} |
|
function d3_geo_spherical(cartesian) { |
|
return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ]; |
|
} |
|
function d3_geo_sphericalEqual(a, b) { |
|
return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; |
|
} |
|
d3.geo.bounds = function() { |
|
var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; |
|
var bound = { |
|
point: point, |
|
lineStart: lineStart, |
|
lineEnd: lineEnd, |
|
polygonStart: function() { |
|
bound.point = ringPoint; |
|
bound.lineStart = ringStart; |
|
bound.lineEnd = ringEnd; |
|
dλSum = 0; |
|
d3_geo_area.polygonStart(); |
|
}, |
|
polygonEnd: function() { |
|
d3_geo_area.polygonEnd(); |
|
bound.point = point; |
|
bound.lineStart = lineStart; |
|
bound.lineEnd = lineEnd; |
|
if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; |
|
range[0] = λ0, range[1] = λ1; |
|
} |
|
}; |
|
function point(λ, φ) { |
|
ranges.push(range = [ λ0 = λ, λ1 = λ ]); |
|
if (φ < φ0) φ0 = φ; |
|
if (φ > φ1) φ1 = φ; |
|
} |
|
function linePoint(λ, φ) { |
|
var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); |
|
if (p0) { |
|
var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); |
|
d3_geo_cartesianNormalize(inflection); |
|
inflection = d3_geo_spherical(inflection); |
|
var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = Math.abs(dλ) > 180; |
|
if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { |
|
var φi = inflection[1] * d3_degrees; |
|
if (φi > φ1) φ1 = φi; |
|
} else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { |
|
var φi = -inflection[1] * d3_degrees; |
|
if (φi < φ0) φ0 = φi; |
|
} else { |
|
if (φ < φ0) φ0 = φ; |
|
if (φ > φ1) φ1 = φ; |
|
} |
|
if (antimeridian) { |
|
if (λ < λ_) { |
|
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; |
|
} else { |
|
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; |
|
} |
|
} else { |
|
if (λ1 >= λ0) { |
|
if (λ < λ0) λ0 = λ; |
|
if (λ > λ1) λ1 = λ; |
|
} else { |
|
if (λ > λ_) { |
|
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; |
|
} else { |
|
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; |
|
} |
|
} |
|
} |
|
} else { |
|
point(λ, φ); |
|
} |
|
p0 = p, λ_ = λ; |
|
} |
|
function lineStart() { |
|
bound.point = linePoint; |
|
} |
|
function lineEnd() { |
|
range[0] = λ0, range[1] = λ1; |
|
bound.point = point; |
|
p0 = null; |
|
} |
|
function ringPoint(λ, φ) { |
|
if (p0) { |
|
var dλ = λ - λ_; |
|
dλSum += Math.abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; |
|
} else λ__ = λ, φ__ = φ; |
|
d3_geo_area.point(λ, φ); |
|
linePoint(λ, φ); |
|
} |
|
function ringStart() { |
|
d3_geo_area.lineStart(); |
|
} |
|
function ringEnd() { |
|
ringPoint(λ__, φ__); |
|
d3_geo_area.lineEnd(); |
|
if (Math.abs(dλSum) > ε) λ0 = -(λ1 = 180); |
|
range[0] = λ0, range[1] = λ1; |
|
p0 = null; |
|
} |
|
function angle(λ0, λ1) { |
|
return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; |
|
} |
|
function compareRanges(a, b) { |
|
return a[0] - b[0]; |
|
} |
|
function withinRange(x, range) { |
|
return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; |
|
} |
|
return function(feature) { |
|
φ1 = λ1 = -(λ0 = φ0 = Infinity); |
|
ranges = []; |
|
d3.geo.stream(feature, bound); |
|
ranges.sort(compareRanges); |
|
for (var i = 1, n = ranges.length, a = ranges[0], b, merged = [ a ]; i < n; ++i) { |
|
b = ranges[i]; |
|
if (withinRange(b[0], a) || withinRange(b[1], a)) { |
|
if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; |
|
if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; |
|
} else { |
|
merged.push(a = b); |
|
} |
|
} |
|
var best = -Infinity, dλ; |
|
for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { |
|
b = merged[i]; |
|
if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; |
|
} |
|
ranges = range = null; |
|
return [ [ λ0, φ0 ], [ λ1, φ1 ] ]; |
|
}; |
|
}(); |
|
d3.geo.centroid = function(object) { |
|
d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; |
|
d3.geo.stream(object, d3_geo_centroid); |
|
var m; |
|
if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) { |
|
return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ]; |
|
} |
|
}; |
|
var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ; |
|
var d3_geo_centroid = { |
|
sphere: function() { |
|
if (d3_geo_centroidDimension < 2) { |
|
d3_geo_centroidDimension = 2; |
|
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; |
|
} |
|
}, |
|
point: d3_geo_centroidPoint, |
|
lineStart: d3_geo_centroidLineStart, |
|
lineEnd: d3_geo_centroidLineEnd, |
|
polygonStart: function() { |
|
if (d3_geo_centroidDimension < 2) { |
|
d3_geo_centroidDimension = 2; |
|
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; |
|
} |
|
d3_geo_centroid.lineStart = d3_geo_centroidRingStart; |
|
}, |
|
polygonEnd: function() { |
|
d3_geo_centroid.lineStart = d3_geo_centroidLineStart; |
|
} |
|
}; |
|
function d3_geo_centroidPoint(λ, φ) { |
|
if (d3_geo_centroidDimension) return; |
|
++d3_geo_centroidW; |
|
λ *= d3_radians; |
|
var cosφ = Math.cos(φ *= d3_radians); |
|
d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW; |
|
d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW; |
|
d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW; |
|
} |
|
function d3_geo_centroidRingStart() { |
|
var λ00, φ00; |
|
d3_geo_centroidDimension = 1; |
|
d3_geo_centroidLineStart(); |
|
d3_geo_centroidDimension = 2; |
|
var linePoint = d3_geo_centroid.point; |
|
d3_geo_centroid.point = function(λ, φ) { |
|
linePoint(λ00 = λ, φ00 = φ); |
|
}; |
|
d3_geo_centroid.lineEnd = function() { |
|
d3_geo_centroid.point(λ00, φ00); |
|
d3_geo_centroidLineEnd(); |
|
d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; |
|
}; |
|
} |
|
function d3_geo_centroidLineStart() { |
|
var x0, y0, z0; |
|
if (d3_geo_centroidDimension > 1) return; |
|
if (d3_geo_centroidDimension < 1) { |
|
d3_geo_centroidDimension = 1; |
|
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0; |
|
} |
|
d3_geo_centroid.point = function(λ, φ) { |
|
λ *= d3_radians; |
|
var cosφ = Math.cos(φ *= d3_radians); |
|
x0 = cosφ * Math.cos(λ); |
|
y0 = cosφ * Math.sin(λ); |
|
z0 = Math.sin(φ); |
|
d3_geo_centroid.point = nextPoint; |
|
}; |
|
function nextPoint(λ, φ) { |
|
λ *= d3_radians; |
|
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); |
|
d3_geo_centroidW += w; |
|
d3_geo_centroidX += w * (x0 + (x0 = x)); |
|
d3_geo_centroidY += w * (y0 + (y0 = y)); |
|
d3_geo_centroidZ += w * (z0 + (z0 = z)); |
|
} |
|
} |
|
function d3_geo_centroidLineEnd() { |
|
d3_geo_centroid.point = d3_geo_centroidPoint; |
|
} |
|
function d3_true() { |
|
return true; |
|
} |
|
function d3_geo_clipPolygon(segments, compare, inside, interpolate, listener) { |
|
var subject = [], clip = []; |
|
segments.forEach(function(segment) { |
|
if ((n = segment.length - 1) <= 0) return; |
|
var n, p0 = segment[0], p1 = segment[n]; |
|
if (d3_geo_sphericalEqual(p0, p1)) { |
|
listener.lineStart(); |
|
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); |
|
listener.lineEnd(); |
|
return; |
|
} |
|
var a = { |
|
point: p0, |
|
points: segment, |
|
other: null, |
|
visited: false, |
|
entry: true, |
|
subject: true |
|
}, b = { |
|
point: p0, |
|
points: [ p0 ], |
|
other: a, |
|
visited: false, |
|
entry: false, |
|
subject: false |
|
}; |
|
a.other = b; |
|
subject.push(a); |
|
clip.push(b); |
|
a = { |
|
point: p1, |
|
points: [ p1 ], |
|
other: null, |
|
visited: false, |
|
entry: false, |
|
subject: true |
|
}; |
|
b = { |
|
point: p1, |
|
points: [ p1 ], |
|
other: a, |
|
visited: false, |
|
entry: true, |
|
subject: false |
|
}; |
|
a.other = b; |
|
subject.push(a); |
|
clip.push(b); |
|
}); |
|
clip.sort(compare); |
|
d3_geo_clipPolygonLinkCircular(subject); |
|
d3_geo_clipPolygonLinkCircular(clip); |
|
if (!subject.length) return; |
|
if (inside) for (var i = 1, e = !inside(clip[0].point), n = clip.length; i < n; ++i) { |
|
clip[i].entry = e = !e; |
|
} |
|
var start = subject[0], current, points, point; |
|
while (1) { |
|
current = start; |
|
while (current.visited) if ((current = current.next) === start) return; |
|
points = current.points; |
|
listener.lineStart(); |
|
do { |
|
current.visited = current.other.visited = true; |
|
if (current.entry) { |
|
if (current.subject) { |
|
for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]); |
|
} else { |
|
interpolate(current.point, current.next.point, 1, listener); |
|
} |
|
current = current.next; |
|
} else { |
|
if (current.subject) { |
|
points = current.prev.points; |
|
for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]); |
|
} else { |
|
interpolate(current.point, current.prev.point, -1, listener); |
|
} |
|
current = current.prev; |
|
} |
|
current = current.other; |
|
points = current.points; |
|
} while (!current.visited); |
|
listener.lineEnd(); |
|
} |
|
} |
|
function d3_geo_clipPolygonLinkCircular(array) { |
|
if (!(n = array.length)) return; |
|
var n, i = 0, a = array[0], b; |
|
while (++i < n) { |
|
a.next = b = array[i]; |
|
b.prev = a; |
|
a = b; |
|
} |
|
a.next = b = array[0]; |
|
b.prev = a; |
|
} |
|
function d3_geo_clip(pointVisible, clipLine, interpolate) { |
|
return function(listener) { |
|
var line = clipLine(listener); |
|
var clip = { |
|
point: point, |
|
lineStart: lineStart, |
|
lineEnd: lineEnd, |
|
polygonStart: function() { |
|
clip.point = pointRing; |
|
clip.lineStart = ringStart; |
|
clip.lineEnd = ringEnd; |
|
invisible = false; |
|
invisibleArea = visibleArea = 0; |
|
segments = []; |
|
listener.polygonStart(); |
|
}, |
|
polygonEnd: function() { |
|
clip.point = point; |
|
clip.lineStart = lineStart; |
|
clip.lineEnd = lineEnd; |
|
segments = d3.merge(segments); |
|
if (segments.length) { |
|
d3_geo_clipPolygon(segments, d3_geo_clipSort, null, interpolate, listener); |
|
} else if (visibleArea < -ε || invisible && invisibleArea < -ε) { |
|
listener.lineStart(); |
|
interpolate(null, null, 1, listener); |
|
listener.lineEnd(); |
|
} |
|
listener.polygonEnd(); |
|
segments = null; |
|
}, |
|
sphere: function() { |
|
listener.polygonStart(); |
|
listener.lineStart(); |
|
interpolate(null, null, 1, listener); |
|
listener.lineEnd(); |
|
listener.polygonEnd(); |
|
} |
|
}; |
|
function point(λ, φ) { |
|
if (pointVisible(λ, φ)) listener.point(λ, φ); |
|
} |
|
function pointLine(λ, φ) { |
|
line.point(λ, φ); |
|
} |
|
function lineStart() { |
|
clip.point = pointLine; |
|
line.lineStart(); |
|
} |
|
function lineEnd() { |
|
clip.point = point; |
|
line.lineEnd(); |
|
} |
|
var segments, visibleArea, invisibleArea, invisible; |
|
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring; |
|
function pointRing(λ, φ) { |
|
ringListener.point(λ, φ); |
|
ring.push([ λ, φ ]); |
|
} |
|
function ringStart() { |
|
ringListener.lineStart(); |
|
ring = []; |
|
} |
|
function ringEnd() { |
|
pointRing(ring[0][0], ring[0][1]); |
|
ringListener.lineEnd(); |
|
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; |
|
if (!n) { |
|
invisible = true; |
|
invisibleArea += d3_geo_clipAreaRing(ring, -1); |
|
ring = null; |
|
return; |
|
} |
|
ring = null; |
|
if (clean & 1) { |
|
segment = ringSegments[0]; |
|
visibleArea += d3_geo_clipAreaRing(segment, 1); |
|
var n = segment.length - 1, i = -1, point; |
|
listener.lineStart(); |
|
while (++i < n) listener.point((point = segment[i])[0], point[1]); |
|
listener.lineEnd(); |
|
return; |
|
} |
|
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); |
|
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); |
|
} |
|
return clip; |
|
}; |
|
} |
|
function d3_geo_clipSegmentLength1(segment) { |
|
return segment.length > 1; |
|
} |
|
function d3_geo_clipBufferListener() { |
|
var lines = [], line; |
|
return { |
|
lineStart: function() { |
|
lines.push(line = []); |
|
}, |
|
point: function(λ, φ) { |
|
line.push([ λ, φ ]); |
|
}, |
|
lineEnd: d3_noop, |
|
buffer: function() { |
|
var buffer = lines; |
|
lines = []; |
|
line = null; |
|
return buffer; |
|
}, |
|
rejoin: function() { |
|
if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); |
|
} |
|
}; |
|
} |
|
function d3_geo_clipAreaRing(ring, invisible) { |
|
if (!(n = ring.length)) return 0; |
|
var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y; |
|
while (++i < n) { |
|
p = ring[i]; |
|
cosφ = Math.cos(φ = p[1]); |
|
x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ)); |
|
y = 1 - invisible * Math.cos(λ) * cosφ; |
|
if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue; |
|
if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) { |
|
if (y + y0 > 2) area += 4 * (x - x0); |
|
} else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y); |
|
x1 = x0, x0 = x, y0 = y; |
|
} |
|
return area; |
|
} |
|
function d3_geo_clipSort(a, b) { |
|
return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]); |
|
} |
|
var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate); |
|
function d3_geo_clipAntimeridianLine(listener) { |
|
var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; |
|
return { |
|
lineStart: function() { |
|
listener.lineStart(); |
|
clean = 1; |
|
}, |
|
point: function(λ1, φ1) { |
|
var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0); |
|
if (Math.abs(dλ - π) < ε) { |
|
listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2); |
|
listener.point(sλ0, φ0); |
|
listener.lineEnd(); |
|
listener.lineStart(); |
|
listener.point(sλ1, φ0); |
|
listener.point(λ1, φ0); |
|
clean = 0; |
|
} else if (sλ0 !== sλ1 && dλ >= π) { |
|
if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; |
|
if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; |
|
φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); |
|
listener.point(sλ0, φ0); |
|
listener.lineEnd(); |
|
listener.lineStart(); |
|
listener.point(sλ1, φ0); |
|
clean = 0; |
|
} |
|
listener.point(λ0 = λ1, φ0 = φ1); |
|
sλ0 = sλ1; |
|
}, |
|
lineEnd: function() { |
|
listener.lineEnd(); |
|
λ0 = φ0 = NaN; |
|
}, |
|
clean: function() { |
|
return 2 - clean; |
|
} |
|
}; |
|
} |
|
function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { |
|
var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); |
|
return Math.abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; |
|
} |
|
function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { |
|
var φ; |
|
if (from == null) { |
|
φ = direction * π / 2; |
|
listener.point(-π, φ); |
|
listener.point(0, φ); |
|
listener.point(π, φ); |
|
listener.point(π, 0); |
|
listener.point(π, -φ); |
|
listener.point(0, -φ); |
|
listener.point(-π, -φ); |
|
listener.point(-π, 0); |
|
listener.point(-π, φ); |
|
} else if (Math.abs(from[0] - to[0]) > ε) { |
|
var s = (from[0] < to[0] ? 1 : -1) * π; |
|
φ = direction * s / 2; |
|
listener.point(-s, φ); |
|
listener.point(0, φ); |
|
listener.point(s, φ); |
|
} else { |
|
listener.point(to[0], to[1]); |
|
} |
|
} |
|
function d3_geo_clipCircle(radius) { |
|
var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = Math.abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); |
|
return d3_geo_clip(visible, clipLine, interpolate); |
|
function visible(λ, φ) { |
|
return Math.cos(λ) * Math.cos(φ) > cr; |
|
} |
|
function clipLine(listener) { |
|
var point0, c0, v0, v00, clean; |
|
return { |
|
lineStart: function() { |
|
v00 = v0 = false; |
|
clean = 1; |
|
}, |
|
point: function(λ, φ) { |
|
var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; |
|
if (!point0 && (v00 = v0 = v)) listener.lineStart(); |
|
if (v !== v0) { |
|
point2 = intersect(point0, point1); |
|
if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { |
|
point1[0] += ε; |
|
point1[1] += ε; |
|
v = visible(point1[0], point1[1]); |
|
} |
|
} |
|
if (v !== v0) { |
|
clean = 0; |
|
if (v) { |
|
listener.lineStart(); |
|
point2 = intersect(point1, point0); |
|
listener.point(point2[0], point2[1]); |
|
} else { |
|
point2 = intersect(point0, point1); |
|
listener.point(point2[0], point2[1]); |
|
listener.lineEnd(); |
|
} |
|
point0 = point2; |
|
} else if (notHemisphere && point0 && smallRadius ^ v) { |
|
var t; |
|
if (!(c & c0) && (t = intersect(point1, point0, true))) { |
|
clean = 0; |
|
if (smallRadius) { |
|
listener.lineStart(); |
|
listener.point(t[0][0], t[0][1]); |
|
listener.point(t[1][0], t[1][1]); |
|
listener.lineEnd(); |
|
} else { |
|
listener.point(t[1][0], t[1][1]); |
|
listener.lineEnd(); |
|
listener.lineStart(); |
|
listener.point(t[0][0], t[0][1]); |
|
} |
|
} |
|
} |
|
if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { |
|
listener.point(point1[0], point1[1]); |
|
} |
|
point0 = point1, v0 = v, c0 = c; |
|
}, |
|
lineEnd: function() { |
|
if (v0) listener.lineEnd(); |
|
point0 = null; |
|
}, |
|
clean: function() { |
|
return clean | (v00 && v0) << 1; |
|
} |
|
}; |
|
} |
|
function intersect(a, b, two) { |
|
var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); |
|
var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; |
|
if (!determinant) return !two && a; |
|
var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); |
|
d3_geo_cartesianAdd(A, B); |
|
var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); |
|
if (t2 < 0) return; |
|
var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); |
|
d3_geo_cartesianAdd(q, A); |
|
q = d3_geo_spherical(q); |
|
if (!two) return q; |
|
var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; |
|
if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; |
|
var δλ = λ1 - λ0, polar = Math.abs(δλ - π) < ε, meridian = polar || δλ < ε; |
|
if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; |
|
if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (Math.abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { |
|
var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); |
|
d3_geo_cartesianAdd(q1, A); |
|
return [ q, d3_geo_spherical(q1) ]; |
|
} |
|
} |
|
function code(λ, φ) { |
|
var r = smallRadius ? radius : π - radius, code = 0; |
|
if (λ < -r) code |= 1; else if (λ > r) code |= 2; |
|
if (φ < -r) code |= 4; else if (φ > r) code |= 8; |
|
return code; |
|
} |
|
} |
|
var d3_geo_clipViewMAX = 1e9; |
|
function d3_geo_clipView(x0, y0, x1, y1) { |
|
return function(listener) { |
|
var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), segments, polygon, ring; |
|
var clip = { |
|
point: point, |
|
lineStart: lineStart, |
|
lineEnd: lineEnd, |
|
polygonStart: function() { |
|
listener = bufferListener; |
|
segments = []; |
|
polygon = []; |
|
}, |
|
polygonEnd: function() { |
|
listener = listener_; |
|
if ((segments = d3.merge(segments)).length) { |
|
listener.polygonStart(); |
|
d3_geo_clipPolygon(segments, compare, inside, interpolate, listener); |
|
listener.polygonEnd(); |
|
} else if (insidePolygon([ x0, y0 ])) { |
|
listener.polygonStart(), listener.lineStart(); |
|
interpolate(null, null, 1, listener); |
|
listener.lineEnd(), listener.polygonEnd(); |
|
} |
|
segments = polygon = ring = null; |
|
} |
|
}; |
|
function inside(point) { |
|
var a = corner(point, -1), i = insidePolygon([ a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0 ]); |
|
return i; |
|
} |
|
function insidePolygon(p) { |
|
var wn = 0, n = polygon.length, y = p[1]; |
|
for (var i = 0; i < n; ++i) { |
|
for (var j = 1, v = polygon[i], m = v.length, a = v[0]; j < m; ++j) { |
|
b = v[j]; |
|
if (a[1] <= y) { |
|
if (b[1] > y && isLeft(a, b, p) > 0) ++wn; |
|
} else { |
|
if (b[1] <= y && isLeft(a, b, p) < 0) --wn; |
|
} |
|
a = b; |
|
} |
|
} |
|
return wn !== 0; |
|
} |
|
function isLeft(a, b, c) { |
|
return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]); |
|
} |
|
function interpolate(from, to, direction, listener) { |
|
var a = 0, a1 = 0; |
|
if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { |
|
do { |
|
listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); |
|
} while ((a = (a + direction + 4) % 4) !== a1); |
|
} else { |
|
listener.point(to[0], to[1]); |
|
} |
|
} |
|
function visible(x, y) { |
|
return x0 <= x && x <= x1 && y0 <= y && y <= y1; |
|
} |
|
function point(x, y) { |
|
if (visible(x, y)) listener.point(x, y); |
|
} |
|
var x__, y__, v__, x_, y_, v_, first; |
|
function lineStart() { |
|
clip.point = linePoint; |
|
if (polygon) polygon.push(ring = []); |
|
first = true; |
|
v_ = false; |
|
x_ = y_ = NaN; |
|
} |
|
function lineEnd() { |
|
if (segments) { |
|
linePoint(x__, y__); |
|
if (v__ && v_) bufferListener.rejoin(); |
|
segments.push(bufferListener.buffer()); |
|
} |
|
clip.point = point; |
|
if (v_) listener.lineEnd(); |
|
} |
|
function linePoint(x, y) { |
|
x = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, x)); |
|
y = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, y)); |
|
var v = visible(x, y); |
|
if (polygon) ring.push([ x, y ]); |
|
if (first) { |
|
x__ = x, y__ = y, v__ = v; |
|
first = false; |
|
if (v) { |
|
listener.lineStart(); |
|
listener.point(x, y); |
|
} |
|
} else { |
|
if (v && v_) listener.point(x, y); else { |
|
var a = [ x_, y_ ], b = [ x, y ]; |
|
if (clipLine(a, b)) { |
|
if (!v_) { |
|
listener.lineStart(); |
|
listener.point(a[0], a[1]); |
|
} |
|
listener.point(b[0], b[1]); |
|
if (!v) listener.lineEnd(); |
|
} else if (v) { |
|
listener.lineStart(); |
|
listener.point(x, y); |
|
} |
|
} |
|
} |
|
x_ = x, y_ = y, v_ = v; |
|
} |
|
return clip; |
|
}; |
|
function corner(p, direction) { |
|
return Math.abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : Math.abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : Math.abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; |
|
} |
|
function compare(a, b) { |
|
return comparePoints(a.point, b.point); |
|
} |
|
function comparePoints(a, b) { |
|
var ca = corner(a, 1), cb = corner(b, 1); |
|
return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; |
|
} |
|
function clipLine(a, b) { |
|
var dx = b[0] - a[0], dy = b[1] - a[1], t = [ 0, 1 ]; |
|
if (Math.abs(dx) < ε && Math.abs(dy) < ε) return x0 <= a[0] && a[0] <= x1 && y0 <= a[1] && a[1] <= y1; |
|
if (d3_geo_clipViewT(x0 - a[0], dx, t) && d3_geo_clipViewT(a[0] - x1, -dx, t) && d3_geo_clipViewT(y0 - a[1], dy, t) && d3_geo_clipViewT(a[1] - y1, -dy, t)) { |
|
if (t[1] < 1) { |
|
b[0] = a[0] + t[1] * dx; |
|
b[1] = a[1] + t[1] * dy; |
|
} |
|
if (t[0] > 0) { |
|
a[0] += t[0] * dx; |
|
a[1] += t[0] * dy; |
|
} |
|
return true; |
|
} |
|
return false; |
|
} |
|
} |
|
function d3_geo_clipViewT(num, denominator, t) { |
|
if (Math.abs(denominator) < ε) return num <= 0; |
|
var u = num / denominator; |
|
if (denominator > 0) { |
|
if (u > t[1]) return false; |
|
if (u > t[0]) t[0] = u; |
|
} else { |
|
if (u < t[0]) return false; |
|
if (u < t[1]) t[1] = u; |
|
} |
|
return true; |
|
} |
|
function d3_geo_compose(a, b) { |
|
function compose(x, y) { |
|
return x = a(x, y), b(x[0], x[1]); |
|
} |
|
if (a.invert && b.invert) compose.invert = function(x, y) { |
|
return x = b.invert(x, y), x && a.invert(x[0], x[1]); |
|
}; |
|
return compose; |
|
} |
|
function d3_geo_resample(project) { |
|
var δ2 = .5, maxDepth = 16; |
|
function resample(stream) { |
|
var λ0, x0, y0, a0, b0, c0; |
|
var resample = { |
|
point: point, |
|
lineStart: lineStart, |
|
lineEnd: lineEnd, |
|
polygonStart: function() { |
|
stream.polygonStart(); |
|
resample.lineStart = polygonLineStart; |
|
}, |
|
polygonEnd: function() { |
|
stream.polygonEnd(); |
|
resample.lineStart = lineStart; |
|
} |
|
}; |
|
function point(x, y) { |
|
x = project(x, y); |
|
stream.point(x[0], x[1]); |
|
} |
|
function lineStart() { |
|
x0 = NaN; |
|
resample.point = linePoint; |
|
stream.lineStart(); |
|
} |
|
function linePoint(λ, φ) { |
|
var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); |
|
resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); |
|
stream.point(x0, y0); |
|
} |
|
function lineEnd() { |
|
resample.point = point; |
|
stream.lineEnd(); |
|
} |
|
function polygonLineStart() { |
|
var λ00, φ00, x00, y00, a00, b00, c00; |
|
lineStart(); |
|
resample.point = function(λ, φ) { |
|
linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; |
|
resample.point = linePoint; |
|
}; |
|
resample.lineEnd = function() { |
|
resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); |
|
resample.lineEnd = lineEnd; |
|
lineEnd(); |
|
}; |
|
} |
|
return resample; |
|
} |
|
function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { |
|
var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; |
|
if (d2 > 4 * δ2 && depth--) { |
|
var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; |
|
if (dz * dz / d2 > δ2 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) { |
|
resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); |
|
stream.point(x2, y2); |
|
resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); |
|
} |
|
} |
|
} |
|
resample.precision = function(_) { |
|
if (!arguments.length) return Math.sqrt(δ2); |
|
maxDepth = (δ2 = _ * _) > 0 && 16; |
|
return resample; |
|
}; |
|
return resample; |
|
} |
|
d3.geo.projection = d3_geo_projection; |
|
d3.geo.projectionMutator = d3_geo_projectionMutator; |
|
fun |