Merge branch 'projection' into projection-clipAngle

Conflicts:
	d3.v2.js
	d3.v2.min.js
	src/geo/circle.js
	src/geo/projection.js
This commit is contained in:
Jason Davies 2012-10-02 10:45:51 +01:00
Родитель a8adbde339 14235f4aa6
Коммит cdf79a4648
14 изменённых файлов: 615 добавлений и 427 удалений

Просмотреть файл

@ -183,6 +183,7 @@ d3.layout.js: \
d3.geo.js: \
src/geo/geo.js \
src/geo/type.js \
src/geo/albers-usa.js \
src/geo/albers.js \
src/geo/azimuthal-equal-area.js \
@ -201,8 +202,7 @@ d3.geo.js: \
src/geo/projection.js \
src/geo/rotation.js \
src/geo/stereographic.js \
src/geo/azimuthal.js \
src/geo/type.js
src/geo/azimuthal.js
d3.dsv.js: \
src/dsv/dsv.js \

324
d3.v2.js поставляемый
Просмотреть файл

@ -1900,6 +1900,14 @@
};
return dsv;
}
function d3_geo_type(types) {
for (var type in d3_geo_typeDefaults) {
if (!(type in types)) {
types[type] = d3_geo_typeDefaults[type];
}
}
return types;
}
function d3_geo_albers(φ0, φ1) {
function albers(λ, φ) {
var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
@ -1912,49 +1920,6 @@
};
return albers;
}
function d3_geo_bounds(o, f) {
if (d3_geo_boundsTypes.hasOwnProperty(o.type)) d3_geo_boundsTypes[o.type](o, f);
}
function d3_geo_boundsFeature(o, f) {
d3_geo_bounds(o.geometry, f);
}
function d3_geo_boundsFeatureCollection(o, f) {
for (var a = o.features, i = 0, n = a.length; i < n; i++) {
d3_geo_bounds(a[i].geometry, f);
}
}
function d3_geo_boundsGeometryCollection(o, f) {
for (var a = o.geometries, i = 0, n = a.length; i < n; i++) {
d3_geo_bounds(a[i], f);
}
}
function d3_geo_boundsLineString(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
f.apply(null, a[i]);
}
}
function d3_geo_boundsMultiLineString(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
for (var b = a[i], j = 0, m = b.length; j < m; j++) {
f.apply(null, b[j]);
}
}
}
function d3_geo_boundsMultiPolygon(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
for (var b = a[i][0], j = 0, m = b.length; j < m; j++) {
f.apply(null, b[j]);
}
}
}
function d3_geo_boundsPoint(o, f) {
f.apply(null, o.coordinates);
}
function d3_geo_boundsPolygon(o, f) {
for (var a = o.coordinates[0], i = 0, n = a.length; i < n; i++) {
f.apply(null, a[i]);
}
}
function d3_geo_circleContext(lineStrings) {
var lineString = null;
return {
@ -2162,6 +2127,22 @@
function d3_geo_equirectangular(λ, φ) {
return [ λ, φ ];
}
function d3_geo_graticuleX(y0, y1) {
var y = d3.range(y0, y1 - ε, d3_geo_graticulePrecision).concat(y1);
return function(x) {
return y.map(function(y) {
return [ x, y ];
});
};
}
function d3_geo_graticuleY(x0, x1) {
var x = d3.range(x0, x1 - ε, d3_geo_graticulePrecision).concat(x1);
return function(y) {
return x.map(function(x) {
return [ x, y ];
});
};
}
function d3_geo_greatArcSource(d) {
return d.source;
}
@ -2231,6 +2212,7 @@
function lineTo(λ, φ) {
var p = projectPoint(λ, φ);
resampleLineTo(x0, y0, λ0, φ0, x0 = p[0], y0 = p[1], λ0 = λ, φ0 = φ, maxDepth);
context.lineTo(x0, y0);
}
function resampleLineTo(x0, y0, λ0, φ0, x1, y1, λ1, φ1, depth) {
var dx = x1 - x0, dy = y1 - y0, distance2 = dx * dx + dy * dy;
@ -2238,14 +2220,15 @@
var sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), cosΩ = sinφ0 * sinφ1 + cosφ0 * cosφ1 * Math.cos(λ1 - λ0), k = 1 / (Math.SQRT2 * Math.sqrt(1 + cosΩ)), x = k * cosφ0 * Math.cos(λ0) + k * cosφ1 * Math.cos(λ1), y = k * cosφ0 * Math.sin(λ0) + k * cosφ1 * Math.sin(λ1), z = k * sinφ0 + k * sinφ1, λ2 = Math.abs(x) < ε || Math.abs(y) < ε ? (λ0 + λ1) / 2 : Math.atan2(y, x), φ2 = Math.asin(Math.max(-1, Math.min(1, z))), p = projectPoint(λ2, φ2), x2 = p[0], y2 = p[1], dz = dx * (y0 - y2) - dy * (x0 - x2);
if (dz * dz / distance2 > δ2) {
resampleLineTo(x0, y0, λ0, φ0, x2, y2, λ2, φ2, depth);
context.lineTo(x2, y2);
resampleLineTo(x2, y2, λ2, φ2, x1, y1, λ1, φ1, depth);
return;
}
}
context.lineTo(x1, y1);
}
function closePath() {
lineTo(λ00, φ00);
var p = projectPoint(λ00, φ00);
resampleLineTo(x0, y0, λ0, φ0, p[0], p[1], λ00, φ00, maxDepth);
context.closePath();
}
var λ00, φ00, λ0, φ0, x0, y0, maxDepth = δ2 > 0 && 16;
@ -2431,11 +2414,6 @@
function d3_geo_azimuthalMode(mode) {
return d3_geo_azimuthalModes[mode];
}
function d3_geo_type(types, defaultValue) {
return function(object) {
return object && types.hasOwnProperty(object.type) ? types[object.type](object) : defaultValue;
};
}
function d3_geom_contourStart(grid) {
var x = 0, y = 0;
while (true) {
@ -3018,7 +2996,9 @@
d3 = {
version: "2.10.2"
};
var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π;
var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π, d3_zero = function() {
return 0;
};
var d3_array = d3_arraySlice;
try {
d3_array(document.documentElement.childNodes)[0].nodeType;
@ -6331,6 +6311,68 @@
d3.csv = d3_dsv(",", "text/csv");
d3.tsv = d3_dsv(" ", "text/tab-separated-values");
d3.geo = {};
var d3_geo_typeDefaults = {
Feature: function(feature) {
this.geometry(feature.geometry);
},
FeatureCollection: function(colllection) {
var features = colllection.features, i = -1, n = features.length;
while (++i < n) this.Feature(features[i]);
},
GeometryCollection: function(colllection) {
var geometries = colllection.geometries, i = -1, n = geometries.length;
while (++i < n) this.geometry(geometries[i]);
},
LineString: function(lineString) {
this.line(lineString.coordinates);
},
MultiLineString: function(multiLineString) {
var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
},
MultiPoint: function(multiPoint) {
var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
MultiPolygon: function(multiPolygon) {
var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.polygon(coordinates[i]);
},
Point: function(point) {
this.point(point.coordinates);
},
Polygon: function(polygon) {
this.polygon(polygon.coordinates);
},
object: function(object) {
return d3_geo_typeObjects.hasOwnProperty(object.type) ? this[object.type](object) : this.geometry(object);
},
geometry: function(geometry) {
return d3_geo_typeGeometries.hasOwnProperty(geometry.type) ? this[geometry.type](geometry) : null;
},
point: d3_noop,
line: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
polygon: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
}
};
var d3_geo_typeGeometries = {
LineString: 1,
MultiLineString: 1,
MultiPoint: 1,
MultiPolygon: 1,
Point: 1,
Polygon: 1
};
var d3_geo_typeObjects = {
Feature: 1,
FeatureCollection: 1,
GeometryCollection: 1
};
d3.geo.albersUsa = function() {
function albersUsa(coordinates) {
var lon = coordinates[0], lat = coordinates[1];
@ -6388,26 +6430,23 @@
return d3_geo_projection(d3_geo_azimuthalEquidistant);
}).raw = d3_geo_azimuthalEquidistant;
d3.geo.bounds = function(feature) {
var left = Infinity, bottom = Infinity, right = -Infinity, top = -Infinity;
d3_geo_bounds(feature, function(x, y) {
if (x < left) left = x;
if (x > right) right = x;
if (y < bottom) bottom = y;
if (y > top) top = y;
});
return [ [ left, bottom ], [ right, top ] ];
};
var d3_geo_boundsTypes = {
Feature: d3_geo_boundsFeature,
FeatureCollection: d3_geo_boundsFeatureCollection,
GeometryCollection: d3_geo_boundsGeometryCollection,
LineString: d3_geo_boundsLineString,
MultiLineString: d3_geo_boundsMultiLineString,
MultiPoint: d3_geo_boundsLineString,
MultiPolygon: d3_geo_boundsMultiPolygon,
Point: d3_geo_boundsPoint,
Polygon: d3_geo_boundsPolygon
d3_geo_boundsTop = d3_geo_boundsRight = -(d3_geo_boundsLeft = d3_geo_boundsBottom = Infinity);
d3_geo_bounds.object(feature);
return [ [ d3_geo_boundsLeft, d3_geo_boundsBottom ], [ d3_geo_boundsRight, d3_geo_boundsTop ] ];
};
var d3_geo_boundsLeft, d3_geo_boundsBottom, d3_geo_boundsRight, d3_geo_boundsTop;
var d3_geo_bounds = d3_geo_type({
point: function(point) {
var x = point[0], y = point[1];
if (x < d3_geo_boundsLeft) d3_geo_boundsLeft = x;
if (x > d3_geo_boundsRight) d3_geo_boundsRight = x;
if (y < d3_geo_boundsBottom) d3_geo_boundsBottom = y;
if (y > d3_geo_boundsTop) d3_geo_boundsTop = y;
},
polygon: function(coordinates) {
this.line(coordinates[0]);
}
});
d3.geo.circle = function() {
function circle() {}
var origin = [ 0, 0 ], degrees = 90, clip, precision;
@ -6416,15 +6455,15 @@
clip = d3_geo_circleClip(degrees, function(coordinates) {
return rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
});
return clipType(d) || null;
return clipType.object(d) || null;
};
var clipType = d3_geo_type({
FeatureCollection: function(o) {
var features = o.features.map(clipType).filter(d3_identity);
var features = o.features.map(clipType.Feature, clipType).filter(d3_identity);
return features && (o = Object.create(o), o.features = features, o);
},
Feature: function(o) {
var geometry = clipType(o.geometry);
var geometry = clipType.geometry(o.geometry);
return geometry && (o = Object.create(o), o.geometry = geometry, o);
},
Point: function(o) {
@ -6437,12 +6476,9 @@
o.coordinates.forEach(function(coordinates) {
clip.point(coordinates, context);
});
return coordinates.length && {
type: o.type,
coordinates: coordinates.map(function(lineString) {
return lineString[0];
})
};
return coordinates.length && (o = Object.create(o), o.coordinates = coordinates.map(function(lineString) {
return lineString[0];
}), o);
},
LineString: function(o) {
var lineStrings = [], context = d3_geo_circleContext(lineStrings);
@ -6475,7 +6511,7 @@
return polygons.length && (o = Object.create(o), o.type = "MultiPolygon", o.coordinates = polygons, o);
},
GeometryCollection: function(o) {
var geometries = o.geometries.map(clipType).filter(d3_identity);
var geometries = o.geometries.map(clipType.geometry, clipType).filter(d3_identity);
return geometries.length && (o = Object.create(o), o.geometries = geometries, o);
}
});
@ -6512,18 +6548,9 @@
geometries: graticule.lines()
};
}
var x1 = 180 - ε, x0 = -x1, y1 = 90 - ε, y0 = -y1, dx = 22.5, dy = dx, δx = 2, δy = 2;
var x1, x0, y1, y0, dx = 22.5, dy = dx, x, y;
graticule.lines = function() {
var xSteps = d3.range(x0, x1 - ε, δx).concat(x1), ySteps = d3.range(y0, y1 - ε, δy).concat(y1), xLines = d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(function(x) {
return ySteps.map(function(y) {
return [ x, y ];
});
}), yLines = d3.range(Math.ceil(y0 / dy) * dy, y1, dy).map(function(y) {
return xSteps.map(function(x) {
return [ x, y ];
});
});
return xLines.concat(yLines).map(function(coordinates) {
return d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(x).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).map(y)).map(function(coordinates) {
return {
type: "LineString",
coordinates: coordinates
@ -6531,10 +6558,9 @@
});
};
graticule.outline = function() {
var x2 = (x0 + x1) / 2;
return {
type: "Polygon",
coordinates: [ [ [ x0, y1 ], [ x2, y1 ], [ x1, y1 ], [ x1, y0 ], [ x2, y0 ], [ x0, y0 ], [ x0, y1 ] ] ]
coordinates: [ x(x0).concat(y(y1).slice(1), x(x1).reverse().slice(1), y(y0).reverse().slice(1)) ]
};
};
graticule.extent = function(_) {
@ -6543,6 +6569,8 @@
y0 = +_[0][1], y1 = +_[1][1];
if (x0 > x1) _ = x0, x0 = x1, x1 = _;
if (y0 > y1) _ = y0, y0 = y1, y1 = _;
x = d3_geo_graticuleX(y0, y1);
y = d3_geo_graticuleY(x0, x1);
return graticule;
};
graticule.step = function(_) {
@ -6550,8 +6578,9 @@
dx = +_[0], dy = +_[1];
return graticule;
};
return graticule;
return graticule.extent([ [ -180 + ε, -90 + ε ], [ 180 - ε, 90 - ε ] ]);
};
var d3_geo_graticulePrecision = 3;
d3.geo.greatArc = function() {
function greatArc() {
var d = greatArc.distance.apply(this, arguments), t = 0, dt = precision / d, coordinates = [ p0 ];
@ -6604,57 +6633,19 @@
function path(object) {
var result = null;
if (object != result) {
if (context == result) {
if (typeof pointRadius === "function") pointCircle = d3_geo_pathCircle(pointRadius.apply(this, arguments));
pathObject(object, bufferContext);
if (buffer.length) result = buffer.join(""), buffer = [];
} else {
pathObject(object, context);
}
if (typeof pointRadius === "function") pointCircle = d3_geo_pathCircle(pointRadius.apply(this, arguments));
pathType.object(object);
if (buffer.length) result = buffer.join(""), buffer = [];
}
return result;
}
function pathObject(object, context) {
var pathType = pathObjectByType.get(object.type);
if (pathType) pathType(object, context);
function ringArea(coordinates) {
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
}
function pathGeometry(geometry, context) {
var pathType = pathGeometryByType.get(geometry.type);
if (pathType) pathType(geometry, context);
function polygonArea(coordinates) {
return ringArea(coordinates[0]) - d3.sum(coordinates.slice(1), ringArea);
}
function pathFeature(feature, context) {
pathGeometry(feature.geometry, context);
}
function pathFeatureCollection(collection, context) {
var features = collection.features, i = -1, n = features.length;
while (++i < n) pathFeature(features[i], context);
}
function pathGeometryCollection(collection, context) {
var geometries = collection.geometries, i = -1, n = geometries.length;
while (++i < n) pathGeometry(geometries[i], context);
}
function pathLineString(lineString, context) {
projection.line(lineString.coordinates, context);
}
function pathMultiLineString(multiLineString, context) {
var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.line(coordinates[i], context);
}
function pathMultiPoint(multiPoint, context) {
var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.point(coordinates[i], context);
}
function pathMultiPolygon(multiPolygon, context) {
var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.polygon(coordinates[i], context);
}
function pathPoint(point, context) {
projection.point(point.coordinates, context);
}
function pathPolygon(polygon, context) {
projection.polygon(polygon.coordinates, context);
}
var pointRadius = 4.5, pointCircle = d3_geo_pathCircle(pointRadius), projection = d3.geo.albersUsa(), buffer = [], context;
var pointRadius = 4.5, pointCircle = d3_geo_pathCircle(pointRadius), projection = d3.geo.albersUsa(), buffer = [];
var bufferContext = {
point: function(x, y) {
buffer.push("M", x, ",", y, pointCircle);
@ -6669,34 +6660,49 @@
buffer.push("Z");
}
};
var pathObjectByType = d3.map({
Feature: pathFeature,
FeatureCollection: pathFeatureCollection,
GeometryCollection: pathGeometryCollection,
LineString: pathLineString,
MultiLineString: pathMultiLineString,
MultiPoint: pathMultiPoint,
MultiPolygon: pathMultiPolygon,
Point: pathPoint,
Polygon: pathPolygon
var context = bufferContext;
var pathType = d3_geo_type({
line: function(coordinates) {
projection.line(coordinates, context);
},
polygon: function(coordinates) {
projection.polygon(coordinates, context);
},
point: function(coordinates) {
projection.point(coordinates, context);
}
});
var pathGeometryByType = d3.map({
GeometryCollection: pathGeometryCollection,
LineString: pathLineString,
MultiLineString: pathMultiLineString,
MultiPoint: pathMultiPoint,
MultiPolygon: pathMultiPolygon,
Point: pathPoint,
Polygon: pathPolygon
var areaType = d3_geo_type({
Feature: function(feature) {
return areaType.geometry(feature.geometry);
},
FeatureCollection: function(collection) {
return d3.sum(collection.features, areaType.Feature);
},
GeometryCollection: function(collection) {
return d3.sum(collection.geometries, areaType.geometry);
},
LineString: d3_zero,
MultiLineString: d3_zero,
MultiPoint: d3_zero,
MultiPolygon: function(multiPolygon) {
return d3.sum(multiPolygon.coordinates, polygonArea);
},
Point: d3_zero,
Polygon: function(polygon) {
return polygonArea(polygon.coordinates);
}
});
path.area = areaType.object;
path.projection = function(_) {
if (!arguments.length) return projection;
projection = _;
return path;
};
path.context = function(_) {
if (!arguments.length) return context;
if (!arguments.length) return context === bufferContext ? null : context;
context = _;
if (context == null) context = bufferContext;
return path;
};
path.pointRadius = function(x) {

8
d3.v2.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -3,4 +3,5 @@ d3 = {version: "2.10.2"}; // semver
var π = Math.PI,
ε = 1e-6,
d3_radians = π / 180,
d3_degrees = 180 / π;
d3_degrees = 180 / π,
d3_zero = function() { return 0; };

Просмотреть файл

@ -1,4 +1,5 @@
// TODO composite invert
// TODO projection.{point,line,polygon}
// A composite projection for the United States, 960x500. The set of standard
// parallels for each region comes from USGS, which is published here:

Просмотреть файл

@ -1,83 +1,23 @@
/**
* Given a GeoJSON object, returns the corresponding bounding box. The bounding
* box is represented by a two-dimensional array: [[left, bottom], [right,
* top]], where left is the minimum longitude, bottom is the minimum latitude,
* right is maximum longitude, and top is the maximum latitude.
*/
d3.geo.bounds = function(feature) {
var left = Infinity,
bottom = Infinity,
right = -Infinity,
top = -Infinity;
d3_geo_bounds(feature, function(x, y) {
if (x < left) left = x;
if (x > right) right = x;
if (y < bottom) bottom = y;
if (y > top) top = y;
});
return [[left, bottom], [right, top]];
d3_geo_boundsTop = d3_geo_boundsRight = -(d3_geo_boundsLeft = d3_geo_boundsBottom = Infinity);
d3_geo_bounds.object(feature);
return [[d3_geo_boundsLeft, d3_geo_boundsBottom], [d3_geo_boundsRight, d3_geo_boundsTop]];
};
function d3_geo_bounds(o, f) {
if (d3_geo_boundsTypes.hasOwnProperty(o.type)) d3_geo_boundsTypes[o.type](o, f);
}
var d3_geo_boundsLeft,
d3_geo_boundsBottom,
d3_geo_boundsRight,
d3_geo_boundsTop;
var d3_geo_boundsTypes = {
Feature: d3_geo_boundsFeature,
FeatureCollection: d3_geo_boundsFeatureCollection,
GeometryCollection: d3_geo_boundsGeometryCollection,
LineString: d3_geo_boundsLineString,
MultiLineString: d3_geo_boundsMultiLineString,
MultiPoint: d3_geo_boundsLineString,
MultiPolygon: d3_geo_boundsMultiPolygon,
Point: d3_geo_boundsPoint,
Polygon: d3_geo_boundsPolygon
};
function d3_geo_boundsFeature(o, f) {
d3_geo_bounds(o.geometry, f);
}
function d3_geo_boundsFeatureCollection(o, f) {
for (var a = o.features, i = 0, n = a.length; i < n; i++) {
d3_geo_bounds(a[i].geometry, f);
var d3_geo_bounds = d3_geo_type({
point: function(point) {
var x = point[0], y = point[1];
if (x < d3_geo_boundsLeft) d3_geo_boundsLeft = x;
if (x > d3_geo_boundsRight) d3_geo_boundsRight = x;
if (y < d3_geo_boundsBottom) d3_geo_boundsBottom = y;
if (y > d3_geo_boundsTop) d3_geo_boundsTop = y;
},
polygon: function(coordinates) {
this.line(coordinates[0]); // ignore holes
}
}
function d3_geo_boundsGeometryCollection(o, f) {
for (var a = o.geometries, i = 0, n = a.length; i < n; i++) {
d3_geo_bounds(a[i], f);
}
}
function d3_geo_boundsLineString(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
f.apply(null, a[i]);
}
}
function d3_geo_boundsMultiLineString(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
for (var b = a[i], j = 0, m = b.length; j < m; j++) {
f.apply(null, b[j]);
}
}
}
function d3_geo_boundsMultiPolygon(o, f) {
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
for (var b = a[i][0], j = 0, m = b.length; j < m; j++) {
f.apply(null, b[j]);
}
}
}
function d3_geo_boundsPoint(o, f) {
f.apply(null, o.coordinates);
}
function d3_geo_boundsPolygon(o, f) {
for (var a = o.coordinates[0], i = 0, n = a.length; i < n; i++) {
f.apply(null, a[i]);
}
}
});

Просмотреть файл

@ -14,16 +14,16 @@ d3.geo.circle = function() {
clip = d3_geo_circleClip(degrees, function(coordinates) {
return rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
});
return clipType(d) || null;
return clipType.object(d) || null;
};
var clipType = d3_geo_type({
FeatureCollection: function(o) {
var features = o.features.map(clipType).filter(d3_identity);
var features = o.features.map(clipType.Feature, clipType).filter(d3_identity);
return features && (o = Object.create(o), o.features = features, o);
},
Feature: function(o) {
var geometry = clipType(o.geometry);
var geometry = clipType.geometry(o.geometry);
return geometry && (o = Object.create(o), o.geometry = geometry, o);
},
Point: function(o) { // TODO check
@ -37,10 +37,8 @@ d3.geo.circle = function() {
o.coordinates.forEach(function(coordinates) {
clip.point(coordinates, context);
});
return coordinates.length && {
type: o.type,
coordinates: coordinates.map(function(lineString) { return lineString[0]; })
};
return coordinates.length && (o = Object.create(o),
o.coordinates = coordinates.map(function(lineString) { return lineString[0]; }), o);
},
LineString: function(o) {
var lineStrings = [],
@ -72,7 +70,7 @@ d3.geo.circle = function() {
return polygons.length && (o = Object.create(o), o.type = "MultiPolygon", o.coordinates = polygons, o);
},
GeometryCollection: function(o) {
var geometries = o.geometries.map(clipType).filter(d3_identity);
var geometries = o.geometries.map(clipType.geometry, clipType).filter(d3_identity);
return geometries.length && (o = Object.create(o), o.geometries = geometries, o);
}
});

Просмотреть файл

@ -1,8 +1,8 @@
d3.geo.graticule = function() {
var x1 = 180 - ε, x0 = -x1,
y1 = 90 - ε, y0 = -y1,
var x1, x0,
y1, y0,
dx = 22.5, dy = dx,
δx = 2, δy = 2;
x, y;
function graticule() {
return {
@ -12,27 +12,25 @@ d3.geo.graticule = function() {
}
graticule.lines = function() {
var xSteps = d3.range(x0, x1 - ε, δx).concat(x1),
ySteps = d3.range(y0, y1 - ε, δy).concat(y1),
xLines = d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(function(x) { return ySteps.map(function(y) { return [x, y]; }); }),
yLines = d3.range(Math.ceil(y0 / dy) * dy, y1, dy).map(function(y) { return xSteps.map(function(x) { return [x, y]; }); });
return xLines.concat(yLines).map(function(coordinates) {
return {
type: "LineString",
coordinates: coordinates
};
});
return d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(x)
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).map(y))
.map(function(coordinates) {
return {
type: "LineString",
coordinates: coordinates
};
});
}
graticule.outline = function() {
var x2 = (x0 + x1) / 2;
return {
type: "Polygon",
coordinates: [[
[x0, y1], [x2, y1], [x1, y1],
[x1, y0], [x2, y0], [x0, y0],
[x0, y1]
]]
coordinates: [
x(x0)
.concat(y(y1).slice(1),
x(x1).reverse().slice(1),
y(y0).reverse().slice(1))
]
};
};
@ -42,6 +40,8 @@ d3.geo.graticule = function() {
y0 = +_[0][1], y1 = +_[1][1];
if (x0 > x1) _ = x0, x0 = x1, x1 = _;
if (y0 > y1) _ = y0, y0 = y1, y1 = _;
x = d3_geo_graticuleX(y0, y1);
y = d3_geo_graticuleY(x0, x1);
return graticule;
};
@ -51,5 +51,25 @@ d3.geo.graticule = function() {
return graticule;
};
return graticule;
return graticule.extent([[-180 + ε, -90 + ε], [180 - ε, 90 - ε]]);
};
var d3_geo_graticulePrecision = 3;
function d3_geo_graticuleX(y0, y1) {
var y = d3.range(y0, y1 - ε, d3_geo_graticulePrecision).concat(y1);
return function(x) {
return y.map(function(y) {
return [x, y];
});
};
}
function d3_geo_graticuleY(x0, x1) {
var x = d3.range(x0, x1 - ε, d3_geo_graticulePrecision).concat(x1);
return function(y) {
return x.map(function(x) {
return [x, y];
});
};
}

Просмотреть файл

@ -5,8 +5,7 @@ d3.geo.path = function() {
var pointRadius = 4.5,
pointCircle = d3_geo_pathCircle(pointRadius),
projection = d3.geo.albersUsa(),
buffer = [],
context;
buffer = [];
var bufferContext = {
point: function(x, y) { buffer.push("M", x, ",", y, pointCircle); },
@ -15,93 +14,46 @@ d3.geo.path = function() {
closePath: function() { buffer.push("Z"); }
};
var context = bufferContext;
function path(object) {
var result = null;
if (object != result) {
if (context == result) {
if (typeof pointRadius === "function") pointCircle = d3_geo_pathCircle(pointRadius.apply(this, arguments));
pathObject(object, bufferContext);
if (buffer.length) result = buffer.join(""), buffer = [];
} else {
pathObject(object, context);
}
if (typeof pointRadius === "function") pointCircle = d3_geo_pathCircle(pointRadius.apply(this, arguments));
pathType.object(object);
if (buffer.length) result = buffer.join(""), buffer = [];
}
return result;
}
function pathObject(object, context) {
var pathType = pathObjectByType.get(object.type);
if (pathType) pathType(object, context);
}
function pathGeometry(geometry, context) {
var pathType = pathGeometryByType.get(geometry.type);
if (pathType) pathType(geometry, context);
}
function pathFeature(feature, context) {
pathGeometry(feature.geometry, context);
}
function pathFeatureCollection(collection, context) {
var features = collection.features, i = -1, n = features.length;
while (++i < n) pathFeature(features[i], context);
}
function pathGeometryCollection(collection, context) {
var geometries = collection.geometries, i = -1, n = geometries.length;
while (++i < n) pathGeometry(geometries[i], context);
}
function pathLineString(lineString, context) {
projection.line(lineString.coordinates, context);
}
function pathMultiLineString(multiLineString, context) {
var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.line(coordinates[i], context);
}
function pathMultiPoint(multiPoint, context) {
var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.point(coordinates[i], context);
}
function pathMultiPolygon(multiPolygon, context) {
var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length;
while (++i < n) projection.polygon(coordinates[i], context);
}
function pathPoint(point, context) {
projection.point(point.coordinates, context);
}
function pathPolygon(polygon, context) {
projection.polygon(polygon.coordinates, context);
}
var pathObjectByType = d3.map({
Feature: pathFeature,
FeatureCollection: pathFeatureCollection,
GeometryCollection: pathGeometryCollection,
LineString: pathLineString,
MultiLineString: pathMultiLineString,
MultiPoint: pathMultiPoint,
MultiPolygon: pathMultiPolygon,
Point: pathPoint,
Polygon: pathPolygon
var pathType = d3_geo_type({
line: function(coordinates) { projection.line(coordinates, context); },
polygon: function(coordinates) { projection.polygon(coordinates, context); },
point: function(coordinates) { projection.point(coordinates, context); }
});
var pathGeometryByType = d3.map({
GeometryCollection: pathGeometryCollection,
LineString: pathLineString,
MultiLineString: pathMultiLineString,
MultiPoint: pathMultiPoint,
MultiPolygon: pathMultiPolygon,
Point: pathPoint,
Polygon: pathPolygon
var areaType = d3_geo_type({
Feature: function(feature) { return areaType.geometry(feature.geometry); },
FeatureCollection: function(collection) { return d3.sum(collection.features, areaType.Feature); },
GeometryCollection: function(collection) { return d3.sum(collection.geometries, areaType.geometry); },
LineString: d3_zero,
MultiLineString: d3_zero,
MultiPoint: d3_zero,
MultiPolygon: function(multiPolygon) { return d3.sum(multiPolygon.coordinates, polygonArea); },
Point: d3_zero,
Polygon: function(polygon) { return polygonArea(polygon.coordinates); }
});
function ringArea(coordinates) {
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
}
function polygonArea(coordinates) {
return ringArea(coordinates[0]) - d3.sum(coordinates.slice(1), ringArea);
}
path.area = areaType.object;
path.projection = function(_) {
if (!arguments.length) return projection;
projection = _;
@ -109,8 +61,9 @@ d3.geo.path = function() {
};
path.context = function(_) {
if (!arguments.length) return context;
if (!arguments.length) return context === bufferContext ? null : context;
context = _;
if (context == null) context = bufferContext;
return path;
};
@ -131,14 +84,6 @@ function d3_geo_pathCircle(radius) {
+ "z";
}
// function polygonArea(coordinates) {
// var sum = area(coordinates[0]), // exterior ring
// i = 0, // coordinates.index
// n = coordinates.length;
// while (++i < n) sum -= area(coordinates[i]); // holes
// return sum;
// }
// function polygonCentroid(coordinates) {
// var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
// area = polygon.area(),
@ -196,46 +141,3 @@ function d3_geo_pathCircle(radius) {
// }
// });
// function area(coordinates) {
// return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
// }
// var areaType = path.area = d3_geo_type({
// FeatureCollection: function(o) {
// var area = 0,
// features = o.features,
// i = -1, // features.index
// n = features.length;
// while (++i < n) area += areaType(features[i]);
// return area;
// },
// Feature: function(o) {
// return areaType(o.geometry);
// },
// Polygon: function(o) {
// return polygonArea(o.coordinates);
// },
// MultiPolygon: function(o) {
// var sum = 0,
// coordinates = o.coordinates,
// i = -1, // coordinates index
// n = coordinates.length;
// while (++i < n) sum += polygonArea(coordinates[i]);
// return sum;
// },
// GeometryCollection: function(o) {
// var sum = 0,
// geometries = o.geometries,
// i = -1, // geometries index
// n = geometries.length;
// while (++i < n) sum += areaType(geometries[i]);
// return sum;
// }
// }, 0);

Просмотреть файл

@ -65,6 +65,7 @@ function d3_geo_projectionMutator(projectAt) {
function lineTo(λ, φ) {
var p = projectPoint(λ, φ);
resampleLineTo(x0, y0, λ0, φ0, x0 = p[0], y0 = p[1], λ0 = λ, φ0 = φ, maxDepth);
context.lineTo(x0, y0);
}
function resampleLineTo(x0, y0, λ0, φ0, x1, y1, λ1, φ1, depth) {
@ -89,15 +90,16 @@ function d3_geo_projectionMutator(projectAt) {
dz = dx * (y0 - y2) - dy * (x0 - x2);
if (dz * dz / distance2 > δ2) {
resampleLineTo(x0, y0, λ0, φ0, x2, y2, λ2, φ2, depth);
context.lineTo(x2, y2);
resampleLineTo(x2, y2, λ2, φ2, x1, y1, λ1, φ1, depth);
return;
}
}
context.lineTo(x1, y1);
}
function closePath() {
lineTo(λ00, φ00);
var p = projectPoint(λ00, φ00);
resampleLineTo(x0, y0, λ0, φ0, p[0], p[1], λ00, φ00, maxDepth);
context.closePath();
}

Просмотреть файл

@ -1,5 +1,96 @@
function d3_geo_type(types, defaultValue) {
return function(object) {
return object && types.hasOwnProperty(object.type) ? types[object.type](object) : defaultValue;
};
function d3_geo_type(types) {
for (var type in d3_geo_typeDefaults) {
if (!(type in types)) {
types[type] = d3_geo_typeDefaults[type];
}
}
return types;
}
var d3_geo_typeDefaults = {
Feature: function(feature) {
this.geometry(feature.geometry);
},
FeatureCollection: function(colllection) {
var features = colllection.features, i = -1, n = features.length;
while (++i < n) this.Feature(features[i]);
},
GeometryCollection: function(colllection) {
var geometries = colllection.geometries, i = -1, n = geometries.length;
while (++i < n) this.geometry(geometries[i]);
},
LineString: function(lineString) {
this.line(lineString.coordinates);
},
MultiLineString: function(multiLineString) {
var coordinates = multiLineString.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
},
MultiPoint: function(multiPoint) {
var coordinates = multiPoint.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
MultiPolygon: function(multiPolygon) {
var coordinates = multiPolygon.coordinates, i = -1, n = coordinates.length;
while (++i < n) this.polygon(coordinates[i]);
},
Point: function(point) {
this.point(point.coordinates);
},
Polygon: function(polygon) {
this.polygon(polygon.coordinates);
},
// dispatch for any GeoJSON object type
object: function(object) {
return d3_geo_typeObjects.hasOwnProperty(object.type)
? this[object.type](object)
: this.geometry(object);
},
// dispatch for any GeoJSON geometry type
geometry: function(geometry) {
return d3_geo_typeGeometries.hasOwnProperty(geometry.type)
? this[geometry.type](geometry)
: null;
},
// coordinates [x, y]
point: d3_noop,
// coordinates [[x1, y1], [x2, y2], …]
line: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.point(coordinates[i]);
},
// coordinates [[[x1, y1], [x2, y2], …], [[x1, y1], [x2, y2], …], …]
polygon: function(coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) this.line(coordinates[i]);
}
};
var d3_geo_typeGeometries = {
LineString: 1,
MultiLineString: 1,
MultiPoint: 1,
MultiPolygon: 1,
Point: 1,
Polygon: 1
};
var d3_geo_typeObjects = {
Feature: 1,
FeatureCollection: 1,
GeometryCollection: 1
};

97
test/geo/bounds-test.js Normal file
Просмотреть файл

@ -0,0 +1,97 @@
require("../env");
var vows = require("vows"),
assert = require("assert");
var suite = vows.describe("d3.geo.bounds");
suite.addBatch({
"bounds": {
topic: function() {
return d3.geo.bounds;
},
"Feature": function(bounds) {
assert.deepEqual(bounds({
type: "Feature",
geometry: {
type: "MultiPoint",
coordinates: [[-123, 39], [-122, 38]]
}
}), [[-123, 38], [-122, 39]])
},
"FeatureCollection": function(bounds) {
assert.deepEqual(bounds({
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [-123, 39]
}
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [-122, 38]
}
}
]
}), [[-123, 38], [-122, 39]])
},
"GeometryCollection": function(bounds) {
assert.deepEqual(bounds({
type: "GeometryCollection",
geometries: [
{
type: "Point",
coordinates: [-123, 39]
},
{
type: "Point",
coordinates: [-122, 38]
}
]
}), [[-123, 38], [-122, 39]])
},
"LineString": function(bounds) {
assert.deepEqual(bounds({
type: "LineString",
coordinates: [[-123, 39], [-122, 38]]
}), [[-123, 38], [-122, 39]])
},
"MultiLineString": function(bounds) {
assert.deepEqual(bounds({
type: "MultiLineString",
coordinates: [[[-123, 39], [-122, 38]]]
}), [[-123, 38], [-122, 39]])
},
"MultiPoint": function(bounds) {
assert.deepEqual(bounds({
type: "MultiPoint",
coordinates: [[-123, 39], [-122, 38]]
}), [[-123, 38], [-122, 39]])
},
"MultiPolygon": function(bounds) {
assert.deepEqual(bounds({
type: "MultiPolygon",
coordinates: [[[[-123, 39], [-122, 39], [-122, 38], [-123, 39]], [[10, 20], [20, 20], [20, 10], [10, 10], [10, 20]]]]
}), [[-123, 38], [-122, 39]])
},
"Point": function(bounds) {
assert.deepEqual(bounds({
type: "Point",
coordinates: [-123, 39]
}), [[-123, 39], [-123, 39]])
},
"Polygon": function(bounds) {
assert.deepEqual(bounds({
type: "Polygon",
coordinates: [[[-123, 39], [-122, 39], [-122, 38], [-123, 39]], [[10, 20], [20, 20], [20, 10], [10, 10], [10, 20]]]
}), [[-123, 38], [-122, 39]])
}
}
});
suite.export(module);

Просмотреть файл

@ -0,0 +1,87 @@
require("../env");
var vows = require("vows"),
assert = require("assert");
var suite = vows.describe("d3.geo.graticule");
var ε = 1e-6;
suite.addBatch({
"graticule": {
topic: function() {
return d3.geo.graticule()
.extent([[-90, -45], [90, 45]])
.step([45, 45]);
},
"extent": {
"defaults to just inside –180º, -90º to +180º, +90º": function() {
assert.deepEqual(d3.geo.graticule().extent(), [[-180 + ε, -90 + ε], [180 - ε, 90 - ε]]);
},
"coerces input values to numbers": function() {
var graticule = d3.geo.graticule().extent([["-90", "-45"], ["+90", "+45"]]),
extent = graticule.extent();
assert.strictEqual(extent[0][0], -90);
assert.strictEqual(extent[0][1], -45);
assert.strictEqual(extent[1][0], +90);
assert.strictEqual(extent[1][1], +45);
}
},
"returns a GeometryCollection of LineStrings": function(graticule) {
assert.deepEqual(graticule(), {
type: "GeometryCollection",
geometries: [
{type: "LineString", coordinates: [[-90,-45],[-90,-42],[-90,-39],[-90,-36],[-90,-33],[-90,-30],[-90,-27],[-90,-24],[-90,-21],[-90,-18],[-90,-15],[-90,-12],[-90,-9],[-90,-6],[-90,-3],[-90,0],[-90,3],[-90,6],[-90,9],[-90,12],[-90,15],[-90,18],[-90,21],[-90,24],[-90,27],[-90,30],[-90,33],[-90,36],[-90,39],[-90,42],[-90,45]]},
{type: "LineString", coordinates: [[-45,-45],[-45,-42],[-45,-39],[-45,-36],[-45,-33],[-45,-30],[-45,-27],[-45,-24],[-45,-21],[-45,-18],[-45,-15],[-45,-12],[-45,-9],[-45,-6],[-45,-3],[-45,0],[-45,3],[-45,6],[-45,9],[-45,12],[-45,15],[-45,18],[-45,21],[-45,24],[-45,27],[-45,30],[-45,33],[-45,36],[-45,39],[-45,42],[-45,45]]},
{type: "LineString", coordinates: [[0,-45],[0,-42],[0,-39],[0,-36],[0,-33],[0,-30],[0,-27],[0,-24],[0,-21],[0,-18],[0,-15],[0,-12],[0,-9],[0,-6],[0,-3],[0,0],[0,3],[0,6],[0,9],[0,12],[0,15],[0,18],[0,21],[0,24],[0,27],[0,30],[0,33],[0,36],[0,39],[0,42],[0,45]]},
{type: "LineString", coordinates: [[45,-45],[45,-42],[45,-39],[45,-36],[45,-33],[45,-30],[45,-27],[45,-24],[45,-21],[45,-18],[45,-15],[45,-12],[45,-9],[45,-6],[45,-3],[45,0],[45,3],[45,6],[45,9],[45,12],[45,15],[45,18],[45,21],[45,24],[45,27],[45,30],[45,33],[45,36],[45,39],[45,42],[45,45]]},
{type: "LineString", coordinates: [[-90,-45],[-87,-45],[-84,-45],[-81,-45],[-78,-45],[-75,-45],[-72,-45],[-69,-45],[-66,-45],[-63,-45],[-60,-45],[-57,-45],[-54,-45],[-51,-45],[-48,-45],[-45,-45],[-42,-45],[-39,-45],[-36,-45],[-33,-45],[-30,-45],[-27,-45],[-24,-45],[-21,-45],[-18,-45],[-15,-45],[-12,-45],[-9,-45],[-6,-45],[-3,-45],[0,-45],[3,-45],[6,-45],[9,-45],[12,-45],[15,-45],[18,-45],[21,-45],[24,-45],[27,-45],[30,-45],[33,-45],[36,-45],[39,-45],[42,-45],[45,-45],[48,-45],[51,-45],[54,-45],[57,-45],[60,-45],[63,-45],[66,-45],[69,-45],[72,-45],[75,-45],[78,-45],[81,-45],[84,-45],[87,-45],[90,-45]]},
{type: "LineString", coordinates: [[-90,0],[-87,0],[-84,0],[-81,0],[-78,0],[-75,0],[-72,0],[-69,0],[-66,0],[-63,0],[-60,0],[-57,0],[-54,0],[-51,0],[-48,0],[-45,0],[-42,0],[-39,0],[-36,0],[-33,0],[-30,0],[-27,0],[-24,0],[-21,0],[-18,0],[-15,0],[-12,0],[-9,0],[-6,0],[-3,0],[0,0],[3,0],[6,0],[9,0],[12,0],[15,0],[18,0],[21,0],[24,0],[27,0],[30,0],[33,0],[36,0],[39,0],[42,0],[45,0],[48,0],[51,0],[54,0],[57,0],[60,0],[63,0],[66,0],[69,0],[72,0],[75,0],[78,0],[81,0],[84,0],[87,0],[90,0]]}
]
});
},
"step": {
"defaults to 22.5º, 22.5º": function(graticule) {
assert.deepEqual(d3.geo.graticule().step(), [22.5, 22.5]);
},
"coerces input values to numbers": function() {
var graticule = d3.geo.graticule().step(["45", "11.25"]),
step = graticule.step();
assert.strictEqual(step[0], 45);
assert.strictEqual(step[1], 11.25);
}
},
"outline": {
"returns a Polygon": function(graticule) {
assert.deepEqual(graticule.outline(), {
type: "Polygon",
coordinates: [[
[-90,-45],[-90,-42],[-90,-39],[-90,-36],[-90,-33],[-90,-30],[-90,-27],[-90,-24],[-90,-21],[-90,-18],[-90,-15],[-90,-12],[-90,-9],[-90,-6],[-90,-3],[-90,0],[-90,3],[-90,6],[-90,9],[-90,12],[-90,15],[-90,18],[-90,21],[-90,24],[-90,27],[-90,30],[-90,33],[-90,36],[-90,39],[-90,42],[-90,45],
[-87,45],[-84,45],[-81,45],[-78,45],[-75,45],[-72,45],[-69,45],[-66,45],[-63,45],[-60,45],[-57,45],[-54,45],[-51,45],[-48,45],[-45,45],[-42,45],[-39,45],[-36,45],[-33,45],[-30,45],[-27,45],[-24,45],[-21,45],[-18,45],[-15,45],[-12,45],[-9,45],[-6,45],[-3,45],[0,45],[3,45],[6,45],[9,45],[12,45],[15,45],[18,45],[21,45],[24,45],[27,45],[30,45],[33,45],[36,45],[39,45],[42,45],[45,45],[48,45],[51,45],[54,45],[57,45],[60,45],[63,45],[66,45],[69,45],[72,45],[75,45],[78,45],[81,45],[84,45],[87,45],[90,45],
[90,42],[90,39],[90,36],[90,33],[90,30],[90,27],[90,24],[90,21],[90,18],[90,15],[90,12],[90,9],[90,6],[90,3],[90,0],[90,-3],[90,-6],[90,-9],[90,-12],[90,-15],[90,-18],[90,-21],[90,-24],[90,-27],[90,-30],[90,-33],[90,-36],[90,-39],[90,-42],[90,-45],
[87,-45],[84,-45],[81,-45],[78,-45],[75,-45],[72,-45],[69,-45],[66,-45],[63,-45],[60,-45],[57,-45],[54,-45],[51,-45],[48,-45],[45,-45],[42,-45],[39,-45],[36,-45],[33,-45],[30,-45],[27,-45],[24,-45],[21,-45],[18,-45],[15,-45],[12,-45],[9,-45],[6,-45],[3,-45],[0,-45],[-3,-45],[-6,-45],[-9,-45],[-12,-45],[-15,-45],[-18,-45],[-21,-45],[-24,-45],[-27,-45],[-30,-45],[-33,-45],[-36,-45],[-39,-45],[-42,-45],[-45,-45],[-48,-45],[-51,-45],[-54,-45],[-57,-45],[-60,-45],[-63,-45],[-66,-45],[-69,-45],[-72,-45],[-75,-45],[-78,-45],[-81,-45],[-84,-45],[-87,-45],[-90,-45]
]]
});
}
},
"line": {
"returns an array of LineStrings": function(graticule) {
assert.deepEqual(graticule.lines(), [
{type: "LineString", coordinates: [[-90,-45],[-90,-42],[-90,-39],[-90,-36],[-90,-33],[-90,-30],[-90,-27],[-90,-24],[-90,-21],[-90,-18],[-90,-15],[-90,-12],[-90,-9],[-90,-6],[-90,-3],[-90,0],[-90,3],[-90,6],[-90,9],[-90,12],[-90,15],[-90,18],[-90,21],[-90,24],[-90,27],[-90,30],[-90,33],[-90,36],[-90,39],[-90,42],[-90,45]]},
{type: "LineString", coordinates: [[-45,-45],[-45,-42],[-45,-39],[-45,-36],[-45,-33],[-45,-30],[-45,-27],[-45,-24],[-45,-21],[-45,-18],[-45,-15],[-45,-12],[-45,-9],[-45,-6],[-45,-3],[-45,0],[-45,3],[-45,6],[-45,9],[-45,12],[-45,15],[-45,18],[-45,21],[-45,24],[-45,27],[-45,30],[-45,33],[-45,36],[-45,39],[-45,42],[-45,45]]},
{type: "LineString", coordinates: [[0,-45],[0,-42],[0,-39],[0,-36],[0,-33],[0,-30],[0,-27],[0,-24],[0,-21],[0,-18],[0,-15],[0,-12],[0,-9],[0,-6],[0,-3],[0,0],[0,3],[0,6],[0,9],[0,12],[0,15],[0,18],[0,21],[0,24],[0,27],[0,30],[0,33],[0,36],[0,39],[0,42],[0,45]]},
{type: "LineString", coordinates: [[45,-45],[45,-42],[45,-39],[45,-36],[45,-33],[45,-30],[45,-27],[45,-24],[45,-21],[45,-18],[45,-15],[45,-12],[45,-9],[45,-6],[45,-3],[45,0],[45,3],[45,6],[45,9],[45,12],[45,15],[45,18],[45,21],[45,24],[45,27],[45,30],[45,33],[45,36],[45,39],[45,42],[45,45]]},
{type: "LineString", coordinates: [[-90,-45],[-87,-45],[-84,-45],[-81,-45],[-78,-45],[-75,-45],[-72,-45],[-69,-45],[-66,-45],[-63,-45],[-60,-45],[-57,-45],[-54,-45],[-51,-45],[-48,-45],[-45,-45],[-42,-45],[-39,-45],[-36,-45],[-33,-45],[-30,-45],[-27,-45],[-24,-45],[-21,-45],[-18,-45],[-15,-45],[-12,-45],[-9,-45],[-6,-45],[-3,-45],[0,-45],[3,-45],[6,-45],[9,-45],[12,-45],[15,-45],[18,-45],[21,-45],[24,-45],[27,-45],[30,-45],[33,-45],[36,-45],[39,-45],[42,-45],[45,-45],[48,-45],[51,-45],[54,-45],[57,-45],[60,-45],[63,-45],[66,-45],[69,-45],[72,-45],[75,-45],[78,-45],[81,-45],[84,-45],[87,-45],[90,-45]]},
{type: "LineString", coordinates: [[-90,0],[-87,0],[-84,0],[-81,0],[-78,0],[-75,0],[-72,0],[-69,0],[-66,0],[-63,0],[-60,0],[-57,0],[-54,0],[-51,0],[-48,0],[-45,0],[-42,0],[-39,0],[-36,0],[-33,0],[-30,0],[-27,0],[-24,0],[-21,0],[-18,0],[-15,0],[-12,0],[-9,0],[-6,0],[-3,0],[0,0],[3,0],[6,0],[9,0],[12,0],[15,0],[18,0],[21,0],[24,0],[27,0],[30,0],[33,0],[36,0],[39,0],[42,0],[45,0],[48,0],[51,0],[54,0],[57,0],[60,0],[63,0],[66,0],[69,0],[72,0],[75,0],[78,0],[81,0],[84,0],[87,0],[90,0]]}
]);
}
}
}
});
suite.export(module);

Просмотреть файл

@ -7,32 +7,49 @@ var suite = vows.describe("d3.geo.path");
suite.addBatch({
"path": {
topic: d3.geo.path,
"returns null when passed a null object": function(path) {
assert.isNull(path(null));
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.scale(900 / Math.PI)
.precision(0));
},
"projection": {
"returns the current projection when called with no arguments": function() {
var path = d3.geo.path(), projection = d3.geo.albers();
path.projection(projection);
assert.strictEqual(path.projection(), projection);
}
},
"pointRadius": {
"returns the current point radius when called with no arguments": function() {
var path = d3.geo.path(), radius = function() { return 5; };
assert.strictEqual(path.pointRadius(), 4.5);
assert.strictEqual(path.pointRadius(radius).pointRadius(), radius);
}
"LineString": function(path) {
path({
type: "Feature",
geometry: {
type: "LineString",
coordinates: [[-63, 18], [-62, 18], [-62, 17]]
},
});
assert.deepEqual(testContext.buffer(), [
{type: "moveTo", x: 165, y: 160},
{type: "lineTo", x: 170, y: 160},
{type: "lineTo", x: 170, y: 165}
]);
},
"Polygon": function(path) {
assert.equal(path({
path({
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[[-63.03, 18.02], [-63.14, 18.06], [-63.01, 18.07], [-63.03, 18.02]]]
coordinates: [[[-63, 18], [-62, 18], [-62, 17], [-63, 18]]]
},
}), "M984.5652086349427,468.99159422596244L981.8396467935554,467.9114977057422L985.0785139575695,467.688661596079Z");
});
assert.deepEqual(testContext.buffer(), [
{type: "moveTo", x: 165, y: 160},
{type: "lineTo", x: 170, y: 160},
{type: "lineTo", x: 170, y: 165},
{type: "closePath"}
]);
},
"returns null when passed null or undefined": function(path) {
assert.isNull(path(null));
assert.isNull(path(undefined));
assert.isNull(path());
},
"bogus type name": function(path) {
assert.isNull(path({
@ -42,8 +59,34 @@ suite.addBatch({
coordinates: [[[-63.03, 18.02], [-63.14, 18.06], [-63.01, 18.07], [-63.03, 18.02]]]
},
}));
},
"projection": {
"returns the current projection when called with no arguments": function() {
var path = d3.geo.path(), projection = d3.geo.albers();
path.projection(projection);
assert.strictEqual(path.projection(), projection);
}
},
"pointRadius": {
"returns the current point radius when called with no arguments": function() {
var path = d3.geo.path(), radius = function() { return 5; };
assert.strictEqual(path.pointRadius(), 4.5);
assert.strictEqual(path.pointRadius(radius).pointRadius(), radius);
}
}
}
});
var testBuffer = [];
var testContext = {
point: function(x, y) { testBuffer.push({type: "point", x: Math.round(x), y: Math.round(y)}); },
moveTo: function(x, y) { testBuffer.push({type: "moveTo", x: Math.round(x), y: Math.round(y)}); },
lineTo: function(x, y) { testBuffer.push({type: "lineTo", x: Math.round(x), y: Math.round(y)}); },
closePath: function() { testBuffer.push({type: "closePath"}); },
buffer: function() { var result = testBuffer; testBuffer = []; return result; }
};
suite.export(module);