import { Link } from "../common/graph/link"; import { NodeType, NodeTypeData } from "../common/graph/nodetype"; import { Node, NodeData, SimNodeData } from "../common/graph/node"; import * as Common from "../common/graph/graph"; import { History } from "../common/history"; import { GraphContent, GraphData, SimGraphData } from "../common/graph/graph"; export class DynamicGraph extends Common.Graph { public history: History<SimGraphData>; constructor(data?: GraphContent) { super(data); if (data != undefined) { this.history = new History<SimGraphData>( this, 20, "Created new graph." ); } } public fromSerializedObject(data: GraphData | SimGraphData): DynamicGraph { super.fromSerializedObject(data); this.history = new History<SimGraphData>( this, 20, "Created new graph." ); return this; } public createObjectGroup(data?: NodeTypeData): NodeType { if (data == undefined) { data = { id: 0, name: "Unnamed", color: "#000000", }; } return super.createObjectGroup(data); } public createNode( data?: NodeData | SimNodeData, x?: number, y?: number, vx?: number, vy?: number ): Node { if (data == undefined) { data = { id: 0, name: "Undefined", type: this.objectGroups[0].id, x: x, y: y, vx: vx, vy: vy, }; } return super.createNode(data); } getLink( sourceId: number, targetId: number, directionSensitive = true ): Link { return this.links.find((l) => { if (l.sourceId === sourceId && l.targetId === targetId) { return true; } // Check other direction if allowed return ( !directionSensitive && l.sourceId === targetId && l.targetId === sourceId ); }); } public createLink(source: number, target: number): Link { const link = this.getLink(source, target, false); if (link !== undefined) { return link; // Already exists in graph. } return super.createLink(source, target); } /** * Goes over all nodes and finds the closest node based on distance. * @returns Closest node and distance. Undefined, if no closest node can be found. */ public getClosestNode( x: number, y: number, exclude?: Node ): { node: Node; distance: number; } { // Iterate over all nodes, keep the one with the shortest distance let closestDistance = Number.MAX_VALUE; let closestNode: Node = undefined; this.nodes.forEach((node) => { if (node.equals(exclude)) { return; // Don't compare to itself } const currentDistance = Math.hypot(x - node.x, y - node.y); if (closestDistance > currentDistance) { closestDistance = currentDistance; closestNode = node; } }); return { node: closestNode, distance: closestDistance }; } }