comparison pkg/octree/strtree.go @ 4591:f456ce0a6a0e

STRTree: Made number of entries per node a parameter.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 09 Oct 2019 11:40:11 +0200
parents 114979e97a6c
children 680f1d8802f0
comparison
equal deleted inserted replaced
4589:9cd00133dff9 4591:f456ce0a6a0e
16 import ( 16 import (
17 "math" 17 "math"
18 "sort" 18 "sort"
19 ) 19 )
20 20
21 const numEntries = 8 21 const STRTreeDefaultEntries = 8
22 22
23 type STRTree struct { 23 type STRTree struct {
24 tin *Tin 24 Entries int
25 index []int32 25 tin *Tin
26 bboxes []Box2D 26 index []int32
27 bboxes []Box2D
27 } 28 }
28 29
29 func (s *STRTree) Build(t *Tin) { 30 func (s *STRTree) Build(t *Tin) {
31
32 if s.Entries == 0 {
33 s.Entries = STRTreeDefaultEntries
34 }
30 35
31 s.tin = t 36 s.tin = t
32 37
33 all := make([]int32, len(t.Triangles)) 38 all := make([]int32, len(t.Triangles))
34 39
111 ti := s.tin.Triangles[items[i]] 116 ti := s.tin.Triangles[items[i]]
112 tj := s.tin.Triangles[items[j]] 117 tj := s.tin.Triangles[items[j]]
113 return s.tin.Vertices[ti[0]].X < s.tin.Vertices[tj[0]].X 118 return s.tin.Vertices[ti[0]].X < s.tin.Vertices[tj[0]].X
114 }) 119 })
115 120
116 P := int(math.Ceil(float64(len(items)) / float64(numEntries))) 121 P := int(math.Ceil(float64(len(items)) / float64(s.Entries)))
117 S := int(math.Ceil(math.Sqrt(float64(P)))) 122 S := int(math.Ceil(math.Sqrt(float64(P))))
118 123
119 slices := strSplit(items, S) 124 slices := s.strSplit(items, S)
120 125
121 leaves := strJoin( 126 leaves := s.strJoin(
122 slices, S, 127 slices, S,
123 func(i, j int32) bool { 128 func(i, j int32) bool {
124 ti := s.tin.Triangles[i] 129 ti := s.tin.Triangles[i]
125 tj := s.tin.Triangles[j] 130 tj := s.tin.Triangles[j]
126 return s.tin.Vertices[ti[0]].Y < s.tin.Vertices[tj[0]].Y 131 return s.tin.Vertices[ti[0]].Y < s.tin.Vertices[tj[0]].Y
131 return s.buildNodes(leaves) 136 return s.buildNodes(leaves)
132 } 137 }
133 138
134 func (s *STRTree) buildNodes(items []int32) int32 { 139 func (s *STRTree) buildNodes(items []int32) int32 {
135 140
136 if len(items) <= numEntries { 141 if len(items) <= s.Entries {
137 return s.allocNode(items) 142 return s.allocNode(items)
138 } 143 }
139 144
140 sort.Slice(items, func(i, j int) bool { 145 sort.Slice(items, func(i, j int) bool {
141 return s.bbox(items[i]).X1 < s.bbox(items[j]).X1 146 return s.bbox(items[i]).X1 < s.bbox(items[j]).X1
142 }) 147 })
143 148
144 P := int(math.Ceil(float64(len(items)) / float64(numEntries))) 149 P := int(math.Ceil(float64(len(items)) / float64(s.Entries)))
145 S := int(math.Ceil(math.Sqrt(float64(P)))) 150 S := int(math.Ceil(math.Sqrt(float64(P))))
146 151
147 slices := strSplit(items, S) 152 slices := s.strSplit(items, S)
148 153
149 nodes := strJoin( 154 nodes := s.strJoin(
150 slices, S, 155 slices, S,
151 func(i, j int32) bool { return s.bbox(i).Y1 < s.bbox(j).Y1 }, 156 func(i, j int32) bool { return s.bbox(i).Y1 < s.bbox(j).Y1 },
152 s.allocNode, 157 s.allocNode,
153 ) 158 )
154 159
160 idx = -idx - 1 165 idx = -idx - 1
161 } 166 }
162 return s.bboxes[s.index[idx]] 167 return s.bboxes[s.index[idx]]
163 } 168 }
164 169
165 func strSplit(items []int32, S int) [][]int32 { 170 func (s *STRTree) strSplit(items []int32, S int) [][]int32 {
166 sm := S * numEntries 171 sm := S * s.Entries
167 slices := make([][]int32, S) 172 slices := make([][]int32, S)
168 for i := range slices { 173 for i := range slices {
169 var n int 174 var n int
170 if l := len(items); l < sm { 175 if l := len(items); l < sm {
171 n = l 176 n = l
176 items = items[n:] 181 items = items[n:]
177 } 182 }
178 return slices 183 return slices
179 } 184 }
180 185
181 func strJoin( 186 func (s *STRTree) strJoin(
182 slices [][]int32, S int, 187 slices [][]int32, S int,
183 less func(int32, int32) bool, 188 less func(int32, int32) bool,
184 alloc func([]int32) int32, 189 alloc func([]int32) int32,
185 ) []int32 { 190 ) []int32 {
186 nodes := make([]int32, 0, S*S) 191 nodes := make([]int32, 0, S*S)
190 return less(slice[i], slice[j]) 195 return less(slice[i], slice[j])
191 }) 196 })
192 197
193 for len(slice) > 0 { 198 for len(slice) > 0 {
194 var n int 199 var n int
195 if l := len(slice); l >= numEntries { 200 if l := len(slice); l >= s.Entries {
196 n = numEntries 201 n = s.Entries
197 } else { 202 } else {
198 n = l 203 n = l
199 } 204 }
200 nodes = append(nodes, alloc(slice[:n])) 205 nodes = append(nodes, alloc(slice[:n]))
201 slice = slice[n:] 206 slice = slice[n:]