mirror of https://github.com/tidwall/tile38.git
96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
package index
|
|
|
|
import (
|
|
"github.com/tidwall/boxtree/d2"
|
|
)
|
|
|
|
// Index is a geospatial index
|
|
type Index struct {
|
|
r d2.BoxTree
|
|
}
|
|
|
|
// New create a new index
|
|
func New() *Index {
|
|
return &Index{}
|
|
}
|
|
|
|
// Item represents an index item.
|
|
type Item interface {
|
|
Point() (x, y float64)
|
|
Rect() (minX, minY, maxX, maxY float64)
|
|
}
|
|
|
|
// FlexItem can represent a point or a rectangle
|
|
type FlexItem struct {
|
|
MinX, MinY, MaxX, MaxY float64
|
|
}
|
|
|
|
// Rect returns the rectangle
|
|
func (item *FlexItem) Rect() (minX, minY, maxX, maxY float64) {
|
|
return item.MinX, item.MinY, item.MaxX, item.MaxY
|
|
}
|
|
|
|
// Point returns the point
|
|
func (item *FlexItem) Point() (x, y float64) {
|
|
return item.MinX, item.MinY
|
|
}
|
|
|
|
// Insert inserts an item into the index
|
|
func (ix *Index) Insert(item Item) {
|
|
minX, minY, maxX, maxY := item.Rect()
|
|
ix.r.Insert([]float64{minX, minY}, []float64{maxX, maxY}, item)
|
|
}
|
|
|
|
// Remove removed an item from the index
|
|
func (ix *Index) Remove(item Item) {
|
|
minX, minY, maxX, maxY := item.Rect()
|
|
ix.r.Delete([]float64{minX, minY}, []float64{maxX, maxY}, item)
|
|
}
|
|
|
|
// Count counts all items in the index.
|
|
func (ix *Index) Count() int {
|
|
return ix.r.Count()
|
|
}
|
|
|
|
// Bounds returns the minimum bounding rectangle of all items in the index.
|
|
func (ix *Index) Bounds() (MinX, MinY, MaxX, MaxY float64) {
|
|
min, max := ix.r.Bounds()
|
|
return min[0], min[1], max[0], max[1]
|
|
|
|
}
|
|
|
|
// RemoveAll removes all items from the index.
|
|
func (ix *Index) RemoveAll() {
|
|
ix.r = d2.BoxTree{}
|
|
}
|
|
|
|
// KNN returns the nearsest neighbors
|
|
func (ix *Index) KNN(x, y float64, iterator func(item interface{}) bool) bool {
|
|
res := true
|
|
ix.r.Nearby([]float64{x, y}, []float64{x, y},
|
|
func(_, _ []float64, item interface{}) bool {
|
|
if !iterator(item) {
|
|
res = false
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
return res
|
|
}
|
|
|
|
// Search returns all items that intersect the bounding box.
|
|
func (ix *Index) Search(minX, minY, maxX, maxY float64,
|
|
iterator func(item interface{}) bool,
|
|
) bool {
|
|
res := true
|
|
ix.r.Search([]float64{minX, minY}, []float64{maxX, maxY},
|
|
func(_, _ []float64, item interface{}) bool {
|
|
if !iterator(item) {
|
|
res = false
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
return res
|
|
}
|