Giter Site home page Giter Site logo

kdbush's Introduction

Go - KDBush

Go Reference codecov

Golang KD-Bush implementation

A very fast static spatial index for 2D points based on a flat KD-tree and almost Zero-Allocation

  • 2 Dimensional Points only โ€” no rectangles.
  • Static โ€” you can't add/remove items after initial indexing (You need to rebuild index)
  • Faster indexing and search, with lower memory footprint
  • Build-in API with almost Zero-Allocation (See #Benchmark)
    • Range: return indexes within 2 point
    • Within: return indexes within radius of point

Extension

  • Geo Ext. A simple geographic extension for Golang port of KDBush, support get point around location coordinates

This implementation is based on:

Requirement:

  • Go 1.18+ (Generic)

Usage

Install like usually

go get github.com/raditzlawliet/kdbush

Before building index, you need to create list of Points by implement Point interface

// Point interface
type Point interface {
	GetX() (X float64)
	GetY() (Y float64)
}

// Example Simple Point implement Point Interface
type SimplePoint struct {
	X, Y float64
}

func (p *SimplePoint) GetX() (X float64) {
	return p.X
}

func (p *SimplePoint) GetY() (Y float64) {
	return p.Y
}

Then, you can building KDBush index. Standard Node Size is 64. Higher value means faster indexing but slower search and vice versa.

// 0. Creating array Points
points = []kdbush.Point{
    &kdbush.SimplePoint{0.0, 0.0},
    &kdbush.SimplePoint{2.0, 2.0},
    &kdbush.SimplePoint{1.0, 1.0},
    &kdbush.SimplePoint{-2.0, -2.0},
    &kdbush.SimplePoint{-1.0, -1.0},
    &kdbush.SimplePoint{2.0, -2.0},
    &kdbush.SimplePoint{1.0, -1.0},
    &kdbush.SimplePoint{-2.0, 2.0},
    &kdbush.SimplePoint{-1.0, 1.0},
    &kdbush.SimplePoint{1.0, 0.0},
    &kdbush.SimplePoint{2.0, 0.0},
    &kdbush.SimplePoint{-1.0, 0.0},
    &kdbush.SimplePoint{-2.0, 0.0},
    &kdbush.SimplePoint{0.0, 1.0},
    &kdbush.SimplePoint{0.0, 2.0},
    &kdbush.SimplePoint{0.0, -1.0},
    &kdbush.SimplePoint{0.0, -2.0},

// 1. Build Index (prefered way)
bush := kdbush.NewBush().
    BuildIndex(points, kdbush.STANDARD_NODE_SIZE)

// Ready to use
// API Range
indexes := bush.Range(-2.1, 1.0, 2.1, 1.0)
// [2 8 13]
for _, v := range indexes {
  fmt.Println(points[v])
}
// &{1 1} &{-1 1} &{0 1}

// API Within X, Y with Radius
indexes := bush.Within(0, 0, 1)
// [0 9 11 13 15]
for _, v := range indexes {
  fmt.Println(points[v])
}
// &{0 0} &{1 0} &{-1 0} &{0 1} &{0 -1}

kDBush library didn't store original slices to avoid duplication slice

Since index are static. if you need rebuild or adding new point for some case, you can call BuildIndex() multiple times. Keep in mind, you will need more resources to rebuild...

bush := kdbush.NewBush().
  BuildIndex(points, kdbush.STANDARD_NODE_SIZE)
points.Add(newPoint)
bush.BuildIndex(points, kdbush.STANDARD_NODE_SIZE)

To avoid datarace on concurrency, please make sure lock bush when build index and you also can check it's already indexed or not via KDBush.Indexed()

API

BuildIndex(points, nodeSize) *KDBush

bulding kd-tree index given list of points and nodeSize, and return *KDBush

  • points: list Point interface []Point
  • nodeSize: kd-tree node size. Standard Node Size is 64. Higher value means faster indexing but slower search and vice versa. int

Range(minX, minY, maxX, maxY) []int

return all indexes points across 2 point minX, minY, maxX, maxY

  • minX: point X of A float64
  • minY: point Y of A float64
  • maxX: point X of B float64
  • maxY: point Y of B float64

Within(x, y, radius) []int

return all indexes points within radius of given single point x, y

  • x: X point float64
  • y: Y point float64
  • radius: radius to search within float64

Benchmark

All benchmark are run on Go 1.20.3, Windows 11 & 12th Gen Intel(R) Core(TM) i7-12700H (Laptop version).

Do not trust benchmark

go test -bench=. -benchmem

BenchmarkBuildIndex/nodeSize_64_total_1000-20              66031             17605 ns/op           24576 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_64_total_10000-20              1380            825414 ns/op          245760 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_64_total_100000-20              100          10672552 ns/op         2408448 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_64_total_1000000-20               8         125372525 ns/op        24010752 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_8_total_1000-20               19930             58559 ns/op           24576 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_8_total_10000-20               1090           1097253 ns/op          245760 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_8_total_100000-20                81          14333335 ns/op         2408448 B/op          2 allocs/op
BenchmarkBuildIndex/nodeSize_8_total_1000000-20                7         164077629 ns/op        24010752 B/op          2 allocs/op
BenchmarkRange/nodeSize_64_total_10-20                  88866507                14.03 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_64_total_100-20                 16080229                76.07 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_64_total_1000-20                12128733                99.23 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_64_total_10000-20               17081582                69.91 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_64_total_100000-20              12586558                92.07 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_64_total_1000000-20             10143787               119.4 ns/op             0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_10-20                   140908826                8.477 ns/op           0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_100-20                  70526006                17.62 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_1000-20                 47799242                26.17 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_10000-20                32195490                38.34 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_100000-20               24681555                48.29 ns/op            0 B/op          0 allocs/op
BenchmarkRange/nodeSize_8_total_1000000-20              20815878                56.69 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_10-20                 97434231                11.75 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_100-20                17370007                66.08 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_1000-20               14064499                90.85 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_10000-20              19023159                61.59 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_100000-20             14507365                81.15 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_64_total_1000000-20            11783131               101.1 ns/op             0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_10-20                  134839747                8.773 ns/op           0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_100-20                 62120803                19.70 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_1000-20                43613366                27.79 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_10000-20               29173159                40.47 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_100000-20              23700660                50.03 ns/op            0 B/op          0 allocs/op
BenchmarkWithin/nodeSize_8_total_1000000-20             21675673                55.10 ns/op            0 B/op          0 allocs/op

kdbush's People

Contributors

raditzlawliet avatar

Stargazers

 avatar

Watchers

 avatar

kdbush's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.