| [e4c61dd] | 1 | import {epsilon} from "../math.js";
|
|---|
| 2 | import albers from "./albers.js";
|
|---|
| 3 | import conicEqualArea from "./conicEqualArea.js";
|
|---|
| 4 | import {fitExtent, fitSize, fitWidth, fitHeight} from "./fit.js";
|
|---|
| 5 |
|
|---|
| 6 | // The projections must have mutually exclusive clip regions on the sphere,
|
|---|
| 7 | // as this will avoid emitting interleaving lines and polygons.
|
|---|
| 8 | function multiplex(streams) {
|
|---|
| 9 | var n = streams.length;
|
|---|
| 10 | return {
|
|---|
| 11 | point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
|
|---|
| 12 | sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
|
|---|
| 13 | lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
|
|---|
| 14 | lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
|
|---|
| 15 | polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
|
|---|
| 16 | polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
|
|---|
| 17 | };
|
|---|
| 18 | }
|
|---|
| 19 |
|
|---|
| 20 | // A composite projection for the United States, configured by default for
|
|---|
| 21 | // 960×500. The projection also works quite well at 960×600 if you change the
|
|---|
| 22 | // scale to 1285 and adjust the translate accordingly. The set of standard
|
|---|
| 23 | // parallels for each region comes from USGS, which is published here:
|
|---|
| 24 | // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
|
|---|
| 25 | export default function() {
|
|---|
| 26 | var cache,
|
|---|
| 27 | cacheStream,
|
|---|
| 28 | lower48 = albers(), lower48Point,
|
|---|
| 29 | alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
|
|---|
| 30 | hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
|
|---|
| 31 | point, pointStream = {point: function(x, y) { point = [x, y]; }};
|
|---|
| 32 |
|
|---|
| 33 | function albersUsa(coordinates) {
|
|---|
| 34 | var x = coordinates[0], y = coordinates[1];
|
|---|
| 35 | return point = null,
|
|---|
| 36 | (lower48Point.point(x, y), point)
|
|---|
| 37 | || (alaskaPoint.point(x, y), point)
|
|---|
| 38 | || (hawaiiPoint.point(x, y), point);
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | albersUsa.invert = function(coordinates) {
|
|---|
| 42 | var k = lower48.scale(),
|
|---|
| 43 | t = lower48.translate(),
|
|---|
| 44 | x = (coordinates[0] - t[0]) / k,
|
|---|
| 45 | y = (coordinates[1] - t[1]) / k;
|
|---|
| 46 | return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
|
|---|
| 47 | : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
|
|---|
| 48 | : lower48).invert(coordinates);
|
|---|
| 49 | };
|
|---|
| 50 |
|
|---|
| 51 | albersUsa.stream = function(stream) {
|
|---|
| 52 | return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
|
|---|
| 53 | };
|
|---|
| 54 |
|
|---|
| 55 | albersUsa.precision = function(_) {
|
|---|
| 56 | if (!arguments.length) return lower48.precision();
|
|---|
| 57 | lower48.precision(_), alaska.precision(_), hawaii.precision(_);
|
|---|
| 58 | return reset();
|
|---|
| 59 | };
|
|---|
| 60 |
|
|---|
| 61 | albersUsa.scale = function(_) {
|
|---|
| 62 | if (!arguments.length) return lower48.scale();
|
|---|
| 63 | lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
|
|---|
| 64 | return albersUsa.translate(lower48.translate());
|
|---|
| 65 | };
|
|---|
| 66 |
|
|---|
| 67 | albersUsa.translate = function(_) {
|
|---|
| 68 | if (!arguments.length) return lower48.translate();
|
|---|
| 69 | var k = lower48.scale(), x = +_[0], y = +_[1];
|
|---|
| 70 |
|
|---|
| 71 | lower48Point = lower48
|
|---|
| 72 | .translate(_)
|
|---|
| 73 | .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
|
|---|
| 74 | .stream(pointStream);
|
|---|
| 75 |
|
|---|
| 76 | alaskaPoint = alaska
|
|---|
| 77 | .translate([x - 0.307 * k, y + 0.201 * k])
|
|---|
| 78 | .clipExtent([[x - 0.425 * k + epsilon, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]])
|
|---|
| 79 | .stream(pointStream);
|
|---|
| 80 |
|
|---|
| 81 | hawaiiPoint = hawaii
|
|---|
| 82 | .translate([x - 0.205 * k, y + 0.212 * k])
|
|---|
| 83 | .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]])
|
|---|
| 84 | .stream(pointStream);
|
|---|
| 85 |
|
|---|
| 86 | return reset();
|
|---|
| 87 | };
|
|---|
| 88 |
|
|---|
| 89 | albersUsa.fitExtent = function(extent, object) {
|
|---|
| 90 | return fitExtent(albersUsa, extent, object);
|
|---|
| 91 | };
|
|---|
| 92 |
|
|---|
| 93 | albersUsa.fitSize = function(size, object) {
|
|---|
| 94 | return fitSize(albersUsa, size, object);
|
|---|
| 95 | };
|
|---|
| 96 |
|
|---|
| 97 | albersUsa.fitWidth = function(width, object) {
|
|---|
| 98 | return fitWidth(albersUsa, width, object);
|
|---|
| 99 | };
|
|---|
| 100 |
|
|---|
| 101 | albersUsa.fitHeight = function(height, object) {
|
|---|
| 102 | return fitHeight(albersUsa, height, object);
|
|---|
| 103 | };
|
|---|
| 104 |
|
|---|
| 105 | function reset() {
|
|---|
| 106 | cache = cacheStream = null;
|
|---|
| 107 | return albersUsa;
|
|---|
| 108 | }
|
|---|
| 109 |
|
|---|
| 110 | return albersUsa.scale(1070);
|
|---|
| 111 | }
|
|---|