├── src ├── r-nearest.js ├── r-nearest-test.js ├── nearest.js ├── octree.js ├── octree-test.js ├── naive-nearest.js └── naive-nearest-test.js ├── .babelrc ├── .gitignore ├── package.json └── webpack.config.js /src/r-nearest.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/r-nearest-test.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | *.swp 4 | -------------------------------------------------------------------------------- /src/nearest.js: -------------------------------------------------------------------------------- 1 | import {NaiveNearest} from './naive-nearest.js'; 2 | import {RNearest} from './r-nearest.js'; 3 | 4 | // Nearest 5 | export class Nearest { 6 | insert() {} 7 | get() {} 8 | update() {} 9 | refresh() {} 10 | } 11 | 12 | 13 | 14 | export {NaiveNearest}; 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nearest", 3 | "version": "0.4.20", 4 | "description": "nearest-neighbors... as fast as I can", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "yah": "./node_modules/mocha/bin/mocha --require babel-register --require babel-polyfill src/*-test.js" 9 | }, 10 | "author": "", 11 | "license": "UNLICENSE", 12 | "dependencies": { 13 | "babel": "^6.23.0", 14 | "babel-polyfill": "^6.26.0", 15 | "babel-preset-es2015": "^6.24.1", 16 | "babel-register": "^6.26.0" 17 | }, 18 | "devDependencies": { 19 | "babel-core": "^6.26.3", 20 | "mocha": "^5.2.0", 21 | "uglifyjs-webpack-plugin": "^1.2.5" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | 4 | module.exports = { 5 | context: __dirname + "/src", 6 | entry: './index.js', 7 | output: { 8 | path: __dirname + '/dist', 9 | filename: 'nearest.bundled.min.js', 10 | publicPath: "assets/", 11 | libraryTarget: 'var', 12 | library: 'nearest', 13 | }, 14 | // devtool: 'source-map', 15 | plugins: new webpack.optimize.UglifyJsPlugin(), 16 | module: { 17 | { 18 | test: /\.js?$/, 19 | exclude: /node_modules/, 20 | loader: 'babel', 21 | query: { 22 | presets: ['es2015'], 23 | }, 24 | }, 25 | ], 26 | }, 27 | externals: { 28 | "THREE": "THREE", 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/octree.js: -------------------------------------------------------------------------------- 1 | 2 | // Octnode: parent-child aware 3 | class Octnode { 4 | 5 | // Constructor 6 | constructor(id, position) { 7 | this.id = id; 8 | this.parent = null; 9 | this.children = null; 10 | } 11 | 12 | leaf() { 13 | return null; 14 | } 15 | 16 | // Return where in the tree it is 17 | depth() { 18 | return 0; 19 | } 20 | } 21 | 22 | 23 | // Octree 24 | export class Octree { 25 | constructor() { 26 | this.root = new Octnode(); 27 | this.nodes = {}; 28 | this.keys = []; 29 | } 30 | 31 | update(id, node) { 32 | if (!this.nodes.hasOwnProperty(id)) { 33 | this.keys.push(id); 34 | } 35 | this.nodes[id] = node; 36 | } 37 | 38 | remove(node) { 39 | } 40 | 41 | near(box) { 42 | return []; 43 | } 44 | 45 | size() { 46 | return this.keys.length; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/octree-test.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import {Octree} from './octree.js'; 3 | 4 | 5 | describe("Octree", () => { 6 | 7 | describe("- Basic Operations", () => { 8 | 9 | it("add nodes", () => { 10 | let t = new Octree(); 11 | t.update("ok", [0.0, 0.0, 0.0]); 12 | t.update("ok", [0.0, 0.0, 0.0]); 13 | assert.equal(t.size(), 1); 14 | t.update("butt", [1.0, 0.0, 0.0]); 15 | assert.equal(t.size(), 2); 16 | }); 17 | 18 | it("x_x", () => { 19 | let t = new Octree(); 20 | t.update("ok", [0.0, 0.0, 0.0]); 21 | t.update("ok", [0.0, 0.0, 0.0]); 22 | let hits = t.near({ 23 | center: [0.0, 0.0, 0.0], 24 | width: 1.0, 25 | height: 1.0, 26 | depth: 1.0, 27 | }); 28 | assert.equal(hits.length, 2); 29 | }); 30 | 31 | it("should never", () => { 32 | }); 33 | 34 | }); 35 | }); 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/naive-nearest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Naive Nearest 3 | * Naive implementation of nearest-neighbor map. 4 | * Mostly used to ensure everything works. 5 | */ 6 | export class NaiveNearest { 7 | constructor() { 8 | this.points = []; 9 | } 10 | 11 | // 12 | insert(points) { 13 | points.forEach((v) => { 14 | this.points.push(v); 15 | }); 16 | } 17 | 18 | // Return list of points matching position 19 | get({center, width, height, depth}) { 20 | let results = []; 21 | 22 | let w2 = width/2.0; 23 | let h2 = height/2.0; 24 | let d2 = depth/2.0; 25 | 26 | this.points.forEach((v) => { 27 | let cx = v[0] - center[0]; 28 | let cy = v[1] - center[1]; 29 | let cz = v[2] - center[2]; 30 | 31 | if (Math.abs(cx) > w2) { 32 | return; 33 | } else if (Math.abs(cy) > h2) { 34 | return; 35 | } else if (Math.abs(cx) > d2) { 36 | return; 37 | } 38 | 39 | results.push(v); 40 | }); 41 | 42 | return results; 43 | } 44 | 45 | // Update 46 | update(obj) { 47 | // Update a single node 48 | } 49 | 50 | // Savage 51 | refresh() { 52 | // Refresh all nodes (in case they moved) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/naive-nearest-test.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import {NaiveNearest} from './nearest.js'; 3 | 4 | 5 | describe("Box", () => { 6 | 7 | describe("- Basic", () => { 8 | }); 9 | 10 | }); 11 | 12 | describe("Nearest", () => { 13 | 14 | describe("- Basic Operations", function() { 15 | 16 | it("should insert multiple points", () => { 17 | let n = new NaiveNearest(); 18 | n.insert( 19 | [0.0, 0.0, 0.0], 20 | [0.0, 0.0, 0.0], 21 | [0.0, 0.0, 0.0], 22 | ); 23 | assert.equal(n.points.length, 3); 24 | }); 25 | 26 | it("should find points in a region", () => { 27 | let n = new NaiveNearest(); 28 | 29 | let insert_these = [ 30 | [0.0, 0.0, 0.0], 31 | [0.0, 0.0, 0.0], 32 | [0.0, 0.0, 0.0], 33 | [10.0, 0.0, 0.0], 34 | [11.0, 11.0, 11.0], 35 | ]; 36 | 37 | n.insert(insert_these); 38 | 39 | let matches = n.get({ 40 | center: [0.0, 0.0, 0.0], 41 | width: 2.0, 42 | height: 2.0, 43 | depth: 2.0, 44 | }) 45 | 46 | assert.equal(matches.length, 3); 47 | assert.equal(matches[0], insert_these[0]); 48 | assert.equal(matches[1], insert_these[1]); 49 | assert.equal(matches[2], insert_these[2]); 50 | 51 | matches = n.get({ 52 | center: [0.0, 0.0, 0.0], 53 | width: 20.0, 54 | height: 20.0, 55 | depth: 20.0, 56 | }) 57 | 58 | assert.equal(matches.length, 4); 59 | assert.equal(matches[0], insert_these[0]); 60 | assert.equal(matches[1], insert_these[1]); 61 | assert.equal(matches[2], insert_these[2]); 62 | assert.equal(matches[3], insert_these[3]); 63 | 64 | matches = n.get({ 65 | center: [15.0, 15.0, 10.0], 66 | width: 10.0, 67 | height: 10.0, 68 | depth: 10.0, 69 | }) 70 | 71 | assert.equal(matches.length, 1); 72 | assert.equal(matches[0], insert_these[4]); 73 | }); 74 | 75 | }); 76 | }); 77 | --------------------------------------------------------------------------------