ツリーマップの描画
それでは,
まず始めに,
リスト1 TreeMapRenderer.
public interface TreeMapRenderer {
void render(Graphics2D g, Node node, Rectangle2D bounds);
}
そして,
- ノードが末端なら,
領域を確定し, 内部を塗りつぶす。 - ノードが末端でなければ,
領域を分割し, 子ノードを再帰的に処理する。 - 子ノードの処理が終了後,
親ノードの輪郭を描画する。
上記の方針に対応する実際の部分コードを,
末端ノードの塗りつぶし
以下は,
リスト2 BinaryTreeMapRenderer.
if (node instanceof ColorItem) {
g.setPaint(((ColorItem) node).getColor());
g.fill(bounds);
}
ノード領域の分割
以下は,
リスト3 BinaryTreeMapRenderer.
} else if (node instanceof Cluster) {
Cluster cluster = (Cluster) node;
// 子ノードchild1とchild2を取得
Node child1 = cluster.getLeft();
Node child2 = cluster.getRight();
// 子ノードの面積比を計算 (A)
double area1 = child1.getArea();
double area2 = child2.getArea();
double ratio1 = area1 / (area1 + area2);
double ratio2 = area2 / (area1 + area2);
double x = bounds.getX();
double y = bounds.getY();
double w = bounds.getWidth();
double h = bounds.getHeight();
Rectangle2D rect1;
Rectangle2D rect2;
// 領域分割を実行 (B)
if (w > h) {
// boundsが横長の場合,左右に分割
rect1 = new Rectangle2D.Double(x, y, ratio1 * w, h);
rect2 = new Rectangle2D.Double(x + ratio1 * w, y, ratio2 * w, h);
} else {
// boundsが縦長の場合,上下に分割
rect1 = new Rectangle2D.Double(x, y, w, ratio1 * h);
rect2 = new Rectangle2D.Double(x, y + ratio1 * h, w, ratio2 * h);
}
// 子ノードを再帰的に処理 (C)
doRender(g, child1, rect1, depth + 1);
doRender(g, child2, rect2, depth + 1);
}
始めに,
ノードの輪郭の描画
ノードの塗りつぶしと,
以下が,
リスト4 BinaryTreeMapRenderer.
float borderWidth = Math.max(8f - depth, 1f);
g.setStroke(new BasicStroke(borderWidth));
g.setPaint(Color.BLACK);
g.draw(bounds);