Created
November 1, 2013 21:05
-
-
Save dougmarcey/7271937 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var path = require("path"), | |
fs = require("fs"), | |
dsv = require("dsv"), | |
optimist = require("optimist"), | |
queue = require("queue-async"), | |
topojson = require("topojson"), | |
jsts = require("jsts"), | |
d3 = require("d3"); | |
var us = JSON.parse(fs.readFileSync("../us-counties.json", "utf-8")); | |
var top = {}, transform = us.transform; | |
var counties = d3.map(); | |
var msas = d3.map(); | |
var eas = d3.map(); | |
for (var key in us.objects) { | |
console.log(key); | |
top[key] = topojson.feature(us, us.objects[key]); | |
} | |
console.log("top level objects: " + top); | |
console.log("counties: " + top.counties.type); | |
us.objects.counties.geometries.forEach(function(c) { | |
counties.set(c.id, topojson.feature(us, c)); | |
}); | |
var reader = new jsts.io.GeoJSONReader(); | |
var writer = new jsts.io.GeoJSONWriter(); | |
top['msa'] = {type: "FeatureCollection", features: []}; | |
top['ea'] = {type: "FeatureCollection", features: []}; | |
fs.readFile("../msa.csv", "utf-8", function(error, text){ | |
var count = 0; | |
dsv.csv.parse(text).map(function(row) { | |
var msa_id = +row.regiongroup_id; | |
var fips = row.region_code; | |
if (!msas.has(msa_id)) { | |
msas.set(msa_id, { id: msa_id, name: row.name_msa, counties: d3.set()}); | |
} | |
msa = msas.get(msa_id); | |
msa.counties.add(fips); | |
count++; | |
}); | |
var largest = 0; | |
var i = 1; | |
var errors = []; | |
var invalid = 0; | |
msas.forEach(function(_id ,msa) { | |
console.log(i + "/" + msas.keys().length + " " + msa.name); | |
msa.counties = msa.counties.values(); | |
if (msa.counties.length > largest) { | |
largest = msa.counties.length; | |
} | |
var msa_geo; | |
var geos = []; | |
msa.counties.forEach(function(cid) { | |
var c = counties.get(cid); | |
if (!c) { | |
console.log(" Could not file county: " + cid + " for msa: " + msa.id + " -- " + msa.name); | |
} else { | |
var geo = reader.read(c.geometry); | |
geo.buffer(0); | |
var isValidOp = new jsts.operation.valid.IsValidOp(geo); | |
if (!isValidOp.isValid()) invalid++; | |
geos.push(geo); | |
try { | |
msa_geo = ( msa_geo ? msa_geo.union(geo) : geo); | |
} catch (ex) { | |
errors.push({msa: msa.name, id: msa.id, valid: (isValidOp.isValid() ? true: isValidOp.getValidationError()), error: ex, county: cid}); | |
} | |
} | |
}); | |
if (!msa_geo) console.log("not geo for msa: " + msa.name); | |
else { | |
msa.feature = {type: "Feature", id: msa.id, geometry: writer.write(msa_geo)}; | |
top['msa'].features.push(msa.feature); | |
} | |
i++; | |
}); | |
console.log("invalid: " + invalid); | |
console.log("errors: " + errors.length); | |
console.log("mappings: " + count); | |
console.log("msa count: " + msas.keys().length); | |
console.log("largest msa: " + largest + " counties"); | |
fs.readFile("../ea.csv", "utf-8", function(error, text) { | |
var count = 0; | |
dsv.csv.parse(text).map(function(row) { | |
//ea_code,eax,fips,county_name | |
var ea_id = +row.ea_code; | |
var fips = row.fips; | |
if (!eas.has(ea_id)) { | |
eas.set(ea_id, { id: ea_id, eax: row.eax, counties: d3.set()}); | |
} | |
ea = eas.get(ea_id); | |
ea.counties.add(fips); | |
count++; | |
}); | |
var i = 0; | |
eas.forEach(function(_id, ea) { | |
console.log(++i + "/" + eas.keys().length + " " + ea.id); | |
ea.counties = ea.counties.values(); | |
var ea_geo; | |
var geos = []; | |
var j = 0; | |
ea.counties.forEach(function(cid) { | |
console.log("\t" + ++j + "/" + ea.counties.length + " counties"); | |
var c = counties.get(cid); | |
if (!c) { | |
console.log(" Could not find county: " + cid + " for ea: " + ea.id + " -- " + ea.eax); | |
} else { | |
var geo = reader.read(c.geometry); | |
geo.buffer(0); | |
var isValidOp = new jsts.operation.valid.IsValidOp(geo); | |
geos.push(geo); | |
try { | |
ea_geo = ( ea_geo ? ea_geo.union(geo) : geo); | |
} catch (ex) { | |
errors.push({ea: ea.eax, id: ea.id, valid: (isValidOp.isValid() ? true: isValidOp.getValidationError()), error: ex, county: cid}); | |
} | |
} | |
}); | |
if (!ea_geo) console.log("not geo for ea: " + ea.id); | |
else { | |
ea.feature = {type: "Feature", id: ea.id, geometry: writer.write(ea_geo)}; | |
top['ea'].features.push(ea.feature); | |
} | |
}); | |
output(top, 1, "output.json"); | |
}); | |
}); | |
function print_errors(errors) { | |
if (errors.length > 0) { | |
console.log("Errors"); | |
console.log("==========="); | |
errors.forEach(function(e) { | |
console.log(" ID: " + e.id); | |
console.log(" Name: " + e.msa); | |
console.log("County: " + e.county); | |
console.log(" Valid: " + e.valid); | |
console.log(" Error: " + e.error); | |
console.log(" GEO: " + JSON.stringify(e.geom)); | |
console.log(" MGEO: " + JSON.stringify(e.msag)); | |
console.log(); | |
}); | |
} | |
} | |
function output(objects, min_area, file) { | |
var options = { | |
"verbose": true, | |
"quantization": 1e4, | |
"coordinate-system": "cartesian", | |
"id": function(d) { return d.id } | |
}; | |
// Convert GeoJSON to TopoJSON. | |
var object = topojson.topology(objects, options); | |
// Simplify. | |
topojson.simplify(object, { | |
"verbose": true, | |
"coordinate-system": options["coordinate-system"], | |
"minimum-area": min_area | |
// "retain-proportion": +argv["simplify-proportion"] | |
}); | |
topojson.clockwise(object, { | |
"verbose": true, | |
"coordinate-system": options["coordinate-system"] | |
}); | |
topojson.filter(object, { | |
"verbose": true, | |
"coordinate-system": options["coordinate-system"] | |
}); | |
// Bind with external properties. | |
// if (argv.e) topojson.bind(object, externalProperties); | |
delete object.bbox; | |
// Output JSON. | |
var json = JSON.stringify(object); | |
fs.writeFileSync(file, json, "utf8"); | |
} | |
// Build same for EA | |
// Create data file that maps country names, containing ea, msa, state |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment