// expand performs expansion of the root node, n, towards r's center. If a new // root node is created then it is returned and n.parent is set to the new root // node. func (n *Node) expand(r math.Rect3) *Node { nb := n.bounds if nb.Empty() { // For starting bounds we will (squarely) encapsulate the rectangle. rsz := r.Size() s := rsz.X if rsz.Y > s { s = rsz.Y } if rsz.Z > s { s = rsz.Z } rcenter := r.Center() s /= 2 s *= 32 startSize := math.Vec3{s, s, s} n.bounds = math.Rect3{ Min: rcenter.Sub(startSize), Max: rcenter.Add(startSize), } return nil } // Expansion occurs by growing the octree such that the root node becomes // a new node whose child is the old root node. Thus we can simply // determine in which direction the new root should be extended (by twice // the old root's size) by comparing the centres of the old root and the // rectangle in question. c := nb.Center() rc := r.Center() sz := nb.Size() // Expand by becoming the opposite octant of r's closest point to nb. var ci ChildIndex if rc.Z > c.Z { // Top if rc.Y > c.Y { // Top, Front if rc.X > c.X { ci = TopFrontRight } else { ci = TopFrontLeft } } else { // Top, Back if rc.X > c.X { ci = TopBackRight } else { ci = TopBackLeft } } } else { // Bottom if rc.Y > c.Y { // Bottom, Front if rc.X > c.X { ci = BottomFrontRight } else { ci = BottomFrontLeft } } else { // Bottom, Back if rc.X > c.X { ci = BottomBackRight } else { ci = BottomBackLeft } } } expDown := ci.Bottom() expBack := ci.Back() expLeft := ci.Left() fb := n.bounds if expDown { fb.Min.Z -= sz.Z } else { fb.Max.Z += sz.Z } if expBack { fb.Min.Y -= sz.Y } else { fb.Max.Y += sz.Y } if expLeft { fb.Min.X -= sz.X } else { fb.Max.X += sz.X } newRoot := &Node{ access: n.access, bounds: fb, level: n.level + 1, objects: make([][]*entry, 9), } newRoot.children[ci] = n n.parent = newRoot return newRoot }