(function() { window.jigsaw = { hex_generate_svg_path: function(scale) { var a, r; a = scale / 2; r = a / Math.sin(Math.PI / 3); return "M" + r + " 0 L" + (r / 2) + " " + a + " L" + (-r / 2) + " " + a + " L" + (-r) + " 0 L" + (-r / 2) + " " + (-a) + " L" + (r / 2) + " " + (-a) + " Z"; }, square_generate_svg_path: function(scale) { var a; a = scale / 2; return "M" + (-a) + " " + (-a) + " L" + (-a) + " " + a + " L" + a + " " + a + " L" + a + " " + (-a) + " Z"; }, iso_generate_svg_path: function(scale) { var rx, ry; rx = scale * Math.sqrt(2) / 2; ry = scale * Math.sqrt(2) / (2 * Math.sqrt(3)); return "M" + 0 + " " + (-ry) + " L" + rx + " " + 0 + " L" + 0 + " " + ry + " L" + (-rx) + " " + 0 + " Z"; }, HEX_CELL: function(node, scale) { var a, r, region; a = scale / 2; r = a / Math.sin(Math.PI / 3); region = [ [ { X: node.x + r, Y: node.y }, { X: node.x + r / 2, Y: node.y + a }, { X: node.x - r / 2, Y: node.y + a }, { X: node.x - r, Y: node.y }, { X: node.x - r / 2, Y: node.y - a }, { X: node.x + r / 2, Y: node.y - a } ] ]; return region; }, SQUARE_CELL: function(node, scale) { var a, region; a = scale / 2; region = [ [ { X: node.x - a, Y: node.y - a }, { X: node.x - a, Y: node.y + a }, { X: node.x + a, Y: node.y + a }, { X: node.x + a, Y: node.y - a } ] ]; return region; }, ISO_CELL: function(node, scale) { var region, rx, ry; rx = scale * Math.sqrt(2) / 2; ry = scale * Math.sqrt(2) / (2 * Math.sqrt(3)); return region = [ [ { X: node.x, Y: node.y - ry }, { X: node.x + rx, Y: node.y }, { X: node.x, Y: node.y + ry }, { X: node.x - rx, Y: node.y } ] ]; }, treemap: function(node, scale, base) { var child, children_paths, cpr, upscale; if (!(node.children != null)) { node.region = base(node, scale); return node.region; } children_paths = ((function() { var _i, _len, _ref, _results; _ref = node.children; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; _results.push(jigsaw.treemap(child, scale, base)); } return _results; })()).reduce(function(a, d) { return a.concat(d); }); upscale = 1000; ClipperLib.JS.ScaleUpPaths(children_paths, upscale); cpr = new ClipperLib.Clipper(); cpr.AddPaths(children_paths, ClipperLib.PolyType.ptSubject, true); node.region = new ClipperLib.Paths(); cpr.Execute(ClipperLib.ClipType.ctUnion, node.region, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero); ClipperLib.JS.ScaleDownPaths(children_paths, upscale); ClipperLib.JS.ScaleDownPaths(node.region, upscale); return node.region; }, /* Converts Paths to SVG path string */ /* and scales down the coordinates */ /* from http://jsclipper.sourceforge.net/6.1.3.1/index.html?p=starter_boolean.html */ get_svg_path: function(paths, scale) { var i, p, path, svgpath, _i, _len, _len2; svgpath = ''; if (!(scale != null)) scale = 1; for (_i = 0, _len = paths.length; _i < _len; _i++) { path = paths[_i]; for (i = 0, _len2 = path.length; i < _len2; i++) { p = path[i]; if (i === 0) { svgpath += 'M'; } else { svgpath += 'L'; } svgpath += p.X / scale + ", " + p.Y / scale; } svgpath += 'Z'; } if (svgpath === '') svgpath = 'M0,0'; return svgpath; }, hilbert_labels: function(node, scale) { /* create a sort of bitmap of this node's cells */ var box, boxes, cell, child, grow, ix, ixg, iy, iyg, last_box, matrix, max_area, max_ix, max_iy, max_x, max_y, min_ix, min_iy, min_x, min_y, original_area, x_boxes, y_boxes, _i, _j, _k, _l, _len, _len2, _len3, _len4, _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _results; matrix = {}; _ref = node.leaf_descendants; for (_i = 0, _len = _ref.length; _i < _len; _i++) { cell = _ref[_i]; if (!(cell.ix in matrix)) matrix[cell.ix] = {}; matrix[cell.ix][cell.iy] = cell; } /* compute the matrix boundaries */ min_ix = d3.min(node.leaf_descendants, function(d) { return d.ix; }); max_ix = d3.max(node.leaf_descendants, function(d) { return d.ix; }); min_iy = d3.min(node.leaf_descendants, function(d) { return d.iy; }); max_iy = d3.max(node.leaf_descendants, function(d) { return d.iy; }); /* scan X to create tall boxes */ x_boxes = []; for (ix = min_ix; min_ix <= max_ix ? ix <= max_ix : ix >= max_ix; min_ix <= max_ix ? ix++ : ix--) { x_boxes.push({}); for (iy = min_iy; min_iy <= max_iy ? iy <= max_iy : iy >= max_iy; min_iy <= max_iy ? iy++ : iy--) { last_box = x_boxes[x_boxes.length - 1]; if (ix in matrix && iy in matrix[ix]) { if (!('topleft' in last_box)) { last_box.bottomright = last_box.topleft = matrix[ix][iy]; last_box.area = 1; } else { last_box.bottomright = matrix[ix][iy]; last_box.area += 1; } } else if ('topleft' in last_box) { x_boxes.push({}); } } } /* scan Y to create wide boxes */ y_boxes = []; for (iy = min_iy; min_iy <= max_iy ? iy <= max_iy : iy >= max_iy; min_iy <= max_iy ? iy++ : iy--) { y_boxes.push({}); for (ix = min_ix; min_ix <= max_ix ? ix <= max_ix : ix >= max_ix; min_ix <= max_ix ? ix++ : ix--) { last_box = y_boxes[y_boxes.length - 1]; if (ix in matrix && iy in matrix[ix]) { if (!('topleft' in last_box)) { last_box.topleft = matrix[ix][iy]; last_box.bottomright = matrix[ix][iy]; last_box.area = 1; } else { last_box.bottomright = matrix[ix][iy]; last_box.area += 1; } } else if ('topleft' in last_box) { y_boxes.push({}); } } } /* grow boxes along X */ for (_j = 0, _len2 = x_boxes.length; _j < _len2; _j++) { box = x_boxes[_j]; if (!(box.topleft != null)) continue; grow = true; original_area = box.area; while (grow) { ixg = box.bottomright.ix + 1; for (iyg = _ref2 = box.topleft.iy, _ref3 = box.bottomright.iy; _ref2 <= _ref3 ? iyg <= _ref3 : iyg >= _ref3; _ref2 <= _ref3 ? iyg++ : iyg--) { grow = ixg in matrix && iyg in matrix[ixg]; if (!grow) break; } if (grow) { box.bottomright = matrix[ixg][box.bottomright.iy]; box.area += original_area; } } } /* grow boxes along Y */ for (_k = 0, _len3 = y_boxes.length; _k < _len3; _k++) { box = y_boxes[_k]; if (!(box.topleft != null)) continue; grow = true; original_area = box.area; while (grow) { iyg = box.bottomright.iy + 1; for (ixg = _ref4 = box.topleft.ix, _ref5 = box.bottomright.ix; _ref4 <= _ref5 ? ixg <= _ref5 : ixg >= _ref5; _ref4 <= _ref5 ? ixg++ : ixg--) { grow = ixg in matrix && iyg in matrix[ixg]; if (!grow) break; } if (grow) { box.bottomright = matrix[box.bottomright.ix][iyg]; box.area += original_area; } } } /* select the biggest box */ boxes = x_boxes.concat(y_boxes); max_area = d3.max(boxes, function(b) { return b.area; }); box = boxes.filter(function(d) { return d.area === max_area; })[0]; /* convert into x,y coordinates */ min_x = box.topleft.x - scale / 2; max_x = box.bottomright.x + scale / 2; min_y = box.topleft.y - scale / 2; max_y = box.bottomright.y + scale / 2; node.label_bbox = { x: min_x, y: min_y, width: max_x - min_x, height: max_y - min_y }; if (node.children != null) { _ref6 = node.children; _results = []; for (_l = 0, _len4 = _ref6.length; _l < _len4; _l++) { child = _ref6[_l]; _results.push(jigsaw.hilbert_labels(child, scale)); } return _results; } } }; }).call(this);