Пример #1
0
// Takes a child node position and returns it's bounds.
func (n *Node) childBounds(pos, divisor math.Vec3) math.Rect3 {
	size := n.childSize(divisor)
	cb := math.Rect3{
		Min: pos,
		Max: pos.Add(size),
	}
	if !n.bounds.Contains(cb.Min) || !n.bounds.Contains(cb.Max) {
		fmt.Println(pos)
		fmt.Println(n.bounds)

		fmt.Println(n.bounds.Contains(cb.Min))
		fmt.Println(n.bounds.Contains(cb.Max))
		panic("not contained")
	}

	if !cb.In(n.bounds) {
		//fmt.Println("pos   ", pos)
		//fmt.Println("size  ", size)
		//fmt.Println("child ", cb)
		//fmt.Println("parent", n.bounds)
		//panic("")
	}

	return math.Rect3{
		Min: pos,
		Max: pos.Add(size),
	}
}
Пример #2
0
// findPlace finds a place in this node or any node below it in the tree where
// r can be placed.
func (n *Node) findPlace(r math.Rect3) (*Node, ChildIndex) {
	if !r.In(n.bounds) {
		return nil, -1
	}
	childIndex := n.childFits(r)
	if childIndex != -1 && n.children[childIndex] != nil {
		cn, ci := n.children[childIndex].findPlace(r)
		if cn != nil {
			return cn, ci
		}
	}
	return n, -1
}
Пример #3
0
// find finds this or a distance node where the given rectangle, r, would have
// been placed.
func (n *Node) find(r math.Rect3) *Node {
	if !r.In(n.bounds) {
		// Not inside this node at all.
		return nil
	}

	// Check children...
	for _, child := range n.Children {
		ccn := child.find(r)
		if ccn != nil {
			return ccn
		}
	}
	return n
}
Пример #4
0
// childFits finds a direct child of this node that can fit the rectangle, r,
// and returns it's bounds.
func (n *Node) childFits(r math.Rect3, divisor math.Vec3) (b math.Rect3, ok bool) {
	// Find a child path to create.
	nb := n.bounds
	sz := n.childSize(divisor)
	for x := nb.Min.X; x <= nb.Max.X; x += sz.X {
		for y := nb.Min.Y; y <= nb.Max.Y; y += sz.Y {
			for z := nb.Min.Z; z <= nb.Max.Z; z += sz.Z {
				cb := n.childBounds(math.Vec3{x, y, z}, divisor)
				if r.In(cb) {
					return cb, true
				}
			}
		}
	}
	return math.Rect3Zero, false
}
Пример #5
0
// createPath creates nodes along the needed path up to maxDepth where the
// given spatial's bounds, sb, can be placed.
func (n *Node) createPath(divisor math.Vec3, maxDepth int, sb math.Rect3) *Node {
	nb := n.bounds
	if !sb.In(nb) {
		// Not inside this node at all.
		return nil
	}
	if n.Level+1 > maxDepth {
		// Any child would exceed the maximum depth.
		return n
	}

	// Check existing children...
	for _, child := range n.Children {
		ccn := child.find(sb)
		if ccn != nil {
			// An existing child node can fit the spatials bounds, sb, so ask
			// it to create the path instead.
			return child.createPath(divisor, maxDepth, sb)
		}
	}

	// Find a child path to create.
	db, ok := n.childFits(sb, divisor)
	if ok {
		// Create the child.
		child := &Node{
			Level:  n.Level + 1,
			bounds: db,
		}
		n.Children = append(n.Children, child)
		ccn := child.createPath(divisor, maxDepth, sb)
		if ccn != nil {
			return ccn
		}
		return child
	}
	return n
}
Пример #6
0
func (n *Node) fits(sb math.Rect3) bool {
	if sb.In(n.bounds) {
		return true
	}
	return false
}