Skip to content

Commit

Permalink
Add d3.geoAlbersUsa.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Jun 18, 2016
1 parent 43936c7 commit 31d259d
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {default as geoInterpolate} from "./src/interpolate";
export {default as geoLength} from "./src/length";
export {default as geoPath} from "./src/path/index";
export {default as geoAlbers} from "./src/projection/albers";
export {default as geoAlbersUsa} from "./src/projection/albersUsa";
export {default as geoAzimuthalEqualArea} from "./src/projection/azimuthalEqualArea";
export {default as geoAzimuthalEquidistant} from "./src/projection/azimuthalEquidistant";
export {default as geoConicConformal} from "./src/projection/conicConformal";
Expand Down
85 changes: 85 additions & 0 deletions src/projection/albersUsa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {epsilon} from "../math";
import albers from "./albers";
import conicEqualArea from "./conicEqualArea";

// The projections must have mutually exclusive clip regions on the sphere,
// as this will avoid emitting interleaving lines and polygons.
function multiplex(sinks) {
var n = sinks.length;
return {
point: function(x, y) { var i = -1; while (++i < n) sinks[i].point(x, y); },
sphere: function() { var i = -1; while (++i < n) sinks[i].sphere(); },
lineStart: function() { var i = -1; while (++i < n) sinks[i].lineStart(); },
lineEnd: function() { var i = -1; while (++i < n) sinks[i].lineEnd(); },
polygonStart: function() { var i = -1; while (++i < n) sinks[i].polygonStart(); },
polygonEnd: function() { var i = -1; while (++i < n) sinks[i].polygonEnd(); }
};
}

// A composite projection for the United States, configured by default for
// 960×500. Also works quite well at 960×600 with scale 1285. The set of
// standard parallels for each region comes from USGS, which is published here:
// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
export default function() {
var stream,
streamSink,
lower48 = albers(), lower48Point,
alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
point, pointSink = {point: function(x, y) { point = [x, y]; }};

function albersUsa(coordinates) {
var x = coordinates[0], y = coordinates[1];
return point = null, (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || (hawaiiPoint(x, y), point);
}

albersUsa.invert = function(coordinates) {
var k = lower48.scale(),
t = lower48.translate(),
x = (coordinates[0] - t[0]) / k,
y = (coordinates[1] - t[1]) / k;
return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
: y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
: lower48).invert(coordinates);
};

albersUsa.stream = function(sink) {
return stream && streamSink === sink ? stream : stream = multiplex([lower48.stream(streamSink = sink), alaska.stream(sink), hawaii.stream(sink)]);
};

albersUsa.precision = function(_) {
if (!arguments.length) return lower48.precision();
lower48.precision(_), alaska.precision(_), hawaii.precision(_);
return albersUsa;
};

albersUsa.scale = function(_) {
if (!arguments.length) return lower48.scale();
lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
return albersUsa.translate(lower48.translate());
};

albersUsa.translate = function(_) {
if (!arguments.length) return lower48.translate();
var k = lower48.scale(), x = +_[0], y = +_[1];

lower48Point = lower48
.translate(_)
.clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
.stream(pointSink).point;

alaskaPoint = alaska
.translate([x - 0.307 * k, y + 0.201 * k])
.clipExtent([[x - 0.425 * k + epsilon, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]])
.stream(pointSink).point;

hawaiiPoint = hawaii
.translate([x - 0.205 * k, y + 0.212 * k])
.clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]])
.stream(pointSink).point;

return albersUsa;
};

return albersUsa.scale(1070);
}

0 comments on commit 31d259d

Please sign in to comment.