Skip to content

Instantly share code, notes, and snippets.

@mbostock
Forked from mbostock/.block
Last active September 11, 2018 09:45
Show Gist options
  • Select an option

  • Save mbostock/4136647 to your computer and use it in GitHub Desktop.

Select an option

Save mbostock/4136647 to your computer and use it in GitHub Desktop.
U.S. TopoJSON

These county, state and country boundaries are extracted from a single TopoJSON file. Counties are stroked in thin gray, states in thin black, and the country in thick black.

More commonly, this would be done by encoding three geometry collections within the TopoJSON file; however, this demonstrates that you can derive these boundaries from the topology.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
fill: none;
stroke: #000;
stroke-width: .5px;
}
.country {
stroke-width: 1px;
}
.counties {
stroke: #aaa;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="topojson.js"></script>
<script>
var width = 960,
height = 500;
var path = d3.geo.path();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("../4090846/us.json", function(error, topology) {
var infoByArc = [];
topology.objects[0].geometries.forEach(function(object) {
object.arcs.forEach(object.type === "MultiPolygon"
? function(polygon) { polygon.forEach(function(ring) { ring.forEach(info); }); }
: function(ring) { ring.forEach(info); });
function info(arc) {
if (arc < 0) arc = ~arc;
var info = infoByArc[arc] || (infoByArc[arc] = {count: 0, states: {}});
info.states[Math.floor(object.id / 1000)] = 1;
++info.count;
}
});
var countyBoundaries = Object.create(topology),
stateBoundaries = Object.create(topology),
countryBoundaries = Object.create(topology);
// Intra-state boundaries
countyBoundaries.arcs = topology.arcs.filter(function(arc, i) {
var info = infoByArc[i];
return info.count > 1 && d3.keys(info.states).length === 1;
});
// Inter-state boundaries
stateBoundaries.arcs = topology.arcs.filter(function(arc, i) {
var info = infoByArc[i];
return info.count > 1 && d3.keys(info.states).length > 1;
});
// Exterior boundaries
countryBoundaries.arcs = topology.arcs.filter(function(arc, i) {
var info = infoByArc[i];
return info.count === 1;
});
svg.append("path")
.datum(topojson.mesh(countyBoundaries))
.attr("class", "counties")
.attr("d", path);
svg.append("path")
.datum(topojson.mesh(stateBoundaries))
.attr("class", "states")
.attr("d", path);
svg.append("path")
.datum(topojson.mesh(countryBoundaries))
.attr("class", "country")
.attr("d", path);
});
</script>
var topojson = {
version: "0.0.1",
mesh: function(topology) {
var kx = topology.transform.scale[0],
ky = topology.transform.scale[1],
dx = topology.transform.translate[0],
dy = topology.transform.translate[1];
return {
type: "MultiLineString",
coordinates: topology.arcs.map(function(arc) {
var y0 = 0,
x0 = 0;
return arc.map(function(point) {
var x1 = x0 + point[0],
y1 = y0 + point[1];
x0 = x1;
y0 = y1;
return [x1 * kx + dx, y1 * ky + dy];
});
})
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment