@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
82 lines (59 loc) • 2.01 kB
JavaScript
/**
* Multi-node graph function
* @template N
* @param {Graph<MultiNode<N>>} graph
* @param {WeightedEdge<MultiNode<N>>} edge
* @param {number} source_limit
* @param {BinaryHeap<Edge>} heap
* @returns {boolean} whether collapse was performed or rejected
*/
export function mn_graph_collapse_weighted_edge(
graph,
edge,
source_limit,
heap
) {
const successor_node = edge.first;
const victim_node = edge.second;
// new count
const total_source_count = victim_node.source_nodes.length + successor_node.source_nodes.length;
if (total_source_count > source_limit) {
return false;
}
// remove original edge from the graph
graph.removeEdge(edge);
// join multi-nodes
const b_ctx = graph.getNodeContainer(victim_node);
// patch graph
const b_edges = b_ctx.getEdges();
const b_edge_count = b_edges.length;
for (let i = b_edge_count - 1; i >= 0; i--) {
const b_edge = b_edges[i];
const other = b_edge.other(victim_node);
graph.removeEdge(b_edge);
let target_edge = graph.getAnyEdgeBetween(successor_node, other);
if (target_edge === undefined) {
// re-use edge
if (b_edge.first === other) {
b_edge.second = successor_node;
} else {
b_edge.first = successor_node;
}
graph.addEdge(b_edge);
target_edge = b_edge;
} else {
target_edge.weight += b_edge.weight;
heap.delete(b_edge);
}
const heap_index = heap.data.indexOf(target_edge);
if (heap_index !== -1) {
// updated edge is in the heap, re-score
heap.bubbleDown(heap_index);
}
}
// move sources from victim to successor
successor_node.add(victim_node);
// remove victim node
graph.removeNode(victim_node);
return true;
}