import { Graph } from "./graph"; import { GraphElement } from "./graphelement"; import { NodeType } from "./nodetype"; import { Link } from "./link"; import { GLOBAL_PARAMS } from "../helper/serializableitem"; const NODE_PARAMS = [ "label", "icon", "description", "references", "video", "type", "banner", ...GLOBAL_PARAMS, ]; const NODE_SIM_PARAMS = ["index", "x", "y", "vx", "vy", "fx", "fy"]; // Based on https://github.com/d3/d3-force#simulation_nodes export class Node extends GraphElement { public label: string; public description: string; public type: NodeType; public icon: string; public banner: string; public video: string; public references: string[]; constructor(graph: Graph = undefined) { super(graph); this.isNode = true; } public setType(typeId: number) { // Is it even different? if (this.type.id === typeId) { return; } const newType = this.graph.getType(typeId); // Exists? if (newType === undefined) { return; } this.type = newType; // Store change this.graph.storeCurrentData( "Set type [" + newType.toString() + "] for [" + this.toString() + "]" ); } public delete() { return this.graph.deleteNode(this); } public add(graph: Graph = this.graph) { this.graph = graph; if (this.graph == undefined) { return false; } return this.graph.addNode(this); } /** * Calculates a list of all connected links to the current node. * @returns Array containing all connected links. */ public get links(): Link[] { const links: Link[] = []; this.graph.links.forEach((link) => { if (link.contains(this)) { links.push(link); } }); return links; } /** * Calculates a list of all connected nodes to the current node. * @returns Array containing all connected nodes. */ public get neighbors(): Node[] { const nodes: Node[] = []; this.links.forEach((link) => { // Find "other" node let otherNode = link.source; if (this.equals(otherNode)) { otherNode = link.target; } // Still undefined? if (otherNode == undefined) { // Link apparently not properly set up return; } // Add to list if doesn't exist if (!nodes.includes(otherNode)) { nodes.push(otherNode); } }); return nodes; } /** * Connects a given node to itself. Only works if they are in the same graph. * @param node Other node to connect. * @returns The created link, if successful, otherwise undefined. */ public connect(node: Node): Link { if (this.graph !== node.graph) { return undefined; } const link = new Link(this.graph); link.source = this; link.target = node; if (link.add()) { return link; } } public serialize(): any { return this.serializeProperties(NODE_PARAMS); } public getCleanInstance(): any { return { ...this.serialize(), ...this.serializeProperties(NODE_SIM_PARAMS), }; } public static parse(raw: any): Node { const node: Node = new Node(); if (raw.label !== undefined) { node.label = raw.label; } else { node.label = raw.name; } node.id = Number(raw.id); node.description = raw.description; node.type = NodeType.parse(raw.type); // Try to parse simulation parameters NODE_SIM_PARAMS.forEach((param) => { if (raw[param] === undefined) { return; } (node as any)[param] = raw[param]; }); return node; } public toString(): string { return this.label; } }