rtree.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. package rtred
  2. import (
  3. "math"
  4. "sync"
  5. "github.com/tidwall/rtred/base"
  6. )
  7. type Iterator func(item Item) bool
  8. type Item interface {
  9. Rect(ctx interface{}) (min []float64, max []float64)
  10. }
  11. type RTree struct {
  12. dims int
  13. maxEntries int
  14. ctx interface{}
  15. trs []*base.RTree
  16. used int
  17. }
  18. func New(ctx interface{}) *RTree {
  19. tr := &RTree{
  20. ctx: ctx,
  21. dims: 20,
  22. maxEntries: 13,
  23. }
  24. tr.trs = make([]*base.RTree, 20)
  25. return tr
  26. }
  27. func (tr *RTree) Insert(item Item) {
  28. if item == nil {
  29. panic("nil item")
  30. }
  31. min, max := item.Rect(tr.ctx)
  32. if len(min) != len(max) {
  33. return // just return
  34. panic("invalid item rectangle")
  35. }
  36. if len(min) < 1 || len(min) > len(tr.trs) {
  37. return // just return
  38. panic("invalid dimension")
  39. }
  40. btr := tr.trs[len(min)-1]
  41. if btr == nil {
  42. btr = base.New(len(min), tr.maxEntries)
  43. tr.trs[len(min)-1] = btr
  44. tr.used++
  45. }
  46. amin := make([]float64, len(min))
  47. amax := make([]float64, len(max))
  48. for i := 0; i < len(min); i++ {
  49. amin[i], amax[i] = min[i], max[i]
  50. }
  51. btr.Insert(amin, amax, item)
  52. }
  53. func (tr *RTree) Remove(item Item) {
  54. if item == nil {
  55. panic("nil item")
  56. }
  57. min, max := item.Rect(tr.ctx)
  58. if len(min) != len(max) {
  59. return // just return
  60. panic("invalid item rectangle")
  61. }
  62. if len(min) < 1 || len(min) > len(tr.trs) {
  63. return // just return
  64. panic("invalid dimension")
  65. }
  66. btr := tr.trs[len(min)-1]
  67. if btr == nil {
  68. return
  69. }
  70. amin := make([]float64, len(min))
  71. amax := make([]float64, len(max))
  72. for i := 0; i < len(min); i++ {
  73. amin[i], amax[i] = min[i], max[i]
  74. }
  75. btr.Remove(amin, amax, item)
  76. if btr.IsEmpty() {
  77. tr.trs[len(min)-1] = nil
  78. tr.used--
  79. }
  80. }
  81. func (tr *RTree) Reset() {
  82. for i := 0; i < len(tr.trs); i++ {
  83. tr.trs[i] = nil
  84. }
  85. tr.used = 0
  86. }
  87. func (tr *RTree) Count() int {
  88. var count int
  89. for _, btr := range tr.trs {
  90. if btr != nil {
  91. count += btr.Count()
  92. }
  93. }
  94. return count
  95. }
  96. func (tr *RTree) Search(bounds Item, iter Iterator) {
  97. if bounds == nil {
  98. panic("nil bounds being used for search")
  99. }
  100. min, max := bounds.Rect(tr.ctx)
  101. if len(min) != len(max) {
  102. return // just return
  103. panic("invalid item rectangle")
  104. }
  105. if len(min) < 1 || len(min) > len(tr.trs) {
  106. return // just return
  107. panic("invalid dimension")
  108. }
  109. used := tr.used
  110. for i, btr := range tr.trs {
  111. if used == 0 {
  112. break
  113. }
  114. if btr != nil {
  115. if !search(btr, min, max, i+1, iter) {
  116. return
  117. }
  118. used--
  119. }
  120. }
  121. }
  122. func search(btr *base.RTree, min, max []float64, dims int, iter Iterator) bool {
  123. amin := make([]float64, dims)
  124. amax := make([]float64, dims)
  125. for i := 0; i < dims; i++ {
  126. if i < len(min) {
  127. amin[i] = min[i]
  128. amax[i] = max[i]
  129. } else {
  130. amin[i] = math.Inf(-1)
  131. amax[i] = math.Inf(+1)
  132. }
  133. }
  134. var ended bool
  135. btr.Search(amin, amax, func(item interface{}) bool {
  136. if !iter(item.(Item)) {
  137. ended = true
  138. return false
  139. }
  140. return true
  141. })
  142. return !ended
  143. }
  144. func (tr *RTree) KNN(bounds Item, center bool, iter func(item Item, dist float64) bool) {
  145. if bounds == nil {
  146. panic("nil bounds being used for search")
  147. }
  148. min, max := bounds.Rect(tr.ctx)
  149. if len(min) != len(max) {
  150. return // just return
  151. panic("invalid item rectangle")
  152. }
  153. if len(min) < 1 || len(min) > len(tr.trs) {
  154. return // just return
  155. panic("invalid dimension")
  156. }
  157. if tr.used == 0 {
  158. return
  159. }
  160. if tr.used == 1 {
  161. for i, btr := range tr.trs {
  162. if btr != nil {
  163. knn(btr, min, max, center, i+1, func(item interface{}, dist float64) bool {
  164. return iter(item.(Item), dist)
  165. })
  166. break
  167. }
  168. }
  169. return
  170. }
  171. type queueT struct {
  172. done bool
  173. step int
  174. item Item
  175. dist float64
  176. }
  177. var mu sync.Mutex
  178. var ended bool
  179. queues := make(map[int][]queueT)
  180. cond := sync.NewCond(&mu)
  181. for i, btr := range tr.trs {
  182. if btr != nil {
  183. dims := i + 1
  184. mu.Lock()
  185. queues[dims] = []queueT{}
  186. cond.Signal()
  187. mu.Unlock()
  188. go func(dims int, btr *base.RTree) {
  189. knn(btr, min, max, center, dims, func(item interface{}, dist float64) bool {
  190. mu.Lock()
  191. if ended {
  192. mu.Unlock()
  193. return false
  194. }
  195. queues[dims] = append(queues[dims], queueT{item: item.(Item), dist: dist})
  196. cond.Signal()
  197. mu.Unlock()
  198. return true
  199. })
  200. mu.Lock()
  201. queues[dims] = append(queues[dims], queueT{done: true})
  202. cond.Signal()
  203. mu.Unlock()
  204. }(dims, btr)
  205. }
  206. }
  207. mu.Lock()
  208. for {
  209. ready := true
  210. for i := range queues {
  211. if len(queues[i]) == 0 {
  212. ready = false
  213. break
  214. }
  215. if queues[i][0].done {
  216. delete(queues, i)
  217. }
  218. }
  219. if len(queues) == 0 {
  220. break
  221. }
  222. if ready {
  223. var j int
  224. var minDist float64
  225. var minItem Item
  226. var minQueue int
  227. for i := range queues {
  228. if j == 0 || queues[i][0].dist < minDist {
  229. minDist = queues[i][0].dist
  230. minItem = queues[i][0].item
  231. minQueue = i
  232. }
  233. }
  234. queues[minQueue] = queues[minQueue][1:]
  235. if !iter(minItem, minDist) {
  236. ended = true
  237. break
  238. }
  239. continue
  240. }
  241. cond.Wait()
  242. }
  243. mu.Unlock()
  244. }
  245. func knn(btr *base.RTree, min, max []float64, center bool, dims int, iter func(item interface{}, dist float64) bool) bool {
  246. amin := make([]float64, dims)
  247. amax := make([]float64, dims)
  248. for i := 0; i < dims; i++ {
  249. if i < len(min) {
  250. amin[i] = min[i]
  251. amax[i] = max[i]
  252. } else {
  253. amin[i] = math.Inf(-1)
  254. amax[i] = math.Inf(+1)
  255. }
  256. }
  257. var ended bool
  258. btr.KNN(amin, amax, center, func(item interface{}, dist float64) bool {
  259. if !iter(item.(Item), dist) {
  260. ended = true
  261. return false
  262. }
  263. return true
  264. })
  265. return !ended
  266. }