golang高性能零内存分配通用四叉树插件库quadtree的使用

golang高性能零内存分配通用四叉树插件库quadtree的使用

quadtree是一个用于Golang的四叉树实现库。

特性

  • 泛型支持
  • 高度优化
  • 零内存分配
  • 100%测试覆盖率

示例代码

下面是一个完整的使用示例:

import (
    "log"

    "github.com/s0rg/quadtree"
)

func main() {
    // 创建新的四叉树,参数为宽度、高度和最大深度
    tree := quadtree.New[int](100.0, 100.0, 4)

    // 添加一些点
    tree.Add(10.0, 10.0, 5.0, 5.0, 1)
    tree.Add(15.0, 20.0, 10.0, 10.0, 2)
    tree.Add(40.0, 10.0, 4.0, 4.0, 3)
    tree.Add(90.0, 90.0, 5.0, 8.0, 4)

    // 查询指定区域内的值
    val, ok := tree.Get(9.0, 9.0, 11.0, 11.0)
    if !ok {
        log.Fatal("not found")
    }

    log.Println(val) // 应该输出1

    const (
        distance = 20.0
        count = 2
    )

    // 查找最近的K个邻居
    tree.KNearest(80.0, 80.0, distance, count, func(x, y, w, h float64, val int) {
        log.Printf("(%f, %f, %f, %f) = %d", x, y, w, h, val)
    })

    // 输出: (90.000000, 90.000000, 5.000000, 8.000000) = 4
}

性能基准测试

goos: linux
goarch: amd64
pkg: github.com/s0rg/quadtree
cpu: AMD Ryzen 5 5500U with Radeon Graphics
BenchmarkNode/Insert-12             14974236      71.07 ns/op       249 B/op          0 allocs/op
BenchmarkNode/Del-12                6415672       188.3 ns/op         0 B/op          0 allocs/op
BenchmarkNode/Search-12             21702474      51.83 ns/op         0 B/op          0 allocs/op
BenchmarkTree/Add-12                18840514      67.83 ns/op       241 B/op          0 allocs/op
BenchmarkTree/Get-12                21204722      55.46 ns/op         0 B/op          0 allocs/op
BenchmarkTree/Move-12               8061322       147.5 ns/op         0 B/op          0 allocs/op
BenchmarkTree/ForEach-12            18723290      58.60 ns/op         0 B/op          0 allocs/op
BenchmarkTree/KNearest-12           3595956       324.7 ns/op         0 B/op          0 allocs/op
BenchmarkTree/Del-12                6234123       193.1 ns/op         0 B/op          0 allocs/op
PASS
ok      github.com/s0rg/quadtree    12.666s

从基准测试结果可以看出,该库在各种操作上都表现出色,且确实实现了零内存分配的目标。


更多关于golang高性能零内存分配通用四叉树插件库quadtree的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能零内存分配通用四叉树插件库quadtree的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go高性能四叉树库quadtree使用指南

quadtree是一个高性能的Go语言四叉树实现库,特别注重零内存分配和高效查询。下面我将详细介绍它的使用方法和示例代码。

安装

go get github.com/paulmach/orb/quadtree

基本概念

四叉树是一种树数据结构,每个节点最多有四个子节点,用于二维空间划分。常用于:

  • 空间索引
  • 碰撞检测
  • 图像处理
  • 地理信息系统(GIS)

基本使用

1. 创建四叉树

package main

import (
	"fmt"
	"github.com/paulmach/orb"
	"github.com/paulmach/orb/quadtree"
)

func main() {
	// 定义四叉树边界 (minX, minY, maxX, maxY)
	bounds := orb.Bound{Min: orb.Point{0, 0}, Max: orb.Point{100, 100}}
	
	// 创建四叉树
	qt := quadtree.New(bounds)
	
	// 可选:设置最大深度和节点容量
	// qt := quadtree.NewWithOptions(bounds, quadtree.Options{
	//     MaxDepth:     10,
	//     NodeCapacity: 4,
	// })
}

2. 插入数据

// 插入点数据
points := []orb.Point{
	{10, 10}, {20, 20}, {30, 30}, {40, 40},
	{50, 50}, {60, 60}, {70, 70}, {80, 80},
}

for _, p := range points {
	qt.Insert(p)
}

// 插入带数据的点
type DataPoint struct {
	ID   int
	Data string
}

qtData := quadtree.New(bounds)
for i, p := range points {
	qtData.Insert(quadtree.Point{
		Point: p,
		Data:  DataPoint{ID: i, Data: fmt.Sprintf("point-%d", i)},
	})
}

3. 查询操作

// 查找矩形区域内的所有点
searchBound := orb.Bound{Min: orb.Point{15, 15}, Max: orb.Point{45, 45}}
results := qt.InBound(searchBound)
fmt.Println("Points in bound:", results)

// 查找距离某点最近的点
nearest := qt.FindNearest(orb.Point{25, 25})
fmt.Println("Nearest point:", nearest)

// 范围查询带数据的点
dataResults := qtData.InBound(searchBound)
for _, r := range dataResults {
	if dp, ok := r.Data.(DataPoint); ok {
		fmt.Printf("Point %v with data: %+v\n", r.Point, dp)
	}
}

高性能技巧

1. 避免内存分配

// 重用切片减少分配
var reuse []orb.Point
results = qt.InBound(searchBound, reuse[:0])

// 使用预分配的缓冲区
buffer := make([]orb.Point, 0, 10)
results = qt.InBound(searchBound, buffer)

2. 批量插入

// 批量插入比单次插入更高效
allPoints := make([]orb.Point, 0, len(points))
for _, p := range points {
	allPoints = append(allPoints, p)
}
qt.InsertAll(allPoints)

3. 自定义数据类型

// 轻量级自定义类型减少内存占用
type LightPoint struct {
	X, Y float64
	ID   uint16
}

qtCustom := quadtree.New(bounds)
for i, p := range points {
	qtCustom.Insert(quadtree.Point{
		Point: p,
		Data:  LightPoint{X: p[0], Y: p[1], ID: uint16(i)},
	})
}

实际应用示例:碰撞检测

type GameObject struct {
	ID     int
	Bounds orb.Bound
}

// 创建游戏对象四叉树
gameBounds := orb.Bound{Min: orb.Point{0, 0}, Max: orb.Point{1000, 1000}}
gameQT := quadtree.New(gameBounds)

objects := []GameObject{
	{1, orb.Bound{Min: orb.Point{100, 100}, Max: orb.Point{150, 150}}},
	{2, orb.Bound{Min: orb.Point{200, 200}, Max: orb.Point{250, 250}}},
	// 更多对象...
}

// 插入对象中心点
for _, obj := range objects {
	center := obj.Bounds.Center()
	gameQT.Insert(quadtree.Point{
		Point: center,
		Data:  obj,
	})
}

// 检测碰撞
func CheckCollisions(qt *quadtree.Quadtree, obj GameObject) []GameObject {
	center := obj.Bounds.Center()
	radius := obj.Bounds.Max[0] - obj.Bounds.Min[0] // 假设是正方形
	
	searchBound := orb.Bound{
		Min: orb.Point{center[0] - radius, center[1] - radius},
		Max: orb.Point{center[0] + radius, center[1] + radius},
	}
	
	var collisions []GameObject
	for _, item := range qt.InBound(searchBound) {
		if other, ok := item.Data.(GameObject); ok && other.ID != obj.ID {
			if obj.Bounds.Intersects(other.Bounds) {
				collisions = append(collisions, other)
			}
		}
	}
	return collisions
}

性能注意事项

  1. 选择合适的边界大小 - 太大会降低查询效率,太小会导致频繁分裂
  2. 调整MaxDepth和NodeCapacity参数以适应你的数据分布
  3. 对于静态数据,构建后不再修改的四叉树性能最佳
  4. 频繁更新的场景考虑批量更新而非单次操作

quadtree库通过精心设计实现了高性能和低内存开销,非常适合需要高效空间查询的Go应用程序。

回到顶部