---
category: swing
folder: FlatTreeNodeRoundedCornerSelection
title: JTreeのノード選択で生成された直角多角形の角を丸める
tags: [JTree, Path2D, Graphics]
author: aterai
pubdate: 2024-04-29T04:35:48+09:00
description: JTreeのノード選択で生成された直角多角形の角を尖点などが発生しないよう平坦化してから丸めます。
image: https://drive.google.com/uc?id=112_GkswNjQvzb1PwmPixbn2o2kw3VLgW
hreflang:
    href: https://java-swing-tips.blogspot.com/2024/05/rounding-corners-of-rectilinear-polygon.html
    lang: en
---
* 概要 [#summary]
`JTree`のノード選択で生成された直角多角形の角を尖点などが発生しないよう平坦化してから丸めます。

#download(https://drive.google.com/uc?id=112_GkswNjQvzb1PwmPixbn2o2kw3VLgW)

* サンプルコード [#sourcecode]
#code(link){{
public static List<Point2D> flatteningStepsOnRightSide(
    List<Point2D> list, double arc) {
  int sz = list.size();
  for (int i = 0; i < sz; i++) {
    int i1 = (i + 1) % sz;
    int i2 = (i + 2) % sz;
    int i3 = (i + 3) % sz;
    Point2D pt0 = list.get(i);
    Point2D pt1 = list.get(i1);
    Point2D pt2 = list.get(i2);
    Point2D pt3 = list.get(i3);
    double dx1 = pt2.getX() - pt1.getX();
    if (Math.abs(dx1) > 1.0e-1 && Math.abs(dx1) < arc) {
      double max = Math.max(pt0.getX(), pt2.getX());
      replace(list, i, max, pt0.getY());
      replace(list, i1, max, pt1.getY());
      replace(list, i2, max, pt2.getY());
      replace(list, i3, max, pt3.getY());
    }
  }
  return list;
}

private static void replace(List<Point2D> list, int i, double x, double y) {
  list.remove(i);
  list.add(i, new Point2D.Double(x, y));
}
}}

* 解説 [#explanation]
- 左: デフォルトの`JTree`
-- `TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION`でノードを複数範囲選択可能に設定
- 中: ノード選択で生成された直角多角形の角を丸める
-- [[JListで作成したカレンダーのセル選択領域を角丸で描画する>Swing/RoundedSelectionListCalendar]]と同様の方法でノード選択の直角多角形の角を丸める
-- たとえば`soccer`、`football`、`hockey`ノードを選択したときそのノード選択領域の直角多角形は右側に丸めのラウンド直径より幅が短い辺が生成されて、これを丸めるとスクリーンショットのように尖点やなめらかでない段差が発生してしまう
- 右: ノード選択で生成された直角多角形のラウンド直径より短い辺を平坦化してから角を丸める
-- `JTree`のノード選択から生成される直角多角形の場合、尖点になるような角は右側にのみ発生する可能性がある
--- このサンプルの`JTree`では`Tree.leftChildIndent`と`Tree.rightChildIndent`の合計が丸めのラウンド直径より大きくなるので左側ではラウンド直径より短い辺は生成されない
-- 右側で丸めのラウンド直径より幅が短い辺を発見したら、その前後の角の座標を正方向に拡大するよう置換して平坦化
-- 平坦化を適用した直角多角形に「中」と同様の丸めを適用するので`soccer`、`football`、`hockey`ノードの選択領域の右辺は角がなくなり一直線になる

* 参考リンク [#reference]
- [[JListで作成したカレンダーのセル選択領域を角丸で描画する>Swing/RoundedSelectionListCalendar]]
- [[JTreeの選択領域描画をラウンド矩形に変更する>Swing/RoundedSelectionTree]]
- [[JTreeのノードインデントを変更する>Swing/TreeChildIndent]]

* コメント [#comment]
#comment
#comment