Ejemplo n.º 1
0
func (t *Table) Remove(s gfx.Spatial) {
	sb := s.Bounds()

	// Remove minimum.
	i := t.Index(sb.Min)
	for ki, k := range t.Data[i] {
		if k == s {
			t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
		}
	}

	// Remove center.
	i = t.Index(sb.Center())
	for ki, k := range t.Data[i] {
		if k == s {
			t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
		}
	}

	// Remove maximum.
	i = t.Index(sb.Max)
	for ki, k := range t.Data[i] {
		if k == s {
			t.Data[i] = append(t.Data[i][ki:], t.Data[i][ki+1:]...)
		}
	}
	return
}
Ejemplo n.º 2
0
// Remove tries to remove the given spatial from the N tree.
//
// It should be explicitly noted that it is only possible to remove a spatial
// if Bounds() returns the same identical bounds as when it was added, this is
// for efficiency reasons. Clients wishing to not have to keep track can just
// use a map of spatials to their gfx.Bounds of when they where added to the N
// tree.
//
// This method returns true if the spatial was removed or false if it could not
// be located in the tree due to:
//  1. The spatial's bounds having changed since the last time it was added.
//  2. The spatial having already been removed.
func (t *Tree) Remove(s gfx.Spatial) bool {
	if t.Root == nil {
		return false
	}
	sb := s.Bounds()
	found := t.Root.find(sb)
	if found == nil {
		goto outside
	}
	for i, o := range found.Objects {
		if o == s {
			found.Objects = append(found.Objects[:i], found.Objects[i+1:]...)
			t.count--
			return true
		}
	}

outside:
	for i, o := range t.outside {
		if o == s {
			t.outside = append(t.outside[:i], t.outside[i+1:]...)
			t.count--
			return true
		}
	}
	return false
}
Ejemplo n.º 3
0
// findLeaf finds the leaf node containing obj.
func (t *Tree) findLeaf(n *node, obj gfx.Spatial) *node {
	if n.leaf {
		return n
	}
	// if not leaf, search all candidate subtrees
	objBounds := obj.Bounds()
	for _, e := range n.entries {
		fmt.Printf("\nin %p\n", n, objBounds.In(e.bounds))
		fmt.Println("objBounds", objBounds)
		fmt.Println("e.bounds", e.bounds)
		if objBounds.In(e.bounds) {
			leaf := t.findLeaf(e.child, obj)
			if leaf == nil {
				continue
			}
			// check if the leaf actually contains the object
			for _, leafEntry := range leaf.entries {
				if leafEntry.obj == obj {
					return leaf
				}
			}
		}
	}
	return nil
}
Ejemplo n.º 4
0
// Add adds the spatial to the tree.
func (t *Tree) Add(s gfx.Spatial) {
	t.count++
	sb := s.Bounds()
	if sb.Empty() {
		panic("Tree.Add(): cannot add empty spatial")
	}

	if t.root == nil {
		t.root = &Node{
			parent:  t.root,
			bounds:  sb,
			Objects: []gfx.Spatial{s},
		}
		return
	}

	n := t.root.findNode(sb)
	if n != nil {
		n.place(sb, s)
		return
	}

	t.root.place(sb, s)
	t.root.sanitizeBounds()
	return
}
Ejemplo n.º 5
0
// Insert inserts the given spatial object into the tree.
func (t *Tree) Insert(s gfx.Spatial) {
	t.size++
	e := entry{
		bounds: s.Bounds(),
		obj:    s,
	}
	t.insert(e, 1)
}
Ejemplo n.º 6
0
// Insert inserts the given entry into the tree, splitting the tree as needed.
func (t *Tree) Insert(e gfx.Spatial) {
	var l, ll *Node

	// Select a leaf node, l, in which to place the entry, e.
	eBounds := e.Bounds()
	l = t.Root.ChooseLeaf(eBounds)

	// Add the entry to the leaf node. If L has room for another entry, install
	// it. Otherwise invoke SplitNode to obtain L and LL containing E and all
	// of the old entries of L.
	if len(l.Entries) < t.Max {
		// We have room to store the entry.
		l.Entries = append(l.Entries, &Node{
			Parent: l,
			Bounds: eBounds,
			Height: t.Root.Height,
			Object: e,
		})
	} else {
		// We must split the node.
		l, ll = l.SplitNode()
	}

	// Propagate the changes to the tree upward. Invoke AdjustTree on L, also
	// passing LL if a split was performed.
	// XXX: AdjustTree must check if ll != nil to see if a split was performed.
	root, splitRoot := t.AdjustTree(l, ll)
	if splitRoot != nil {
		// Grow the tree taller. If node split propagation caused the root to
		// split then create a new root whose children are the two resulting
		// nodes.
		oldRoot := root
		t.Root.Height++
		t.Root = &Node{
			Parent: nil, // XXX: It's the root but is nil okay?
			Height: t.Root.Height,
		}
		t.Root.Entries = []*Node{
			&Node{
				Parent: t.Root,
				Bounds: splitRoot.calcBounds(),
				Height: t.Root.Height,
			},
			&Node{
				Parent: t.Root,
				Bounds: oldRoot.calcBounds(),
				Height: t.Root.Height,
			},
		}
		t.Root.Bounds = t.Root.calcBounds()
	}
}
Ejemplo n.º 7
0
// Add adds the given spatial to the N tree.
func (t *Tree) Add(s gfx.Spatial) {
	t.count++
	sb := s.Bounds()
	if t.Root == nil {
		size := sb.Size()
		if size.Y > size.X {
			size.X = size.X
			size.Y = size.X
			size.Z = size.X
		}
		if size.Z > size.X {
			size.X = size.X
			size.Y = size.X
			size.Z = size.X
		}
		s := t.startScale
		t.Root = &Node{
			bounds: math.Rect3{
				Min: sb.Min.MulScalar(s),
				Max: sb.Min.Add(size).MulScalar(s),
			},
		}
	}
	for !sb.In(t.Root.bounds) {
		rootBounds := t.Root.bounds
		rootSize := rootBounds.Size()
		if t.Root.Level < -t.maxExpand {
			break
		}
		expanded := &Node{
			Level: t.Root.Level - 1,
			bounds: math.Rect3{
				Min: rootBounds.Min.Sub(rootSize),
				Max: rootBounds.Max.Add(rootSize),
			},
			Children: []*Node{t.Root},
		}
		t.Root = expanded
	}

	// Create a path of nodes, subdividings as needed to insert the object into
	// the tree.
	p := t.Root.createPath(t.divisor, t.maxDepth, sb)
	if p == nil {
		// Doesn't fit in the tree.
		t.outside = append(t.outside, s)
		return
	}
	p.Objects = append(p.Objects, s)
}
Ejemplo n.º 8
0
func (t *Table) Add(s gfx.Spatial) {
	sb := s.Bounds()

	// Add minimum.
	i := t.Index(sb.Min)
	t.Data[i] = append(t.Data[i], s)

	// Add center.
	i = t.Index(sb.Center())
	t.Data[i] = append(t.Data[i], s)

	// Add maximum.
	i = t.Index(sb.Max)
	t.Data[i] = append(t.Data[i], s)
}
Ejemplo n.º 9
0
func (o *Octant) add(b gfx.Spatial, maxDepth int) {
	if o.Depth+1 <= maxDepth {
		bounds := b.Bounds()
		childIndex := o.childFits(bounds)
		fmt.Println("\n\nChild fits")
		fmt.Println("Boundable:", b)
		fmt.Println("Child:", childIndex, o.childBounds(childIndex))
		if childIndex != -1 {
			child := &Octant{
				Bounds: o.childBounds(childIndex),
				Depth:  o.Depth + 1,
			}
			o.Children[childIndex] = child
			child.add(b, maxDepth)
			return
		}
	}

	o.Objects = append(o.Objects, b)
	fmt.Printf("add %v %p\n", b, o)
	return
}
Ejemplo n.º 10
0
func (s *Shash) Add(sp gfx.Spatial) {
	// Find the distance from the center of the spatial's bounding box to the
	// center of the world.
	b := sp.Bounds()
	dist := b.Center().Sub(math.Vec3Zero)
	s.AvgLengthSq += dist.LengthSq()
	s.AvgLengthSq /= 2.0

	// Find the angle between the spatial's position in space relative to the
	// center of the world.
	angle, _ := dist.Normalized()

	// Computer the start and end indices.
	start := s.AngleIndex(angle)
	end := s.AngleIndex(angle)
	distStart := s.DistIndex(b.Min)
	distEnd := s.DistIndex(b.Max)

	if start > end || distStart > distEnd {
		panic("ups")
	}

	//fmt.Println(start, end, "|", distStart, distEnd)
	_ = fmt.Println

	// Insert into table.
	for a := start; a <= end; a *= len(s.Table) {
		ak := a % len(s.Table)
		for d := distStart; d <= distEnd; d *= len(s.Table) {
			dk := d % len(s.Table)
			s.Table[ak][dk] = append(s.Table[ak][dk], Index{
				AvgLengthSq: s.AvgLengthSq,
				S:           sp,
			})
		}
	}
}