A map of US railroads and Amtrak stations. Data from the National Atlas. Based on Mike Bostock's Swiss Cantons example and the U.S. Atlas project.
Last active
August 29, 2015 13:58
-
-
Save madelfio/10343474 to your computer and use it in GitHub Desktop.
U.S. Rail
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
build/ |
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 fs = require("fs"); | |
var idProperty = process.argv[2], | |
collection = JSON.parse(fs.readFileSync("/dev/stdin")), | |
featureIds = {}; | |
collection.features = collection.features.filter(function(feature) { | |
var id = feature.properties[idProperty]; | |
if (id == null) throw new Error("id is required for geouniq"); | |
if (!(id in featureIds)) { | |
featureIds[id] = 1; | |
return true; | |
} | |
}); | |
console.log(JSON.stringify(collection)); |
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
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.background { | |
fill: none; | |
pointer-events: all; | |
} | |
.boundary { | |
fill: none; | |
stroke: #fff; | |
stroke-linejoin: round; | |
stroke-linecap: round; | |
} | |
.feature--state { | |
fill: #bbb; | |
} | |
.feature--station { | |
fill: steelblue; | |
fill-opacity: .8; | |
} | |
.feature--railroad { | |
fill: none; | |
fill-opacity: .8; | |
stroke: #d77; | |
} | |
.feature--state :hover, | |
.feature--station :hover { | |
fill: #eba; | |
} | |
.feature--state .active { | |
fill: orange; | |
} | |
.feature--railroad { | |
pointer-events: none; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/topojson.v1.min.js"></script> | |
<script src="./railroads.js"></script> |
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
.PHONY: all clean | |
GENERATED_FILES = \ | |
railroads.json | |
all: railroads.json | |
clean: | |
rm -rf -- $(GENERATED_FILES) build | |
build/%.tar.gz: | |
mkdir -p $(dir $@) | |
curl 'http://dds.cr.usgs.gov/pub/data/nationalatlas/$(notdir $@)' -o $@.build | |
mv $@.build $@ | |
build/%.shp: | |
rm -rf $(basename $@) | |
mkdir -p $(basename $@) | |
tar -xzm -C $(basename $@) -f $< | |
for file in $(basename $@)/*; do chmod 644 $$file; mv $$file $(basename $@).$${file##*.}; done | |
rmdir $(basename $@) | |
build/states-unfiltered.shp: build/statep010_nt00798.tar.gz | |
build/stations-unfiltered.shp: build/amtrakx010g.shp_nt00823.tar.gz | |
build/railroads.shp: build/railrdl010_nt00800.tar.gz | |
# remove duplicate states for water (e.g., Great Lakes) | |
build/states.shp: build/states-unfiltered.shp ./geouniq | |
@rm -f -- $@ $(basename $@)-unfiltered.json | |
ogr2ogr -f 'GeoJSON' $(basename $@)-unfiltered.json $< | |
./geouniq STATE_FIPS < $(basename $@)-unfiltered.json > $(basename $@).json | |
ogr2ogr -f 'ESRI Shapefile' $@ $(basename $@).json | |
rm -f -- $(basename $@).json $(basename $@).json | |
build/stations.shp: build/stations-unfiltered.shp | |
rm -f $@ | |
ogr2ogr -f 'ESRI Shapefile' -where "STNTYPE = 'RAIL'" $@ $< | |
build/states.json: build/states.shp | |
topojson \ | |
-o $@ \ | |
--id-property=FIPS,STATE_FIPS \ | |
-p name=STATE \ | |
--no-quantization \ | |
-- states=$< | |
build/stations.json: build/stations.shp | |
topojson \ | |
-o $@ \ | |
--no-quantization \ | |
-- stations=$< | |
build/railroads.json: build/railroads.shp | |
topojson \ | |
-o $@ \ | |
--no-quantization \ | |
-- railroads=$< | |
build/%.json: build/%-unmerged.json | |
topojson-merge \ | |
-o $@ \ | |
--in-object=$* \ | |
--out-object=$* \ | |
-- $< | |
railroads.json: build/states.json build/stations.json build/railroads.json | |
topojson \ | |
-o $@ \ | |
--projection 'd3.geo.albersUsa()' \ | |
--width=1920 \ | |
--height=1000 \ | |
--margin=20 \ | |
--simplify=.5 \ | |
-- $^ |
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
"use strict"; | |
var width = 960, | |
height = 500, | |
active = d3.select(null); | |
var zoom = d3.behavior.zoom() | |
.translate([0, 0]) | |
.scale(1) | |
.scaleExtent([.5, 8]) | |
.on("zoom", zoomed); | |
var path = d3.geo.path() | |
.pointRadius(3) | |
.projection(null); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.on("click", stopped, true); | |
svg.append("rect") | |
.attr("class", "background") | |
.attr("width", width) | |
.attr("height", height) | |
.on("click", reset); | |
var g = svg.append("g"); | |
svg.call(zoom) | |
.call(zoom.event); | |
d3.json("railroads.json", function(error, rr) { | |
window.rr = rr; | |
g.append("g") | |
.attr("class", "feature feature--state") | |
.selectAll("path") | |
.data(topojson.feature(rr, rr.objects.states).features) | |
.enter().append("path") | |
.attr("d", path) | |
.on("click", clicked); | |
g.append("path") | |
.datum(topojson.mesh(rr, rr.objects.states, function(a, b) { return a !== b; })) | |
.attr("class", "boundary boundary--states") | |
.attr("d", path); | |
g.append("g") | |
.attr("class", "feature feature--railroad") | |
.selectAll("path") | |
.data(topojson.feature(rr, rr.objects.railroads).features) | |
.enter().append("path") | |
.attr("d", path); | |
g.append("g") | |
.attr("class", "feature feature--station") | |
.selectAll("path") | |
.data(topojson.feature(rr, rr.objects.stations).features) | |
.enter().append("path") | |
.attr("d", path) | |
.on("click", clicked); | |
svg.call(zoom.scale(0.5).event); | |
}); | |
function clicked(d) { | |
if (active.node() === this) return reset(); | |
active.classed("active", false); | |
active = d3.select(this).classed("active", true); | |
var bounds = path.bounds(d), | |
dx = bounds[1][0] - bounds[0][0], | |
dy = bounds[1][1] - bounds[0][1], | |
x = (bounds[0][0] + bounds[1][0]) / 2, | |
y = (bounds[0][1] + bounds[1][1]) / 2, | |
scale = Math.min(.9 / Math.max(dx / width, dy / height), zoom.scaleExtent()[1]), | |
translate = [width / 2 - scale * x, height / 2 - scale * y]; | |
svg.transition() | |
.duration(750) | |
.call(zoom.translate(translate).scale(scale).event); | |
} | |
function reset() { | |
active.classed("active", false); | |
active = d3.select(null); | |
svg.transition() | |
.duration(750) | |
.call(zoom.translate([0, 0]).scale(.5).event); | |
} | |
function zoomed() { | |
g.style("stroke-width", 1.0 / d3.event.scale + "px"); | |
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); | |
path.pointRadius(5 / (d3.event.scale + .45)); | |
g.selectAll("g.feature--station path").attr("d", path); | |
g.selectAll("g.boundary--states").style("stroke-width", .8 / d3.event.scale + "px"); | |
} | |
function stopped() { | |
if (d3.event.defaultPrevented) d3.event.stopPropagation(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment