-
Notifications
You must be signed in to change notification settings - Fork 0
/
spatial_index.go
101 lines (81 loc) · 3.19 KB
/
spatial_index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package cm
import "github.com/setanarut/vec"
type SpatialIndexBB func(obj *Shape) BB
type SpatialIndexIterator func(obj *Shape)
type SpatialIndexQuery func(obj1 any, obj2 *Shape, collisionId uint32, data any) uint32
type SpatialIndexSegmentQuery func(obj1 any, obj2 *Shape, data any) float64
// SpatialIndexer is an interface for spatial indexing that provides
// methods to manage spatial objects efficiently. It is implemented by
// a BBTree structure, which organizes objects in a bounding volume tree.
type SpatialIndexer interface {
// Count returns the number of objects currently stored in the index.
Count() int
// Each iterates over all objects in the spatial index, applying
// the provided iterator function `f` to each object.
Each(f SpatialIndexIterator)
// Contains checks if a given object `obj` with the specified
// `hashId` exists in the spatial index.
Contains(obj *Shape, hashId HashValue) bool
// Insert adds a new object `obj` with the specified `hashId` to
// the spatial index.
Insert(obj *Shape, hashId HashValue)
// Remove deletes the object `obj` with the specified `hashId`
// from the spatial index, if it exists.
Remove(obj *Shape, hashId HashValue)
// Reindex rebuilds the spatial index from the existing objects
// to optimize query performance.
Reindex()
// ReindexObject updates the spatial position of the given object
// `obj` in the index using the specified `hashId`.
ReindexObject(obj *Shape, hashId HashValue)
// ReindexQuery performs a reindexing query using the given
// spatial query function `f` and additional `data`.
ReindexQuery(f SpatialIndexQuery, data any)
// Query allows querying the spatial index for objects that intersect
// or are contained within the bounding box `bb` using the provided
// query function `f` and additional `data`.
Query(obj any, bb BB, f SpatialIndexQuery, data any)
// SegmentQuery performs a segment-based query using the line segment
// defined by points `a` and `b`. It allows querying objects affected
// by the segment based on the `tExit` parameter, applying the
// provided segment query function `f` and additional `data`.
SegmentQuery(obj any, a, b vec.Vec2, tExit float64, f SpatialIndexSegmentQuery, data any)
}
func ShapeGetBB(obj *Shape) BB {
return obj.BB
}
type SpatialIndex struct {
class SpatialIndexer
bbfunc SpatialIndexBB
staticIndex, dynamicIndex *SpatialIndex
}
func NewSpatialIndex(klass SpatialIndexer, bbfunc SpatialIndexBB, staticIndex *SpatialIndex) *SpatialIndex {
index := &SpatialIndex{
class: klass,
bbfunc: bbfunc,
staticIndex: staticIndex,
}
if staticIndex != nil {
staticIndex.dynamicIndex = index
}
return index
}
func (index *SpatialIndex) GetTree() *BBTree {
if index == nil {
return nil
}
return index.class.(*BBTree)
}
func (index *SpatialIndex) GetRootIfTree() *Node {
if index == nil {
return nil
}
return index.class.(*BBTree).root
}
func (dynamicIndex *SpatialIndex) CollideStatic(staticIndex *SpatialIndex, f SpatialIndexQuery, data any) {
if staticIndex != nil && staticIndex.class.Count() > 0 {
dynamicIndex.class.Each(func(obj *Shape) {
staticIndex.class.Query(obj, dynamicIndex.bbfunc(obj), f, data)
})
}
}