### Inspect R-tree properties and bounding boxes Source: https://context7.com/dhconnelly/rtreego/llms.txt Demonstrates how to initialize an R-tree, populate it with spatial objects, and query its internal structure and node bounding boxes. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) type Area struct { bounds rtreego.Rect name string } func (a *Area) Bounds() rtreego.Rect { return a.bounds } func main() { // Create tree with known parameters rt := rtreego.NewTree(2, 2, 4) // Insert enough items to create multiple levels for i := 0; i < 20; i++ { rect, _ := rtreego.NewRect( rtreego.Point{float64(i % 5), float64(i / 5)}, []float64{0.8, 0.8}, ) rt.Insert(&Area{rect, fmt.Sprintf("area-%d", i)}) } // Inspect tree structure fmt.Printf("Tree properties:\n") fmt.Printf(" Dimensions: %d\n", rt.Dim) fmt.Printf(" Min children: %d\n", rt.MinChildren) fmt.Printf(" Max children: %d\n", rt.MaxChildren) fmt.Printf(" Size (objects): %d\n", rt.Size()) fmt.Printf(" Depth (levels): %d\n", rt.Depth()) // Output: // Tree properties: // Dimensions: 2 // Min children: 2 // Max children: 4 // Size (objects): 20 // Depth (levels): 3 // Get all internal bounding boxes (useful for visualization) allBB := rt.GetAllBoundingBoxes() fmt.Printf("\nInternal bounding boxes (%d nodes):\n", len(allBB)) for i, bb := range allBB { if i < 3 { // Print first few fmt.Printf(" %s (size: %.2f)\n", bb, bb.Size()) } } // Output shows bounding boxes of internal tree nodes } ``` -------------------------------- ### Create Points and Rectangles Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Initialize spatial primitives using points (slices of float64) and rectangles (location and side lengths). ```Go p1 := rtreego.Point{0.4, 0.5} p2 := rtreego.Point{6.2, -3.4} ``` ```Go r1, _ := rtreego.NewRect(p1, []float64{1, 2}) r2, _ := rtreego.NewRect(p2, []float64{1.7, 2.7}) ``` -------------------------------- ### Initialize and Bulk-load an R-tree Source: https://context7.com/dhconnelly/rtreego/llms.txt Create a new R-tree with specified dimensions and branching factors, optionally bulk-loading objects using the OMT algorithm. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) func main() { // Create an empty 2D R-tree with min=25, max=50 branching factor rt := rtreego.NewTree(2, 25, 50) fmt.Printf("Empty tree size: %d, depth: %d\n", rt.Size(), rt.Depth()) // Output: Empty tree size: 0, depth: 1 // Bulk-load objects during creation (uses OMT algorithm for large datasets) objects := make([]rtreego.Spatial, 1000) for i := 0; i < 1000; i++ { rect, _ := rtreego.NewRect(rtreego.Point{float64(i), float64(i)}, []float64{1, 1}) objects[i] = &Location{rect, fmt.Sprintf("loc-%d", i)} } rtBulk := rtreego.NewTree(2, 25, 50, objects...) fmt.Printf("Bulk-loaded tree size: %d, depth: %d\n", rtBulk.Size(), rtBulk.Depth()) // Output: Bulk-loaded tree size: 1000, depth: 3 } type Location struct { bounds rtreego.Rect name string } func (l *Location) Bounds() rtreego.Rect { return l.bounds } ``` -------------------------------- ### Initialize an R-tree Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Create a new R-tree instance by specifying dimensions and branching factors, with an optional bulk-load of objects. ```Go rt := rtreego.NewTree(2, 25, 50) ``` ```Go rt := rtreego.NewTree(2, 25, 50, objects...) ``` -------------------------------- ### Perform K-Nearest Neighbors Search in Go Source: https://context7.com/dhconnelly/rtreego/llms.txt Shows how to find the nearest neighbor or k-nearest neighbors to a point, including applying filters to the KNN search. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) type Restaurant struct { name string location rtreego.Point cuisine string } func (r *Restaurant) Bounds() rtreego.Rect { return r.location.ToRect(0.001) } func main() { rt := rtreego.NewTree(2, 5, 10) // Insert restaurants restaurants := []struct { name string x, y float64 cuisine string }{ {"Italian Place", 1.0, 1.0, "Italian"}, {"Sushi Bar", 2.5, 0.5, "Japanese"}, {"Taco Stand", 0.5, 2.0, "Mexican"}, {"Burger Joint", 3.0, 3.0, "American"}, {"Thai Kitchen", 1.5, 1.5, "Thai"}, {"French Bistro", 4.0, 1.0, "French"}, } for _, r := range restaurants { rt.Insert(&Restaurant{r.name, rtreego.Point{r.x, r.y}, r.cuisine}) } // Find the single nearest neighbor userLocation := rtreego.Point{1.2, 1.3} nearest := rt.NearestNeighbor(userLocation) if nearest != nil { rest := nearest.(*Restaurant) fmt.Printf("Closest restaurant: %s (%s)\n", rest.name, rest.cuisine) } // Output: Closest restaurant: Thai Kitchen (Thai) // Find k=3 nearest neighbors k := 3 nearestK := rt.NearestNeighbors(k, userLocation) fmt.Printf("\nTop %d nearest restaurants:\n", k) for i, r := range nearestK { rest := r.(*Restaurant) fmt.Printf(" %d. %s (%s)\n", i+1, rest.name, rest.cuisine) } // Output: // Top 3 nearest restaurants: // 1. Thai Kitchen (Thai) // 2. Italian Place (Italian) // 3. Sushi Bar (Japanese) // KNN with custom filter (only Japanese restaurants) japaneseFilter := func(results []rtreego.Spatial, obj rtreego.Spatial) (refuse, abort bool) { rest := obj.(*Restaurant) return rest.cuisine != "Japanese", false } nearestJapanese := rt.NearestNeighbors(2, userLocation, japaneseFilter) fmt.Printf("\nNearest Japanese restaurants:\n") for _, r := range nearestJapanese { rest := r.(*Restaurant) fmt.Printf(" - %s\n", rest.name) } // Output: // Nearest Japanese restaurants: // - Sushi Bar } ``` -------------------------------- ### Apply Search Filters in Go Source: https://context7.com/dhconnelly/rtreego/llms.txt Demonstrates using LimitFilter to restrict result counts and custom filter functions to refine search results based on object properties. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) type Store struct { name string bounds rtreego.Rect category string rating float64 } func (s *Store) Bounds() rtreego.Rect { return s.bounds } func main() { rt := rtreego.NewTree(2, 5, 10) // Insert stores stores := []struct { name string x, y float64 category string rating float64 }{ {"Coffee Shop A", 1, 1, "coffee", 4.5}, {"Restaurant B", 2, 2, "restaurant", 4.2}, {"Coffee Shop C", 3, 1, "coffee", 4.8}, {"Grocery D", 1, 3, "grocery", 3.9}, {"Coffee Shop E", 2, 1, "coffee", 4.1}, } for _, s := range stores { rect, _ := rtreego.NewRect(rtreego.Point{s.x, s.y}, []float64{0.5, 0.5}) rt.Insert(&Store{s.name, rect, s.category, s.rating}) } searchBB, _ := rtreego.NewRect(rtreego.Point{0, 0}, []float64{5, 5}) // Search with limit filter - only return first 2 results limited := rt.SearchIntersect(searchBB, rtreego.LimitFilter(2)) fmt.Printf("Limited to 2 results: %d stores found\n", len(limited)) // Output: Limited to 2 results: 2 stores found // Custom filter: only coffee shops with rating >= 4.5 coffeeFilter := func(results []rtreego.Spatial, obj rtreego.Spatial) (refuse, abort bool) { store := obj.(*Store) if store.category != "coffee" || store.rating < 4.5 { return true, false // refuse this entry, continue search } return false, false // accept entry } coffeeShops := rt.SearchIntersect(searchBB, coffeeFilter) fmt.Printf("High-rated coffee shops:\n") for _, r := range coffeeShops { store := r.(*Store) fmt.Printf(" - %s (%.1f stars)\n", store.name, store.rating) } // Output: // High-rated coffee shops: // - Coffee Shop A (4.5 stars) // - Coffee Shop C (4.8 stars) // Combine filters: coffee shops, max 1 result combined := rt.SearchIntersect(searchBB, coffeeFilter, rtreego.LimitFilter(1)) fmt.Printf("First high-rated coffee shop: %d found\n", len(combined)) // Output: First high-rated coffee shop: 1 found } ``` -------------------------------- ### Insert and Manage Objects Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Store objects implementing the Spatial interface and retrieve the current tree size. ```Go 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 ``` -------------------------------- ### Insert and Delete Objects in Rtreego Source: https://context7.com/dhconnelly/rtreego/llms.txt Demonstrates inserting items, deleting by pointer reference, and using custom comparators for deletion. Note that updating an object requires a delete-then-insert cycle to avoid tree corruption. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) type Item struct { id int bounds rtreego.Rect } func (i *Item) Bounds() rtreego.Rect { return i.bounds } func main() { rt := rtreego.NewTree(2, 2, 4) // Create and insert items items := make([]*Item, 5) for i := 0; i < 5; i++ { rect, _ := rtreego.NewRect(rtreego.Point{float64(i * 10), float64(i * 10)}, []float64{5, 5}) items[i] = &Item{id: i, bounds: rect} rt.Insert(items[i]) } fmt.Printf("After insert: size=%d\n", rt.Size()) // Output: After insert: size=5 // Delete using pointer reference deleted := rt.Delete(items[2]) fmt.Printf("Delete items[2]: success=%v, size=%d\n", deleted, rt.Size()) // Output: Delete items[2]: success=true, size=4 // Delete using custom comparator (when you don't have the original pointer) comparator := func(obj1, obj2 rtreego.Spatial) bool { item1 := obj1.(*Item) item2 := obj2.(*Item) return item1.id == item2.id } // Create a new Item with same ID to find and delete searchItem := &Item{id: 4, bounds: items[4].bounds} deleted = rt.DeleteWithComparator(searchItem, comparator) fmt.Printf("Delete by ID: success=%v, size=%d\n", deleted, rt.Size()) // Output: Delete by ID: success=true, size=3 // Updating an object requires delete + re-insert items[0].bounds, _ = rtreego.NewRect(rtreego.Point{100, 100}, []float64{5, 5}) // WARNING: Direct modification corrupts the tree! Must delete first rt.Delete(items[0]) rt.Insert(items[0]) fmt.Printf("After update: size=%d\n", rt.Size()) // Output: After update: size=3 } ``` -------------------------------- ### Define Points and Rectangles Source: https://context7.com/dhconnelly/rtreego/llms.txt Construct spatial primitives including points, axis-aligned rectangles, and point-to-rectangle conversions for N-dimensional space. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) func main() { // Create 2D points p1 := rtreego.Point{0.4, 0.5} p2 := rtreego.Point{6.2, -3.4} fmt.Printf("Point 1: %v, Point 2: %v\n", p1, p2) // Create rectangle from point and side lengths rect1, err := rtreego.NewRect(p1, []float64{1.0, 2.0}) if err != nil { panic(err) } fmt.Printf("Rect1: %v, Size: %.2f\n", rect1, rect1.Size()) // Output: Rect1: [0.40, 1.40]x[0.50, 2.50], Size: 2.00 // Create rectangle from two corner points minPt := rtreego.Point{0.0, 0.0} maxPt := rtreego.Point{5.0, 10.0} rect2, _ := rtreego.NewRectFromPoints(minPt, maxPt) fmt.Printf("Rect2: %v, Size: %.2f\n", rect2, rect2.Size()) // Output: Rect2: [0.00, 5.00]x[0.00, 10.00], Size: 50.00 // Convert a point to a rectangle (useful for point-based objects) tolerance := 0.01 pointRect := p1.ToRect(tolerance) fmt.Printf("Point as Rect (tol=0.01): %v\n", pointRect) // Output: Point as Rect (tol=0.01): [0.39, 0.41]x[0.49, 0.51] // 3D example p3d := rtreego.Point{1.0, 2.0, 3.0} rect3d, _ := rtreego.NewRect(p3d, []float64{1.0, 1.0, 1.0}) fmt.Printf("3D Rect: %v, Size: %.2f\n", rect3d, rect3d.Size()) // Output: 3D Rect: [1.00, 2.00]x[2.00, 3.00]x[3.00, 4.00], Size: 1.00 } ``` -------------------------------- ### Perform Bounding-Box Queries Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Search for objects that intersect with a specified search rectangle. ```Go 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) ``` -------------------------------- ### Implement the Spatial Interface Source: https://context7.com/dhconnelly/rtreego/llms.txt Define custom types that satisfy the Spatial interface by implementing the Bounds() method to enable storage in an R-tree. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) // Store rectangles with metadata type Building struct { bounds rtreego.Rect name string floors int } func (b *Building) Bounds() rtreego.Rect { return b.bounds } // Store points with a tolerance for the bounding box type Sensor struct { location rtreego.Point id string value float64 } const sensorTolerance = 0.001 func (s *Sensor) Bounds() rtreego.Rect { return s.location.ToRect(sensorTolerance) } func main() { rt := rtreego.NewTree(2, 5, 10) // Insert buildings b1Rect, _ := rtreego.NewRect(rtreego.Point{0, 0}, []float64{100, 50}) building := &Building{b1Rect, "Office Tower", 20} rt.Insert(building) // Insert sensors as points sensor := &Sensor{rtreego.Point{50, 25}, "temp-001", 72.5} rt.Insert(sensor) fmt.Printf("Tree contains %d objects\n", rt.Size()) // Output: Tree contains 2 objects } ``` -------------------------------- ### Perform Nearest-Neighbor Queries Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Retrieve a specified number of objects closest to a given point using the NearestNeighbors method. ```Go 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) ``` -------------------------------- ### Apply a Limit Filter Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Use the built-in LimitFilter to restrict the number of results returned by a search operation. ```Go // maximum of three results will be returned tree.SearchIntersect(bb, LimitFilter(3)) ``` -------------------------------- ### Store Points as Rectangles Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Convert a point into a rectangle using the ToRect method to satisfy the Spatial interface. ```Go var tol = 0.01 type 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}) ``` -------------------------------- ### Define a Filter Function Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Implement this function signature to create custom logic for refusing or aborting spatial search results. ```Go type Filter func(results []Spatial, object Spatial) (refuse, abort bool) ``` -------------------------------- ### Define Spatial Interface Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Implement the Spatial interface to allow custom types to be stored in the R-tree. ```Go type Spatial interface { Bounds() *Rect } ``` -------------------------------- ### Delete Objects Source: https://github.com/dhconnelly/rtreego/blob/master/README.md Remove objects from the tree using standard deletion or a custom comparator for equality checks. ```Go rt.Delete(thing2) // do some stuff... rt.Insert(anotherThing) ``` ```Go type Comparator func(obj1, obj2 Spatial) (equal bool) ``` ```Go cmp := func(obj1, obj2 Spatial) bool { sp1 := obj1.(*IDRect) sp2 := obj2.(*IDRect) return sp1.ID == sp2.ID } rt.DeleteWithComparator(obj, cmp) ``` -------------------------------- ### Search Intersecting Objects in Rtreego Source: https://context7.com/dhconnelly/rtreego/llms.txt Performs a spatial search to find all objects whose bounding boxes intersect with a specified query rectangle. ```go package main import ( "fmt" "github.com/dhconnelly/rtreego" ) type City struct { name string bounds rtreego.Rect } func (c *City) Bounds() rtreego.Rect { return c.bounds } func main() { rt := rtreego.NewTree(2, 5, 10) // Insert cities with their geographic bounds cities := []struct { name string x, y float64 w, h float64 }{ {"New York", -74.0, 40.7, 0.3, 0.2}, {"Los Angeles", -118.2, 34.0, 0.4, 0.3}, {"Chicago", -87.6, 41.8, 0.2, 0.2}, {"Houston", -95.3, 29.7, 0.3, 0.3}, {"Phoenix", -112.0, 33.4, 0.3, 0.2}, } for _, c := range cities { rect, _ := rtreego.NewRect(rtreego.Point{c.x, c.y}, []float64{c.w, c.h}) rt.Insert(&City{c.name, rect}) } // Search for cities in the midwest/northeast region searchBB, _ := rtreego.NewRect(rtreego.Point{-90, 40}, []float64{20, 5}) results := rt.SearchIntersect(searchBB) fmt.Printf("Cities in search region:\n") for _, r := range results { city := r.(*City) fmt.Printf(" - %s\n", city.name) } // Output: // Cities in search region: // - New York // - Chicago } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.