UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

77 lines (55 loc) 2.54 kB
import { BinaryDataType } from "../binary/type/BinaryDataType.js"; import { Deque } from "../collection/queue/Deque.js"; import { SquareMatrix } from "../math/matrix/SquareMatrix.js"; /** * Produce a distance matrix from an input graph, tracing distances from each node to every node specified in target vector * @see "A Fast Algorithm to Find All-Pairs Shortest Paths in Complex Networks" by Wei Peng et Al. 2012 * @template T * @param {Graph<T>} graph * @param {T[]} node_array graph nodes as an array * @param {number[]} targets node indices, distances to which need to be calculated * @param {Map<T, number>} node_index_map * @returns {SquareMatrix} */ export function graph_compute_distance_matrix(graph, node_array, targets, node_index_map) { const node_count = node_array.length; const m_distances = new SquareMatrix(node_count, BinaryDataType.Float32); // initialize distances m_distances.fill(Number.POSITIVE_INFINITY); // fill diagonal for (let i = 0; i < node_count; i++) { // Distance to self is 0 m_distances.setCellValue(i, i, 0); } /** * * @type {Deque<number>} */ const queue = new Deque(); for (const target_index of targets) { queue.addLast(target_index); while (!queue.isEmpty()) { const index_1 = queue.removeFirst(); const node_1 = node_array[index_1]; const node_1_container = graph.getNodeContainer(node_1); const edges = node_1_container.getEdges(); const edge_count = edges.length; for (let i = 0; i < edge_count; i++) { const edge = edges[i]; const node_0 = edge.other(node_1); if (!edge.validateTransition(node_0, node_1)) { continue; } const index_0 = node_index_map.get(node_0); // If we haven't visited this neighbor yet, its distance is the current distance + 1 if (m_distances.getCellValue(index_0, target_index) === Number.POSITIVE_INFINITY) { const transition_cost = edge.weight; const new_distance = m_distances.getCellValue(index_1, target_index) + transition_cost; m_distances.setCellValue(index_0, target_index, new_distance); queue.addLast(index_0); } } } } return m_distances; }