#!/usr/bin/env node var fs = require("fs"); var topology = JSON.parse(fs.readFileSync(process.argv[2])); for (var arcs = [], i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); var mesh = merge(topology, arcs); process.stdout.write("{\"type\":\"Topology\",\"transform\":"); process.stdout.write(JSON.stringify(topology.transform)); process.stdout.write(",\"objects\":{\"mesh\":{\"type\":\"MultiLineString\",\"arcs\":["); if (mesh.length) process.stdout.write("[0]"); for (var i = 1, n = mesh.length; i < n; ++i) process.stdout.write(",[" + i + "]"); process.stdout.write("]}},\"arcs\":["); for (var i = 0, n = mesh.length; i < n; ++i) { process.stdout.write("["); for (var line = mesh[i], j = 0, m = line.length, q = false; j < m; ++j) { var index = line[j], arc = topology.arcs[index < 0 ? ~index : index], l = arc.length; if (index < 0) arc = reverse(arc); for (var k = j ? 1 : 0; k < l; ++k) { if (q) process.stdout.write(","); else q = true; process.stdout.write(JSON.stringify(arc[k])); } } process.stdout.write("]"); if (i < n - 1) process.stdout.write(",\n"); } process.stdout.write("]}\n"); function reverse(arc) { return relative(absolute(arc).reverse()); } function absolute(relative) { var n = relative.length; if (!n) return relative; var absolute = [], i = 0, p = relative[0], x = p[0], y = p[1]; absolute.push(p); while (++i < n) { p = relative[i]; x += p[0]; y += p[1]; absolute.push([x, y]); } return absolute; } function relative(absolute) { var n = absolute.length; if (!n) return absolute; var relative = [], i = 0, p = absolute[0], x = p[0], y = p[1]; relative.push(p); while (++i < n) { p = absolute[i]; relative.push([p[0] - x, p[1] - y]); x = p[0]; y = p[1]; } return relative; } // From topojson.js 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; }