@@ -8,32 +8,26 @@ import (
8
8
)
9
9
10
10
type arrayMap [T any ] struct {
11
- topRight [][]* T
12
- topLeft [][]* T
13
- botRight [][]* T
14
- botLeft [][]* T
11
+ // (+x, +y) => 0
12
+ // (+x, -y) => 2
13
+ // (-x, +y) => 1
14
+ // (-x, -y) => 3
15
+ quad [][][]* T
15
16
}
16
17
17
18
func newArrayMap [T any ](size int ) * arrayMap [T ] {
18
19
size = size / 2 // Note: We cut in half b/c we use 4 quadrants
19
20
m := & arrayMap [T ]{
20
- topRight : make ([][]* T , size ),
21
- topLeft : make ([][]* T , size ),
22
- botRight : make ([][]* T , size ),
23
- botLeft : make ([][]* T , size ),
21
+ quad : make ([][][]* T , size ),
24
22
}
25
23
26
- for i := range m .topRight {
27
- m .topRight [i ] = make ([]* T , size )
28
- }
29
- for i := range m .topLeft {
30
- m .topLeft [i ] = make ([]* T , size )
31
- }
32
- for i := range m .botRight {
33
- m .botRight [i ] = make ([]* T , size )
34
- }
35
- for i := range m .botLeft {
36
- m .botLeft [i ] = make ([]* T , size )
24
+ // Create 4 quadrants
25
+ for range 4 {
26
+ slice := make ([][]* T , size )
27
+ for i := range slice {
28
+ slice [i ] = make ([]* T , size )
29
+ }
30
+ m .quad = append (m .quad , slice )
37
31
}
38
32
39
33
return m
@@ -61,20 +55,29 @@ func (m *arrayMap[T]) safePut(slice [][]*T, x, y int, t *T) [][]*T {
61
55
return slice
62
56
}
63
57
64
- func (m * arrayMap [T ]) Put (x , y int , t * T ) {
65
- if x >= 0 {
66
- if y >= 0 {
67
- m .topRight = m .safePut (m .topRight , x , y , t )
68
- } else {
69
- m .botRight = m .safePut (m .botRight , x , - y , t )
70
- }
71
- } else {
72
- if y >= 0 {
73
- m .topLeft = m .safePut (m .topLeft , - x , y , t )
74
- } else {
75
- m .botLeft = m .safePut (m .botLeft , - x , - y , t )
76
- }
58
+ // Returns the qudrant index, the X index, and the Y Index
59
+ func (m * arrayMap [T ]) getQuadIndexes (x , y int ) (int , int , int ) {
60
+ // Calculates the following Quadrants:
61
+ // (+x, +y) => 0
62
+ // (+x, -y) => 2
63
+ // (-x, +y) => 1
64
+ // (-x, -y) => 3
65
+
66
+ idx := 0
67
+ if x < 0 {
68
+ idx += 1
69
+ x = - x
70
+ }
71
+ if y < 0 {
72
+ idx += 2
73
+ y = - y
77
74
}
75
+ return idx , x , y
76
+ }
77
+
78
+ func (m * arrayMap [T ]) Put (x , y int , t * T ) {
79
+ idx , xIdx , yIdx := m .getQuadIndexes (x , y )
80
+ m .quad [idx ] = m .safePut (m .quad [idx ], xIdx , yIdx , t )
78
81
}
79
82
80
83
func (m * arrayMap [T ]) safeGet (slice [][]* T , x , y int ) (* T , bool ) {
@@ -90,56 +93,20 @@ func (m *arrayMap[T]) safeGet(slice [][]*T, x, y int) (*T, bool) {
90
93
}
91
94
92
95
func (m * arrayMap [T ]) Get (x , y int ) (* T , bool ) {
93
- if x >= 0 {
94
- if y >= 0 {
95
- return m .safeGet (m .topRight , x , y )
96
- } else {
97
- return m .safeGet (m .botRight , x , - y )
98
- }
99
- } else {
100
- if y >= 0 {
101
- return m .safeGet (m .topLeft , - x , y )
102
- } else {
103
- return m .safeGet (m .botLeft , - x , - y )
104
- }
105
- }
96
+ idx , xIdx , yIdx := m .getQuadIndexes (x , y )
97
+ return m .safeGet (m .quad [idx ], xIdx , yIdx )
106
98
}
107
99
108
100
func (m * arrayMap [T ]) ForEachValue (lambda func (t * T )) {
109
- for x := range m .topRight {
110
- for y := range m .topRight [x ] {
111
- val := m.topRight [x ][y ]
112
- if val == nil {
113
- continue
114
- }
115
- lambda (val )
116
- }
117
- }
118
- for x := range m .topLeft {
119
- for y := range m .topLeft [x ] {
120
- val := m.topLeft [x ][y ]
121
- if val == nil {
122
- continue
123
- }
124
- lambda (val )
125
- }
126
- }
127
- for x := range m .botLeft {
128
- for y := range m .botLeft [x ] {
129
- val := m.botLeft [x ][y ]
130
- if val == nil {
131
- continue
132
- }
133
- lambda (val )
134
- }
135
- }
136
- for x := range m .botRight {
137
- for y := range m .botRight [x ] {
138
- val := m.botRight [x ][y ]
139
- if val == nil {
140
- continue
101
+ for idx := range m .quad {
102
+ for x := range m .quad [idx ] {
103
+ for y := range m.quad [idx ][x ] {
104
+ val := m.quad [idx ][x ][y ]
105
+ if val == nil {
106
+ continue
107
+ }
108
+ lambda (val )
141
109
}
142
- lambda (val )
143
110
}
144
111
}
145
112
}
@@ -287,6 +254,13 @@ func (h *Hashmap[T]) Add(shape Shape, val T) {
287
254
min := h .PositionToIndex (shape .Bounds .Min )
288
255
max := h .PositionToIndex (shape .Bounds .Max )
289
256
257
+ // Early case if it's only one bucket
258
+ if min == max {
259
+ bucket := h .GetBucket (min )
260
+ bucket .Add (shape , val )
261
+ return
262
+ }
263
+
290
264
for x := min .X ; x <= max .X ; x ++ {
291
265
for y := min .Y ; y <= max .Y ; y ++ {
292
266
bucket := h .GetBucket (Index {x , y })
0 commit comments