/// <summary> /// 指定ノードに葉ノードを追加する /// </summary> /// <param name="root">追加先ノード</param> /// <param name="leaf">追加する葉ノード</param> private void InsertLeaf(Node root, LeafNode leaf) { if (_Root == null) { // ツリーが空なら追加ノードをルートとする _Root = leaf; leaf.Parent = null; } else { // 兄弟となる葉ノードを探す、境界ボリュームの距離が近い方へ辿っていく LeafNode sibling = root.AsLeaf; BranchNode branch = root.AsBranch; if (branch != null) { var volume = leaf.Volume; while (true) { var c = branch.GetChild(Select(volume, branch.Child1.Volume, branch.Child2.Volume)); sibling = c.AsLeaf; if (sibling != null) { break; } branch = c.AsBranch; } } // 追加ノードと兄弟ノードの親となるノードを作成 var prev = sibling.Parent; branch = new BranchNode(prev, sibling, leaf); if (prev != null) { // 見つかった兄弟ノードに親があるなら、親ノードの子をすり替えて根に向かって境界ボリュームを計算し直す prev.SetChild(sibling.Index, branch); sibling.Parent = branch; leaf.Parent = branch; do { if (prev.Volume.Contains(branch.Volume)) { break; } prev.UpdateVolume(); branch = prev; } while (null != (prev = branch.Parent)); } else { // 見つかった兄弟ノードに親が無いなら、作成した親ノードをルートとする sibling.Parent = branch; leaf.Parent = branch; _Root = branch; } } }