initial commit

This commit is contained in:
azykov@mail.ru
2026-08-31 20:54:53 +03:00
commit f76370151e
27 changed files with 3473 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
import createGraph, { Graph } from "ngraph.graph";
import createLayout from "ngraph.forcelayout";
import { Node } from "../types";
const ITERATION_COUNT = 10;
export type Node2D = {
id: Node['id'];
position: { x: number, y: number };
node: Node;
}
export function build2dNodes(nodes: Node[], area: { width: number, height: number, padding: number }): Node2D[] {
const graph = createGraph();
for (const node of nodes) {
graph.addNode(node.behaviour.id, { node });
}
for (const node of nodes) {
for (const link of node.behaviour.getDisplayInfo().links)
graph.addLink(node.behaviour.id, link.target);
}
return buildGraph2dNodes(graph, area);
}
function buildGraph2dNodes(graph: Graph, area: { width: number, height: number, padding: number }): Node2D[] {
const layout = createLayout(
graph,
{
springLength: 300,
// springTransform: (link, spring) => {
// const from = graph.getNode(link.fromId).data.radius;
// const to = graph.getNode(link.toId).data.radius;
// spring.length = from + to + 10; // отступ 10px
// },
},
);
function clampToBounds() {
const minX = area.padding;
const maxX = area.width - area.padding;
const minY = area.padding;
const maxY = area.height - area.padding;
layout.forEachBody((body) => {
if (body.pos.x < minX) { body.pos.x = minX; body.velocity.x = 0; }
if (body.pos.x > maxX) { body.pos.x = maxX; body.velocity.x = 0; }
if (body.pos.y < minY) { body.pos.y = minY; body.velocity.y = 0; }
if (body.pos.y > maxY) { body.pos.y = maxY; body.velocity.y = 0; }
});
}
for (var i = 0; i < ITERATION_COUNT; ++i) {
layout.step();
// clampToBounds();
}
// const rect = layout.getGraphRect();
// const W = area.width, H = 600, PADDING = 40;
// const scaleX = (area.width - area.padding * 2) / (rect.x2 - rect.x1);
// const scaleY = (area.height - area.padding * 2) / (rect.y2 - rect.y1);
// const scale = Math.min(scaleX, scaleY); // сохраняем пропорции
// function toCanvas(pos: { x: number; y: number }) {
// return {
// x: area.padding + (pos.x - rect.x1) * scale,
// y: area.padding + (pos.y - rect.y1) * scale,
// };
// }
const nodes: Node2D[] = [];
layout.forEachBody((body, nodeId) => {
nodes.push({
id: nodeId.toString(),
position: { x: body.pos.x + area.width / 2, y: body.pos.y + area.height / 2 },
node: graph.getNode(nodeId)?.data.node,
});
});
return nodes;
}