diff options
Diffstat (limited to 'modules/Geometry.test.js')
-rw-r--r-- | modules/Geometry.test.js | 116 |
1 files changed, 114 insertions, 2 deletions
diff --git a/modules/Geometry.test.js b/modules/Geometry.test.js index b44f25d..bfac85f 100644 --- a/modules/Geometry.test.js +++ b/modules/Geometry.test.js @@ -1,6 +1,6 @@ import { test, assert } from './test-assert.js'; -import { AABB, QTNode } from './Geometry.js'; +import { AABB, QTNode, QuadTree } from './Geometry.js'; test('AABB correctly contains/excludes points', () => { @@ -141,5 +141,117 @@ test('QTNode correctly inserts multiple points', () => { assert.equal(node.subnode[2].type.toString(), 'QTNode.Empty'); assert.equal(node.subnode[3].type.toString(), 'QTNode.Leaf'); - assert.deepEqual(node.subnode[3].point, p0); +assert.deepEqual(node.subnode[3].point, p0); }); + + +const randomPoint = () => ({ x: Math.random(), y: Math.random() }); + + +test('QTNode correctly returns points in region', () => { + const node = new QTNode(0, 0, 1, 1); + let points = []; + for (let i=0; i<100; i++) { + const pt = randomPoint(); + node.insert(pt); + points.push(pt); + } + + const pointsInRegion = aabb => { + let pts = []; + for (let pt of points) { + if (aabb.contains(pt)) pts.push(pt); + } + return pts; + }; + + const region = new AABB(0.25, 0.25, 0.5, 0.5); + let bf_points = pointsInRegion(region); + let qt_points = node.getPointsInRegion(region); + const compare = (a, b) => { + if (a.x == b.x) + return b.y - a.y; + return b.x - a.x; + }; + bf_points.sort(compare); + qt_points.sort(compare); + assert.deepEqual(bf_points, qt_points);}); + + +test('QuadTree correctly finds closest point for 10,000 random points', () => { + const tree = new QuadTree(1, 1); + + let points = []; + for (let i=0; i<10000; i++) { + const pt = randomPoint(); + tree.insert(pt); + points.push(pt); + } + + const distance = (a, b) => Math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2); + const bf_closest = a => { + let closest = null; + let min_dist = 1000; + for (let b of points) { + let d = distance(a, b); + if (d < min_dist) { + min_dist = d; + closest = b; + } + } + return closest; + } + + for (let i=0; i<10000; i++) { + const pt = randomPoint(); + assert.deepEqual(bf_closest(pt), tree.closest(pt)); + } +}); + + +function benchmark(desc, f, iterations) { + process.stdout.write(`${desc}: `); + const start = process.uptime(); + for (let i=0; i<iterations; i++) f(); + const elapsed = process.uptime() - start; + console.log(`${elapsed} seconds`); +} + +const closest_benchmark = () => { + const n_points = 1e5; + const iterations = 1e4; + console.log(`> benchmark get closest of ${n_points} random points ${iterations} times`); + + const tree = new QuadTree(1, 1); + let points = []; + for (let i=0; i<n_points; i++) { + const pt = randomPoint(); + tree.insert(pt); + points.push(pt); + } + + const distance = (a, b) => Math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2); + const bf_closest = a => { + let closest = null; + let min_dist = 1000; + for (let b of points) { + let d = distance(a, b); + if (d < min_dist) { + min_dist = d; + closest = b; + } + } + return closest; + } + + benchmark('\tbrute force', () => { + const pt = randomPoint(); + bf_closest(pt); + }, iterations); + + benchmark('\tquadtree', () => { + const pt = randomPoint(); + tree.closest(pt); + }, iterations); +} +closest_benchmark(); |