diff --git a/geoAlbersUsaPr.js b/geoAlbersUsaPr.js new file mode 100644 index 0000000..ee6979a --- /dev/null +++ b/geoAlbersUsaPr.js @@ -0,0 +1,99 @@ +var d3 = require("d3-geo"); + +var epsilon = 1e-6; + +function multiplex(streams) { + const n = streams.length; + return { + point(x, y) { for (const s of streams) s.point(x, y); }, + sphere() { for (const s of streams) s.sphere(); }, + lineStart() { for (const s of streams) s.lineStart(); }, + lineEnd() { for (const s of streams) s.lineEnd(); }, + polygonStart() { for (const s of streams) s.polygonStart(); }, + polygonEnd() { for (const s of streams) s.polygonEnd(); } + }; +} + +module.exports = function geoAlbersUsaPr() { + var cache, + cacheStream, + lower48 = d3.geoAlbers(), lower48Point, + alaska = d3.geoConicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), + alaskaPoint, + hawaii = d3.geoConicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), + hawaiiPoint, + puertoRico = d3.geoConicEqualArea().rotate([66, 0]).center([0, 18]).parallels([8, 18]), + puertoRicoPoint, + point, + pointStream = {point: function(x, y) { point = [x, y]; }}; + + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, + (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), point) + || (puertoRicoPoint.point(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 + : y >= 0.204 && y < 0.234 && x >= 0.320 && x < 0.380 ? puertoRico + : lower48).invert(coordinates); + }; + + albersUsa.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream), puertoRico.stream(stream)]); + }; + + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_), puertoRico.precision(_); + return reset(); + }; + + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_), puertoRico.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(pointStream); + + 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(pointStream); + + 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(pointStream); + + puertoRicoPoint = puertoRico + .translate([x + 0.350 * k, y + 0.224 * k]) + .clipExtent([[x + 0.320 * k, y + 0.204 * k], [x + 0.380 * k, y + 0.234 * k]]) + .stream(pointStream).point; + + return reset(); + }; + + function reset() { + cache = cacheStream = null; + return albersUsa; + } + + return albersUsa.scale(1070); +}; diff --git a/package.json b/package.json index 8dedc52..2dfbfd3 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "d3-dsv": "^1.0.3", + "d3-geo": "^1.12.0", "d3-geo-projection": "^2.0.0", "ndjson-cli": "^0.3.0", "shapefile": "^0.6.1", diff --git a/prepublish b/prepublish index 42298ff..d5d6b63 100755 --- a/prepublish +++ b/prepublish @@ -35,7 +35,7 @@ geo2topo -q 1e5 -n counties=<( \ shp2json -n build/cb_2017_us_county_5m.shp \ | ndjson-filter '!/000$/.test(d.properties.GEOID)' \ | ndjson-map '(d.id = d.properties.GEOID, delete d.properties, d)' \ - | geoproject -n 'd3.geoAlbersUsa().scale(1300).translate([487.5, 305])') \ + | geoproject -r projection=./geoAlbersUsaPr.js -n 'projection().scale(1300).translate([487.5, 305])') \ | toposimplify -f -p 0.25 \ | topomerge states=counties -k 'd.id.slice(0, 2)' \ | topomerge nation=states \ @@ -54,7 +54,7 @@ geo2topo -q 1e5 -n states=<( \ shp2json -n build/cb_2017_us_state_5m.shp \ | ndjson-filter '!/000$/.test(d.properties.GEOID)' \ | ndjson-map '(d.id = d.properties.GEOID, d.properties = {name: d.properties.NAME}, d)' \ - | geoproject -n 'd3.geoAlbersUsa().scale(1300).translate([487.5, 305])') \ + | geoproject -r projection=./geoAlbersUsaPr.js -n 'projection().scale(1300).translate([487.5, 305])') \ | toposimplify -f -p 0.25 \ | topomerge nation=states \ > states-albers-10m.json @@ -70,6 +70,6 @@ geo2topo -q 1e5 -n nation=<( \ shp2json -n build/cb_2017_us_nation_5m.shp \ | ndjson-filter '!/000$/.test(d.properties.GEOID)' \ | ndjson-map '(d.id = d.properties.GEOID, d.properties = {name: d.properties.NAME}, d)' \ - | geoproject -n 'd3.geoAlbersUsa().scale(1300).translate([487.5, 305])') \ + | geoproject -r projection=./geoAlbersUsaPr.js -n 'projection().scale(1300).translate([487.5, 305])') \ | toposimplify -f -p 0.25 \ > nation-albers-10m.json diff --git a/yarn.lock b/yarn.lock index 0d6ba21..2c60300 100644 --- a/yarn.lock +++ b/yarn.lock @@ -48,6 +48,13 @@ d3-geo@^1.10.0: dependencies: d3-array "1" +d3-geo@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.0.tgz#58ddbdf4d9db5f199db69d1b7c93dca6454a6f24" + integrity sha512-NalZVW+6/SpbKcnl+BCO67m8gX+nGeJdo6oGL9H6BRUGUL1e+AtPcP4vE4TwCQ/gl8y5KE7QvBzrLn+HsKIl+w== + dependencies: + d3-array "1" + file-source@0.6: version "0.6.1" resolved "https://registry.yarnpkg.com/file-source/-/file-source-0.6.1.tgz#ae189d4993766b865a77f83adcf9b9a504cd37dc"