{"url":"https://api.github.com/gists/4134037","forks_url":"https://api.github.com/gists/4134037/forks","commits_url":"https://api.github.com/gists/4134037/commits","id":"4134037","node_id":"MDQ6R2lzdDQxMzQwMzc=","git_pull_url":"https://gist.github.com/4134037.git","git_push_url":"https://gist.github.com/4134037.git","html_url":"https://gist.github.com/mbostock/4134037","files":{"index.js":{"filename":"index.js","type":"text/javascript","language":"JavaScript","raw_url":"https://gist.githubusercontent.com/mbostock/4134037/raw/e2c7fbc83b20748fe968dee14829dea8d41e7211/index.js","size":5631,"truncated":false,"content":"d3.json(\"us-counties.json\", function(error, topology) {\n  if (error) throw error;\n\n  var infoByArc = {},\n      arcsByState = {};\n\n  topology.objects[0].geometries.forEach(function(object) {\n    object.arcs.forEach(object.type === \"MultiPolygon\"\n        ? function(polygon) { polygon.forEach(function(ring) { ring.forEach(info); }); }\n        : function(ring) { ring.forEach(info); });\n\n    function info(arc) {\n      if (arc < 0) arc = ~arc;\n      var info = infoByArc[arc] || (infoByArc[arc] = {count: 0, states: {}});\n      info.states[Math.floor(object.id / 1000)] = 1;\n      ++info.count;\n    }\n  });\n\n  topology.arcs.forEach(function(arc, i) {\n    var info = infoByArc[arc.index = i];\n    if (info.count === d3.keys(info.states).length) {\n      d3.keys(info.states).forEach(function(state) {\n        (arcsByState[state] || (arcsByState[state] = [])).push(arc);\n      });\n    }\n  });\n\n  for (var state in arcsByState) {\n    var arcs = arcsByState[state],\n        arcsByEnd = {},\n        fragmentsByStart = {},\n        fragmentsByEnd = {};\n\n    arcs.forEach(function(arc) {\n      var e = ends(arc);\n      (arcsByEnd[e[0]] || (arcsByEnd[e[0]] = [])).push(arc.index);\n      (arcsByEnd[e[1]] || (arcsByEnd[e[1]] = [])).push(~arc.index);\n    });\n\n    arcs.forEach(function(arc) {\n      var e = ends(arc),\n          start = e[0],\n          end = e[1],\n          f, g;\n\n      if (f = fragmentsByEnd[start]) { // add to end of existing fragment\n        delete fragmentsByStart[f.start];\n        delete fragmentsByEnd[f.end];\n        f.push(arc.index);\n        f.end = end;\n        if (g = fragmentsByStart[end]) { // stitch together existing fragments f:g\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var fg = f.concat(g);\n          fragmentsByStart[fg.start = f.start] = fragmentsByEnd[fg.end = g.end] = fg;\n        } else if (g = fragmentsByEnd[end]) { // stitch together existing fragments f:~g\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var fg = f.concat(g.map(function(i) { return ~i; }).reverse());\n          fragmentsByStart[fg.start = f.start] = fragmentsByEnd[fg.end = g.start] = fg;\n        } else {\n          fragmentsByStart[f.start] = fragmentsByEnd[f.end] = f;\n        }\n      } else if (f = fragmentsByStart[end]) { // add to start of existing fragment\n        delete fragmentsByStart[f.start];\n        delete fragmentsByEnd[f.end];\n        f.unshift(arc.index);\n        f.start = start;\n        if (g = fragmentsByEnd[start]) { // stitch together existing fragments g:f\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var gf = g.concat(f);\n          fragmentsByStart[gf.start = g.start] = fragmentsByEnd[gf.end = f.end] = gf;\n        } else if (g = fragmentsByStart[start]) { // stitch together existing fragments ~g:f\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var gf = g.map(function(i) { return ~i; }).reverse().concat(f);\n          fragmentsByStart[gf.start = g.end] = fragmentsByEnd[gf.end = f.end] = gf;\n        } else {\n          fragmentsByStart[f.start] = fragmentsByEnd[f.end] = f;\n        }\n      } else if (f = fragmentsByStart[start]) { // add reverse to start of existing fragment\n        delete fragmentsByStart[f.start];\n        delete fragmentsByEnd[f.end];\n        f.unshift(~arc.index);\n        f.start = end;\n        if (g = fragmentsByEnd[end]) { // stitch together existing fragments g:f\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var gf = g.concat(f);\n          fragmentsByStart[gf.start = g.start] = fragmentsByEnd[gf.end = f.end] = gf;\n        } else if (g = fragmentsByStart[end]) { // stitch together existing fragments ~g:f\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var gf = g.map(function(i) { return ~i; }).reverse().concat(f);\n          fragmentsByStart[gf.start = g.end] = fragmentsByEnd[gf.end = f.end] = gf;\n        } else {\n          fragmentsByStart[f.start] = fragmentsByEnd[f.end] = f;\n        }\n      } else if (f = fragmentsByEnd[end]) { // add reverse to end of existing fragment\n        delete fragmentsByStart[f.start];\n        delete fragmentsByEnd[f.end];\n        f.push(~arc.index);\n        f.end = start;\n        if (g = fragmentsByEnd[start]) { // stitch together existing fragments f:g\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var fg = f.concat(g);\n          fragmentsByStart[fg.start = f.start] = fragmentsByEnd[fg.end = g.end] = fg;\n        } else if (g = fragmentsByStart[start]) { // stitch together existing fragments f:~g\n          delete fragmentsByStart[g.start];\n          delete fragmentsByEnd[g.end];\n          var fg = f.concat(g.map(function(i) { return ~i; }).reverse());\n          fragmentsByStart[fg.start = f.start] = fragmentsByEnd[fg.end = g.start] = fg;\n        } else {\n          fragmentsByStart[f.start] = fragmentsByEnd[f.end] = f;\n        }\n      } else {\n        f = [arc.index];\n        fragmentsByStart[f.start = start] = fragmentsByEnd[f.end = end] = f;\n      }\n    });\n\n    if (state == 6) {\n      console.log(fragmentsByEnd);\n    }\n\n    arcs.multiPolygon = d3.values(fragmentsByEnd).map(function(arcs) { return [arcs]; });\n    arcs.multiLineString = arcs.map(function(arc) { return [arc.index]; });\n  }\n\n  function ends(arc) {\n    var p0 = arc[0], p1 = [0, 0];\n    arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });\n    return [p0, p1];\n  }\n\n  console.log(arcsByState);\n});\n","encoding":"utf-8"}},"public":true,"created_at":"2012-11-23T04:43:47Z","updated_at":"2015-10-13T03:47:52Z","description":"Stitching States from Counties","comments":0,"user":null,"comments_enabled":true,"comments_url":"https://api.github.com/gists/4134037/comments","owner":{"login":"mbostock","id":230541,"node_id":"MDQ6VXNlcjIzMDU0MQ==","avatar_url":"https://avatars.githubusercontent.com/u/230541?v=4","gravatar_id":"","url":"https://api.github.com/users/mbostock","html_url":"https://github.com/mbostock","followers_url":"https://api.github.com/users/mbostock/followers","following_url":"https://api.github.com/users/mbostock/following{/other_user}","gists_url":"https://api.github.com/users/mbostock/gists{/gist_id}","starred_url":"https://api.github.com/users/mbostock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbostock/subscriptions","organizations_url":"https://api.github.com/users/mbostock/orgs","repos_url":"https://api.github.com/users/mbostock/repos","events_url":"https://api.github.com/users/mbostock/events{/privacy}","received_events_url":"https://api.github.com/users/mbostock/received_events","type":"User","user_view_type":"public","site_admin":false},"forks":[],"history":[{"user":{"login":"mbostock","id":230541,"node_id":"MDQ6VXNlcjIzMDU0MQ==","avatar_url":"https://avatars.githubusercontent.com/u/230541?v=4","gravatar_id":"","url":"https://api.github.com/users/mbostock","html_url":"https://github.com/mbostock","followers_url":"https://api.github.com/users/mbostock/followers","following_url":"https://api.github.com/users/mbostock/following{/other_user}","gists_url":"https://api.github.com/users/mbostock/gists{/gist_id}","starred_url":"https://api.github.com/users/mbostock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbostock/subscriptions","organizations_url":"https://api.github.com/users/mbostock/orgs","repos_url":"https://api.github.com/users/mbostock/repos","events_url":"https://api.github.com/users/mbostock/events{/privacy}","received_events_url":"https://api.github.com/users/mbostock/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"7b1cd6a0b8721b605feced546f28534a59e6840b","committed_at":"2015-06-11T19:31:04Z","change_status":{"total":2,"additions":2,"deletions":0},"url":"https://api.github.com/gists/4134037/7b1cd6a0b8721b605feced546f28534a59e6840b"},{"user":{"login":"mbostock","id":230541,"node_id":"MDQ6VXNlcjIzMDU0MQ==","avatar_url":"https://avatars.githubusercontent.com/u/230541?v=4","gravatar_id":"","url":"https://api.github.com/users/mbostock","html_url":"https://github.com/mbostock","followers_url":"https://api.github.com/users/mbostock/followers","following_url":"https://api.github.com/users/mbostock/following{/other_user}","gists_url":"https://api.github.com/users/mbostock/gists{/gist_id}","starred_url":"https://api.github.com/users/mbostock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbostock/subscriptions","organizations_url":"https://api.github.com/users/mbostock/orgs","repos_url":"https://api.github.com/users/mbostock/repos","events_url":"https://api.github.com/users/mbostock/events{/privacy}","received_events_url":"https://api.github.com/users/mbostock/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"f93e844b7198612dd6bf878a4fadd1b0f892efca","committed_at":"2012-11-23T04:43:47Z","change_status":{"total":138,"additions":138,"deletions":0},"url":"https://api.github.com/gists/4134037/f93e844b7198612dd6bf878a4fadd1b0f892efca"}],"truncated":false}