// A modified d3.geoAlbersUsa to include Puerto Rico. // See also https://bl.ocks.org/rveciana/5040be82aea528b6f785464f8816690f function albersUsaPr() { var ε = 1e-6; var lower48 = d3.geoAlbers(); // EPSG:3338 var alaska = d3.geoConicEqualArea() .rotate([154, 0]) .center([-2, 58.5]) .parallels([55, 65]); // ESRI:102007 var hawaii = d3.geoConicEqualArea() .rotate([157, 0]) .center([-3, 19.9]) .parallels([8, 18]); // XXX? You should check that this is a standard PR projection! var puertoRico = d3.geoConicEqualArea() .rotate([66, 0]) .center([0, 18]) .parallels([8, 18]); var point, pointStream = {point: function(x, y) { point = [x, y]; }}, lower48Point, alaskaPoint, hawaiiPoint, puertoRicoPoint; function albersUsa(coordinates) { var x = coordinates[0], y = coordinates[1]; point = null; (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || (hawaiiPoint(x, y), point) || (puertoRicoPoint(x, y), point); return 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 >= .120 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : y >= .204 && y < .234 && x >= .320 && x < .380 ? puertoRico : lower48).invert(coordinates); }; // A naïve multi-projection stream. // The projections must have mutually exclusive clip regions on the sphere, // as this will avoid emitting interleaving lines and polygons. albersUsa.stream = function(stream) { var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream), puertoRicoStream = puertoRico.stream(stream); return { point: function(x, y) { lower48Stream.point(x, y); alaskaStream.point(x, y); hawaiiStream.point(x, y); puertoRicoStream.point(x, y); }, sphere: function() { lower48Stream.sphere(); alaskaStream.sphere(); hawaiiStream.sphere(); puertoRicoStream.sphere(); }, lineStart: function() { lower48Stream.lineStart(); alaskaStream.lineStart(); hawaiiStream.lineStart(); puertoRicoStream.lineStart(); }, lineEnd: function() { lower48Stream.lineEnd(); alaskaStream.lineEnd(); hawaiiStream.lineEnd(); puertoRicoStream.lineEnd(); }, polygonStart: function() { lower48Stream.polygonStart(); alaskaStream.polygonStart(); hawaiiStream.polygonStart(); puertoRicoStream.polygonStart(); }, polygonEnd: function() { lower48Stream.polygonEnd(); alaskaStream.polygonEnd(); hawaiiStream.polygonEnd(); puertoRicoStream.polygonEnd(); } }; }; albersUsa.precision = function(_) { if (!arguments.length) return lower48.precision(); lower48.precision(_); alaska.precision(_); hawaii.precision(_); puertoRico.precision(_); return albersUsa; }; albersUsa.scale = function(_) { if (!arguments.length) return lower48.scale(); lower48.scale(_ * .75); alaska.scale(_ * .75); hawaii.scale(_* .75); puertoRico.scale(_* .75); 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([x + 0.16 * k, y - 0.08 * k]) .clipExtent([[x - .455 * k, y - 0.4172864 * k], [x + .55 * k, y + .238 * k]]) .stream(pointStream).point; alaskaPoint = alaska .translate([x - 0.34 * k, y + 0.19 * k]) .clipExtent([[x - .825 * k + ε, y - .820 * k + ε], [x + 0 * k - ε, y + .434 * k - ε]]) .stream(pointStream).point; hawaiiPoint = hawaii .translate([x - .01 * k, y + .23 * k]) .clipExtent([[x - .214 * k + ε, y + .016 * k + ε], [x + .115 * k - ε, y + .334 * k - ε]]) .stream(pointStream).point; puertoRicoPoint = puertoRico .translate([x + .420 * k, y + .214 * k]) .clipExtent([[x + .320 * k, y + .104 * k], [x + .480 * k, y + .434 * k]]) .stream(pointStream).point; return albersUsa; }; return albersUsa.scale(1070); }