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.

Revisions

  1. mbostock revised this gist Jan 24, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    These county, state and country boundaries are extracted from a single [TopoJSON](https://github.com/topojson) file from [us-atlas](https://github.com/topojson/us-atlas).
    These county, state and country boundaries are extracted from a single [TopoJSON](https://github.com/topojson) file from [us-atlas](https://github.com/topojson/us-atlas). See also the [non-fancy variant](/mbostock/4108203).
  2. mbostock revised this gist Jan 24, 2017. 3 changed files with 31 additions and 78 deletions.
    2 changes: 2 additions & 0 deletions .block
    Original file line number Diff line number Diff line change
    @@ -1 +1,3 @@
    license: gpl-3.0
    height: 600
    border: no
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    A demo of [TopoJSON](https://github.com/mbostock/topojson) using a single file that contains county, state and country boundaries. This example uses `topojson.mesh` to extract separating lines between states and counties from the geometry collections.
    These county, state and country boundaries are extracted from a single [TopoJSON](https://github.com/topojson) file from [us-atlas](https://github.com/topojson/us-atlas).
    105 changes: 28 additions & 77 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,97 +1,48 @@
    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>

    path {
    stroke-linejoin: round;
    }

    .land-glow {
    fill-opacity: .2;
    filter: url(#blur);
    }

    .land-fill {
    fill: #fff;
    }

    .state-boundary {
    fill: none;
    stroke: #777;
    stroke-width: .70px;
    }

    .county-boundary {
    fill: none;
    }

    .land-fill,
    .county-boundary {
    stroke: #777;
    stroke-width: .35px;
    }

    </style>
    <body>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="//d3js.org/topojson.v1.min.js"></script>
    <svg width="960" height="600" stroke-linejoin="round" stroke-linecap="round">
    <defs>
    <filter id="blur">
    <feGaussianBlur stdDeviation="5"></feGaussianBlur>
    </filter>
    </defs>
    </svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/topojson.v2.min.js"></script>
    <script>

    var width = 960,
    height = 600;

    var projection = d3.geo.albersUsa()
    .scale(1285)
    .translate([width / 2, height / 2]);

    var path = d3.geo.path()
    .projection(projection);
    var svg = d3.select("svg");

    var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
    var defs = svg.select("defs");

    var defs = svg.append("defs");
    var path = d3.geoPath();

    defs.append("filter")
    .attr("id", "blur")
    .append("feGaussianBlur")
    .attr("stdDeviation", 5);

    d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    d3.json("https://d3js.org/us-10m.v1.json", function(error, us) {
    if (error) throw error;

    defs.append("path")
    .datum(topojson.feature(us, us.objects.land))
    .attr("id", "land")
    .attr("d", path);
    .attr("id", "nation")
    .attr("d", path(topojson.feature(us, us.objects.nation)));

    svg.append("use")
    .attr("class", "land-glow")
    .attr("xlink:href", "#land");
    .attr("xlink:href", "#nation")
    .attr("fill-opacity", 0.2)
    .attr("filter", "url(#blur)");

    svg.append("use")
    .attr("class", "land-fill")
    .attr("xlink:href", "#land");
    .attr("xlink:href", "#nation")
    .attr("fill", "#fff");

    svg.append("path")
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) {
    return a !== b // a border between two counties
    && (a.id === 53000 || b.id === 5300 // where a and b are in puget sound
    || a.id % 1000 && b.id % 1000) // or a and b are not in a lake
    && !(a.id / 1000 ^ b.id / 1000); // and a and b are in the same state
    }))
    .attr("class", "county-boundary")
    .attr("d", path);
    .attr("fill", "none")
    .attr("stroke", "#777")
    .attr("stroke-width", 0.35)
    .attr("d", path(topojson.mesh(us, us.objects.counties, function(a, b) { return (a.id / 1000 | 0) === (b.id / 1000 | 0); })));

    svg.append("path")
    .datum(topojson.mesh(us, us.objects.states, function(a, b) {
    return a !== b; // a border between two states
    }))
    .attr("class", "state-boundary")
    .attr("d", path);
    .attr("fill", "none")
    .attr("stroke", "#777")
    .attr("stroke-width", 0.70)
    .attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));
    });

    d3.select(self.frameElement).style("height", height + "px");

    </script>
  3. mbostock revised this gist Feb 9, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions .block
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    license: gpl-3.0
  4. mbostock revised this gist Oct 31, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -33,8 +33,8 @@

    </style>
    <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script src="//d3js.org/topojson.v1.min.js"></script>
    <script>

    var width = 960,
  5. mbostock revised this gist Jun 11, 2015. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -33,8 +33,8 @@

    </style>
    <body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="http://d3js.org/topojson.v1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
    <script>

    var width = 960,
    @@ -59,6 +59,8 @@
    .attr("stdDeviation", 5);

    d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    if (error) throw error;

    defs.append("path")
    .datum(topojson.feature(us, us.objects.land))
    .attr("id", "land")
  6. mbostock revised this gist Jun 4, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -75,8 +75,8 @@
    svg.append("path")
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) {
    return a !== b // a border between two counties
    && (a.id % 1000) // and a is not in a great lake
    && (b.id % 1000) // and b is not in a great lake
    && (a.id === 53000 || b.id === 5300 // where a and b are in puget sound
    || a.id % 1000 && b.id % 1000) // or a and b are not in a lake
    && !(a.id / 1000 ^ b.id / 1000); // and a and b are in the same state
    }))
    .attr("class", "county-boundary")
  7. mbostock revised this gist Jun 4, 2013. 2 changed files with 45 additions and 84 deletions.
    48 changes: 0 additions & 48 deletions albers-usa.js
    Original file line number Diff line number Diff line change
    @@ -1,48 +0,0 @@
    function albersUsa() {
    var lower48 = d3.geo.albers().rotate([96, 0]).center([0, 38]).parallels([29.5, 45.5]),
    alaska = d3.geo.albers().rotate([160, 0, -35]).center([45, 44]).parallels([55, 65]),
    hawaii = d3.geo.albers().rotate([160, 0]).center([0, 20]).parallels([8, 18]);

    function albersUsa(coordinates) {
    return projection(coordinates)(coordinates);
    }

    function projection(point) {
    var lon = point[0], lat = point[1];
    return lat > 50 ? alaska : lon < -140 ? hawaii : lower48;
    }

    albersUsa.point = function(coordinates, context) {
    return projection(coordinates).point(coordinates, context);
    };

    albersUsa.line = function(coordinates, context) {
    return projection(coordinates[0]).line(coordinates, context);
    };

    albersUsa.polygon = function(coordinates, context) {
    return projection(coordinates[0][0]).polygon(coordinates, context);
    };

    albersUsa.scale = function(x) {
    if (!arguments.length) return lower48.scale();
    lower48.scale(x);
    alaska.scale(x * .35);
    hawaii.scale(x);
    return albersUsa.translate(lower48.translate());
    };

    albersUsa.translate = function(x) {
    var k = lower48.scale();
    if (!arguments.length) {
    x = lower48.translate();
    return [x[0] - .007 * k, x[1] - .007 * k];
    }
    lower48.translate([x[0] + .0075 * k, x[1] + .0065 * k]);
    alaska.translate([x[0] - .307 * k, x[1] + .187 * k]);
    hawaii.translate([x[0] - .206 * k, x[1] + .196 * k]);
    return albersUsa;
    };

    return albersUsa.scale(1056).translate([400, 250]);
    }
    81 changes: 45 additions & 36 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -2,34 +2,29 @@
    <meta charset="utf-8">
    <style>

    body,
    svg {
    height: 100%;
    margin: 0;
    width: 100%;
    float: left;
    }

    path {
    fill: none;
    stroke-linejoin: round;
    }

    .land-glow {
    fill: #000;
    fill-opacity: .2;
    filter: url(#glow);
    filter: url(#blur);
    }

    .land-fill {
    fill: #fff;
    }

    .state-boundary {
    fill: none;
    stroke: #777;
    stroke-width: .70px;
    }

    .county-boundary {
    fill: none;
    }

    .land-fill,
    .county-boundary {
    stroke: #777;
    @@ -40,47 +35,61 @@
    <body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="http://d3js.org/topojson.v1.min.js"></script>
    <script src="albers-usa.js"></script>
    <script>

    var width = 800,
    height = 500;
    var width = 960,
    height = 600;

    var projection = albersUsa();
    var projection = d3.geo.albersUsa()
    .scale(1285)
    .translate([width / 2, height / 2]);

    var path = d3.geo.path()
    .projection(projection);

    var svg = d3.select("body").append("svg")
    .attr("viewBox", "0 0 " + width + " " + height)
    .attr("width", width)
    .attr("height", height);

    svg.append("filter")
    .attr("id", "glow")
    var defs = svg.append("defs");

    defs.append("filter")
    .attr("id", "blur")
    .append("feGaussianBlur")
    .attr("stdDeviation", 5);

    d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    svg.append("path") // translucent outer glow
    defs.append("path")
    .datum(topojson.feature(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-glow");

    svg.append("path") // solid white fill
    .datum(topojson.feature(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-fill");

    svg.append("path") // thin grey stroke for internal county boundaries
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b && !(a.id / 1000 ^ b.id / 1000); }))
    .attr("d", path)
    .attr("class", "county-boundary");

    svg.append("path") // thick grey stroke for internal state boundaries
    .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
    .attr("d", path)
    .attr("class", "state-boundary");
    .attr("id", "land")
    .attr("d", path);

    svg.append("use")
    .attr("class", "land-glow")
    .attr("xlink:href", "#land");

    svg.append("use")
    .attr("class", "land-fill")
    .attr("xlink:href", "#land");

    svg.append("path")
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) {
    return a !== b // a border between two counties
    && (a.id % 1000) // and a is not in a great lake
    && (b.id % 1000) // and b is not in a great lake
    && !(a.id / 1000 ^ b.id / 1000); // and a and b are in the same state
    }))
    .attr("class", "county-boundary")
    .attr("d", path);

    svg.append("path")
    .datum(topojson.mesh(us, us.objects.states, function(a, b) {
    return a !== b; // a border between two states
    }))
    .attr("class", "state-boundary")
    .attr("d", path);
    });

    d3.select(self.frameElement).style("height", height + "px");

    </script>
  8. mbostock revised this gist May 13, 2013. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -39,7 +39,7 @@
    </style>
    <body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="http://d3js.org/topojson.v0.min.js"></script>
    <script src="http://d3js.org/topojson.v1.min.js"></script>
    <script src="albers-usa.js"></script>
    <script>

    @@ -63,12 +63,12 @@

    d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    svg.append("path") // translucent outer glow
    .datum(topojson.object(us, us.objects.land))
    .datum(topojson.feature(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-glow");

    svg.append("path") // solid white fill
    .datum(topojson.object(us, us.objects.land))
    .datum(topojson.feature(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-fill");

  9. mbostock revised this gist Mar 23, 2013. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@

    .land-glow {
    fill: #000;
    fill-opacity: .1;
    fill-opacity: .2;
    filter: url(#glow);
    }

    @@ -26,13 +26,13 @@
    }

    .state-boundary {
    stroke: #ccc;
    stroke: #777;
    stroke-width: .70px;
    }

    .land-fill,
    .county-boundary {
    stroke: #ccc;
    stroke: #777;
    stroke-width: .35px;
    }

    @@ -73,14 +73,14 @@
    .attr("class", "land-fill");

    svg.append("path") // thin grey stroke for internal county boundaries
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a.id !== b.id && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b && !(a.id / 1000 ^ b.id / 1000); }))
    .attr("d", path)
    .attr("class", "county-boundary");

    svg.append("path") // thick grey stroke for internal state boundaries
    .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a.id !== b.id; }))
    .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
    .attr("d", path)
    .attr("class", "state-boundary");
    });

    </script>
    </script>
  10. mbostock revised this gist Feb 18, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -61,7 +61,7 @@
    .append("feGaussianBlur")
    .attr("stdDeviation", 5);

    d3.json("../4090846/us.json", function(error, us) {
    d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    svg.append("path") // translucent outer glow
    .datum(topojson.object(us, us.objects.land))
    .attr("d", path)
  11. mbostock revised this gist Dec 1, 2012. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -61,24 +61,24 @@
    .append("feGaussianBlur")
    .attr("stdDeviation", 5);

    d3.json("../4090846/us.json", function(error, topology) {
    d3.json("../4090846/us.json", function(error, us) {
    svg.append("path") // translucent outer glow
    .datum(topojson.object(topology, topology.objects.land))
    .datum(topojson.object(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-glow");

    svg.append("path") // solid white fill
    .datum(topojson.object(topology, topology.objects.land))
    .datum(topojson.object(us, us.objects.land))
    .attr("d", path)
    .attr("class", "land-fill");

    svg.append("path") // thin grey stroke for internal county boundaries
    .datum(topojson.mesh(topology, topology.objects.counties, function(a, b) { return a.id !== b.id && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
    .datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a.id !== b.id && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
    .attr("d", path)
    .attr("class", "county-boundary");

    svg.append("path") // thick grey stroke for internal state boundaries
    .datum(topojson.mesh(topology, topology.objects.states, function(a, b) { return a.id !== b.id; }))
    .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a.id !== b.id; }))
    .attr("d", path)
    .attr("class", "state-boundary");
    });
  12. mbostock revised this gist Nov 23, 2012. 1 changed file with 0 additions and 0 deletions.
    Binary file modified thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  13. mbostock revised this gist Nov 23, 2012. No changes.
  14. mbostock revised this gist Nov 23, 2012. 2 changed files with 1 addition and 201 deletions.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -39,7 +39,7 @@
    </style>
    <body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="topojson.js"></script>
    <script src="http://d3js.org/topojson.v0.min.js"></script>
    <script src="albers-usa.js"></script>
    <script>

    200 changes: 0 additions & 200 deletions topojson.js
    Original file line number Diff line number Diff line change
    @@ -1,200 +0,0 @@
    topojson = (function() {

    function merge(topology, arcs) {
    var arcsByEnd = {},
    fragmentByStart = {},
    fragmentByEnd = {};

    arcs.forEach(function(i) {
    var e = ends(i);
    (arcsByEnd[e[0]] || (arcsByEnd[e[0]] = [])).push(i);
    (arcsByEnd[e[1]] || (arcsByEnd[e[1]] = [])).push(~i);
    });

    arcs.forEach(function(i) {
    var e = ends(i),
    start = e[0],
    end = e[1],
    f, g;

    if (f = fragmentByEnd[start]) {
    delete fragmentByEnd[f.end];
    f.push(i);
    f.end = end;
    if (g = fragmentByStart[end]) {
    delete fragmentByStart[g.start];
    var fg = f.concat(g);
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
    } else if (g = fragmentByEnd[end]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByStart[end]) {
    delete fragmentByStart[f.start];
    f.unshift(i);
    f.start = start;
    if (g = fragmentByEnd[start]) {
    delete fragmentByEnd[g.end];
    var gf = g.concat(f);
    fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
    } else if (g = fragmentByStart[start]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
    fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByStart[start]) {
    delete fragmentByStart[f.start];
    f.unshift(~i);
    f.start = end;
    if (g = fragmentByEnd[end]) {
    delete fragmentByEnd[g.end];
    var gf = g.concat(f);
    fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
    } else if (g = fragmentByStart[end]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
    fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByEnd[end]) {
    delete fragmentByEnd[f.end];
    f.push(~i);
    f.end = start;
    if (g = fragmentByEnd[start]) {
    delete fragmentByStart[g.start];
    var fg = f.concat(g);
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
    } else if (g = fragmentByStart[start]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else {
    f = [i];
    fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
    }
    });

    function ends(i) {
    var arc = topology.arcs[i], p0 = arc[0], p1 = [0, 0];
    arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
    return [p0, p1];
    }

    var fragments = [];
    for (var k in fragmentByEnd) fragments.push(fragmentByEnd[k]);
    return fragments;
    }

    function mesh(topology, o, filter) {
    var arcs = [];

    if (arguments.length > 1) {
    var geomsByArc = [],
    geom;

    function arc(i) {
    if (i < 0) i = ~i;
    (geomsByArc[i] || (geomsByArc[i] = [])).push(geom);
    }

    function line(arcs) {
    arcs.forEach(arc);
    }

    function polygon(arcs) {
    arcs.forEach(line);
    }

    function geometry(o) {
    geom = o;
    geometryType[o.type](o.arcs);
    }

    var geometryType = {
    LineString: line,
    MultiLineString: polygon,
    Polygon: polygon,
    MultiPolygon: function(arcs) { arcs.forEach(polygon); }
    };

    o.type === "GeometryCollection"
    ? o.geometries.forEach(geometry)
    : geometry(o);

    if (arguments.length < 3) for (var i in geomsByArc) arcs.push([i]);
    else for (var i in geomsByArc) if (filter((geom = geomsByArc[i])[0], geom[geom.length - 1])) arcs.push([i]);
    } else {
    for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push([i]);
    }

    return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)});
    }

    function object(topology, o) {
    var tf = topology.transform,
    kx = tf.scale[0],
    ky = tf.scale[1],
    dx = tf.translate[0],
    dy = tf.translate[1],
    arcs = topology.arcs;

    function arc(i, points) {
    if (points.length) points.pop();
    for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, x = 0, y = 0, p; k < n; ++k) points.push([
    (x += (p = a[k])[0]) * kx + dx,
    (y += p[1]) * ky + dy
    ]);
    if (i < 0) reverse(points, n);
    }

    function line(arcs) {
    var points = [];
    for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
    return points;
    }

    function polygon(arcs) {
    return arcs.map(line);
    }

    function geometry(o) {
    o = Object.create(o);
    o.coordinates = geometryType[o.type](o.arcs);
    return o;
    }

    var geometryType = {
    LineString: line,
    MultiLineString: polygon,
    Polygon: polygon,
    MultiPolygon: function(arcs) { return arcs.map(polygon); }
    };

    return o.type === "GeometryCollection"
    ? (o = Object.create(o), o.geometries = o.geometries.map(geometry), o)
    : geometry(o);
    }

    function reverse(array, n) {
    var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
    }

    return {
    version: "0.0.3",
    mesh: mesh,
    object: object
    };
    })();
  15. mbostock revised this gist Nov 23, 2012. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -30,6 +30,7 @@
    stroke-width: .70px;
    }

    .land-fill,
    .county-boundary {
    stroke: #ccc;
    stroke-width: .35px;
    @@ -76,10 +77,10 @@
    .attr("d", path)
    .attr("class", "county-boundary");

    svg.append("path") // thick grey stroke for state boundaries
    .datum(topojson.mesh(topology, topology.objects.states))
    svg.append("path") // thick grey stroke for internal state boundaries
    .datum(topojson.mesh(topology, topology.objects.states, function(a, b) { return a.id !== b.id; }))
    .attr("d", path)
    .attr("class", "state-boundary");
    });

    </script>
    </script>
  16. mbostock revised this gist Nov 23, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -6,8 +6,8 @@
    svg {
    height: 100%;
    margin: 0;
    padding: 0;
    width: 100%;
    float: left;
    }

    path {
  17. mbostock revised this gist Nov 23, 2012. 2 changed files with 53 additions and 3 deletions.
    48 changes: 48 additions & 0 deletions albers-usa.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    function albersUsa() {
    var lower48 = d3.geo.albers().rotate([96, 0]).center([0, 38]).parallels([29.5, 45.5]),
    alaska = d3.geo.albers().rotate([160, 0, -35]).center([45, 44]).parallels([55, 65]),
    hawaii = d3.geo.albers().rotate([160, 0]).center([0, 20]).parallels([8, 18]);

    function albersUsa(coordinates) {
    return projection(coordinates)(coordinates);
    }

    function projection(point) {
    var lon = point[0], lat = point[1];
    return lat > 50 ? alaska : lon < -140 ? hawaii : lower48;
    }

    albersUsa.point = function(coordinates, context) {
    return projection(coordinates).point(coordinates, context);
    };

    albersUsa.line = function(coordinates, context) {
    return projection(coordinates[0]).line(coordinates, context);
    };

    albersUsa.polygon = function(coordinates, context) {
    return projection(coordinates[0][0]).polygon(coordinates, context);
    };

    albersUsa.scale = function(x) {
    if (!arguments.length) return lower48.scale();
    lower48.scale(x);
    alaska.scale(x * .35);
    hawaii.scale(x);
    return albersUsa.translate(lower48.translate());
    };

    albersUsa.translate = function(x) {
    var k = lower48.scale();
    if (!arguments.length) {
    x = lower48.translate();
    return [x[0] - .007 * k, x[1] - .007 * k];
    }
    lower48.translate([x[0] + .0075 * k, x[1] + .0065 * k]);
    alaska.translate([x[0] - .307 * k, x[1] + .187 * k]);
    hawaii.translate([x[0] - .206 * k, x[1] + .196 * k]);
    return albersUsa;
    };

    return albersUsa.scale(1056).translate([400, 250]);
    }
    8 changes: 5 additions & 3 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -39,14 +39,16 @@
    <body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="topojson.js"></script>
    <script src="albers-usa.js"></script>
    <script>

    var width = 960,
    var width = 800,
    height = 500;

    var color = d3.scale.category20c();
    var projection = albersUsa();

    var path = d3.geo.path();
    var path = d3.geo.path()
    .projection(projection);

    var svg = d3.select("body").append("svg")
    .attr("viewBox", "0 0 " + width + " " + height)
  18. mbostock revised this gist Nov 23, 2012. 2 changed files with 8 additions and 7 deletions.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -70,7 +70,7 @@
    .attr("class", "land-fill");

    svg.append("path") // thin grey stroke for internal county boundaries
    .datum(topojson.mesh(topology, topology.objects.counties, true))
    .datum(topojson.mesh(topology, topology.objects.counties, function(a, b) { return a.id !== b.id && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
    .attr("d", path)
    .attr("class", "county-boundary");

    13 changes: 7 additions & 6 deletions topojson.js
    Original file line number Diff line number Diff line change
    @@ -98,17 +98,16 @@ topojson = (function() {
    return fragments;
    }

    function mesh(topology, o, internalOnly) {
    function mesh(topology, o, filter) {
    var arcs = [];

    if (arguments.length > 1) {
    var countByArc = [];

    if (arguments.length < 3) internalOnly = false;
    var geomsByArc = [],
    geom;

    function arc(i) {
    if (i < 0) i = ~i;
    countByArc[i] = (countByArc[i] || 0) + 1;
    (geomsByArc[i] || (geomsByArc[i] = [])).push(geom);
    }

    function line(arcs) {
    @@ -120,6 +119,7 @@ topojson = (function() {
    }

    function geometry(o) {
    geom = o;
    geometryType[o.type](o.arcs);
    }

    @@ -134,7 +134,8 @@ topojson = (function() {
    ? o.geometries.forEach(geometry)
    : geometry(o);

    for (var i in countByArc) if (countByArc[i] > internalOnly) arcs.push([i]);
    if (arguments.length < 3) for (var i in geomsByArc) arcs.push([i]);
    else for (var i in geomsByArc) if (filter((geom = geomsByArc[i])[0], geom[geom.length - 1])) arcs.push([i]);
    } else {
    for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push([i]);
    }
  19. mbostock revised this gist Nov 23, 2012. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,11 @@
    <meta charset="utf-8">
    <style>

    body,
    svg {
    height: 100%;
    margin: 0;
    padding: 0;
    width: 100%;
    }

  20. mbostock revised this gist Nov 23, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,7 @@
    <style>

    svg {
    height: 100%;
    width: 100%;
    }

  21. mbostock revised this gist Nov 23, 2012. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,10 @@
    <meta charset="utf-8">
    <style>

    svg {
    width: 100%;
    }

    path {
    fill: none;
    stroke-linejoin: round;
    @@ -41,6 +45,7 @@
    var path = d3.geo.path();

    var svg = d3.select("body").append("svg")
    .attr("viewBox", "0 0 " + width + " " + height)
    .attr("width", width)
    .attr("height", height);

  22. mbostock revised this gist Nov 23, 2012. 3 changed files with 241 additions and 79 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    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.
    A demo of [TopoJSON](https://github.com/mbostock/topojson) using a single file that contains county, state and country boundaries. This example uses `topojson.mesh` to extract separating lines between states and counties from the geometry collections.
    100 changes: 43 additions & 57 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -4,16 +4,27 @@

    path {
    fill: none;
    stroke: #000;
    stroke-width: .5px;
    stroke-linejoin: round;
    }

    .country {
    stroke-width: 1px;
    .land-glow {
    fill: #000;
    fill-opacity: .1;
    filter: url(#glow);
    }

    .counties {
    stroke: #aaa;
    .land-fill {
    fill: #fff;
    }

    .state-boundary {
    stroke: #ccc;
    stroke-width: .70px;
    }

    .county-boundary {
    stroke: #ccc;
    stroke-width: .35px;
    }

    </style>
    @@ -25,64 +36,39 @@
    var width = 960,
    height = 500;

    var color = d3.scale.category20c();

    var path = d3.geo.path();

    var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

    svg.append("filter")
    .attr("id", "glow")
    .append("feGaussianBlur")
    .attr("stdDeviation", 5);

    d3.json("../4090846/us.json", function(error, topology) {
    var infoByArc = [];

    topology.objects.counties.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);
    svg.append("path") // translucent outer glow
    .datum(topojson.object(topology, topology.objects.land))
    .attr("d", path)
    .attr("class", "land-glow");

    svg.append("path") // solid white fill
    .datum(topojson.object(topology, topology.objects.land))
    .attr("d", path)
    .attr("class", "land-fill");

    svg.append("path") // thin grey stroke for internal county boundaries
    .datum(topojson.mesh(topology, topology.objects.counties, true))
    .attr("d", path)
    .attr("class", "county-boundary");

    svg.append("path") // thick grey stroke for state boundaries
    .datum(topojson.mesh(topology, topology.objects.states))
    .attr("d", path)
    .attr("class", "state-boundary");
    });

    </script>
    218 changes: 197 additions & 21 deletions topojson.js
    Original file line number Diff line number Diff line change
    @@ -1,23 +1,199 @@
    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];
    });
    })
    topojson = (function() {

    function merge(topology, arcs) {
    var arcsByEnd = {},
    fragmentByStart = {},
    fragmentByEnd = {};

    arcs.forEach(function(i) {
    var e = ends(i);
    (arcsByEnd[e[0]] || (arcsByEnd[e[0]] = [])).push(i);
    (arcsByEnd[e[1]] || (arcsByEnd[e[1]] = [])).push(~i);
    });

    arcs.forEach(function(i) {
    var e = ends(i),
    start = e[0],
    end = e[1],
    f, g;

    if (f = fragmentByEnd[start]) {
    delete fragmentByEnd[f.end];
    f.push(i);
    f.end = end;
    if (g = fragmentByStart[end]) {
    delete fragmentByStart[g.start];
    var fg = f.concat(g);
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
    } else if (g = fragmentByEnd[end]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByStart[end]) {
    delete fragmentByStart[f.start];
    f.unshift(i);
    f.start = start;
    if (g = fragmentByEnd[start]) {
    delete fragmentByEnd[g.end];
    var gf = g.concat(f);
    fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
    } else if (g = fragmentByStart[start]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
    fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByStart[start]) {
    delete fragmentByStart[f.start];
    f.unshift(~i);
    f.start = end;
    if (g = fragmentByEnd[end]) {
    delete fragmentByEnd[g.end];
    var gf = g.concat(f);
    fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
    } else if (g = fragmentByStart[end]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
    fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else if (f = fragmentByEnd[end]) {
    delete fragmentByEnd[f.end];
    f.push(~i);
    f.end = start;
    if (g = fragmentByEnd[start]) {
    delete fragmentByStart[g.start];
    var fg = f.concat(g);
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
    } else if (g = fragmentByStart[start]) {
    delete fragmentByStart[g.start];
    delete fragmentByEnd[g.end];
    var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
    } else {
    fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
    }
    } else {
    f = [i];
    fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
    }
    });

    function ends(i) {
    var arc = topology.arcs[i], p0 = arc[0], p1 = [0, 0];
    arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
    return [p0, p1];
    }

    var fragments = [];
    for (var k in fragmentByEnd) fragments.push(fragmentByEnd[k]);
    return fragments;
    }

    function mesh(topology, o, internalOnly) {
    var arcs = [];

    if (arguments.length > 1) {
    var countByArc = [];

    if (arguments.length < 3) internalOnly = false;

    function arc(i) {
    if (i < 0) i = ~i;
    countByArc[i] = (countByArc[i] || 0) + 1;
    }

    function line(arcs) {
    arcs.forEach(arc);
    }

    function polygon(arcs) {
    arcs.forEach(line);
    }

    function geometry(o) {
    geometryType[o.type](o.arcs);
    }

    var geometryType = {
    LineString: line,
    MultiLineString: polygon,
    Polygon: polygon,
    MultiPolygon: function(arcs) { arcs.forEach(polygon); }
    };

    o.type === "GeometryCollection"
    ? o.geometries.forEach(geometry)
    : geometry(o);

    for (var i in countByArc) if (countByArc[i] > internalOnly) arcs.push([i]);
    } else {
    for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push([i]);
    }

    return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)});
    }

    function object(topology, o) {
    var tf = topology.transform,
    kx = tf.scale[0],
    ky = tf.scale[1],
    dx = tf.translate[0],
    dy = tf.translate[1],
    arcs = topology.arcs;

    function arc(i, points) {
    if (points.length) points.pop();
    for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, x = 0, y = 0, p; k < n; ++k) points.push([
    (x += (p = a[k])[0]) * kx + dx,
    (y += p[1]) * ky + dy
    ]);
    if (i < 0) reverse(points, n);
    }

    function line(arcs) {
    var points = [];
    for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
    return points;
    }

    function polygon(arcs) {
    return arcs.map(line);
    }

    function geometry(o) {
    o = Object.create(o);
    o.coordinates = geometryType[o.type](o.arcs);
    return o;
    }

    var geometryType = {
    LineString: line,
    MultiLineString: polygon,
    Polygon: polygon,
    MultiPolygon: function(arcs) { return arcs.map(polygon); }
    };

    return o.type === "GeometryCollection"
    ? (o = Object.create(o), o.geometries = o.geometries.map(geometry), o)
    : geometry(o);
    }

    function reverse(array, n) {
    var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
    }
    };

    return {
    version: "0.0.3",
    mesh: mesh,
    object: object
    };
    })();
  23. mbostock revised this gist Nov 23, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@
    d3.json("../4090846/us.json", function(error, topology) {
    var infoByArc = [];

    topology.objects[0].geometries.forEach(function(object) {
    topology.objects.counties.geometries.forEach(function(object) {
    object.arcs.forEach(object.type === "MultiPolygon"
    ? function(polygon) { polygon.forEach(function(ring) { ring.forEach(info); }); }
    : function(ring) { ring.forEach(info); });
  24. mbostock revised this gist Nov 23, 2012. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1 @@
    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.
    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.
  25. mbostock revised this gist Nov 23, 2012. 2 changed files with 4 additions and 2 deletions.
    4 changes: 3 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,3 @@
    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.
    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.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -31,7 +31,7 @@
    .attr("width", width)
    .attr("height", height);

    d3.json("../4090846/us-counties.json", function(error, topology) {
    d3.json("../4090846/us.json", function(error, topology) {
    var infoByArc = [];

    topology.objects[0].geometries.forEach(function(object) {
  26. mbostock revised this gist Nov 21, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    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. (Note that there appear to be a few disconnected county boundaries in Alaska and Virginia that should be corrected in the data.)
    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.
  27. mbostock revised this gist Nov 20, 2012. 1 changed file with 0 additions and 0 deletions.
    Binary file modified thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  28. mbostock revised this gist Nov 18, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    These county, state and country boundaries were 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. (Note that there appear to be a few disconnected county boundaries in Alaska and Virginia that should be corrected in the data.)
    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. (Note that there appear to be a few disconnected county boundaries in Alaska and Virginia that should be corrected in the data.)
  29. mbostock revised this gist Nov 18, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    Demonstrates extracting county, state and country boundaries from a single TopoJSON file. In practice, this would be done more commonly by encoding three geometry collections within the TopoJSON file; however, this example shows that you can also derive this information from the topology. (Note that there appear to be a few disconnected county boundaries in Alaska and Virginia that should be corrected in the data.)
    These county, state and country boundaries were 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. (Note that there appear to be a few disconnected county boundaries in Alaska and Virginia that should be corrected in the data.)
  30. mbostock revised this gist Nov 18, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -41,7 +41,7 @@

    function info(arc) {
    if (arc < 0) arc = ~arc;
    var info = infoByArc[arc] || (infoByArc[arc] = {count: 0, features: {}});
    var info = infoByArc[arc] || (infoByArc[arc] = {count: 0, states: {}});
    info.states[Math.floor(object.id / 1000)] = 1;
    ++info.count;
    }