122 lines
3.4 KiB
JavaScript
122 lines
3.4 KiB
JavaScript
import "../core/identity";
|
|
import "../core/rebind";
|
|
import "../math/trigonometry";
|
|
import "clip-antimeridian";
|
|
import "clip-circle";
|
|
import "clip-extent";
|
|
import "compose";
|
|
import "geo";
|
|
import "path";
|
|
import "resample";
|
|
import "rotation";
|
|
import "transform";
|
|
|
|
d3.geo.projection = d3_geo_projection;
|
|
d3.geo.projectionMutator = d3_geo_projectionMutator;
|
|
|
|
function d3_geo_projection(project) {
|
|
return d3_geo_projectionMutator(function() { return project; })();
|
|
}
|
|
|
|
function d3_geo_projectionMutator(projectAt) {
|
|
var project,
|
|
rotate,
|
|
projectRotate,
|
|
projectResample = d3_geo_resample(function(x, y) { x = project(x, y); return [x[0] * k + δx, δy - x[1] * k]; }),
|
|
k = 150, // scale
|
|
x = 480, y = 250, // translate
|
|
λ = 0, φ = 0, // center
|
|
δλ = 0, δφ = 0, δγ = 0, // rotate
|
|
δx, δy, // center
|
|
preclip = d3_geo_clipAntimeridian,
|
|
postclip = d3_identity,
|
|
clipAngle = null,
|
|
clipExtent = null,
|
|
stream;
|
|
|
|
function projection(point) {
|
|
point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
|
|
return [point[0] * k + δx, δy - point[1] * k];
|
|
}
|
|
|
|
function invert(point) {
|
|
point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
|
|
return point && [point[0] * d3_degrees, point[1] * d3_degrees];
|
|
}
|
|
|
|
projection.stream = function(output) {
|
|
if (stream) stream.valid = false;
|
|
stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
|
|
stream.valid = true; // allow caching by d3.geo.path
|
|
return stream;
|
|
};
|
|
|
|
projection.clipAngle = function(_) {
|
|
if (!arguments.length) return clipAngle;
|
|
preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
|
|
return invalidate();
|
|
};
|
|
|
|
projection.clipExtent = function(_) {
|
|
if (!arguments.length) return clipExtent;
|
|
clipExtent = _;
|
|
postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
|
|
return invalidate();
|
|
};
|
|
|
|
projection.scale = function(_) {
|
|
if (!arguments.length) return k;
|
|
k = +_;
|
|
return reset();
|
|
};
|
|
|
|
projection.translate = function(_) {
|
|
if (!arguments.length) return [x, y];
|
|
x = +_[0];
|
|
y = +_[1];
|
|
return reset();
|
|
};
|
|
|
|
projection.center = function(_) {
|
|
if (!arguments.length) return [λ * d3_degrees, φ * d3_degrees];
|
|
λ = _[0] % 360 * d3_radians;
|
|
φ = _[1] % 360 * d3_radians;
|
|
return reset();
|
|
};
|
|
|
|
projection.rotate = function(_) {
|
|
if (!arguments.length) return [δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees];
|
|
δλ = _[0] % 360 * d3_radians;
|
|
δφ = _[1] % 360 * d3_radians;
|
|
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
|
|
return reset();
|
|
};
|
|
|
|
d3.rebind(projection, projectResample, "precision");
|
|
|
|
function reset() {
|
|
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
|
var center = project(λ, φ);
|
|
δx = x - center[0] * k;
|
|
δy = y + center[1] * k;
|
|
return invalidate();
|
|
}
|
|
|
|
function invalidate() {
|
|
if (stream) stream.valid = false, stream = null;
|
|
return projection;
|
|
}
|
|
|
|
return function() {
|
|
project = projectAt.apply(this, arguments);
|
|
projection.invert = project.invert && invert;
|
|
return reset();
|
|
};
|
|
}
|
|
|
|
function d3_geo_projectionRadians(stream) {
|
|
return d3_geo_transformPoint(stream, function(x, y) {
|
|
stream.point(x * d3_radians, y * d3_radians);
|
|
});
|
|
}
|