/**
* A lookup table representing the cost associated from traveling from one
* node to every other node in the navgiation mesh's graph.
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class CostTable {
/**
* Creates a new cost table.
*/
constructor() {
this._nodeMap = new Map();
}
/**
* Inits the cost table for the given navigation mesh.
*
* @param {NavMesh} navMesh - The navigation mesh.
* @return {CostTable} A reference to this cost table.
*/
init( navMesh ) {
const graph = navMesh.graph;
const nodes = new Array();
this.clear();
// iterate over all nodes
graph.getNodes( nodes );
for ( let i = 0, il = nodes.length; i < il; i ++ ) {
const from = nodes[ i ];
// compute the distance to all other nodes
for ( let j = 0, jl = nodes.length; j < jl; j ++ ) {
const to = nodes[ j ];
const path = navMesh.findPath( from.position, to.position );
const cost = computeDistanceOfPath( path );
this.set( from.index, to.index, cost );
}
}
return this;
}
/**
* Clears the cost table.
*
* @return {CostTable} A reference to this cost table.
*/
clear() {
this._nodeMap.clear();
return this;
}
/**
* Sets the cost for the given pair of navigation nodes.
*
* @param {Number} from - The start node index.
* @param {Number} to - The destintation node index.
* @param {Number} cost - The cost.
* @return {CostTable} A reference to this cost table.
*/
set( from, to, cost ) {
const nodeMap = this._nodeMap;
if ( nodeMap.has( from ) === false ) nodeMap.set( from, new Map() );
const nodeCostMap = nodeMap.get( from );
nodeCostMap.set( to, cost );
return this;
}
/**
* Returns the cost for the given pair of navigation nodes.
*
* @param {Number} from - The start node index.
* @param {Number} to - The destintation node index.
* @return {Number} The cost.
*/
get( from, to ) {
const nodeCostMap = this._nodeMap.get( from );
return nodeCostMap.get( to );
}
/**
* Returns the size of the cost table (amount of entries).
*
* @return {Number} The size of the cost table.
*/
size() {
return this._nodeMap.size;
}
/**
* Transforms this instance into a JSON object.
*
* @return {Object} The JSON object.
*/
toJSON() {
const json = {
nodes: new Array()
};
for ( let [ key, value ] of this._nodeMap.entries() ) {
json.nodes.push( { index: key, costs: Array.from( value ) } );
}
return json;
}
/**
* Restores this instance from the given JSON object.
*
* @param {Object} json - The JSON object.
* @return {CostTable} A reference to this cost table.
*/
fromJSON( json ) {
const nodes = json.nodes;
for ( let i = 0, l = nodes.length; i < l; i ++ ) {
const node = nodes[ i ];
const index = node.index;
const costs = new Map( node.costs );
this._nodeMap.set( index, costs );
}
return this;
}
}
//
function computeDistanceOfPath( path ) {
let distance = 0;
for ( let i = 0, l = ( path.length - 1 ); i < l; i ++ ) {
const from = path[ i ];
const to = path[ i + 1 ];
distance += from.distanceTo( to );
}
return distance;
}
export { CostTable };