Files
nage/lib/Graph.ts
T
2025-11-25 19:32:27 +01:00

120 lines
2.2 KiB
TypeScript

import type { Vector } from "./Vector.ts";
export type Node<T> = T;
export type Edge<T> = [Node<T>, Node<T>];
export type Graph<T> = Map<Node<T>, Array<Node<T>>>;
type PositionPartial = {
position: Vector;
};
export function drawNode(
node: Node<PositionPartial>,
ctx: CanvasRenderingContext2D,
color: string,
): void {
ctx.lineWidth = 2;
ctx.strokeStyle = color;
ctx.beginPath();
ctx.arc(node.position.x, node.position.y, 8, 0, 2 * Math.PI);
ctx.stroke();
}
export function getNodeByPosition(
nodes: Array<Node<PositionPartial>>,
position: Vector,
): Node<PositionPartial> | null {
for (const node of nodes) {
if (
node.position.x <= position.x + 16 &&
node.position.x >= position.x - 16 &&
node.position.y <= position.y + 16 &&
node.position.y >= position.y - 16
) {
return node;
}
}
return null;
}
export function drawEdge(
edge: Edge<PositionPartial>,
ctx: CanvasRenderingContext2D,
color: string,
): void {
ctx.lineWidth = 2;
ctx.strokeStyle = color;
ctx.beginPath();
ctx.moveTo(edge[0].position.x, edge[0].position.y);
ctx.lineTo(edge[1].position.x, edge[1].position.y);
ctx.stroke();
}
export function createGraph<T>(
nodes: Array<Node<T>>,
edges: Array<Edge<T>>,
): Graph<T> {
const graph: Graph<T> = new Map();
for (const node of nodes) {
const neighbours = edges.reduce(
(acc, edge) => {
if (edge[0] === node) {
acc.push(edge[1]);
return acc;
}
if (edge[1] === node) {
acc.push(edge[0]);
return acc;
}
return acc;
},
[] as Array<Node<T>>,
);
if (neighbours.length > 0) {
graph.set(node, neighbours);
}
}
return graph;
}
export function originDFS<T>(origin: Node<T>, graph: Graph<T>): Array<Node<T>> {
const visited: Array<Node<T>> = [origin];
if (!graph.has(origin)) {
return visited;
}
innerDFS(origin, graph, visited);
return visited;
}
function innerDFS<T>(
node: Node<T>,
graph: Graph<T>,
visited: Array<Node<T>>,
): void {
const neighbours = graph.get(node)!;
for (const node of neighbours) {
if (visited.includes(node)) {
continue;
}
visited.push(node);
innerDFS(node, graph, visited);
}
}
export function getNeighbours<T>(
graph: Graph<T>,
node: Node<T>,
): Array<Node<T>> {
return graph.has(node) ? graph.get(node)! : [];
}