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 = g === f ? f : 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 === f ? f : 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 === f ? f : 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 = g === f ? f : 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 }; })();