This commit is contained in:
kolaflash
2026-01-04 21:03:44 +01:00
parent ead8f3ce5a
commit b191757922
3 changed files with 60 additions and 12 deletions
+51 -6
View File
@@ -1,23 +1,68 @@
import "./GraphBrowser.css";
import { type Component, createSignal, onMount } from "solid-js";
import { createGraph, type Edge, type Graph, type Node } from "#/lib/Graph.ts";
import type { Vector } from "#/lib/Vector.ts";
import {
drawEdge,
drawNode,
type Graph,
type Node,
type PositionPartial,
} from "#/lib/Graph.ts";
import { createVector, type Vector } from "#/lib/Vector.ts";
function drawGraph<T extends PositionPartial>(
graph: Graph<T>,
ctx: CanvasRenderingContext2D,
): void {
for (const [node, neighbours] of graph.entries()) {
drawNode(node, ctx);
for (const neighbour of neighbours) {
drawEdge([node, neighbour], ctx);
}
}
}
function placeNodes<T extends PositionPartial>(graph: Graph<T>): void {
const visited: Array<Node<T>> = [];
const currentPosition = createVector();
const radius = 24;
for (const [node, neighbours] of graph.entries()) {
if (visited.includes(node)) {
continue;
}
visited.push(node);
node.position.x = currentPosition.x;
node.position.y = currentPosition.y;
neighbours.forEach((neighbour, index) => {
const fraction = (index + 1) / neighbours.length;
const rad = Math.PI * 2 * fraction;
neighbour.position.x = currentPosition.x + radius * Math.cos(rad);
neighbour.position.y = currentPosition.y + radius * Math.sin(rad);
visited.push(neighbour);
});
currentPosition.y += radius * 2;
}
}
export const GraphBrowser: Component<{
graph: Graph<{ position: Vector; label: string }>;
}> = (props) => {
let canvasRef!: HTMLCanvasElement;
const [width, setWidth] = createSignal(100);
const [height, setHeight] = createSignal(100);
const [width, setWidth] = createSignal(300);
const [height, setHeight] = createSignal(300);
onMount(() => {
const ctx: CanvasRenderingContext2D = canvasRef.getContext("2d", {
alpha: false,
})!;
ctx.translate(width() / 2, height() / 2);
setWidth(canvasRef.parentElement!.offsetWidth);
setHeight(width());
placeNodes(props.graph);
drawGraph(props.graph, ctx);
});
return (
+6 -1
View File
@@ -39,11 +39,16 @@ const nodes: Array<TestNode> = [
{ position: createVector(), label: "foo" },
{ position: createVector(), label: "bar" },
{ position: createVector(), label: "lol" },
{ position: createVector(), label: "hai" },
{ position: createVector(), label: "sea" },
{ position: createVector(), label: "vot" },
];
const edges: Array<Edge<TestNode>> = [
[nodes[0], nodes[1]],
[nodes[1], nodes[2]],
[nodes[0], nodes[2]],
[nodes[0], nodes[3]],
[nodes[4], nodes[5]],
];
const graph = createGraph<TestNode>(nodes, edges);
+3 -5
View File
@@ -4,14 +4,14 @@ 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 = {
export type PositionPartial = {
position: Vector;
};
export function drawNode(
node: Node<PositionPartial>,
ctx: CanvasRenderingContext2D,
color: string,
color: string = "#fff",
): void {
ctx.lineWidth = 2;
ctx.strokeStyle = color;
@@ -41,7 +41,7 @@ export function getNodeByPosition(
export function drawEdge(
edge: Edge<PositionPartial>,
ctx: CanvasRenderingContext2D,
color: string,
color: string = "#fff",
): void {
ctx.lineWidth = 2;
ctx.strokeStyle = color;
@@ -85,11 +85,9 @@ export function createGraph<T>(
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;