Commit 7dbb732a authored by Mike Bostock's avatar Mike Bostock
Browse files

Merge branch '3.0.7'

parents 4648db5b 3855a60b
...@@ -198,6 +198,7 @@ d3.geo.js: \ ...@@ -198,6 +198,7 @@ d3.geo.js: \
src/geo/equirectangular.js \ src/geo/equirectangular.js \
src/geo/gnomonic.js \ src/geo/gnomonic.js \
src/geo/graticule.js \ src/geo/graticule.js \
src/geo/haversin.js \
src/geo/interpolate.js \ src/geo/interpolate.js \
src/geo/greatArc.js \ src/geo/greatArc.js \
src/geo/mercator.js \ src/geo/mercator.js \
......
{ {
"name": "d3", "name": "d3",
"version": "3.0.6", "version": "3.0.7",
"main": "./d3.js" "main": "./d3.js"
} }
d3 = function() { d3 = function() {
var π = Math.PI, ε = 1e-6, d3 = { var π = Math.PI, ε = 1e-6, d3 = {
version: "3.0.6" version: "3.0.7"
}, d3_radians = π / 180, d3_degrees = 180 / π, d3_document = document, d3_window = window; }, d3_radians = π / 180, d3_degrees = 180 / π, d3_document = document, d3_window = window;
function d3_target(d) { function d3_target(d) {
return d.target; return d.target;
...@@ -124,7 +124,7 @@ d3 = function() { ...@@ -124,7 +124,7 @@ d3 = function() {
function d3_rebind(target, source, method) { function d3_rebind(target, source, method) {
return function() { return function() {
var value = method.apply(source, arguments); var value = method.apply(source, arguments);
return arguments.length ? target : value; return value === source ? target : value;
}; };
} }
d3.ascending = function(a, b) { d3.ascending = function(a, b) {
...@@ -5794,9 +5794,15 @@ d3 = function() { ...@@ -5794,9 +5794,15 @@ d3 = function() {
function d3_geo_clipPolygon(segments, interpolate, listener) { function d3_geo_clipPolygon(segments, interpolate, listener) {
var subject = [], clip = []; var subject = [], clip = [];
segments.forEach(function(segment) { segments.forEach(function(segment) {
var n = segment.length; if ((n = segment.length) <= 1) return;
if (n <= 1) return; var n, p0 = segment[0], p1 = segment[n - 1];
var p0 = segment[0], p1 = segment[n - 1], a = { 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, point: p0,
points: segment, points: segment,
other: null, other: null,
...@@ -6130,15 +6136,20 @@ d3 = function() { ...@@ -6130,15 +6136,20 @@ d3 = function() {
}); });
}; };
} }
function d3_geo_haversin(x) {
return (x = Math.sin(x / 2)) * x;
}
d3.geo.interpolate = function(source, target) { d3.geo.interpolate = function(source, target) {
return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
}; };
function d3_geo_interpolate(x0, y0, x1, y1) { function d3_geo_interpolate(x0, y0, x1, y1) {
var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))), k = 1 / Math.sin(d); var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_geo_haversin(y1 - y0) + cy0 * cy1 * d3_geo_haversin(x1 - x0))), k = 1 / Math.sin(d);
function interpolate(t) { var interpolate = d ? function(t) {
var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
return [ Math.atan2(y, x) / d3_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians ]; return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
} } : function() {
return [ x0 * d3_degrees, y0 * d3_degrees ];
};
interpolate.distance = d; interpolate.distance = d;
return interpolate; return interpolate;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "d3", "name": "d3",
"version": "3.0.6", "version": "3.0.7",
"description": "A small, free JavaScript library for manipulating documents based on data.", "description": "A small, free JavaScript library for manipulating documents based on data.",
"keywords": [ "keywords": [
"dom", "dom",
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
} }
}, },
"dependencies": { "dependencies": {
"jsdom": "0.3.4" "jsdom": "0.3.x"
}, },
"devDependencies": { "devDependencies": {
"uglify-js": "2.2.3", "uglify-js": "2.2.x",
"vows": "0.7.0" "vows": "0.7.x"
}, },
"scripts": { "scripts": {
"test": "./node_modules/vows/bin/vows" "test": "./node_modules/vows/bin/vows"
......
var π = Math.PI, var π = Math.PI,
ε = 1e-6, ε = 1e-6,
d3 = {version: "3.0.6"}, // semver d3 = {version: "3.0.7"}, // semver
d3_radians = π / 180, d3_radians = π / 180,
d3_degrees = 180 / π, d3_degrees = 180 / π,
d3_document = document, d3_document = document,
......
...@@ -11,6 +11,6 @@ d3.rebind = function(target, source) { ...@@ -11,6 +11,6 @@ d3.rebind = function(target, source) {
function d3_rebind(target, source, method) { function d3_rebind(target, source, method) {
return function() { return function() {
var value = method.apply(source, arguments); var value = method.apply(source, arguments);
return arguments.length ? target : value; return value === source ? target : value;
}; };
} }
...@@ -115,11 +115,21 @@ function d3_geo_clipPolygon(segments, interpolate, listener) { ...@@ -115,11 +115,21 @@ function d3_geo_clipPolygon(segments, interpolate, listener) {
clip = []; clip = [];
segments.forEach(function(segment) { segments.forEach(function(segment) {
var n = segment.length; if ((n = segment.length) <= 1) return;
if (n <= 1) return; var n, p0 = segment[0], p1 = segment[n - 1];
var p0 = segment[0],
p1 = segment[n - 1], // If the first and last points of a segment are coincident, then treat as
a = {point: p0, points: segment, other: null, visited: false, entry: true, subject: true}, // a closed ring.
// TODO if all rings are closed, then the winding order of the exterior
// ring should be checked.
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}; b = {point: p0, points: [p0], other: a, visited: false, entry: false, subject: false};
a.other = b; a.other = b;
subject.push(a); subject.push(a);
......
function d3_geo_haversin(x) {
return (x = Math.sin(x / 2)) * x;
}
...@@ -14,20 +14,20 @@ function d3_geo_interpolate(x0, y0, x1, y1) { ...@@ -14,20 +14,20 @@ function d3_geo_interpolate(x0, y0, x1, y1) {
ky0 = cy0 * Math.sin(x0), ky0 = cy0 * Math.sin(x0),
kx1 = cy1 * Math.cos(x1), kx1 = cy1 * Math.cos(x1),
ky1 = cy1 * Math.sin(x1), ky1 = cy1 * Math.sin(x1),
d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))), d = 2 * Math.asin(Math.sqrt(d3_geo_haversin(y1 - y0) + cy0 * cy1 * d3_geo_haversin(x1 - x0))),
k = 1 / Math.sin(d); k = 1 / Math.sin(d);
function interpolate(t) { var interpolate = d ? function(t) {
var B = Math.sin(t *= d) * k, var B = Math.sin(t *= d) * k,
A = Math.sin(d - t) * k, A = Math.sin(d - t) * k,
x = A * kx0 + B * kx1, x = A * kx0 + B * kx1,
y = A * ky0 + B * ky1, y = A * ky0 + B * ky1,
z = A * sy0 + B * sy1; z = A * sy0 + B * sy1;
return [ return [
Math.atan2(y, x) / d3_radians, Math.atan2(y, x) * d3_degrees,
Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees
]; ];
} } : function() { return [x0 * d3_degrees, y0 * d3_degrees]; };
interpolate.distance = d; interpolate.distance = d;
......
...@@ -17,11 +17,11 @@ console.log(JSON.stringify({ ...@@ -17,11 +17,11 @@ console.log(JSON.stringify({
} }
}, },
"dependencies": { "dependencies": {
"jsdom": "0.3.4" "jsdom": "0.3.x"
}, },
"devDependencies": { "devDependencies": {
"uglify-js": "2.2.3", "uglify-js": "2.2.x",
"vows": "0.7.0" "vows": "0.7.x"
}, },
"scripts": {"test": "./node_modules/vows/bin/vows"} "scripts": {"test": "./node_modules/vows/bin/vows"}
}, null, 2)); }, null, 2));
...@@ -10,40 +10,42 @@ suite.addBatch({ ...@@ -10,40 +10,42 @@ suite.addBatch({
topic: function() { topic: function() {
return d3.rebind; return d3.rebind;
}, },
"bound function uses source as context": function(rebind) { "source function always has source as context": function(rebind) {
var a = {}, b = {foo: function() { that = this; }}, that; var target = {}, source = {method: function() { that = this; }}, that;
rebind(a, b, "foo"); rebind(target, source, "method");
assert.strictEqual((a.foo(), that), b); assert.strictEqual((target.method(), that), source);
assert.strictEqual((a.foo.call({}), that), b); assert.strictEqual((target.method.call({}), that), source);
}, },
"bound function receives any arguments": function(rebind) { "source function receives target function's arguments": function(rebind) {
var a = {}, b = {foo: function() { those = Array.prototype.slice.call(arguments); }}, those; var target = {}, source = {method: function() { those = Array.prototype.slice.call(arguments); }}, those;
rebind(a, b, "foo"); rebind(target, source, "method");
assert.deepEqual((a.foo(), those), []); assert.deepEqual((target.method(), those), []);
assert.deepEqual((a.foo(1), those), [1]); assert.deepEqual((target.method(1), those), [1]);
assert.deepEqual((a.foo(null), those), [null]); assert.deepEqual((target.method(null), those), [null]);
assert.deepEqual((a.foo(b, b, 1), those), [b, b, 1]); assert.deepEqual((target.method(source, source, 1), those), [source, source, 1]);
}, },
"bound function returns object if arguments": function(rebind) { "target function returns target if source function returns source": function(rebind) {
var a = {}, b = {foo: function() {}}; var target = {}, source = {method: function(value) { return value ? source : 42; }};
rebind(a, b, "foo"); rebind(target, source, "method");
assert.strictEqual(a.foo(1), a); assert.strictEqual(target.method(true), target);
assert.strictEqual(a.foo(1, 2, 3), a);
}, },
"bound function returns return value if no arguments": function(rebind) { "otherwise, target function returns source function return value": function(rebind) {
var a = {}, b = {foo: function() { return that; }}, that = {}; var target = {}, source = {method: function(value) { return value ? source : 42; }};
rebind(a, b, "foo"); rebind(target, source, "method");
assert.strictEqual(a.foo(), that); assert.strictEqual(target.method(false), 42);
}, },
"can bind multiple methods": function(rebind) { "can bind multiple methods": function(rebind) {
var a = {}, b = {foo: function() { return 1; }, bar: function() { return 2; }}; var target = {}, source = {
rebind(a, b, "foo", "bar"); foo: function() { return 1; },
assert.strictEqual(a.foo(), 1); bar: function() { return 2; }
assert.strictEqual(a.bar(), 2); };
rebind(target, source, "foo", "bar");
assert.strictEqual(target.foo(), 1);
assert.strictEqual(target.bar(), 2);
}, },
"returns the target object": function(rebind) { "returns the target object": function(rebind) {
var a = {}, b = {foo: function() { return that; }}, that = {}; var target = {}, source = {foo: function() {}};
assert.strictEqual(rebind(a, b, "foo"), a); assert.strictEqual(rebind(target, source, "foo"), target);
} }
} }
}); });
......
require("../env");
var vows = require("vows"),
assert = require("assert");
var suite = vows.describe("d3.geo.interpolate");
suite.addBatch({
"interpolate": {
topic: function() {
return d3.geo.interpolate;
},
"zero distance": function(arc) {
assert.deepEqual(d3.geo.interpolate([140.63289, -29.95101], [140.63289, -29.95101])(.5), [140.63289, -29.95101]);
},
"equator": function(arc) {
assert.inDelta(d3.geo.interpolate([10, 0], [20, 0])(.5), [15, 0], 1e-6);
},
"meridian": function(arc) {
assert.inDelta(d3.geo.interpolate([10, -20], [10, 40])(.5), [10, 10], 1e-6);
}
}
});
suite.export(module);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment