Merge branch 'release'
This commit is contained in:
Коммит
082beb1eb9
5
Makefile
5
Makefile
|
@ -36,9 +36,9 @@ d3.custom.js: \
|
|||
src/end.js
|
||||
|
||||
d3.core.js: \
|
||||
src/compat/date.js \
|
||||
src/compat/style.js \
|
||||
src/core/core.js \
|
||||
src/core/date.js \
|
||||
src/core/object.js \
|
||||
src/core/array.js \
|
||||
src/core/this.js \
|
||||
src/core/functor.js \
|
||||
|
@ -185,6 +185,7 @@ d3.geo.js: \
|
|||
src/geo/mercator.js \
|
||||
src/geo/path.js \
|
||||
src/geo/bounds.js \
|
||||
src/geo/greatCircle.js \
|
||||
src/end.js
|
||||
|
||||
d3.csv.js: \
|
||||
|
|
133
d3.geo.js
133
d3.geo.js
|
@ -17,7 +17,7 @@ d3.geo.azimuthal = function() {
|
|||
sx1 = Math.sin(x1),
|
||||
cy1 = Math.cos(y1),
|
||||
sy1 = Math.sin(y1),
|
||||
k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
|
||||
k = mode === "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
|
||||
x = k * cy1 * sx1,
|
||||
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
|
||||
return [
|
||||
|
@ -26,9 +26,22 @@ d3.geo.azimuthal = function() {
|
|||
];
|
||||
}
|
||||
|
||||
azimuthal.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale,
|
||||
p = Math.sqrt(x * x + y * y),
|
||||
c = mode === "stereographic" ? 2 * Math.atan(p) : Math.asin(p),
|
||||
sc = Math.sin(c),
|
||||
cc = Math.cos(c);
|
||||
return [
|
||||
(x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_radians,
|
||||
Math.asin(cc * sy0 - (y * sc * cy0) / p) / d3_radians
|
||||
];
|
||||
};
|
||||
|
||||
azimuthal.mode = function(x) {
|
||||
if (!arguments.length) return mode;
|
||||
mode = x;
|
||||
mode = x + "";
|
||||
return azimuthal;
|
||||
};
|
||||
|
||||
|
@ -79,6 +92,18 @@ d3.geo.albers = function() {
|
|||
];
|
||||
}
|
||||
|
||||
albers.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale,
|
||||
p0y = p0 + y,
|
||||
t = Math.atan2(x, p0y),
|
||||
p = Math.sqrt(x * x + p0y * p0y);
|
||||
return [
|
||||
(lng0 + t / n) / d3_radians,
|
||||
Math.asin((C - p * p * n * n) / (2 * n)) / d3_radians
|
||||
];
|
||||
};
|
||||
|
||||
function reload() {
|
||||
var phi1 = d3_radians * parallels[0],
|
||||
phi2 = d3_radians * parallels[1],
|
||||
|
@ -177,14 +202,23 @@ d3.geo.mercator = function() {
|
|||
translate = [480, 250];
|
||||
|
||||
function mercator(coordinates) {
|
||||
var x = (coordinates[0]) / 360,
|
||||
y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360;
|
||||
var x = coordinates[0] / 360,
|
||||
y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_radians / 2)) / d3_radians) / 360;
|
||||
return [
|
||||
scale * x + translate[0],
|
||||
scale * Math.max(-.5, Math.min(.5, y)) + translate[1]
|
||||
];
|
||||
}
|
||||
|
||||
mercator.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale;
|
||||
return [
|
||||
360 * x,
|
||||
2 * Math.atan(Math.exp(-360 * y * d3_radians)) / d3_radians - 90
|
||||
];
|
||||
};
|
||||
|
||||
mercator.scale = function(x) {
|
||||
if (!arguments.length) return scale;
|
||||
scale = +x;
|
||||
|
@ -564,4 +598,95 @@ function d3_geo_boundsPolygon(o, f) {
|
|||
f.apply(null, a[i]);
|
||||
}
|
||||
}
|
||||
// From http://williams.best.vwh.net/avform.htm#Intermediate
|
||||
d3.geo.greatCircle = function() {
|
||||
var source = d3_geo_greatCircleSource,
|
||||
target = d3_geo_greatCircleTarget,
|
||||
n = 100,
|
||||
radius = 6371; // Mean radius of Earth, in km.
|
||||
// TODO: breakAtDateLine?
|
||||
|
||||
function greatCircle(d, i) {
|
||||
var from = source.call(this, d, i),
|
||||
to = target.call(this, d, i),
|
||||
x0 = from[0] * d3_radians,
|
||||
y0 = from[1] * d3_radians,
|
||||
x1 = to[0] * d3_radians,
|
||||
y1 = to[1] * d3_radians,
|
||||
cx0 = Math.cos(x0), sx0 = Math.sin(x0),
|
||||
cy0 = Math.cos(y0), sy0 = Math.sin(y0),
|
||||
cx1 = Math.cos(x1), sx1 = Math.sin(x1),
|
||||
cy1 = Math.cos(y1), sy1 = Math.sin(y1),
|
||||
d = Math.acos(sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)),
|
||||
sd = Math.sin(d),
|
||||
f = d / (n - 1),
|
||||
e = -f,
|
||||
path = [],
|
||||
i = -1;
|
||||
|
||||
while (++i < n) {
|
||||
e += f;
|
||||
var A = Math.sin(d - e) / sd,
|
||||
B = Math.sin(e) / sd,
|
||||
x = A * cy0 * cx0 + B * cy1 * cx1,
|
||||
y = A * cy0 * sx0 + B * cy1 * sx1,
|
||||
z = A * sy0 + B * sy1;
|
||||
path[i] = [
|
||||
Math.atan2(y, x) / d3_radians,
|
||||
Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians
|
||||
];
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
greatCircle.source = function(x) {
|
||||
if (!arguments.length) return source;
|
||||
source = x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.target = function(x) {
|
||||
if (!arguments.length) return target;
|
||||
target = x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.n = function(x) {
|
||||
if (!arguments.length) return n;
|
||||
n = +x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.radius = function(x) {
|
||||
if (!arguments.length) return radius;
|
||||
radius = +x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
// Haversine formula for great-circle distance.
|
||||
greatCircle.distance = function(d, i) {
|
||||
var from = source.call(this, d, i),
|
||||
to = target.call(this, d, i),
|
||||
x0 = from[0] * d3_radians,
|
||||
y0 = from[1] * d3_radians,
|
||||
x1 = to[0] * d3_radians,
|
||||
y1 = to[1] * d3_radians,
|
||||
sy = Math.sin((y1 - y0) / 2),
|
||||
sx = Math.sin((x1 - x0) / 2),
|
||||
a = sy * sy + Math.cos(y0) * Math.cos(y1) * sx * sx;
|
||||
|
||||
return radius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
};
|
||||
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
function d3_geo_greatCircleSource(d) {
|
||||
return d.source;
|
||||
}
|
||||
|
||||
function d3_geo_greatCircleTarget(d) {
|
||||
return d.target;
|
||||
}
|
||||
})();
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,12 +1,16 @@
|
|||
(function(){d3 = {version: "2.0.4"}; // semver
|
||||
if (!Date.now) Date.now = function() {
|
||||
(function(){if (!Date.now) Date.now = function() {
|
||||
return +new Date;
|
||||
};
|
||||
if (!Object.create) Object.create = function(o) {
|
||||
/** @constructor */ function f() {}
|
||||
f.prototype = o;
|
||||
return new f;
|
||||
};
|
||||
try {
|
||||
document.createElement("div").style.setProperty("opacity", 0, "");
|
||||
} catch (error) {
|
||||
var d3_style_prototype = CSSStyleDeclaration.prototype,
|
||||
d3_style_setProperty = d3_style_prototype.setProperty;
|
||||
d3_style_prototype.setProperty = function(name, value, priority) {
|
||||
d3_style_setProperty.call(this, name, value + "", priority);
|
||||
};
|
||||
}
|
||||
d3 = {version: "2.1.0"}; // semver
|
||||
var d3_arraySubclass = [].__proto__?
|
||||
|
||||
// Until ECMAScript supports array subclassing, prototype injection works well.
|
||||
|
@ -1780,7 +1784,7 @@ function d3_transition(groups, id) {
|
|||
|
||||
delay <= elapsed ? start() : d3.timer(start, delay, then);
|
||||
|
||||
function start() {
|
||||
function start(elapsed) {
|
||||
if (lock.active > id) return stop();
|
||||
lock.active = id;
|
||||
|
||||
|
@ -1791,7 +1795,7 @@ function d3_transition(groups, id) {
|
|||
}
|
||||
|
||||
event.start.dispatch.call(node, d, i);
|
||||
d3.timer(tick, 0, then);
|
||||
if (!tick(elapsed)) d3.timer(tick, 0, then);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1910,12 +1914,12 @@ d3_transitionPrototype.attrTween = function(name, tween) {
|
|||
return this.tween("attr." + name, name.local ? attrTweenNS : attrTween);
|
||||
};
|
||||
d3_transitionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = null;
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.styleTween(name, d3_transitionTween(value), priority);
|
||||
};
|
||||
|
||||
d3_transitionPrototype.styleTween = function(name, tween, priority) {
|
||||
if (arguments.length < 3) priority = null;
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.tween("style." + name, function(d, i) {
|
||||
var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
|
||||
return f && function(t) {
|
||||
|
@ -2368,23 +2372,24 @@ d3.scale.sqrt = function() {
|
|||
return d3.scale.pow().exponent(.5);
|
||||
};
|
||||
d3.scale.ordinal = function() {
|
||||
return d3_scale_ordinal({}, 0, {t: "range", x: []});
|
||||
return d3_scale_ordinal([], {t: "range", x: []});
|
||||
};
|
||||
|
||||
function d3_scale_ordinal(domain, size, ranger) {
|
||||
var range,
|
||||
function d3_scale_ordinal(domain, ranger) {
|
||||
var index,
|
||||
range,
|
||||
rangeBand;
|
||||
|
||||
function scale(x) {
|
||||
return range[((domain[x] || (domain[x] = ++size)) - 1) % range.length];
|
||||
return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length];
|
||||
}
|
||||
|
||||
scale.domain = function(x) {
|
||||
if (!arguments.length) return d3.keys(domain);
|
||||
domain = {};
|
||||
size = 0;
|
||||
if (!arguments.length) return domain;
|
||||
domain = [];
|
||||
index = {};
|
||||
var i = -1, n = x.length, xi;
|
||||
while (++i < n) if (!domain[xi = x[i]]) domain[xi] = ++size;
|
||||
while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi);
|
||||
return scale[ranger.t](ranger.x, ranger.p);
|
||||
};
|
||||
|
||||
|
@ -2400,8 +2405,8 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = (stop - start) / (size - 1 + padding);
|
||||
range = size < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
|
||||
step = (stop - start) / (domain.length - 1 + padding);
|
||||
range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
|
||||
rangeBand = 0;
|
||||
ranger = {t: "rangePoints", x: x, p: padding};
|
||||
return scale;
|
||||
|
@ -2411,7 +2416,7 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = (stop - start) / (size + padding);
|
||||
step = (stop - start) / (domain.length + padding);
|
||||
range = d3.range(start + step * padding, stop, step);
|
||||
rangeBand = step * (1 - padding);
|
||||
ranger = {t: "rangeBands", x: x, p: padding};
|
||||
|
@ -2422,8 +2427,8 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = Math.floor((stop - start) / (size + padding)),
|
||||
err = stop - start - (size - padding) * step;
|
||||
step = Math.floor((stop - start) / (domain.length + padding)),
|
||||
err = stop - start - (domain.length - padding) * step;
|
||||
range = d3.range(start + Math.round(err / 2), stop, step);
|
||||
rangeBand = Math.round(step * (1 - padding));
|
||||
ranger = {t: "rangeRoundBands", x: x, p: padding};
|
||||
|
@ -2435,12 +2440,10 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
};
|
||||
|
||||
scale.copy = function() {
|
||||
var copy = {}, x;
|
||||
for (x in domain) copy[x] = domain[x];
|
||||
return d3_scale_ordinal(copy, size, ranger);
|
||||
return d3_scale_ordinal(domain, ranger);
|
||||
};
|
||||
|
||||
return scale[ranger.t](ranger.x, ranger.p);
|
||||
return scale.domain(domain);
|
||||
};
|
||||
/*
|
||||
* This product includes color specifications and designs developed by Cynthia
|
||||
|
|
49
d3.layout.js
49
d3.layout.js
|
@ -233,15 +233,15 @@ d3.layout.force = function() {
|
|||
/* Barnes-Hut criterion. */
|
||||
if ((x2 - x1) * dn < theta) {
|
||||
var k = kc * quad.count * dn * dn;
|
||||
node.x += dx * k;
|
||||
node.y += dy * k;
|
||||
node.px -= dx * k;
|
||||
node.py -= dy * k;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (quad.point && isFinite(dn)) {
|
||||
var k = kc * dn * dn;
|
||||
node.x += dx * k;
|
||||
node.y += dy * k;
|
||||
node.px -= dx * k;
|
||||
node.py -= dy * k;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -250,12 +250,13 @@ d3.layout.force = function() {
|
|||
function tick() {
|
||||
var n = nodes.length,
|
||||
m = links.length,
|
||||
q = d3.geom.quadtree(nodes),
|
||||
q,
|
||||
i, // current index
|
||||
o, // current object
|
||||
s, // current source
|
||||
t, // current target
|
||||
l, // current distance
|
||||
k, // current force
|
||||
x, // x-distance
|
||||
y; // y-distance
|
||||
|
||||
|
@ -270,30 +271,32 @@ d3.layout.force = function() {
|
|||
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
|
||||
x *= l;
|
||||
y *= l;
|
||||
t.x -= x / t.weight;
|
||||
t.y -= y / t.weight;
|
||||
s.x += x / s.weight;
|
||||
s.y += y / s.weight;
|
||||
t.x -= x * (k = s.weight / (t.weight + s.weight));
|
||||
t.y -= y * k;
|
||||
s.x += x * (k = 1 - k);
|
||||
s.y += y * k;
|
||||
}
|
||||
}
|
||||
|
||||
// apply gravity forces
|
||||
var kg = alpha * gravity;
|
||||
x = size[0] / 2;
|
||||
y = size[1] / 2;
|
||||
i = -1; while (++i < n) {
|
||||
o = nodes[i];
|
||||
o.x += (x - o.x) * kg;
|
||||
o.y += (y - o.y) * kg;
|
||||
if (k = alpha * gravity) {
|
||||
x = size[0] / 2;
|
||||
y = size[1] / 2;
|
||||
i = -1; if (k) while (++i < n) {
|
||||
o = nodes[i];
|
||||
o.x += (x - o.x) * k;
|
||||
o.y += (y - o.y) * k;
|
||||
}
|
||||
}
|
||||
|
||||
// compute quadtree center of mass
|
||||
d3_layout_forceAccumulate(q);
|
||||
|
||||
// apply charge forces
|
||||
var kc = alpha * charge;
|
||||
i = -1; while (++i < n) {
|
||||
q.visit(repulse(nodes[i], kc));
|
||||
// compute quadtree center of mass and apply charge forces
|
||||
if (k = alpha * charge) {
|
||||
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes));
|
||||
i = -1; while (++i < n) {
|
||||
if (!(o = nodes[i]).fixed) {
|
||||
q.visit(repulse(o, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// position verlet integration
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -9,7 +9,8 @@ var vis = d3.select("#chart")
|
|||
|
||||
d3.json("miserables.json", function(json) {
|
||||
var force = d3.layout.force()
|
||||
.charge(-60)
|
||||
.charge(-120)
|
||||
.linkDistance(30)
|
||||
.nodes(json.nodes)
|
||||
.links(json.links)
|
||||
.size([w, h])
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
try {
|
||||
document.createElement("div").style.setProperty("opacity", 0, "");
|
||||
} catch (error) {
|
||||
var d3_style_prototype = CSSStyleDeclaration.prototype,
|
||||
d3_style_setProperty = d3_style_prototype.setProperty;
|
||||
d3_style_prototype.setProperty = function(name, value, priority) {
|
||||
d3_style_setProperty.call(this, name, value + "", priority);
|
||||
};
|
||||
}
|
|
@ -1 +1 @@
|
|||
d3 = {version: "2.0.4"}; // semver
|
||||
d3 = {version: "2.1.0"}; // semver
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
if (!Object.create) Object.create = function(o) {
|
||||
/** @constructor */ function f() {}
|
||||
f.prototype = o;
|
||||
return new f;
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
d3_transitionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = null;
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.styleTween(name, d3_transitionTween(value), priority);
|
||||
};
|
||||
|
||||
d3_transitionPrototype.styleTween = function(name, tween, priority) {
|
||||
if (arguments.length < 3) priority = null;
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.tween("style." + name, function(d, i) {
|
||||
var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
|
||||
return f && function(t) {
|
||||
|
|
|
@ -39,7 +39,7 @@ function d3_transition(groups, id) {
|
|||
|
||||
delay <= elapsed ? start() : d3.timer(start, delay, then);
|
||||
|
||||
function start() {
|
||||
function start(elapsed) {
|
||||
if (lock.active > id) return stop();
|
||||
lock.active = id;
|
||||
|
||||
|
@ -50,7 +50,7 @@ function d3_transition(groups, id) {
|
|||
}
|
||||
|
||||
event.start.dispatch.call(node, d, i);
|
||||
d3.timer(tick, 0, then);
|
||||
if (!tick(elapsed)) d3.timer(tick, 0, then);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,18 @@ d3.geo.albers = function() {
|
|||
];
|
||||
}
|
||||
|
||||
albers.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale,
|
||||
p0y = p0 + y,
|
||||
t = Math.atan2(x, p0y),
|
||||
p = Math.sqrt(x * x + p0y * p0y);
|
||||
return [
|
||||
(lng0 + t / n) / d3_radians,
|
||||
Math.asin((C - p * p * n * n) / (2 * n)) / d3_radians
|
||||
];
|
||||
};
|
||||
|
||||
function reload() {
|
||||
var phi1 = d3_radians * parallels[0],
|
||||
phi2 = d3_radians * parallels[1],
|
||||
|
|
|
@ -16,7 +16,7 @@ d3.geo.azimuthal = function() {
|
|||
sx1 = Math.sin(x1),
|
||||
cy1 = Math.cos(y1),
|
||||
sy1 = Math.sin(y1),
|
||||
k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
|
||||
k = mode === "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
|
||||
x = k * cy1 * sx1,
|
||||
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
|
||||
return [
|
||||
|
@ -25,9 +25,22 @@ d3.geo.azimuthal = function() {
|
|||
];
|
||||
}
|
||||
|
||||
azimuthal.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale,
|
||||
p = Math.sqrt(x * x + y * y),
|
||||
c = mode === "stereographic" ? 2 * Math.atan(p) : Math.asin(p),
|
||||
sc = Math.sin(c),
|
||||
cc = Math.cos(c);
|
||||
return [
|
||||
(x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_radians,
|
||||
Math.asin(cc * sy0 - (y * sc * cy0) / p) / d3_radians
|
||||
];
|
||||
};
|
||||
|
||||
azimuthal.mode = function(x) {
|
||||
if (!arguments.length) return mode;
|
||||
mode = x;
|
||||
mode = x + "";
|
||||
return azimuthal;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// From http://williams.best.vwh.net/avform.htm#Intermediate
|
||||
d3.geo.greatCircle = function() {
|
||||
var source = d3_geo_greatCircleSource,
|
||||
target = d3_geo_greatCircleTarget,
|
||||
n = 100,
|
||||
radius = 6371; // Mean radius of Earth, in km.
|
||||
// TODO: breakAtDateLine?
|
||||
|
||||
function greatCircle(d, i) {
|
||||
var from = source.call(this, d, i),
|
||||
to = target.call(this, d, i),
|
||||
x0 = from[0] * d3_radians,
|
||||
y0 = from[1] * d3_radians,
|
||||
x1 = to[0] * d3_radians,
|
||||
y1 = to[1] * d3_radians,
|
||||
cx0 = Math.cos(x0), sx0 = Math.sin(x0),
|
||||
cy0 = Math.cos(y0), sy0 = Math.sin(y0),
|
||||
cx1 = Math.cos(x1), sx1 = Math.sin(x1),
|
||||
cy1 = Math.cos(y1), sy1 = Math.sin(y1),
|
||||
d = Math.acos(sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)),
|
||||
sd = Math.sin(d),
|
||||
f = d / (n - 1),
|
||||
e = -f,
|
||||
path = [],
|
||||
i = -1;
|
||||
|
||||
while (++i < n) {
|
||||
e += f;
|
||||
var A = Math.sin(d - e) / sd,
|
||||
B = Math.sin(e) / sd,
|
||||
x = A * cy0 * cx0 + B * cy1 * cx1,
|
||||
y = A * cy0 * sx0 + B * cy1 * sx1,
|
||||
z = A * sy0 + B * sy1;
|
||||
path[i] = [
|
||||
Math.atan2(y, x) / d3_radians,
|
||||
Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians
|
||||
];
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
greatCircle.source = function(x) {
|
||||
if (!arguments.length) return source;
|
||||
source = x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.target = function(x) {
|
||||
if (!arguments.length) return target;
|
||||
target = x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.n = function(x) {
|
||||
if (!arguments.length) return n;
|
||||
n = +x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
greatCircle.radius = function(x) {
|
||||
if (!arguments.length) return radius;
|
||||
radius = +x;
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
// Haversine formula for great-circle distance.
|
||||
greatCircle.distance = function(d, i) {
|
||||
var from = source.call(this, d, i),
|
||||
to = target.call(this, d, i),
|
||||
x0 = from[0] * d3_radians,
|
||||
y0 = from[1] * d3_radians,
|
||||
x1 = to[0] * d3_radians,
|
||||
y1 = to[1] * d3_radians,
|
||||
sy = Math.sin((y1 - y0) / 2),
|
||||
sx = Math.sin((x1 - x0) / 2),
|
||||
a = sy * sy + Math.cos(y0) * Math.cos(y1) * sx * sx;
|
||||
|
||||
return radius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
};
|
||||
|
||||
return greatCircle;
|
||||
};
|
||||
|
||||
function d3_geo_greatCircleSource(d) {
|
||||
return d.source;
|
||||
}
|
||||
|
||||
function d3_geo_greatCircleTarget(d) {
|
||||
return d.target;
|
||||
}
|
|
@ -3,14 +3,23 @@ d3.geo.mercator = function() {
|
|||
translate = [480, 250];
|
||||
|
||||
function mercator(coordinates) {
|
||||
var x = (coordinates[0]) / 360,
|
||||
y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360;
|
||||
var x = coordinates[0] / 360,
|
||||
y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_radians / 2)) / d3_radians) / 360;
|
||||
return [
|
||||
scale * x + translate[0],
|
||||
scale * Math.max(-.5, Math.min(.5, y)) + translate[1]
|
||||
];
|
||||
}
|
||||
|
||||
mercator.invert = function(coordinates) {
|
||||
var x = (coordinates[0] - translate[0]) / scale,
|
||||
y = (coordinates[1] - translate[1]) / scale;
|
||||
return [
|
||||
360 * x,
|
||||
2 * Math.atan(Math.exp(-360 * y * d3_radians)) / d3_radians - 90
|
||||
];
|
||||
};
|
||||
|
||||
mercator.scale = function(x) {
|
||||
if (!arguments.length) return scale;
|
||||
scale = +x;
|
||||
|
|
|
@ -27,15 +27,15 @@ d3.layout.force = function() {
|
|||
/* Barnes-Hut criterion. */
|
||||
if ((x2 - x1) * dn < theta) {
|
||||
var k = kc * quad.count * dn * dn;
|
||||
node.x += dx * k;
|
||||
node.y += dy * k;
|
||||
node.px -= dx * k;
|
||||
node.py -= dy * k;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (quad.point && isFinite(dn)) {
|
||||
var k = kc * dn * dn;
|
||||
node.x += dx * k;
|
||||
node.y += dy * k;
|
||||
node.px -= dx * k;
|
||||
node.py -= dy * k;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -44,12 +44,13 @@ d3.layout.force = function() {
|
|||
function tick() {
|
||||
var n = nodes.length,
|
||||
m = links.length,
|
||||
q = d3.geom.quadtree(nodes),
|
||||
q,
|
||||
i, // current index
|
||||
o, // current object
|
||||
s, // current source
|
||||
t, // current target
|
||||
l, // current distance
|
||||
k, // current force
|
||||
x, // x-distance
|
||||
y; // y-distance
|
||||
|
||||
|
@ -64,30 +65,32 @@ d3.layout.force = function() {
|
|||
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
|
||||
x *= l;
|
||||
y *= l;
|
||||
t.x -= x / t.weight;
|
||||
t.y -= y / t.weight;
|
||||
s.x += x / s.weight;
|
||||
s.y += y / s.weight;
|
||||
t.x -= x * (k = s.weight / (t.weight + s.weight));
|
||||
t.y -= y * k;
|
||||
s.x += x * (k = 1 - k);
|
||||
s.y += y * k;
|
||||
}
|
||||
}
|
||||
|
||||
// apply gravity forces
|
||||
var kg = alpha * gravity;
|
||||
x = size[0] / 2;
|
||||
y = size[1] / 2;
|
||||
i = -1; while (++i < n) {
|
||||
o = nodes[i];
|
||||
o.x += (x - o.x) * kg;
|
||||
o.y += (y - o.y) * kg;
|
||||
if (k = alpha * gravity) {
|
||||
x = size[0] / 2;
|
||||
y = size[1] / 2;
|
||||
i = -1; if (k) while (++i < n) {
|
||||
o = nodes[i];
|
||||
o.x += (x - o.x) * k;
|
||||
o.y += (y - o.y) * k;
|
||||
}
|
||||
}
|
||||
|
||||
// compute quadtree center of mass
|
||||
d3_layout_forceAccumulate(q);
|
||||
|
||||
// apply charge forces
|
||||
var kc = alpha * charge;
|
||||
i = -1; while (++i < n) {
|
||||
q.visit(repulse(nodes[i], kc));
|
||||
// compute quadtree center of mass and apply charge forces
|
||||
if (k = alpha * charge) {
|
||||
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes));
|
||||
i = -1; while (++i < n) {
|
||||
if (!(o = nodes[i]).fixed) {
|
||||
q.visit(repulse(o, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// position verlet integration
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
d3.scale.ordinal = function() {
|
||||
return d3_scale_ordinal({}, 0, {t: "range", x: []});
|
||||
return d3_scale_ordinal([], {t: "range", x: []});
|
||||
};
|
||||
|
||||
function d3_scale_ordinal(domain, size, ranger) {
|
||||
var range,
|
||||
function d3_scale_ordinal(domain, ranger) {
|
||||
var index,
|
||||
range,
|
||||
rangeBand;
|
||||
|
||||
function scale(x) {
|
||||
return range[((domain[x] || (domain[x] = ++size)) - 1) % range.length];
|
||||
return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length];
|
||||
}
|
||||
|
||||
scale.domain = function(x) {
|
||||
if (!arguments.length) return d3.keys(domain);
|
||||
domain = {};
|
||||
size = 0;
|
||||
if (!arguments.length) return domain;
|
||||
domain = [];
|
||||
index = {};
|
||||
var i = -1, n = x.length, xi;
|
||||
while (++i < n) if (!domain[xi = x[i]]) domain[xi] = ++size;
|
||||
while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi);
|
||||
return scale[ranger.t](ranger.x, ranger.p);
|
||||
};
|
||||
|
||||
|
@ -31,8 +32,8 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = (stop - start) / (size - 1 + padding);
|
||||
range = size < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
|
||||
step = (stop - start) / (domain.length - 1 + padding);
|
||||
range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
|
||||
rangeBand = 0;
|
||||
ranger = {t: "rangePoints", x: x, p: padding};
|
||||
return scale;
|
||||
|
@ -42,7 +43,7 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = (stop - start) / (size + padding);
|
||||
step = (stop - start) / (domain.length + padding);
|
||||
range = d3.range(start + step * padding, stop, step);
|
||||
rangeBand = step * (1 - padding);
|
||||
ranger = {t: "rangeBands", x: x, p: padding};
|
||||
|
@ -53,8 +54,8 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
if (arguments.length < 2) padding = 0;
|
||||
var start = x[0],
|
||||
stop = x[1],
|
||||
step = Math.floor((stop - start) / (size + padding)),
|
||||
err = stop - start - (size - padding) * step;
|
||||
step = Math.floor((stop - start) / (domain.length + padding)),
|
||||
err = stop - start - (domain.length - padding) * step;
|
||||
range = d3.range(start + Math.round(err / 2), stop, step);
|
||||
rangeBand = Math.round(step * (1 - padding));
|
||||
ranger = {t: "rangeRoundBands", x: x, p: padding};
|
||||
|
@ -66,10 +67,8 @@ function d3_scale_ordinal(domain, size, ranger) {
|
|||
};
|
||||
|
||||
scale.copy = function() {
|
||||
var copy = {}, x;
|
||||
for (x in domain) copy[x] = domain[x];
|
||||
return d3_scale_ordinal(copy, size, ranger);
|
||||
return d3_scale_ordinal(domain, ranger);
|
||||
};
|
||||
|
||||
return scale[ranger.t](ranger.x, ranger.p);
|
||||
return scale.domain(domain);
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ suite.addBatch({
|
|||
},
|
||||
"sets a property as a number": function(body) {
|
||||
body.style("opacity", .3);
|
||||
assert.equal(document.body.style["opacity"], ".3");
|
||||
assert.equal(document.body.style["opacity"], "0.3");
|
||||
},
|
||||
"sets a property as a function": function(body) {
|
||||
body.style("background-color", function() { return "orange"; });
|
||||
|
@ -57,8 +57,8 @@ suite.addBatch({
|
|||
},
|
||||
"sets a property as a number": function(div) {
|
||||
div.style("opacity", .5);
|
||||
assert.equal(div[0][0].style["opacity"], ".5");
|
||||
assert.equal(div[0][1].style["opacity"], ".5");
|
||||
assert.equal(div[0][0].style["opacity"], "0.5");
|
||||
assert.equal(div[0][1].style["opacity"], "0.5");
|
||||
},
|
||||
"sets a property as a function": function(div) {
|
||||
div.style("background-color", d3.interpolateRgb("orange", "yellow"));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
document = require("jsdom").jsdom("<html><head></head><body></body></html>");
|
||||
window = document.createWindow();
|
||||
navigator = window.navigator;
|
||||
CSSStyleDeclaration = window.CSSStyleDeclaration;
|
||||
|
||||
require("../lib/sizzle/sizzle");
|
||||
Sizzle = window.Sizzle;
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
require("../env");
|
||||
require("../../d3");
|
||||
require("../../d3.geo");
|
||||
|
||||
var vows = require("vows"),
|
||||
assert = require("assert");
|
||||
|
||||
var suite = vows.describe("d3.geo.albers");
|
||||
|
||||
suite.addBatch({
|
||||
"albers": {
|
||||
topic: function() {
|
||||
return d3.geo.albers();
|
||||
},
|
||||
"Arctic": function(albers) {
|
||||
var coords = albers([0, 85]);
|
||||
assert.inDelta(coords[0], 1031.393796, 1e-6);
|
||||
assert.inDelta(coords[1], -714.160436, 1e-6);
|
||||
var lonlat = albers.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
},
|
||||
"Antarctic": function(albers) {
|
||||
var coords = albers([0, -85]);
|
||||
assert.inDelta(coords[0], 2753.458335, 1e-6);
|
||||
assert.inDelta(coords[1], 317.371122, 1e-6);
|
||||
var lonlat = albers.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], -85, 1e-6);
|
||||
},
|
||||
"Hawaii": function(albers) {
|
||||
var coords = albers([-180, 0]);
|
||||
assert.inDelta(coords[0], -984.779405, 1e-6);
|
||||
assert.inDelta(coords[1], 209.571197, 1e-6);
|
||||
var lonlat = albers.invert(coords);
|
||||
assert.inDelta(lonlat[0], -180, 1e-6);
|
||||
assert.inDelta(lonlat[1], 0, 1e-6);
|
||||
},
|
||||
"Phillipines": function(albers) {
|
||||
var coords = albers([180, 0]);
|
||||
assert.inDelta(coords[0], 894.435228, 1e-6);
|
||||
assert.inDelta(coords[1], -2927.636630, 1e-6);
|
||||
var lonlat = albers.invert(coords);
|
||||
assert.inDelta(lonlat[0], 180, 1e-6);
|
||||
assert.inDelta(lonlat[1], 0, 1e-6);
|
||||
},
|
||||
"Inversion works for non-zero translation": function() {
|
||||
var albers = d3.geo.albers().translate([123, 99]).scale(100),
|
||||
coords = albers([0, 85]),
|
||||
lonlat = albers.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
suite.export(module);
|
|
@ -0,0 +1,89 @@
|
|||
require("../env");
|
||||
require("../../d3");
|
||||
require("../../d3.geo");
|
||||
|
||||
var vows = require("vows"),
|
||||
assert = require("assert");
|
||||
|
||||
var suite = vows.describe("d3.geo.azimuthal");
|
||||
|
||||
suite.addBatch({
|
||||
"azimuthal.stereographic": {
|
||||
topic: function() {
|
||||
return d3.geo.azimuthal().mode("stereographic").translate([0, 0]).scale(100);
|
||||
},
|
||||
"Arctic": function(azimuthal) {
|
||||
var coords = azimuthal([0, 85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], -91.633117, 1e-6);
|
||||
var lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
},
|
||||
"Antarctic": function(azimuthal) {
|
||||
var coords = azimuthal([0, -85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], 91.633117, 1e-6);
|
||||
var lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], -85, 1e-6);
|
||||
},
|
||||
"Hawaii": function(azimuthal) {
|
||||
var coords = azimuthal([-180, 0]);
|
||||
assert.equal(coords[0], -Infinity);
|
||||
assert.isTrue(isNaN(coords[1]));
|
||||
},
|
||||
"Phillipines": function(azimuthal) {
|
||||
var coords = azimuthal([180, 0]);
|
||||
assert.equal(coords[0], Infinity);
|
||||
assert.isTrue(isNaN(coords[1]));
|
||||
},
|
||||
"Inversion works for non-zero translation": function() {
|
||||
var azimuthal = d3.geo.azimuthal().mode("stereographic").translate([123, 99]).scale(100),
|
||||
coords = azimuthal([0, 85]),
|
||||
lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
}
|
||||
},
|
||||
"azimuthal.orthographic": {
|
||||
topic: function() {
|
||||
return d3.geo.azimuthal().mode("orthographic").translate([0, 0]).scale(100);
|
||||
},
|
||||
"Arctic": function(azimuthal) {
|
||||
var coords = azimuthal([0, 85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], -99.619469, 1e-6);
|
||||
var lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
},
|
||||
"Antarctic": function(azimuthal) {
|
||||
var coords = azimuthal([0, -85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], 99.619469, 1e-6);
|
||||
var lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], -85, 1e-6);
|
||||
},
|
||||
"Hawaii": function(azimuthal) {
|
||||
var coords = azimuthal([-180, 0]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], 0, 1e-6);
|
||||
},
|
||||
"Phillipines": function(azimuthal) {
|
||||
var coords = azimuthal([180, 0]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], 0, 1e-6);
|
||||
},
|
||||
"Inversion works for non-zero translation": function() {
|
||||
var azimuthal = d3.geo.azimuthal().mode("orthographic").translate([123, 99]).scale(100),
|
||||
coords = azimuthal([0, 85]),
|
||||
lonlat = azimuthal.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
suite.export(module);
|
|
@ -0,0 +1,42 @@
|
|||
require("../env");
|
||||
require("../../d3");
|
||||
require("../../d3.geo");
|
||||
|
||||
var vows = require("vows"),
|
||||
assert = require("assert");
|
||||
|
||||
var suite = vows.describe("d3.geo.greatCircle");
|
||||
|
||||
suite.addBatch({
|
||||
"greatCircle": {
|
||||
topic: function() {
|
||||
return d3.geo.greatCircle()
|
||||
.n(12);
|
||||
},
|
||||
"distance": function(circle) {
|
||||
assert.equal(circle.distance({source: [0, 0], target: [0, 0]}), 0);
|
||||
assert.inDelta(circle.distance({
|
||||
source: [118 + 24 / 60, 33 + 57 / 60],
|
||||
target: [ 73 + 47 / 60, 40 + 38 / 60]
|
||||
}), 3973, .5);
|
||||
},
|
||||
"geodesic": function(circle) {
|
||||
assert.inDelta(circle({source: [5, 52], target: [-120, 37]}), [
|
||||
[ 5, 52 ],
|
||||
[ -3.805036, 57.05083],
|
||||
[ -15.122869, 61.30118],
|
||||
[ -29.396213, 64.34584],
|
||||
[ -46.132729, 65.72409],
|
||||
[ -63.394401, 65.15597],
|
||||
[ -78.854311, 62.76337],
|
||||
[ -91.401599, 58.96701],
|
||||
[-101.190927, 54.21333],
|
||||
[-108.843633, 48.83586],
|
||||
[-114.961152, 43.05231],
|
||||
[-120, 37 ]
|
||||
], .5);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
suite.export(module);
|
|
@ -0,0 +1,57 @@
|
|||
require("../env");
|
||||
require("../../d3");
|
||||
require("../../d3.geo");
|
||||
|
||||
var vows = require("vows"),
|
||||
assert = require("assert");
|
||||
|
||||
var suite = vows.describe("d3.geo.mercator");
|
||||
|
||||
suite.addBatch({
|
||||
"mercator": {
|
||||
topic: function() {
|
||||
return d3.geo.mercator().translate([0, 0]).scale(100);
|
||||
},
|
||||
"Arctic": function(mercator) {
|
||||
var coords = mercator([0, 85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], -49.8362085, 1e-6);
|
||||
var lonlat = mercator.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
},
|
||||
"Antarctic": function(mercator) {
|
||||
var coords = mercator([0, -85]);
|
||||
assert.inDelta(coords[0], 0, 1e-6);
|
||||
assert.inDelta(coords[1], 49.8362085, 1e-6);
|
||||
var lonlat = mercator.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], -85, 1e-6);
|
||||
},
|
||||
"Hawaii": function(mercator) {
|
||||
var coords = mercator([-180, 0]);
|
||||
assert.inDelta(coords[0], -50, 1e-6);
|
||||
assert.inDelta(coords[1], 0, 1e-6);
|
||||
var lonlat = mercator.invert(coords);
|
||||
assert.inDelta(lonlat[0], -180, 1e-6);
|
||||
assert.inDelta(lonlat[1], 0, 1e-6);
|
||||
},
|
||||
"Phillipines": function(mercator) {
|
||||
var coords = mercator([180, 0]);
|
||||
assert.inDelta(coords[0], 50, 1e-6);
|
||||
assert.inDelta(coords[1], 0, 1e-6);
|
||||
var lonlat = mercator.invert(coords);
|
||||
assert.inDelta(lonlat[0], 180, 1e-6);
|
||||
assert.inDelta(lonlat[1], 0, 1e-6);
|
||||
},
|
||||
"Inversion works for non-zero translation": function() {
|
||||
var mercator = d3.geo.mercator().translate([123, 99]).scale(100),
|
||||
coords = mercator([0, 85]),
|
||||
lonlat = mercator.invert(coords);
|
||||
assert.inDelta(lonlat[0], 0, 1e-6);
|
||||
assert.inDelta(lonlat[1], 85, 1e-6);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
suite.export(module);
|
|
@ -29,17 +29,39 @@ suite.addBatch({
|
|||
var x = ordinal().range(["foo", "bar"]);
|
||||
assert.equal(x(1), "foo");
|
||||
assert.equal(x(0), "bar");
|
||||
assert.deepEqual(x.domain(), ["0", "1"]);
|
||||
assert.deepEqual(x.domain(), [1, 0]);
|
||||
x.domain(["0", "1"]);
|
||||
assert.equal(x(0), "foo"); // it changed!
|
||||
assert.equal(x(1), "bar");
|
||||
assert.deepEqual(x.domain(), ["0", "1"]);
|
||||
},
|
||||
"coerces domain values to strings": function(ordinal) {
|
||||
"uniqueness is based on string coercion": function(ordinal) {
|
||||
var x = ordinal().domain(["foo"]).range([42, 43, 44]);
|
||||
assert.equal(x(new String("foo")), 42);
|
||||
assert.equal(x({toString: function() { return "foo"; }}), 42);
|
||||
assert.equal(x({toString: function() { return "bar"; }}), 43);
|
||||
},
|
||||
"orders domain values by the order in which they are seen": function(ordinal) {
|
||||
var x = ordinal();
|
||||
x("foo");
|
||||
x("bar");
|
||||
x("baz");
|
||||
assert.deepEqual(x.domain(), ["foo", "bar", "baz"]);
|
||||
x.domain(["baz", "bar"]);
|
||||
x("foo");
|
||||
assert.deepEqual(x.domain(), ["baz", "bar", "foo"]);
|
||||
x.domain(["baz", "foo"]);
|
||||
assert.deepEqual(x.domain(), ["baz", "foo"]);
|
||||
x.domain([]);
|
||||
x("foo");
|
||||
x("bar");
|
||||
assert.deepEqual(x.domain(), ["foo", "bar"]);
|
||||
},
|
||||
"does not coerce domain values to strings": function(ordinal) {
|
||||
var x = ordinal().domain([0, 1]);
|
||||
assert.deepEqual(x.domain(), ["0", "1"]);
|
||||
assert.typeOf(x.domain()[0], "string");
|
||||
assert.typeOf(x.domain()[1], "string");
|
||||
assert.deepEqual(x.domain(), [0, 1]);
|
||||
assert.typeOf(x.domain()[0], "number");
|
||||
assert.typeOf(x.domain()[1], "number");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче