- Notifications
You must be signed in to change notification settings - Fork1
lovoo/rtreego
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A library for efficiently storing and querying spatial datain the Go programming language.
The R-tree is a popular data structure for efficiently storing andquerying spatial objects; one common use is implementing geospatialindexes in database management systems. Both bounding-box queriesand k-nearest-neighbor queries are supported.
R-trees are balanced, so maximum tree height is guaranteed to belogarithmic in the number of entries; however, good worst-caseperformance is not guaranteed. Instead, a number of rebalancingheuristics are applied that perform well in practice. For moredetails please refer to the references.
This implementation handles the general N-dimensional case; for a moreefficient implementation for the 3-dimensional case, seePatrickHiggins' fork.
Get the source code fromGitHub or,with Go 1 installed, rungo get github.com/dhconnelly/rtreego
.
Make sure youimport github.com/dhconnelly/rtreego
in your Go source files.
To create a new tree, specify the number of spatial dimensions and the minimumand maximum branching factor:
rt := rtreego.NewTree(2, 25, 50)
You can also bulk-load the tree when creating it by passing the objects asa parameter.
rt := rtreego.NewTree(2, 25, 50, objects...)
Any type that implements theSpatial
interface can be stored in the tree:
type Spatial interface { Bounds() *Rect}
Rect
s are data structures for representing spatial objects, whilePoint
srepresent spatial locations. CreatingPoint
s is easy--they're just slicesoffloat64
s:
p1 := rtreego.Point{0.4, 0.5}p2 := rtreego.Point{6.2, -3.4}
To create aRect
, specify a location and the lengths of the sides:
r1, _ := rtreego.NewRect(p1, []float64{1, 2})r2, _ := rtreego.NewRect(p2, []float64{1.7, 2.7})
To demonstrate, let's create and store some test data.
type Thing struct { where *Rect name string}func (t *Thing) Bounds() *Rect { return t.where}rt.Insert(&Thing{r1, "foo"})rt.Insert(&Thing{r2, "bar"})size := rt.Size() // returns 2
We can insert and delete objects from the tree in any order.
rt.Delete(thing2)// do some stuff...rt.Insert(anotherThing)
Note thatDelete
function does the equality comparison by comparing thememory addresses of the objects. If you do not have a pointer to the originalobject anymore, you can define a custom comparator.
type Comparator func(obj1, obj2 Spatial) (equal bool)
You can use a custom comparator withDeleteWithComparator
function.
cmp := func(obj1, obj2 Spatial) bool { sp1 := obj1.(*IDRect) sp2 := obj2.(*IDRect) return sp1.ID == sp2.ID}rt.DeleteWithComparator(obj, cmp)
If you want to store points instead of rectangles, you can easily convert apoint into a rectangle using theToRect
method:
var tol = 0.01type Somewhere struct { location rtreego.Point name string wormhole chan int}func (s *Somewhere) Bounds() *Rect { // define the bounds of s to be a rectangle centered at s.location // with side lengths 2 * tol: return s.location.ToRect(tol)}rt.Insert(&Somewhere{rtreego.Point{0, 0}, "Someplace", nil})
If you want to update the location of an object, you must delete it, update it,and re-insert. Just modifying the object so that the*Rect
returned byLocation()
changes, without deleting and re-inserting the object, willcorrupt the tree.
Bounding-box and k-nearest-neighbors queries are supported.
Bounding-box queries require a search*Rect
. It returns all objects thattouch the search rectangle.
bb, _ := rtreego.NewRect(rtreego.Point{1.7, -3.4}, []float64{3.2, 1.9})// Get a slice of the objects in rt that intersect bb:results := rt.SearchIntersect(bb)
You can filter out values during searches by implementing Filter functions.
type Filter func(results []Spatial, object Spatial) (refuse, abort bool)
A filter for limiting results by result count is included in the package forbackwards compatibility.
// maximum of three results will be returnedtree.SearchIntersect(bb, LimitFilter(3))
Nearest-neighbor queries find the objects in a tree closest to a specifiedquery point.
q := rtreego.Point{6.5, -2.47}k := 5// Get a slice of the k objects in rt closest to q:results = rt.NearestNeighbors(k, q)
SeeGoDoc for full APIdocumentation.
A. Guttman. R-trees: A Dynamic Index Structure for Spatial Searching.Proceedings of ACM SIGMOD, pages 47-57, 1984.http://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Guttman84.pdf
N. Beckmann, H .P. Kriegel, R. Schneider and B. Seeger. The R*-tree: AnEfficient and Robust Access Method for Points and Rectangles. Proceedingsof ACM SIGMOD, pages 323-331, May 1990.http://infolab.usc.edu/csci587/Fall2011/papers/p322-beckmann.pdf
N. Roussopoulos, S. Kelley and F. Vincent. Nearest Neighbor Queries. ACMSIGMOD, pages 71-79, 1995.http://www.postgis.org/support/nearestneighbor.pdf
Written byDaniel Connelly (dhconnelly@gmail.com).
rtreego is released under a BSD-style license, described in theLICENSE
file.