#!/usr/bin/env node var fs = require("fs"), d3 = require("d3"), shapefile = require("shapefile"), dbf = require("../node_modules/shapefile/dbf"), Canvas = require("canvas"), queue = require("queue-async"); var regions = "01 02 03N 03S 03W 04 05 06 07 08 09 10U 10L 11 12 13 14 15 16 17 18".split(/\s+/), file = fs.createWriteStream(process.argv[2]); var scale = 2, width = 960 * scale, height = 600 * scale; var canvas = new Canvas(width, height), context = canvas.getContext("2d"); var projection = d3.geo.albers() .scale(1280 * scale) .translate([width * .5, height * .5]) .precision(0); var path = d3.geo.path() .projection(projection) .context(context); var q = queue(1); q.defer(renderLand); regions.forEach(function(r) { q.defer(renderRegion, r); }); q.await(output); function renderLand(callback) { var set = d3.set(); console.log("rendering land outline"); context.fillStyle = "#000"; context.lineJoin = "round"; shapefile.readStream("shp/land.shp") .on("feature", function(feature) { var id = feature.properties.STATE_FIPS; if (set.has(id)) return; set.add(id); context.beginPath(); path(feature); context.fill(); }) .on("error", callback) .on("end", function() { callback(null); }); } function renderRegion(region, callback) { console.log("loading attributes for " + region); var orderById = {}; context.strokeStyle = "#fff"; context.lineWidth = 1; context.lineCap = "round"; context.lineJoin = "round"; dbf.readStream("shp/" + region + "-attributes.dbf") .on("header", function(header) { if (header.fields[0].name !== "ComID") return void callback(new Error("ComID is not column 0")); if (header.fields[3].name !== "StreamOrde") return void callback(new Error("StreamOrde is not column 3")); }) .on("record", function(record) { orderById[record[0]] = record[3]; }) .on("error", callback) .on("end", readShapefile); function readShapefile() { console.log("rendering geometry for " + region); shapefile.readStream("shp/" + region + "-geometry.shp") .on("feature", function(feature) { var order = orderById[feature.properties.COMID] || orderById[feature.properties.ComID] || 1; context.lineWidth = order / 8; context.beginPath(); path(feature); context.stroke(); }) .on("error", callback) .on("end", function() { callback(null); }); } } function output(error) { if (error) throw error; console.log("generating " + process.argv[2]); canvas.pngStream().pipe(file); }