From 1c92b7e892d5dd0bb07858d54d1ff04cd42a4ef1 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 17 Feb 2025 14:03:05 -0600 Subject: [PATCH] scripts: treemap[d3].py: Squared --squarify, added --rectify This adds --rectify for a parent-aspect-ratio-preserving --squarify variant, reverting squarify to try to match the aspect ratio of a square (1:1). I can see arguments for both of these. On one hand --squarify makes the squarest squares, which according to Mark Bruls et al's paper on the topic is easier visually compare. On the other hand --rectify may be more visually pleasing and fit into parent tiles better. d3 allows for any ratio, but at the moment I'm not seeing a strong reason for the extra parameter. --- scripts/treemap.py | 28 ++++++++++++++++++++++++---- scripts/treemapd3.py | 28 ++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/scripts/treemap.py b/scripts/treemap.py index aa4c2af3..05f1162d 100755 --- a/scripts/treemap.py +++ b/scripts/treemap.py @@ -489,7 +489,16 @@ def partition_dice(children, total, x, y, width, height): y_ += t.height -def partition_squarify(children, total, x, y, width, height): +def partition_squarify(children, total, x, y, width, height, *, + aspect_ratio=(1,1)): + if width == 0 or height == 0: + for t in children: + t.x = x + t.y = y + t.width = width + t.height = height + return + # this algorithm is described here: # https://www.win.tue.nl/~vanwijk/stm.pdf i = 0 @@ -498,9 +507,10 @@ def partition_squarify(children, total, x, y, width, height): total_ = total width_ = width height_ = height - # derive target aspect ratio from top-level tile, note we don't - # really care about width vs height until actually slicing - ratio = max(width/height, height/width) + # note we don't really care about width vs height until + # actually slicing + ratio = max(aspect_ratio[0]/aspect_ratio[1], + aspect_ratio[1]/aspect_ratio[0]) while i < len(children): # calculate initial aspect ratio @@ -734,6 +744,10 @@ def main(csv_paths, *, elif args.get('squarify'): partition_squarify(tile.children, tile.value, x__, y__, width__, height__) + elif args.get('rectify'): + partition_squarify(tile.children, tile.value, + x__, y__, width__, height__, + aspect_ratio=(width_, height_)) else: # default to binary partitioning partition_binary(tile.children, tile.value, @@ -912,6 +926,12 @@ if __name__ == "__main__": help="Use the squarify partitioning scheme. This is a greedy " "algorithm created by Mark Bruls et al that tries to " "minimize tile aspect ratios.") + parser.add_argument( + '--rectify', + action='store_true', + help="Use the rectify partitioning scheme. This is like " + "squarify, but tries to match the aspect ratio of the " + "window.") parser.add_argument( '--to-scale', nargs='?', diff --git a/scripts/treemapd3.py b/scripts/treemapd3.py index 7bb2c908..1db1dcf3 100755 --- a/scripts/treemapd3.py +++ b/scripts/treemapd3.py @@ -337,7 +337,16 @@ def partition_dice(children, total, x, y, width, height): y_ += t.height -def partition_squarify(children, total, x, y, width, height): +def partition_squarify(children, total, x, y, width, height, *, + aspect_ratio=(1,1)): + if width == 0 or height == 0: + for t in children: + t.x = x + t.y = y + t.width = width + t.height = height + return + # this algorithm is described here: # https://www.win.tue.nl/~vanwijk/stm.pdf i = 0 @@ -346,9 +355,10 @@ def partition_squarify(children, total, x, y, width, height): total_ = total width_ = width height_ = height - # derive target aspect ratio from top-level tile, note we don't - # really care about width vs height until actually slicing - ratio = max(width/height, height/width) + # note we don't really care about width vs height until + # actually slicing + ratio = max(aspect_ratio[0]/aspect_ratio[1], + aspect_ratio[1]/aspect_ratio[0]) while i < len(children): # calculate initial aspect ratio @@ -574,6 +584,10 @@ def main(csv_paths, output, *, elif args.get('squarify'): partition_squarify(tile.children, tile.value, x__, y__, width__, height__) + elif args.get('rectify'): + partition_squarify(tile.children, tile.value, + x__, y__, width__, height__, + aspect_ratio=(width_, height_)) else: # default to binary partitioning partition_binary(tile.children, tile.value, @@ -790,6 +804,12 @@ if __name__ == "__main__": help="Use the squarify partitioning scheme. This is a greedy " "algorithm created by Mark Bruls et al that tries to " "minimize tile aspect ratios.") + parser.add_argument( + '--rectify', + action='store_true', + help="Use the rectify partitioning scheme. This is like " + "squarify, but tries to match the aspect ratio of the " + "window.") parser.add_argument( '--to-scale', nargs='?',