/**
* @module Map
*/
const kdTree = require('../lib/kdtreejs/kdTree');
const _ = require('lodash');
const Entity = require('../entity/Entity');
const Sampling = require('discrete-sampling');
let distanceFormula2 = function(e1, e2) {
return Math.pow(e1.x - e2.x, 2) +
Math.pow(e1.y - e2.y, 2);
};
let tree = null;
let list = {};
/**
* @namespace Map
*/
let Map = {};
/**
* Create a new map
*
* @param {Array} entities
* @param {any} dimensions
*/
Map.create = function(entities, dimensions) {
if (entities.length === 0 || !(entities[0] instanceof Entity)) {
throw new TypeError('Invalid array');
}
let dim = dimensions;
if (dim === undefined) dim = ['x', 'y'];
let points = _.map(entities, function(entity, idx) {
list[entity.id] = entity;
return {
x: entity.trueXY().x,
y: entity.trueXY().y,
id: entity.id,
};
});
tree = new kdTree.kdTree(points, distanceFormula2, dim);
};
/**
*
*
* @param {Object} entity
*/
Map.insert = function(entity) {
if (tree === null || list.length === 0) {
this.create([entity]);
} else if (list.hasOwnProperty(entity.id)) {
// Do nothing
} else {
tree.insert({
x: entity.trueXY().x,
y: entity.trueXY().y,
id: entity.id,
});
list[entity.id] = entity;
}
};
/**
*
*
* @param {Object} entity - Entity
* @param {number} count - Number of neighbors
* @param {any} maxDistance - Range to check within
* @return {Array.Neighbors}
*/
Map.nearest = function(entity, count, maxDistance) {
if (tree === null) {
return [];
}
if (!(entity instanceof Entity)) {
throw new TypeError('Invalid array');
}
point = {
x: entity.trueXY().x,
y: entity.trueXY().y,
id: entity.id,
};
maxDistance = Math.pow(maxDistance, 2);
if (count === undefined) {
count = 1;
}
return tree.nearest(point, count + 1, maxDistance)
.map((point) => {
return [
this.getByID(point[0].id),
Math.sqrt(point[1]),
];
})
.filter((e) => (entity.id === point.id));
};
/**
* Get n discrete samples from array
*
* @param {number} [n=] - Number of samples to pick. Default = 1
* @return {any[]}
*/
Map.discreteSamples = function(n = 1) {
return Sampling.sample_from_array(Object.values(list), n, false);
};
Map.sampleRandom = function(max) {
return Sampling.sample_from_array(Object.values(list),
Math.floor(Math.random() * max), false);
};
/**
* Get Entity with ID
*
* @param {string} id - ID of `Entity`
* @return {Entity}
*/
Map.getByID = function(id) {
return list[id];
};
Map.printMap = function() {
return tree.toJSON();
};
Map.toJSON = function() {
return tree.toJSON();
};
module.exports = Map;