BVH implement with less generic parm
This commit is contained in:
@ -1,211 +1,217 @@
|
|||||||
package bvh
|
package bvh
|
||||||
|
|
||||||
//
|
import (
|
||||||
//import (
|
"container/heap"
|
||||||
// "container/heap"
|
"fmt"
|
||||||
// "fmt"
|
"golang.org/x/exp/constraints"
|
||||||
// "golang.org/x/exp/constraints"
|
)
|
||||||
//)
|
|
||||||
//
|
type Node[I constraints.Float, B interface {
|
||||||
//type Node[Vec constraints.Signed | constraints.Float, B interface {
|
Union(B) B
|
||||||
// WithIn(Vec) bool
|
Surface() I
|
||||||
// Union(B) B
|
}, V any] struct {
|
||||||
// Surface() float64
|
box B
|
||||||
//}, V any] struct {
|
Value V
|
||||||
// box B
|
parent *Node[I, B, V]
|
||||||
// Value V
|
children [2]*Node[I, B, V]
|
||||||
// parent *Node[Vec, B, V]
|
isLeaf bool
|
||||||
// children [2]*Node[Vec, B, V]
|
}
|
||||||
// isLeaf bool
|
|
||||||
//}
|
func (n *Node[I, B, V]) findAnotherChild(not *Node[I, B, V]) *Node[I, B, V] {
|
||||||
//
|
if n.children[0] == not {
|
||||||
//func (n *Node[Vec, B, V]) findAnotherChild(not *Node[Vec, B, V]) *Node[Vec, B, V] {
|
return n.children[1]
|
||||||
// if n.children[0] == not {
|
} else if n.children[1] == not {
|
||||||
// return n.children[1]
|
return n.children[0]
|
||||||
// } else if n.children[1] == not {
|
}
|
||||||
// return n.children[0]
|
panic("unreachable, please make sure the 'not' is the n's child")
|
||||||
// }
|
}
|
||||||
// panic("unreachable, please make sure the 'not' is the n's child")
|
|
||||||
//}
|
func (n *Node[I, B, V]) findChildPointer(child *Node[I, B, V]) **Node[I, B, V] {
|
||||||
//
|
if n.children[0] == child {
|
||||||
//func (n *Node[Vec, B, V]) findChildPointer(child *Node[Vec, B, V]) **Node[Vec, B, V] {
|
return &n.children[0]
|
||||||
// if n.children[0] == child {
|
} else if n.children[1] == child {
|
||||||
// return &n.children[0]
|
return &n.children[1]
|
||||||
// } else if n.children[1] == child {
|
}
|
||||||
// return &n.children[1]
|
panic("unreachable, please make sure the 'not' is the n's child")
|
||||||
// }
|
}
|
||||||
// panic("unreachable, please make sure the 'not' is the n's child")
|
|
||||||
//}
|
func (n *Node[I, B, V]) each(test func(bound B) bool, foreach func(v V)) {
|
||||||
//
|
if n == nil {
|
||||||
//type Tree[I constraints.Signed | constraints.Float, B interface {
|
return
|
||||||
// Union(B) B
|
}
|
||||||
// Surface() I
|
if n.isLeaf {
|
||||||
//}, V any] struct {
|
if test(n.box) {
|
||||||
// root *Node[I, B, V]
|
foreach(n.Value)
|
||||||
//}
|
}
|
||||||
//
|
} else {
|
||||||
//func (t *Tree[Vec, B, V]) Insert(leaf B, value V) (n *Node[Vec, B, V]) {
|
n.children[0].each(test, foreach)
|
||||||
// n = &Node[Vec, B, V]{
|
n.children[1].each(test, foreach)
|
||||||
// box: leaf,
|
}
|
||||||
// Value: value,
|
}
|
||||||
// parent: nil,
|
|
||||||
// children: [2]*Node[Vec, B, V]{},
|
type Tree[I constraints.Float, B interface {
|
||||||
// isLeaf: true,
|
Union(B) B
|
||||||
// }
|
Surface() I
|
||||||
// if t.root == nil {
|
}, V any] struct {
|
||||||
// t.root = n
|
root *Node[I, B, V]
|
||||||
// return
|
}
|
||||||
// }
|
|
||||||
//
|
func (t *Tree[I, B, V]) Insert(leaf B, value V) (n *Node[I, B, V]) {
|
||||||
// // Stage 1: find the best sibling for the new leaf
|
n = &Node[I, B, V]{
|
||||||
// sibling := t.root
|
box: leaf,
|
||||||
// bestCost := t.root.box.Union(leaf).Surface()
|
Value: value,
|
||||||
// parentTo := &t.root // the parent's children pointer which point to the sibling
|
parent: nil,
|
||||||
// queue := searchHeap[Node[Vec, B, V]]{searchItem[Node[Vec, B, V]]{pointer: t.root, parentTo: &t.root}}
|
children: [2]*Node[I, B, V]{nil, nil},
|
||||||
//
|
isLeaf: true,
|
||||||
// leafCost := leaf.Surface()
|
}
|
||||||
// for queue.Len() > 0 {
|
if t.root == nil {
|
||||||
// p := heap.Pop(&queue).(searchItem[Node[Vec, B, V]])
|
t.root = n
|
||||||
// // determine if node p has the best cost
|
return
|
||||||
// mergeSurface := p.pointer.box.Union(leaf).Surface()
|
}
|
||||||
// deltaCost := mergeSurface - p.pointer.box.Surface()
|
|
||||||
// cost := p.inheritedCost + mergeSurface
|
// Stage 1: find the best sibling for the new leaf
|
||||||
// if cost <= bestCost {
|
sibling := t.root
|
||||||
// bestCost = cost
|
bestCost := t.root.box.Union(leaf).Surface()
|
||||||
// sibling = p.pointer
|
parentTo := &t.root // the parent's children pointer which point to the sibling
|
||||||
// parentTo = p.parentTo
|
|
||||||
// }
|
var queue searchHeap[I, Node[I, B, V]]
|
||||||
// // determine if it is worthwhile to explore the children of node p.
|
queue.Push(searchItem[I, Node[I, B, V]]{pointer: t.root, parentTo: &t.root})
|
||||||
// inheritedCost := p.inheritedCost + deltaCost // lower bound
|
|
||||||
// if !p.pointer.isLeaf && inheritedCost+leafCost < bestCost {
|
leafCost := leaf.Surface()
|
||||||
// heap.Push(&queue, searchItem[Node[Vec, B, V]]{
|
for queue.Len() > 0 {
|
||||||
// pointer: p.pointer.children[0],
|
p := heap.Pop(&queue).(searchItem[I, Node[I, B, V]])
|
||||||
// parentTo: &p.pointer.children[0],
|
// determine if node p has the best cost
|
||||||
// inheritedCost: inheritedCost,
|
mergeSurface := p.pointer.box.Union(leaf).Surface()
|
||||||
// })
|
deltaCost := mergeSurface - p.pointer.box.Surface()
|
||||||
// heap.Push(&queue, searchItem[Node[Vec, B, V]]{
|
cost := p.inheritedCost + mergeSurface
|
||||||
// pointer: p.pointer.children[1],
|
if cost <= bestCost {
|
||||||
// parentTo: &p.pointer.children[1],
|
bestCost = cost
|
||||||
// inheritedCost: inheritedCost,
|
sibling = p.pointer
|
||||||
// })
|
parentTo = p.parentTo
|
||||||
// }
|
}
|
||||||
// }
|
// determine if it is worthwhile to explore the children of node p.
|
||||||
//
|
inheritedCost := p.inheritedCost + deltaCost // lower bound
|
||||||
// // Stage 2: create a new parent
|
if !p.pointer.isLeaf && inheritedCost+leafCost < bestCost {
|
||||||
// *parentTo = &Node[Vec, B, V]{
|
heap.Push(&queue, searchItem[I, Node[I, B, V]]{
|
||||||
// box: sibling.box.Union(leaf), // we will calculate in Stage3
|
pointer: p.pointer.children[0],
|
||||||
// parent: sibling.parent,
|
parentTo: &p.pointer.children[0],
|
||||||
// children: [2]*Node[Vec, B, V]{sibling, n},
|
inheritedCost: inheritedCost,
|
||||||
// isLeaf: false,
|
})
|
||||||
// }
|
heap.Push(&queue, searchItem[I, Node[I, B, V]]{
|
||||||
// n.parent = *parentTo
|
pointer: p.pointer.children[1],
|
||||||
// sibling.parent = *parentTo
|
parentTo: &p.pointer.children[1],
|
||||||
//
|
inheritedCost: inheritedCost,
|
||||||
// // Stage 3: walk back up the tree refitting AABBs
|
})
|
||||||
// for p := *parentTo; p != nil; p = p.parent {
|
}
|
||||||
// p.box = p.children[0].box.Union(p.children[1].box)
|
}
|
||||||
// t.rotate(p)
|
|
||||||
// }
|
// Stage 2: create a new parent
|
||||||
// return
|
*parentTo = &Node[I, B, V]{
|
||||||
//}
|
box: sibling.box.Union(leaf), // we will calculate in Stage3
|
||||||
//
|
parent: sibling.parent,
|
||||||
//func (t *Tree[Vec, B, V]) Delete(n *Node[Vec, B, V]) interface{} {
|
children: [2]*Node[I, B, V]{sibling, n},
|
||||||
// if n.parent == nil {
|
isLeaf: false,
|
||||||
// // n is the root
|
}
|
||||||
// t.root = nil
|
n.parent = *parentTo
|
||||||
// return n.Value
|
sibling.parent = *parentTo
|
||||||
// }
|
|
||||||
// sibling := n.parent.findAnotherChild(n)
|
// Stage 3: walk back up the tree refitting AABBs
|
||||||
// grand := n.parent.parent
|
for p := *parentTo; p != nil; p = p.parent {
|
||||||
// if grand == nil {
|
p.box = p.children[0].box.Union(p.children[1].box)
|
||||||
// // n's parent is root
|
t.rotate(p)
|
||||||
// t.root = sibling
|
}
|
||||||
// sibling.parent = nil
|
return
|
||||||
// } else {
|
}
|
||||||
// p := grand.findChildPointer(n.parent)
|
|
||||||
// *p = sibling
|
func (t *Tree[I, B, V]) Delete(n *Node[I, B, V]) interface{} {
|
||||||
// sibling.parent = grand
|
if n.parent == nil {
|
||||||
// for p := sibling.parent; p.parent != nil; p = p.parent {
|
// n is the root
|
||||||
// p.box = p.children[0].box.Union(p.children[1].box)
|
t.root = nil
|
||||||
// t.rotate(p)
|
return n.Value
|
||||||
// }
|
}
|
||||||
// }
|
sibling := n.parent.findAnotherChild(n)
|
||||||
// return n.Value
|
grand := n.parent.parent
|
||||||
//}
|
if grand == nil {
|
||||||
//
|
// n's parent is root
|
||||||
//func (t *Tree[Vec, B, V]) rotate(n *Node[Vec, B, V]) {
|
t.root = sibling
|
||||||
// if n.isLeaf || n.parent == nil {
|
sibling.parent = nil
|
||||||
// return
|
} else {
|
||||||
// }
|
p := grand.findChildPointer(n.parent)
|
||||||
// // trying to swap n's sibling and children
|
*p = sibling
|
||||||
// sibling := n.parent.findAnotherChild(n)
|
sibling.parent = grand
|
||||||
// current := n.box.Surface()
|
for p := sibling.parent; p.parent != nil; p = p.parent {
|
||||||
// if n.children[1].box.Union(sibling.box).Surface() < current {
|
p.box = p.children[0].box.Union(p.children[1].box)
|
||||||
// // swap n.children[0] and sibling
|
t.rotate(p)
|
||||||
// n.parent.children, n.children, n.children[0].parent, sibling.parent = [2]*Node[Vec, B, V]{n, n.children[0]}, [2]*Node[Vec, B, V]{sibling, n.children[1]}, n.parent, n
|
}
|
||||||
// n.box = n.children[0].box.Union(n.children[1].box)
|
}
|
||||||
// } else if n.children[0].box.Union(sibling.box).Surface() < current {
|
return n.Value
|
||||||
// // swap n.children[1] and sibling
|
}
|
||||||
// n.parent.children, n.children, n.children[1].parent, sibling.parent = [2]*Node[Vec, B, V]{n, n.children[1]}, [2]*Node[Vec, B, V]{sibling, n.children[0]}, n.parent, n
|
|
||||||
// n.box = n.children[0].box.Union(n.children[1].box)
|
func (t *Tree[I, B, V]) rotate(n *Node[I, B, V]) {
|
||||||
// }
|
if n.isLeaf || n.parent == nil {
|
||||||
//}
|
return
|
||||||
//
|
}
|
||||||
////func lookupPoint[B interface {
|
// trying to swap n's sibling and children
|
||||||
//// Union(B) B
|
sibling := n.parent.findAnotherChild(n)
|
||||||
//// Surface() float64
|
current := n.box.Surface()
|
||||||
////}, V any](n *Node[B, V], point Vec2, f func(v V)) {
|
if n.children[1].box.Union(sibling.box).Surface() < current {
|
||||||
//// if n == nil || !n.box.WithIn(point) {
|
// swap n.children[0] and sibling
|
||||||
//// return
|
t1 := [2]*Node[I, B, V]{n, n.children[0]}
|
||||||
//// }
|
t2 := [2]*Node[I, B, V]{sibling, n.children[1]}
|
||||||
//// if n.isLeaf {
|
n.parent.children, n.children, n.children[0].parent, sibling.parent = t1, t2, n.parent, n
|
||||||
//// f(n.Value)
|
n.box = n.children[0].box.Union(n.children[1].box)
|
||||||
//// } else {
|
} else if n.children[0].box.Union(sibling.box).Surface() < current {
|
||||||
//// lookupVec(n.children[0], point, f)
|
// swap n.children[1] and sibling
|
||||||
//// lookupVec(n.children[1], point, f)
|
t1 := [2]*Node[I, B, V]{n, n.children[1]}
|
||||||
//// }
|
t2 := [2]*Node[I, B, V]{sibling, n.children[0]}
|
||||||
////}
|
n.parent.children, n.children, n.children[1].parent, sibling.parent = t1, t2, n.parent, n
|
||||||
//
|
n.box = n.children[0].box.Union(n.children[1].box)
|
||||||
////
|
}
|
||||||
////func lookupAABB(n *Node, aabb AABB, f func(v interface{})) {
|
}
|
||||||
//// if n == nil || !n.box.Touch(aabb) {
|
|
||||||
//// return
|
func (t *Tree[I, B, V]) Find(test func(bound B) bool, foreach func(v V)) {
|
||||||
//// }
|
t.root.each(test, foreach)
|
||||||
//// if n.isLeaf {
|
}
|
||||||
//// f(n.Value)
|
|
||||||
//// } else {
|
func (t Tree[I, B, V]) String() string {
|
||||||
//// lookupAABB(n.children[0], aabb, f)
|
return t.root.String()
|
||||||
//// lookupAABB(n.children[1], aabb, f)
|
}
|
||||||
//// }
|
|
||||||
////}
|
func (n *Node[I, B, V]) String() string {
|
||||||
//
|
if n.isLeaf {
|
||||||
//type searchHeap[V any] []searchItem[V]
|
return fmt.Sprint(n.Value)
|
||||||
//type searchItem[V any] struct {
|
} else {
|
||||||
// pointer *V
|
return fmt.Sprintf("{%v, %v}", n.children[0], n.children[1])
|
||||||
// parentTo **V
|
}
|
||||||
// inheritedCost float64
|
}
|
||||||
//}
|
|
||||||
//
|
func TouchPoint[Vec any, B interface{ WithIn(Vec) bool }](point Vec) func(bound B) bool {
|
||||||
//func (h searchHeap[V]) Len() int { return len(h) }
|
return func(bound B) bool {
|
||||||
//func (h searchHeap[V]) Less(i, j int) bool { return h[i].inheritedCost < h[j].inheritedCost }
|
return bound.WithIn(point)
|
||||||
//func (h searchHeap[V]) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
}
|
||||||
//func (h *searchHeap[V]) Push(x interface{}) { *h = append(*h, x.(searchItem[V])) }
|
}
|
||||||
//func (h *searchHeap[V]) Pop() interface{} {
|
|
||||||
// old := *h
|
func TouchBound[Vec any, B interface{ Touch(B) bool }](other B) func(bound B) bool {
|
||||||
// n := len(old)
|
return func(bound B) bool {
|
||||||
// x := old[n-1]
|
return bound.Touch(other)
|
||||||
// *h = old[0 : n-1]
|
}
|
||||||
// return x
|
}
|
||||||
//}
|
|
||||||
//
|
type searchHeap[I constraints.Float, V any] []searchItem[I, V]
|
||||||
//func (t Tree[Vec, B, V]) String() string {
|
type searchItem[I constraints.Float, V any] struct {
|
||||||
// return t.root.String()
|
pointer *V
|
||||||
//}
|
parentTo **V
|
||||||
//
|
inheritedCost I
|
||||||
//func (n *Node[Vec, B, V]) String() string {
|
}
|
||||||
// if n.isLeaf {
|
|
||||||
// return fmt.Sprint(n.Value)
|
func (h searchHeap[I, V]) Len() int { return len(h) }
|
||||||
// } else {
|
func (h searchHeap[I, V]) Less(i, j int) bool { return h[i].inheritedCost < h[j].inheritedCost }
|
||||||
// return fmt.Sprintf("{%v, %v}", n.children[0], n.children[1])
|
func (h searchHeap[I, V]) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||||
// }
|
func (h *searchHeap[I, V]) Push(x interface{}) { *h = append(*h, x.(searchItem[I, V])) }
|
||||||
//}
|
func (h *searchHeap[I, V]) Pop() interface{} {
|
||||||
|
old := *h
|
||||||
|
n := len(old)
|
||||||
|
x := old[n-1]
|
||||||
|
*h = old[0 : n-1]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
@ -1,148 +1,144 @@
|
|||||||
package bvh
|
package bvh
|
||||||
|
|
||||||
//
|
import (
|
||||||
//import (
|
"math/rand"
|
||||||
// "math/rand"
|
"testing"
|
||||||
// "testing"
|
)
|
||||||
//)
|
|
||||||
//
|
func TestTree2_Insert(t *testing.T) {
|
||||||
//func TestTree2_Insert(t *testing.T) {
|
aabbs := []AABB[float64, Vec2[float64]]{
|
||||||
// aabbs := []AABB[Vec2[float64]]{
|
{Upper: Vec2[float64]{1, 1}, Lower: Vec2[float64]{0, 0}},
|
||||||
// {Upper: Vec2[float64]{1, 1}, Lower: Vec2[float64]{0, 0}},
|
{Upper: Vec2[float64]{2, 1}, Lower: Vec2[float64]{1, 0}},
|
||||||
// {Upper: Vec2[float64]{2, 1}, Lower: Vec2[float64]{1, 0}},
|
{Upper: Vec2[float64]{11, 1}, Lower: Vec2[float64]{10, 0}},
|
||||||
// {Upper: Vec2[float64]{11, 1}, Lower: Vec2[float64]{10, 0}},
|
{Upper: Vec2[float64]{12, 1}, Lower: Vec2[float64]{11, 0}},
|
||||||
// {Upper: Vec2[float64]{12, 1}, Lower: Vec2[float64]{11, 0}},
|
{Upper: Vec2[float64]{101, 1}, Lower: Vec2[float64]{100, 0}},
|
||||||
// {Upper: Vec2[float64]{101, 1}, Lower: Vec2[float64]{100, 0}},
|
{Upper: Vec2[float64]{102, 1}, Lower: Vec2[float64]{101, 0}},
|
||||||
// {Upper: Vec2[float64]{102, 1}, Lower: Vec2[float64]{101, 0}},
|
{Upper: Vec2[float64]{111, 1}, Lower: Vec2[float64]{110, 0}},
|
||||||
// {Upper: Vec2[float64]{111, 1}, Lower: Vec2[float64]{110, 0}},
|
{Upper: Vec2[float64]{112, 1}, Lower: Vec2[float64]{111, 0}},
|
||||||
// {Upper: Vec2[float64]{112, 1}, Lower: Vec2[float64]{111, 0}},
|
{Upper: Vec2[float64]{1, 1}, Lower: Vec2[float64]{-1, -1}},
|
||||||
// {Upper: Vec2[float64]{1, 1}, Lower: Vec2[float64]{-1, -1}},
|
}
|
||||||
// }
|
var bvh Tree[float64, AABB[float64, Vec2[float64]], int]
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], int]
|
for i, aabb := range aabbs {
|
||||||
// for i, aabb := range aabbs {
|
bvh.Insert(aabb, i)
|
||||||
// bvh.Insert(aabb, i)
|
// visualize
|
||||||
// // visualize
|
t.Log(bvh)
|
||||||
// t.Log(bvh)
|
}
|
||||||
// }
|
bvh.Find(TouchPoint[Vec2[float64], AABB[float64, Vec2[float64]]](Vec2[float64]{0.5, 0.5}), func(v int) {
|
||||||
// //bvh.FindVec(Vec2{0.5, 0.5}, func(v interface{}) {
|
t.Logf("find! %v", v)
|
||||||
// // t.Logf("find! %v", v)
|
})
|
||||||
// //})
|
}
|
||||||
//}
|
|
||||||
//
|
func TestTree2_Find_vec(t *testing.T) {
|
||||||
//func TestTree2_FindVec(t *testing.T) {
|
type Vec2d = Vec2[float64]
|
||||||
// aabbs := []AABB[Vec2[float64]]{
|
type AABBVec2d = AABB[float64, Vec2d]
|
||||||
// {Upper: Vec2[float64]{2, 2}, Lower: Vec2[float64]{-1, -1}},
|
type TreeAABBVec2di = Tree[float64, AABBVec2d, int]
|
||||||
// {Upper: Vec2[float64]{2, 1}, Lower: Vec2[float64]{-1, -2}},
|
|
||||||
// {Upper: Vec2[float64]{1, 1}, Lower: Vec2[float64]{-2, -2}},
|
aabbs := []AABBVec2d{
|
||||||
// {Upper: Vec2[float64]{1, 2}, Lower: Vec2[float64]{-2, -1}},
|
{Upper: Vec2d{2, 2}, Lower: Vec2d{-1, -1}},
|
||||||
// }
|
{Upper: Vec2d{2, 1}, Lower: Vec2d{-1, -2}},
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], int]
|
{Upper: Vec2d{1, 1}, Lower: Vec2d{-2, -2}},
|
||||||
// for i, aabb := range aabbs {
|
{Upper: Vec2d{1, 2}, Lower: Vec2d{-2, -1}},
|
||||||
// bvh.Insert(aabb, i)
|
}
|
||||||
// // visualize
|
var bvh TreeAABBVec2di
|
||||||
// t.Log(bvh)
|
for i, aabb := range aabbs {
|
||||||
// }
|
bvh.Insert(aabb, i)
|
||||||
// //findVec := func(vec Vec2) (list []interface{}) {
|
t.Log(bvh)
|
||||||
// // bvh.FindVec(vec, func(v interface{}) { list = append(list, v) })
|
}
|
||||||
// // return
|
find := func(test func(bound AABBVec2d) bool) []int {
|
||||||
// //}
|
var result []int
|
||||||
// //t.Log(findVec(Vec2{0, 0}))
|
bvh.Find(test, func(i int) {
|
||||||
// //t.Log(findVec(Vec2{1.5, 0}))
|
result = append(result, i)
|
||||||
// //t.Log(findVec(Vec2{1.5, 1.5}))
|
})
|
||||||
// //t.Log(findVec(Vec2{-1.5, 0}))
|
return result
|
||||||
// //
|
}
|
||||||
// //findAABB := func(aabb AABB2) (list []interface{}) {
|
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{0, 0})))
|
||||||
// // bvh.FindAABB(aabb, func(v interface{}) { list = append(list, v) })
|
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{1.5, 0})))
|
||||||
// // return
|
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{1.5, 1.5})))
|
||||||
// //}
|
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{-1.5, 0})))
|
||||||
// //t.Log(findAABB(AABB2{Upper: Vec2{1, 1}, Lower: Vec2{-1, -1}}))
|
|
||||||
// //t.Log(findAABB(AABB2{Upper: Vec2{3, 3}, Lower: Vec2{1.5, 1.5}}))
|
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{-1, -1}})))
|
||||||
// //t.Log(findAABB(AABB2{Upper: Vec2{-1.5, 0.5}, Lower: Vec2{-2.5, -0.5}}))
|
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{1.5, 1.5}})))
|
||||||
//}
|
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{-1.5, 0.5}, Lower: Vec2d{-2.5, -0.5}})))
|
||||||
//
|
}
|
||||||
//func TestTree2_Insert_rotation(t *testing.T) {
|
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], int]
|
func BenchmarkTree_Insert(b *testing.B) {
|
||||||
// for i := 0; i < 5; i++ {
|
type Vec2d = Vec2[float64]
|
||||||
// bvh.Insert(AABB[Vec2[float64]]{
|
type AABBVec2d = AABB[float64, Vec2d]
|
||||||
// Upper: Vec2[float64]{float64(i), float64(i)},
|
type TreeAABBVec2da = Tree[float64, AABBVec2d, any]
|
||||||
// Lower: Vec2[float64]{float64(0), float64(0)},
|
|
||||||
// }, i)
|
const size = 25
|
||||||
// }
|
// generate test cases
|
||||||
//}
|
aabbs := make([]AABBVec2d, b.N)
|
||||||
//
|
poses := make([]Vec2d, b.N)
|
||||||
//func BenchmarkTree2_Insert_random(b *testing.B) {
|
for i := range aabbs {
|
||||||
// const size = 25
|
poses[i] = Vec2d{rand.Float64() * 1e4, rand.Float64() * 1e4}
|
||||||
// // generate test cases
|
aabbs[i] = AABBVec2d{
|
||||||
// aabbs := make([]AABB[Vec2[float64]], b.N)
|
Upper: Vec2d{poses[i][0] + size, poses[i][0] + size},
|
||||||
// poses := make([]Vec2[float64], b.N)
|
Lower: Vec2d{poses[i][0] - size, poses[i][0] - size},
|
||||||
// for i := range aabbs {
|
}
|
||||||
// poses[i] = Vec2[float64]{rand.Float64() * 1e4, rand.Float64() * 1e4}
|
}
|
||||||
// aabbs[i] = AABB[Vec2[float64]]{
|
b.ResetTimer()
|
||||||
// Upper: Vec2[float64]{poses[i][0] + size, poses[i][0] + size},
|
|
||||||
// Lower: Vec2[float64]{poses[i][0] - size, poses[i][0] - size},
|
var bvh TreeAABBVec2da
|
||||||
// }
|
for _, v := range aabbs {
|
||||||
// }
|
bvh.Insert(v, nil)
|
||||||
// b.ResetTimer()
|
}
|
||||||
//
|
}
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], any]
|
|
||||||
// for _, v := range aabbs {
|
func BenchmarkTree2_Find_random(b *testing.B) {
|
||||||
// bvh.Insert(v, nil)
|
type Vec2d = Vec2[float64]
|
||||||
// }
|
type AABBVec2d = AABB[float64, Vec2d]
|
||||||
// //for _, v := range poses {
|
type TreeAABBVec2da = Tree[float64, AABBVec2d, any]
|
||||||
// // bvh.FindVec(v, func(interface{}) {})
|
|
||||||
// //}
|
const size = 25
|
||||||
//}
|
// generate test cases
|
||||||
//
|
aabbs := make([]AABBVec2d, b.N)
|
||||||
//func BenchmarkTree2_Insert_sorted1(b *testing.B) {
|
poses := make([]Vec2d, b.N)
|
||||||
// // generate test cases
|
for i := range aabbs {
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], int]
|
poses[i] = Vec2d{rand.Float64() * 1e4, rand.Float64() * 1e4}
|
||||||
// upper := Vec2[float64]{float64(b.N), float64(b.N)}
|
aabbs[i] = AABBVec2d{
|
||||||
// for i := 0; i < b.N; i++ {
|
Upper: Vec2d{poses[i][0] + size, poses[i][0] + size},
|
||||||
// bvh.Insert(AABB[Vec2[float64]]{
|
Lower: Vec2d{poses[i][0] - size, poses[i][0] - size},
|
||||||
// Upper: upper,
|
}
|
||||||
// Lower: Vec2[float64]{float64(i), float64(i)},
|
}
|
||||||
// }, i)
|
var bvh TreeAABBVec2da
|
||||||
// }
|
for _, v := range aabbs {
|
||||||
//}
|
bvh.Insert(v, nil)
|
||||||
//
|
}
|
||||||
//func BenchmarkTree2_Insert_sorted2(b *testing.B) {
|
b.ResetTimer()
|
||||||
// // generate test cases
|
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], int]
|
for _, v := range poses {
|
||||||
// for i := 0; i < b.N; i++ {
|
bvh.Find(TouchPoint[Vec2d, AABBVec2d](v), func(v any) {})
|
||||||
// bvh.Insert(AABB[Vec2[float64]]{
|
}
|
||||||
// Upper: Vec2[float64]{float64(i), float64(i)},
|
}
|
||||||
// Lower: Vec2[float64]{0, 0},
|
|
||||||
// }, i)
|
func BenchmarkTree2_Delete_random(b *testing.B) {
|
||||||
// }
|
const size = 25
|
||||||
//}
|
// generate test cases
|
||||||
//
|
aabbs := make([]AABB[float64, Vec2[float64]], b.N)
|
||||||
//func BenchmarkTree2_Delete_random(b *testing.B) {
|
poses := make([]Vec2[float64], b.N)
|
||||||
// const size = 25
|
nodes := make([]*Node[float64, AABB[float64, Vec2[float64]], any], b.N)
|
||||||
// // generate test cases
|
for i := range aabbs {
|
||||||
// aabbs := make([]AABB[Vec2[float64]], b.N)
|
poses[i] = Vec2[float64]{rand.Float64() * 1e4, rand.Float64() * 1e4}
|
||||||
// poses := make([]Vec2[float64], b.N)
|
aabbs[i] = AABB[float64, Vec2[float64]]{
|
||||||
// nodes := make([]*Node[AABB[Vec2[float64]], any], b.N)
|
Upper: Vec2[float64]{poses[i][0] + size, poses[i][0] + size},
|
||||||
// for i := range aabbs {
|
Lower: Vec2[float64]{poses[i][0] - size, poses[i][0] - size},
|
||||||
// poses[i] = Vec2[float64]{rand.Float64() * 1e4, rand.Float64() * 1e4}
|
}
|
||||||
// aabbs[i] = AABB[Vec2[float64]]{
|
}
|
||||||
// Upper: Vec2[float64]{poses[i][0] + size, poses[i][0] + size},
|
b.ResetTimer()
|
||||||
// Lower: Vec2[float64]{poses[i][0] - size, poses[i][0] - size},
|
|
||||||
// }
|
var bvh Tree[float64, AABB[float64, Vec2[float64]], any]
|
||||||
// }
|
for i, v := range aabbs {
|
||||||
// b.ResetTimer()
|
nodes[i] = bvh.Insert(v, nil)
|
||||||
//
|
}
|
||||||
// var bvh Tree[float64, AABB[Vec2[float64]], any]
|
|
||||||
// for i, v := range aabbs {
|
b.StopTimer()
|
||||||
// nodes[i] = bvh.Insert(v, nil)
|
rand.Shuffle(b.N, func(i, j int) {
|
||||||
// }
|
nodes[i], nodes[j] = nodes[j], nodes[i]
|
||||||
//
|
})
|
||||||
// b.StopTimer()
|
b.StartTimer()
|
||||||
// rand.Shuffle(b.N, func(i, j int) {
|
|
||||||
// nodes[i], nodes[j] = nodes[j], nodes[i]
|
for _, v := range nodes {
|
||||||
// })
|
bvh.Delete(v)
|
||||||
// b.StartTimer()
|
}
|
||||||
//
|
}
|
||||||
// for _, v := range nodes {
|
|
||||||
// bvh.Delete(v)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
Reference in New Issue
Block a user