├── .babelrc
├── .eslintrc.json
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── index.html
├── index.js
├── index.umd.js
├── logo.svg
├── package.json
├── rollup.config.js
├── test.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["latest", {
4 | "es2015": {
5 | "modules": false
6 | }
7 | }]
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["eslint:recommended", "google"],
3 | "parserOptions": {
4 | "ecmaVersion": 6,
5 | "sourceType": "module",
6 | "ecmaFeatures": {
7 | "jsx": true
8 | }
9 | },
10 | "rules": {
11 | "semi": 2,
12 | "no-console": 0
13 | },
14 | "env": {
15 | "node": true
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | cache:
3 | directories:
4 | - node_modules
5 | notifications:
6 | email: false
7 | node_js:
8 | - '8'
9 | before_script:
10 | - npm prune
11 | after_success:
12 | - npm run semantic-release
13 | branches:
14 | except:
15 | - /^v\d+\.\d+\.\d+$/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 David Aerne
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Closestᐁector
4 | [](https://travis-ci.org/meodai/ClosestVector)
5 |
6 | Get closest Number / Point / Vector / VectorN from an array and caches the previous get request/response paris.
7 |
8 | ## Installation
9 | `npm install closestvector --save` or `yarn add closestvector`
10 |
11 | ## Usage
12 | ```javascript
13 | const Closest = require('closestvector');
14 | const closest = new Closest([[255,0,0], [0,255,0], [0,0,255], [0,0,0]]);
15 | closest.get([200,130,213]) // => [0,0,255]
16 | ```
17 |
18 | **if you wish to return every value only once:**
19 | ```javascript
20 | const closest = new Closest([[255,0,0], [0,255,0], [0,0,255], [0,0,0]], true);
21 | closest.get([200,130,213]) // => [0,0,255] closest Vector
22 | closest.get([200,130,213]) // => [255,0,0] next closest Vector
23 | closest.clearCache() // resets the returned elements
24 | closest.get([200,130,213]) // => [0,0,255] closest Vector
25 | ```
26 |
27 | ## Examples
28 | ### Closest Vector2
29 | ```javascript
30 | const Closest = require('closestvector');
31 | const closestVector = new Closest([[1,2],[222,6],[222,5],[222,4]]);
32 |
33 | closestVector.get([255,255]) // => {"closest":[222,6],"index":1}
34 | closestVector.get([2,5]) // => {"closest":[1,2],"index":0}
35 | closestVector.get([64,12]) // => {"closest":[1,2],"index":0}
36 | ```
37 |
38 | ### Unique closest Vector2
39 | every vector can be retruned only once
40 |
41 | ```javascript
42 | const Closest = require('closestvector');
43 | const closestUniqueVector = new Closest([[1,2],[222,6],[222,5],[222,4]], true);
44 |
45 | closestUniqueVector.get([255,255]) // => {"closest":[222,6],"index":1}
46 | closestUniqueVector.get([255,255]) // => {"closest":[222,5],"index":2}
47 | closestUniqueVector.get([255,255]) // => {"closest":[222,4],"index":3}
48 | closestUniqueVector.get([255,255]) // => {"closest":[1,2],"index":0}
49 | closestUniqueVector.get([255,255]) // => Null (Out of entries to return)
50 | closestUniqueVector.clearCache()
51 | closestUniqueVector.get([255,255]) // => {"closest":[222,6],"index":1}
52 |
53 | ```
54 |
55 | ### Closest Number
56 | ```javascript
57 | const Closest = require('closestvector');
58 | const closestNumber = new Closest([10,3,10,45,30,120]);
59 |
60 | closestNumber.get(10) // => {closest: 10, index: 0}
61 | closestNumber.get(100) // => {closest: 120, index: 5}
62 | closestNumber.get(100000) // => {closest: 120, index: 5}
63 | closestNumber.get(1) // => {closest: 3, index: 1}
64 | ```
65 |
66 | ### Closest Vector3 or RGB Color
67 | ```javascript
68 | const Closest = require('closestvector');
69 | const closestColor = new Closest([
70 | [255,255,255],
71 | [0,0,0],
72 | [255,0,0],
73 | [0,255,0],
74 | [0,0,255],
75 | [0,255,255],
76 | [255,255,0]
77 | ]);
78 | closestColor.get([0,192,200]) // => {"closest":[0,255,255],"index":5}
79 | ```
80 |
81 | ## How it works
82 |
83 | From [the Wikipedia article on the subject](http://en.wikipedia.org/wiki/Nearest_neighbor_search):
84 | > The simplest solution to the NNS problem is to compute the distance from the query point
85 | > to every other point in the database, keeping track of the "best so far". This algorithm,
86 | > sometimes referred to as the naive approach, has a running time of *O(Nd)* where *N* is
87 | > the cardinality of *S* and *d* is the dimensionality of *M*. There are no search data
88 | > structures to maintain, so linear search has no space complexity beyond the storage of the
89 | > database. Naive search can, on average, outperform space partitioning approaches on higher
90 | > dimensional spaces.
91 |
92 | ClosestVector is inspired by [nearest-color] and was rewritten to solve snapping to coordinates in a less specific way. As nearest-color it uses the naive approach and caches the requests made, so the diffing only happens if the vector is requested for the first time.
93 |
94 | [nearest-color]: https://github.com/dtao/nearest-color/
95 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Closestᐁector - Demo Page
7 |
103 |
104 |
105 |
106 |
107 |
145 |
Super fast lightweight and dependency free library to get closest Number / Point / Vector / VectorN from an array
146 | with caching and stuff
147 |
155 |
169 |
178 |
179 |
180 |
181 |
182 |
192 |
193 |
233 |
234 |
392 |
393 |
394 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Return closest Number/Vector2/Vector3/VectorN from a given list
3 | * uses caching for faster response. Has the ability to return every match
4 | * only once.
5 | */
6 | export default class Closest {
7 | /**
8 | * Creates an instance of Closest.
9 | * @param {Array} list Elements of reference can be an Array of Numbers
10 | * or Array's with an equal length
11 | * @param {Boolean} unique If set to true, every entry from `list`
12 | * can be returned only once
13 | * unit clearCache() is called
14 | */
15 | constructor(list, unique) {
16 | // creates a copy of list
17 | this.list = Array.from(list);
18 |
19 | this.dimensions = Closest.getDimensions(list[0]);
20 |
21 | this.unique = unique;
22 |
23 | // sets the adequate diff method based on the depth of the vectors
24 | this.diff = this.dimensions > 1 ? Closest.nDimensionalDiff(this.dimensions)
25 | : Closest.oneDimensionalDiff;
26 | // console.log(this.diff)
27 | // inits the cache and previouslyReturnedIndexes properties
28 | this.clearCache(false);
29 | }
30 |
31 | /**
32 | * determines if the items in the list are simple numbers or arrays
33 | * @static
34 | * @param {Number|Array} item
35 | * @return {Number} number of dimensions (1 being a simple number,
36 | * everything above is an array)
37 | */
38 | static getDimensions(item) {
39 | return typeof item == 'number' ? 1 : item.length;
40 | }
41 |
42 | /**
43 | * diff function for simple numbers
44 | * @static
45 | * @param {Number} val1
46 | * @param {Number} val2
47 | * @return {Number} Abstract difference between two numbers
48 | */
49 | static oneDimensionalDiff(val1, val2) {
50 | return Math.abs(val1-val2);
51 | }
52 |
53 | /**
54 | * diff function for array's of N numbers
55 | * @static
56 | * @param {Number} dimensions number of dimensions of your vector
57 | * @return {Function} returns the adequate diff function
58 | * Euclidean distance
59 | * (https://en.wikipedia.org/wiki/Euclidean_distance)
60 | */
61 | static nDimensionalDiff(dimensions) {
62 | if (dimensions == 2) {
63 | return (val1, val2) => (
64 | (val1[0] - val2[0]) * (val1[0] - val2[0]) +
65 | (val1[1] - val2[1]) * (val1[1] - val2[1])
66 | );
67 | } else if (dimensions == 3) {
68 | return (val1, val2) => (
69 | (val1[0] - val2[0]) * (val1[0] - val2[0]) +
70 | (val1[1] - val2[1]) * (val1[1] - val2[1]) +
71 | (val1[2] - val2[2]) * (val1[2] - val2[2])
72 | );
73 | } else {
74 | // elegant but slow solution
75 | return (val1, val2) => (
76 | val1.reduce(
77 | (acc, val, i) => ((val - val2[i]) * (val - val2[i]) + acc)
78 | , 0)
79 | );
80 | }
81 | }
82 |
83 | /**
84 | Public method to rest cached value / result paris
85 | * especially if set to unique (return every match only once)
86 | * you may want to reset the previously returned indexes
87 | * @param {Boolean} indexOnly if you are using "unique" mode only the returned
88 | * indexes are cleared by default
89 | */
90 | clearCache(indexOnly = this.unique) {
91 | if (!indexOnly) {
92 | this.cache = {};
93 | }
94 | this.previouslyReturnedIndexes = [];
95 | }
96 |
97 | /**
98 | * gets the closes Number/VectorN
99 | * @param {Number|Array} val reference number or array
100 | * @return {Object|Null} closes match within lists containing
101 | * {
102 | * closest: {Number|Array} closest entry from list
103 | * index: {Number} index within list
104 | * distance: {Number} Distance within the
105 | * coordinate system
106 | * }
107 | */
108 | get(val) {
109 | let minDistance = Infinity;
110 | let index = 0;
111 | let closest = this.list[index];
112 |
113 | // is there a better way to do this? If "val" is only a number, it seams
114 | // like a big overhead to JSON stringify it every-time, I don't see an other
115 | // way when val is an array thought. Other than something like
116 | // cache[val[0]][val[1]][val[3]] or whatever
117 | const valUID = JSON.stringify(val);
118 |
119 | // returns previously found match
120 | if (!this.unique && this.cache.hasOwnProperty(valUID)) {
121 | return this.cache[valUID];
122 | }
123 |
124 | // if set to return every value in the list only once
125 | // and being out of entries in the list
126 | if (
127 | this.unique && this.previouslyReturnedIndexes.length === this.list.length
128 | ) {
129 | return null;
130 | }
131 |
132 | for (let i = 0; i < this.list.length; i++) {
133 | // skip if set to unique and value was returned previously
134 | if (!(this.unique && this.previouslyReturnedIndexes.indexOf(i) > -1) ) {
135 | const distance = this.diff(val, this.list[i]);
136 | if (distance < minDistance) {
137 | minDistance = distance;
138 | index = i;
139 | closest = this.list[i];
140 | }
141 | }
142 | }
143 |
144 | // save previously returned indexes if set to unique mode,
145 | if (this.unique) {
146 | this.previouslyReturnedIndexes.push(index);
147 | }
148 |
149 | // return and save in cache
150 | return this.cache[valUID] = {closest, index};
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/index.umd.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (global = global || self, global.Closest = factory());
5 | }(this, function () { 'use strict';
6 |
7 | /**
8 | * Return closest Number/Vector2/Vector3/VectorN from a given list
9 | * uses caching for faster response. Has the ability to return every match
10 | * only once.
11 | */
12 | class Closest {
13 | /**
14 | * Creates an instance of Closest.
15 | * @param {Array} list Elements of reference can be an Array of Numbers
16 | * or Array's with an equal length
17 | * @param {Boolean} unique If set to true, every entry from `list`
18 | * can be returned only once
19 | * unit clearCache() is called
20 | */
21 | constructor(list, unique) {
22 | // creates a copy of list
23 | this.list = Array.from(list);
24 |
25 | this.dimensions = Closest.getDimensions(list[0]);
26 |
27 | this.unique = unique;
28 |
29 | // sets the adequate diff method based on the depth of the vectors
30 | this.diff = this.dimensions > 1 ? Closest.nDimensionalDiff(this.dimensions)
31 | : Closest.oneDimensionalDiff;
32 | // console.log(this.diff)
33 | // inits the cache and previouslyReturnedIndexes properties
34 | this.clearCache(false);
35 | }
36 |
37 | /**
38 | * determines if the items in the list are simple numbers or arrays
39 | * @static
40 | * @param {Number|Array} item
41 | * @return {Number} number of dimensions (1 being a simple number,
42 | * everything above is an array)
43 | */
44 | static getDimensions(item) {
45 | return typeof item == 'number' ? 1 : item.length;
46 | }
47 |
48 | /**
49 | * diff function for simple numbers
50 | * @static
51 | * @param {Number} val1
52 | * @param {Number} val2
53 | * @return {Number} Abstract difference between two numbers
54 | */
55 | static oneDimensionalDiff(val1, val2) {
56 | return Math.abs(val1-val2);
57 | }
58 |
59 | /**
60 | * diff function for array's of N numbers
61 | * @static
62 | * @param {Number} dimensions number of dimensions of your vector
63 | * @return {Function} returns the adequate diff function
64 | * Euclidean distance
65 | * (https://en.wikipedia.org/wiki/Euclidean_distance)
66 | */
67 | static nDimensionalDiff(dimensions) {
68 | if (dimensions == 2) {
69 | return (val1, val2) => (
70 | (val1[0] - val2[0]) * (val1[0] - val2[0]) +
71 | (val1[1] - val2[1]) * (val1[1] - val2[1])
72 | );
73 | } else if (dimensions == 3) {
74 | return (val1, val2) => (
75 | (val1[0] - val2[0]) * (val1[0] - val2[0]) +
76 | (val1[1] - val2[1]) * (val1[1] - val2[1]) +
77 | (val1[2] - val2[2]) * (val1[2] - val2[2])
78 | );
79 | } else {
80 | // elegant but slow solution
81 | return (val1, val2) => (
82 | val1.reduce(
83 | (acc, val, i) => ((val - val2[i]) * (val - val2[i]) + acc)
84 | , 0)
85 | );
86 | }
87 | }
88 |
89 | /**
90 | Public method to rest cached value / result paris
91 | * especially if set to unique (return every match only once)
92 | * you may want to reset the previously returned indexes
93 | * @param {Boolean} indexOnly if you are using "unique" mode only the returned
94 | * indexes are cleared by default
95 | */
96 | clearCache(indexOnly = this.unique) {
97 | if (!indexOnly) {
98 | this.cache = {};
99 | }
100 | this.previouslyReturnedIndexes = [];
101 | }
102 |
103 | /**
104 | * gets the closes Number/VectorN
105 | * @param {Number|Array} val reference number or array
106 | * @return {Object|Null} closes match within lists containing
107 | * {
108 | * closest: {Number|Array} closest entry from list
109 | * index: {Number} index within list
110 | * distance: {Number} Distance within the
111 | * coordinate system
112 | * }
113 | */
114 | get(val) {
115 | let minDistance = Infinity;
116 | let index = 0;
117 | let closest = this.list[index];
118 |
119 | // is there a better way to do this? If "val" is only a number, it seams
120 | // like a big overhead to JSON stringify it every-time, I don't see an other
121 | // way when val is an array thought. Other than something like
122 | // cache[val[0]][val[1]][val[3]] or whatever
123 | const valUID = JSON.stringify(val);
124 |
125 | // returns previously found match
126 | if (!this.unique && this.cache.hasOwnProperty(valUID)) {
127 | return this.cache[valUID];
128 | }
129 |
130 | // if set to return every value in the list only once
131 | // and being out of entries in the list
132 | if (
133 | this.unique && this.previouslyReturnedIndexes.length === this.list.length
134 | ) {
135 | return null;
136 | }
137 |
138 | for (let i = 0; i < this.list.length; i++) {
139 | // skip if set to unique and value was returned previously
140 | if (!(this.unique && this.previouslyReturnedIndexes.indexOf(i) > -1) ) {
141 | const distance = this.diff(val, this.list[i]);
142 | if (distance < minDistance) {
143 | minDistance = distance;
144 | index = i;
145 | closest = this.list[i];
146 | }
147 | }
148 | }
149 |
150 | // save previously returned indexes if set to unique mode,
151 | if (this.unique) {
152 | this.previouslyReturnedIndexes.push(index);
153 | }
154 |
155 | // return and save in cache
156 | return this.cache[valUID] = {closest, index};
157 | }
158 | }
159 |
160 | return Closest;
161 |
162 | }));
163 |
--------------------------------------------------------------------------------
/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "closestvector",
3 | "version": "0.6.1",
4 | "description": "returns the closest value / vector / vectorN from an array",
5 | "main": "index.umd.js",
6 | "es2015": "index.js",
7 | "scripts": {
8 | "pretest": "npm run build",
9 | "test": "mocha",
10 | "build": "rollup --config",
11 | "semantic-release": "semantic-release pre && npm publish && semantic-release post"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/meodai/ClosestVector.git"
16 | },
17 | "keywords": [
18 | "2d",
19 | "3d",
20 | "vector",
21 | "vectors",
22 | "distance",
23 | "diff",
24 | "difference"
25 | ],
26 | "author": "meodai",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/meodai/ClosestVector/issues"
30 | },
31 | "homepage": "https://github.com/meodai/ClosestVector#readme",
32 | "devDependencies": {
33 | "chai": "^4.2.0",
34 | "eslint": "^5.15.1",
35 | "eslint-config-google": "^0.12.0",
36 | "mocha": "^6.0.2",
37 | "rollup": "^1.16.2",
38 | "semantic-release": "^17.2.3",
39 | "rollup-plugin-uglify": "^6.0.4"
40 | },
41 | "standard": {
42 | "env": {
43 | "mocha": true
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import uglify from 'rollup-plugin-uglify';
2 |
3 | export default {
4 | input: 'index.js',
5 | output: {
6 | file: 'index.umd.js',
7 | format: 'umd',
8 | name: 'Closest',
9 | },
10 | /*plugins: [
11 | uglify.uglify(),
12 | ],*/
13 | };
14 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | const expect = require('chai').expect;
2 | const Closest = require('.');
3 |
4 | const simple = new Closest([1]);
5 |
6 | describe('Closest', () => {
7 | it('Closest is a function', () => {
8 | expect(Closest).to.be.an('function');
9 | });
10 |
11 | it('be an instance of Closest', () => {
12 | expect(new Closest([1])).to.be.an.instanceof(Closest);
13 | });
14 |
15 | it('return correct closest vectors2', () => {
16 | const closestVector = new Closest([[1,2],[2,2],[4,4],[255,255]]);
17 |
18 | closestVector.get([255,255]);
19 | closestVector.get([2,5]);
20 | closestVector.get([64,12]);
21 |
22 | expect(closestVector.get([255,255])).to.deep.equal({
23 | "closest":[255,255],
24 | "index":3
25 | });
26 | });
27 |
28 | it('Closest.getDimensions to return 1 on number types', () => {
29 | expect(Closest.getDimensions(12.12)).to.be.equal(1);
30 | expect(Closest.getDimensions(1)).to.be.equal(1);
31 | expect(Closest.getDimensions(Infinity)).to.be.equal(1);
32 | });
33 |
34 | it('Closest.getDimensions to return correct amount of dimensions', () => {
35 | expect(Closest.getDimensions(10)).to.be.equal(1);
36 | const a = new Array(100).fill('1');
37 | expect(Closest.getDimensions(a)).to.be.equal(a.length);
38 | });
39 |
40 | it('Closest.oneDimensionalDiff to diff simple numbers correctly', () => {
41 | expect(Closest.oneDimensionalDiff(0,10)).to.be.equal(10);
42 | expect(Closest.oneDimensionalDiff(-10,10)).to.be.equal(20);
43 | expect(Closest.oneDimensionalDiff(-20,-1)).to.be.equal(19);
44 | });
45 |
46 | it('Closest.oneDimensionalDiff to diff simple numbers correctly', () => {
47 | expect(Closest.oneDimensionalDiff(0,10)).to.be.equal(10);
48 | expect(Closest.oneDimensionalDiff(-10,10)).to.be.equal(20);
49 | expect(Closest.oneDimensionalDiff(-20,-1)).to.be.equal(19);
50 | expect(Closest.oneDimensionalDiff(0,0)).to.be.equal(0);
51 | expect(Closest.oneDimensionalDiff(0.1,0.000001)).to.be.equal(0.099999);
52 | });
53 |
54 | it('Closest.nDimensionalDiff to return correct difference between two Vector2', () => {
55 | expect(Closest.nDimensionalDiff(2)([10,10],[10,10])).to.be.equal(0);
56 | expect(Closest.nDimensionalDiff(2)([10,10],[100,100])).to.be.equal(
57 | (10 - 100) * (10 - 100) +
58 | (10 - 100) * (10 - 100)
59 | );
60 |
61 | expect(Closest.nDimensionalDiff(2)([-1,1],[100,100])).to.be.equal(
62 | (-1 - 100) * (-1 - 100) +
63 | (1 - 100) * (1 - 100)
64 | );
65 | });
66 |
67 | it('Closest.nDimensionalDiff to return correct difference between two Vector3', () => {
68 | expect(Closest.nDimensionalDiff(3)([255,255,255],[255,255,255])).to.be.equal(0);
69 | expect(Closest.nDimensionalDiff(3)([255,255,255],[0,0,0])).to.be.equal(
70 | (255 - 0) * (255 - 0) +
71 | (255 - 0) * (255 - 0) +
72 | (255 - 0) * (255 - 0)
73 | );
74 | });
75 |
76 | it('Clear chache correctly in "unique" mode', () => {
77 | const closest = new Closest([1,2,3,4], true);
78 |
79 | expect(closest.get(1).closest).to.be.equal(1);
80 | expect(closest.get(1).closest).to.be.equal(2);
81 |
82 | closest.clearCache();
83 |
84 | expect(closest.get(1).closest).to.be.equal(1);
85 | });
86 |
87 | });
--------------------------------------------------------------------------------