// Generated by CoffeeScript 1.10.0 /* INITIALIZATION */ (function() { var collection, color, data, data_tiles, features, height, legend, legend_items, lod, n_class, order, path_generator, precision_multiplier, redraw_tiles, regions, regions_group, scale, start, svg, tiles_group, topology, viewport, vis, width, zoom, zoomable_layer; start = 0; scale = 300; 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() * 100) }; }); order = Math.ceil(Math.log(d3.sum(data, function(d) { return d.size; })) / Math.log(4)); /* regions DATA */ 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, order); }); 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 } }; /* tiles DATA */ data_tiles = []; data.forEach(function(d) { var j, n, n_4, ref, ref1, tiles; tiles = []; for (n = j = ref = d.start, ref1 = d.end; ref <= ref1 ? j < ref1 : j > ref1; n = ref <= ref1 ? ++j : --j) { n_4 = n.toString(4); tiles.push(Array(order - n_4.length + 1).join('0') + n_4); } tiles = tiles.map(quad_layout(hquad, scale * precision_multiplier)); tiles.forEach(function(t) { return t.name = d.name; }); return data_tiles = data_tiles.concat(tiles); }); /* 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() { zoomable_layer.attr({ transform: "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")" }); return lod(zoom.translate(), 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'); regions_group = vis.append('g'); tiles_group = vis.append('g'); viewport = vis.append('g').attr({ id: 'viewport' }); color = d3.scale.category10(); path_generator = d3.geo.path().projection(null); /* tiles VISUALIZATION */ redraw_tiles = function(x_start, x_end, y_start, y_end) { var tiles; tiles = tiles_group.selectAll('.tile').data(data_tiles.filter(function(d) { return x_start - d.dx <= d.x + d.dx / 2 && x_end + d.dx >= d.x + d.dx / 2 && y_start - d.dy <= d.y + d.dy / 2 && y_end + d.dy >= d.y + d.dy / 2; })); tiles.enter().append('rect').attr({ "class": 'tile' }); tiles.attr({ x: function(d) { return d.x; }, y: function(d) { return d.y; }, width: function(d) { return d.dx; }, height: function(d) { return d.dy; }, fill: function(d) { return color(d.name); } }).append('title').html(function(d) { return d.name + "
" + d.digits; }); return tiles.exit().remove(); }; /* regions VISUALIZATION */ topology = topojson.server.topology(collection, { 'coordinate-system': 'cartesian', quantization: 0, 'property-transform': function(feature) { return feature.properties; } }); regions = regions_group.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); }); /* viewport */ viewport.append('rect').attr({ x: 0, y: 0, width: scale * precision_multiplier, height: scale * precision_multiplier }).style({ fill: 'none', stroke: 'blue', 'stroke-width': 5 }); /* Viewport and Level of details */ lod = function(translation, z) { var dx, dy, x, y; x = (((width - scale) / 2 - translation[0]) / z - (width - scale) / 2) * precision_multiplier; y = (((height - scale) / 2 - translation[1]) / z - (height - scale) / 2) * precision_multiplier; dx = scale * precision_multiplier / z; dy = scale * precision_multiplier / z; d3.select('#viewport rect').attr({ x: x, y: y, width: dx, height: dy }); return redraw_tiles(x, x + dx, y, y + dy); }; lod([0, 0], 1); }).call(this);