• Stars
    star
    302
  • Rank 135,310 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 10 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A static kdtree data structure

static-kdtree

kd-trees are a compact data structure for answering orthogonal range and nearest neighbor queries on higher dimensional point data in linear time. While they are not as efficient at answering orthogonal range queries as range trees - especially in low dimensions - kdtrees consume exponentially less space, support k-nearest neighbor queries and are relatively cheap to construct. This makes them useful in small to medium dimensions for achieving a modest speed up over a linear scan.

Note that kd-trees are not the best data structure in all circumstances. If you want to do range searching, here is a chart to help you select one which is appropriate for a given dimension:

Dimension Preferred Data Structure Complexity Size
1 Binary search tree O(log(n)) O(n)
2-3 Range tree O(log^(d-1)(n)) O(n log^(d-1) (n))
Medium kd-tree O(d*n^(1-1/d)) O(n)
Big Array O(n) O(n)

And for nearest neighbor searching, here is a survey of some different options:

Dimension Preferred Data Structure Complexity Size
1 Binary search tree O(log(n)) O(n)
2 Voronoi diagram O(log(n)) O(n)
Medium kd-tree O(n) (but maybe better) O(n)
Big Array O(n) O(n)

It is also worth mentioning that for approximate nearest neighbor queries or queries with a fixed size radius, grids and locality sensitive hashing are strictly better options. In these charts the transition between "Medium" and "Big" depends on how many points there are in the data structure. As the number of points grows larger, the dimension at which kdtrees become practical goes up.

This module works both in node.js and with browserify.

testling badge

build status

Example

//Import library
var createKDTree = require("static-kdtree")

//Create a bunch of points
var points = [
  [0, 1, 100],
  [-5, 0.11, Math.PI],
  [0, 10, -13],

  // ...

  [4, 3, 1]
]

//Create the tree
var tree = createKDTree(points)

//Iterate over all points in the bounding box
tree.range([-1, -1, -1], [10, 1, 2], function(idx) {
  console.log("visit:", idx)  //idx = index of point in points array
})

//Can also search in spheres
tree.rnn([0,0,0], 10, function(idx) {
  console.log("point " + idx + " is in sphere at origin with radius=10")
})

//Nearest neighbor queries
console.log("index of closest point to [0,1,2] is ", tree.nn([0,1,2]))

//And k-nearest neighbor queries
console.log("index of 10 closest points to [0,1,2] are ", tree.knn([0,1,2], 10))

//For performance, be sure to delete tree when you are done with it
tree.dispose()

Install

npm install static-kdtree

API

var createKDTree = require("static-kdtree")

By convention, let n denote the number of points and d denote the dimension of the kdtree.

Constructor

var kdt = createKDTree(points)

Creates a kdtree from the given collection of points.

  • points is either an array of arrays of length d, or else an ndarray with shape [n,d]

Returns A kdtree data structure

Time Complexity This operation takes O(n log(n))

var kdt = createKDTree.deserialze(data)

Restores a serialized kdtree.

  • data is a JavaScript object as produced by calling kdt.serialize

Returns A kdtree data structure equivalent to the one which was serialized.

Time Complexity O(n)

Properties

kdt.dimension

The dimension of the tree

kdt.length

The number of points in the tree

Methods

kdt.range(lo, hi, visit)

Executes an orthogonal range query on the kdtree

  • lo is a lower bound on the range
  • hi is an upper bound
  • visit(idx) is a visitor function which is called once for every point contained in the range [lo,hi]. If visit(idx) returns any value !== undefined, then termination is halted.

Returns The last returned value of visit

Time Complexity O(d*n^(1-1/d) + k), where k is the number of points in the range.

kdt.rnn(point, radius, visit)

Visit all points contained in the sphere of radius r centered at point

  • point is the center point for the query, represented by a length d array
  • radius is the radius of the query sphere
  • visit(idx) is a function which is called once for every point contained in the ball. As in the case of kdt.range, if visit(idx) returns a not undefined value, then iteration is terminated.

Returns The last returned value of visit

Time Complexity O(n + k), where k is the number of points in the sphere, though perhaps much less than n depending on the distribution of the points.

kdt.nn(point[, maxDistance])

Returns the index of the closest point to point

  • point is a query point
  • maxDistance is an upper bound on the distance to search for nearest points. Default Infinity

Returns The index of the closest point in the tree to point, or -1 if the tree is empty.

Time Complexity O(n log(n)) in the worst case, but in practice much faster if the points are uniformly distributed.

kdt.knn(point, k[, maxDistance])

Returns a list of the k closest points to point in the tree.

  • point is the point which is being queried
  • k is the number of points to query
  • maxDistance bounds the distance of the returned points. Default is Infinity

Returns A list of indices for the k closest points to point in the tree which are within distance < maxDistance. The indices are ordered by distance to point.

Time Complexity O((n + k) log(n + k)), but may be faster if the points in the tree are uniformly distributed

kdt.serialize()

Returns a serializable JSON object encoding the state of the kdtree. This can be passed to deserialize() to restore the kdtree.

kdt.dispose()

Release all resources associated with the kdtree. This is not necessary, but can reduce garbage collector pressure over time.

Time Complexity O(1)

Comparisons

To test the performance of this module, experiments were performed against two other kdtree libraries (Ubilabs kdtree and node-kdtree), as well as a naive brute force algorithm. Ubilabs kdtree is pure JavaScript, and supports only kNN queries and does not correctly implement rNN queries. node-kdtree is a wrapper over the native C++ library, libkdtree, and only supports rNN and NN queries. Neither library implements range queries. These libraries were tested in node.js 0.10.26 and Chrome 34 on a MacBook Pro, Core i7 2.3GHz with 8GB of RAM. The results from these experiments can be found here:

And the code for these experiments can be found in the bench/ subdirectory of this repository.

Observations

Up to 1000 points or so brute force searching is the fastest method for answering any query, so for small data sets it is probably better to not use a kdtree or any data structure in the first place.

The latest version of v8 in Chrome is strictly faster than node.js for all test cases and modules. Because of native C++ dependencies, node-kdtree cannot run in a browser, but even so the Chrome version of static-kdtree is 2-3x faster. static-kdtree is also up to an order of magnitude faster than Ubilabs kdtree at all operations, making it by far the best choice in the browser.

In node.js, the situation is slightly more ambiguous. node-kdtree has the fastest construction time, and also answers 1-nearest neighbor queries faster. Both Ubilabs kdtree and static-kdtree take about the same amount of time on nearest neighbors queries. On all other queries static-kdtree is again strictly faster. It is unclear why the performance of nearest neighbor queries is slightly slower in node.js, but perhaps it may be related to node.js' v8 engine being several versions behind Chrome. In future updates this situation may start to look more like Chrome, making static-kdtree likely to be the better option for long term.

Credits

(c) 2014 Mikola Lysenko. MIT License

More Repositories

1

l1-path-finder

🗺 Fast path planning for 2D grids
JavaScript
471
star
2

functional-red-black-tree

A purely functional red-black tree data structure
JavaScript
358
star
3

vectorize-text

Turns a text string into a 2D poly line
JavaScript
303
star
4

orthogami

Orthogonal polyhedra origami
JavaScript
279
star
5

box-intersect

📦 Any dimensional box intersection
JavaScript
271
star
6

robust-point-in-polygon

Exactly test if a point is inside, outside or on the boundary of a polygon
JavaScript
229
star
7

cdt2d

2D constrained Delaunay triangulation
JavaScript
223
star
8

mikolalysenko.github.com

JavaScript
210
star
9

laplacian-deformation

Laplacian mesh deformation
C++
209
star
10

robust-arithmetic-notes

Tutorial on robust arithmetic in JavaScript
JavaScript
198
star
11

isosurface

Isosurface polygonizer algorithms
JavaScript
166
star
12

mudb

Low latency state replication for the web
TypeScript
165
star
13

delaunay-triangulate

Easy to use robust Delaunay triangulation
JavaScript
153
star
14

game-shell

Ready to go JavaScript shell for games or other interactive demos
JavaScript
118
star
15

patcher.js

JSON diffing and patching library
JavaScript
112
star
16

electron-recorder

Record animations using Electron
JavaScript
108
star
17

surface-nets

Arbitrary dimensional level sets
JavaScript
96
star
18

binary-search-bounds

Better binary searching
JavaScript
88
star
19

dynamic-forest

Maintain a dynamic spanning forest of a graph under edge insertions and deletions
JavaScript
84
star
20

uniq

Removes duplicate items from an array in place
JavaScript
81
star
21

NodeMinecraftThing

Javascript MMO framework
JavaScript
78
star
22

pitch-shift

Variable speed pitch shifter written in JavaScript
JavaScript
78
star
23

refine-mesh

Iterative mesh refinement
JavaScript
77
star
24

box-intersect-benchmark

Box intersection benchmark
JavaScript
74
star
25

typedarray-pool

Reuse typed arrays
JavaScript
74
star
26

rectangle-decomposition

Computes a minimal rectangular decomposition of a rectilinear polygon
JavaScript
71
star
27

conway-hart

A port of George Hart's implementation/extension of Conway's polyhedral notation to CommonJS
JavaScript
69
star
28

femgl

WebGL finite element viewer
JavaScript
68
star
29

interval-tree-1d

1D interval tree
JavaScript
67
star
30

voxel-mipmap-demo

Demo of mipmapping for voxel terrain
JavaScript
66
star
31

alpha-shape

Any dimensional alpha shapes
JavaScript
66
star
32

simplicial-complex

Tools for manipulating simplicial complexes in JavaScript
JavaScript
63
star
33

mespeak

NPM entry for mespeak for easier installation and usage in browserify
JavaScript
62
star
34

detect-pitch

Detects the pitch of an audio snippet
JavaScript
61
star
35

drag-and-drop-files

Handle file drag-and-drop events without all the Yak shaving
JavaScript
55
star
36

vertex-ao

Vertex based ambient occlusion calculation for meshes
JavaScript
53
star
37

bit-twiddle

Bit twidling hacks for node.js
JavaScript
53
star
38

mouse-wheel

Speed controlled mouse scrolling
JavaScript
50
star
39

to-px

Convert any CSS unit to logical pixels (aka "px")
JavaScript
48
star
40

voronoi-diagram

n-dimensional voronoi diagram constructor
JavaScript
46
star
41

local-perception-filter-demo

Demonstration of local perception filters in a browser
JavaScript
46
star
42

monotone-convex-hull-2d

Robust and fast 2D convex hull
JavaScript
44
star
43

clean-pslg

Clean up messy planar straight line graphs
JavaScript
44
star
44

greedy-mesher

Greedy mesh compiler
JavaScript
43
star
45

ndarray-experiments

Multidimensional typed arrays in JS
JavaScript
42
star
46

glsl-read-float

Read floating point values back from WebGL
JavaScript
41
star
47

a-big-triangle

Draws a big triangle onto the screen
JavaScript
41
star
48

ao-mesher

Voxel mesher with ambient occlusion
JavaScript
40
star
49

convex-hull

Any dimensional convex hull
JavaScript
36
star
50

stft

Short time Fourier transform
JavaScript
34
star
51

taubin-smooth

Taubin's mesh smoothing algorithm implemented in JavaScript
HTML
34
star
52

plastimesh

👾 A free form mesh sculpting tool
JavaScript
34
star
53

3d-view-controls

A camera with input hooks for basic 3D projects
JavaScript
34
star
54

orbit-camera

Orbit camera for 3D scenes
JavaScript
33
star
55

LudumDare23MMO

LudumDare23 MMO source code (rebuilt to remove database stuff)
JavaScript
33
star
56

ndarray-project-list

List of stuff todo with ndarrays
33
star
57

voxelize

Voxelizes a triangulated mesh into an ndarray
JavaScript
32
star
58

gif-3d

3D gif visualizer
JavaScript
29
star
59

haar-tree-3d

3D Wavelet Rasterization
JavaScript
29
star
60

mouse-event

Cross browser mouse event property access
JavaScript
28
star
61

strongly-connected-components

Computes the strongly connected components of a directed graph
JavaScript
27
star
62

union-find

A basic union-find data structure for node.js
JavaScript
26
star
63

0fpsBlog

Code and examples for 0fps blog
JavaScript
25
star
64

point-in-region

Fast and exact point in region location
JavaScript
25
star
65

node-latex

node.js wrapper for LaTeX
JavaScript
25
star
66

incremental-delaunay

Constructs a Delaunay triangulation for a collection of points
JavaScript
24
star
67

angle

Almost Native Graphics Layer Engine (local fork)
C++
24
star
68

bibtex-parser

A CommonJS port of BibTeX-js
JavaScript
24
star
69

count-min-sketch

Count-Min Sketch Data Structure
JavaScript
24
star
70

bound-points

Find a bounding box for a set of points
JavaScript
23
star
71

MineHack

WebGL based AJAX videogame -- with MMO, Minecraft and Roguelike elements.
C
23
star
72

robust-orientation

Robustly computes the orientation of a tuple of points
JavaScript
23
star
73

lpf-ctf

Multiplayer capture the flag demo
JavaScript
23
star
74

parse-obj

Parses a .OBJ file
JavaScript
23
star
75

cubic-hermite

Cubic hermite interpolation
JavaScript
22
star
76

angle-normals

Compute mesh normals using angle weights
JavaScript
22
star
77

ao-shader

Ambient occlusion shader for ao-mesher
JavaScript
22
star
78

svg-3d-simplicial-complex

Renders a simplicial complex to a list of polygons in SVG
JavaScript
22
star
79

ndarray-tutorial

Guide to ndarrays
21
star
80

mesh-fixer

Fixes holes in 3D meshes
HTML
20
star
81

functional-priority-queue

A functional priority queue in JavaScript
JavaScript
20
star
82

3p

Progressive triangle streams
JavaScript
20
star
83

bunny

The Stanford bunny
19
star
84

ndpack-image

Package an image into a requireable module
JavaScript
19
star
85

gl-modules

A modular approach to WebGL programming
19
star
86

csr-matrix

Compressed sparse row matrix for node.js
JavaScript
19
star
87

contour2d

Extracts a rectilinear polygon contour from a binary image
JavaScript
18
star
88

mathmode

Turns LaTeX math mode expressions into images
JavaScript
18
star
89

triangulate-polyline

Triangulates a complex polygon
JavaScript
18
star
90

poly-bool

Exact polygon boolean operations
JavaScript
18
star
91

filtered-vector

Path smoothing for vector valued input curves
JavaScript
18
star
92

gl-render-text

Renders text to a WebGL texture
JavaScript
17
star
93

differential-growth

Differential growth, inspired by @inconvergent
JavaScript
17
star
94

point-in-big-polygon

Industrial strength point in polygon test
JavaScript
17
star
95

vishull2d

Visible regions for 2D poly-lines
JavaScript
17
star
96

normals

Computes normals for triangulated meshes
JavaScript
17
star
97

commutative-rendering

Ideas about modular graphical rendering
16
star
98

vj-stuff

Stream of consciousness programmed WebGL visualizations
JavaScript
16
star
99

split-polygon

Splits a convex polygon by a plane
JavaScript
16
star
100

control-flow

Control flow graph and 3AC form for JavaScript programs
JavaScript
16
star