// Generated by CoffeeScript 1.10.0 (function() { var collection, color, data, features, get_quad_code, get_quads, get_z, height, legend, legend_items, n_class, order, path_generator, precision_multiplier, regions, replace_char, scale, start, svg, topology, vis, width, zoom, zoomable_layer; replace_char = function(s, index, new_char) { return s.substr(0, index) + new_char + s.substr(index + 1); }; get_quad_code = function(offset, N, n) { var b4; b4 = offset.toString(4); b4 = Array(N - b4.length + 1).join('0') + b4; b4 = b4.slice(0, N - n); return b4; }; get_quads = function(cls) { var d, digits, i, j, k, l, len, len1, m, o, offset, quad, quads, ref, ref1, start_to_z, z_to_end; quads = []; if (cls.start !== cls.z) { offset = cls.start; start_to_z = (cls.z - cls.start).toString(4).split('').reverse().join(''); for (i = k = 0, len = start_to_z.length; k < len; i = ++k) { d = start_to_z[i]; for (j = l = 0, ref = parseInt(d); 0 <= ref ? l < ref : l > ref; j = 0 <= ref ? ++l : --l) { digits = start_to_z.length - (start_to_z.length - i); quad = get_quad_code(offset, order, digits); quads.push(quad); offset += parseInt('1' + Array(digits + 1).join('0'), 4); } } } offset = cls.z; z_to_end = (cls.end - cls.z).toString(4); for (i = m = 0, len1 = z_to_end.length; m < len1; i = ++m) { d = z_to_end[i]; for (j = o = 0, ref1 = parseInt(d); 0 <= ref1 ? o < ref1 : o > ref1; j = 0 <= ref1 ? ++o : --o) { digits = z_to_end.length - i - 1; quad = get_quad_code(offset, order, digits); quads.push(quad); offset += parseInt('1' + Array(z_to_end.length - i).join('0'), 4); } } return quads; }; get_z = function(d) { var end_4, i, initial_i, new_start_4, start_4; start_4 = d.start.toString(4); end_4 = d.end.toString(4); if (start_4 === '0') { return parseInt(start_4, 4); } i = start_4.length - 1; initial_i = start_4.length - 1; while (start_4.length <= end_4.length) { new_start_4 = replace_char(start_4, i, '0'); new_start_4 = (parseInt('1' + Array(new_start_4.length - i + 1).join('0'), 4) + parseInt(new_start_4, 4)).toString(4); if (parseInt(new_start_4, 4) < d.end) { start_4 = new_start_4; } else { break; } if (initial_i === start_4.length) { i -= 1; } else { initial_i += 1; } } return parseInt(start_4, 4); }; /* Initialization */ start = 0; scale = 480; precision_multiplier = 10000; n_class = Array(Math.ceil(Math.random() * 10)).fill(); data = n_class.map(function(d, i) { return { name: "class" + (i + 1), size: Math.ceil(Math.random() * 10000000000) }; }); order = Math.ceil(Math.log(d3.sum(data, function(d) { return d.size; })) / Math.log(4)); data.forEach(function(cls) { cls.start = start; cls.end = start + cls.size; start += cls.size; cls.z = get_z(cls); return cls.quads = get_quads(cls); }); data.forEach(function(d) { var quads; quads = d.quads.map(quad_layout(hquad, scale * precision_multiplier)); quads.forEach(function(i) { return i.name = d.name; }); return d._quads = quads; }); features = []; data.forEach(function(d) { var cpr, merge, squares, succeeded; cpr = new ClipperLib.Clipper(); squares = new ClipperLib.Paths(); merge = new ClipperLib.Paths(); squares = d._quads.map(function(q) { return [ { X: q.x, Y: q.y }, { X: q.x + q.dx, Y: q.y }, { X: q.x + q.dx, Y: q.y + q.dy }, { X: q.x, Y: q.y + q.dy } ]; }); cpr.AddPaths(squares, ClipperLib.PolyType.ptSubject, true); succeeded = cpr.Execute(ClipperLib.ClipType.ctUnion, merge); return features.push({ type: "Feature", geometry: { type: "Polygon", coordinates: [ (merge[0].map(function(q) { return [q.X, q.Y]; })).concat([[merge[0][0].X, merge[0][0].Y]]) ] }, properties: { "class": d.name } }); }); collection = { collection: { type: "FeatureCollection", features: features } }; /* Visualization */ svg = d3.select('svg'); width = svg.node().getBoundingClientRect().width; height = svg.node().getBoundingClientRect().height; svg.attr({ width: width, height: height }); zoomable_layer = svg.append('g'); zoom = d3.behavior.zoom().scaleExtent([-Infinity, Infinity]).on('zoom', function() { return zoomable_layer.attr({ transform: "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")" }); }); svg.call(zoom); vis = zoomable_layer.append('g').attr({ transform: "translate(" + ((width - scale) / 2) + ", " + ((height - scale) / 2) + ") scale(" + (1 / precision_multiplier) + ")" }); legend = svg.append('g'); color = d3.scale.category10(); path_generator = d3.geo.path().projection(null); topology = topojson.server.topology(collection, { 'coordinate-system': 'cartesian', quantization: 0, 'property-transform': function(feature) { return feature.properties; } }); regions = vis.selectAll('.region').data(data.map(function(d) { return d.name; })); regions.enter().append('path').attr({ "class": 'region', d: function(d) { return path_generator(topojson.client.merge(topology, topology.objects.collection.geometries.filter(function(g) { return g.properties["class"] === d; }))); }, fill: function(d) { return color(d); } }); legend_items = legend.selectAll('.legend_item').data(data); legend_items.enter().append('g').attr({ "class": 'legend_item' }); legend_items.append('rect').attr({ x: 10, y: function(d, i) { return 10 + i * 15; }, width: function(d) { return 10; }, height: function(d) { return 10; }, fill: function(d) { return color(d.name); } }); legend_items.append('text').attr({ x: 30, y: function(d, i) { return 15 + i * 15; }, dy: '0.35em' }).text(function(d) { return d3.format(',d')(d.size); }); }).call(this);