import { Graph } from "./graph"; import { GraphElement } from "./graphelement"; import { NodeType } from "./nodetype"; import { Link } from "./link"; interface NodeProperties { name: string; description?: string; icon?: string; banner?: string; video?: string; references?: string[]; } export interface NodeData extends NodeProperties { /** * This interfaces provides a data representation for a simple "flat" node without object pointers. * Can be used to store nodes in JSON format. */ id: number; type: string; } // Based on https://github.com/d3/d3-force#simulation_nodes export interface SimNodeData extends NodeData { /** * This interface serves as a data representation for the history of the editor. * Same as the JSON representation + additional parameters related to the simulation. * This ensures that nodes from the history can are restored with the same visual state. */ index: number; x: number; y: number; vx: number; vy: number; fx: number; fy: number; } export interface GraphNode extends NodeProperties { /** * Node representation in a Graph. Contains values for easy traversal and force graph simulation properties. */ id: number; type: NodeType; // Properties used for graph traversal neighbors: Node[]; links: Link[]; // Properties used by the force graph simulation index?: number; x?: number; y?: number; z?: number; vx?: number; vy?: number; vz?: number; fx?: number; fy?: number; fz?: number; } export class Node extends GraphElement<NodeData, SimNodeData> implements GraphNode { public name: string; public description: string; public type: NodeType; public icon: string; public banner: string; public video: string; public references: string[]; public neighbors: Node[]; public links: Link[]; // These parameters will be added by the force graph implementation public index?: number; public x?: number; public y?: number; public z?: number; public vx?: number; public vy?: number; public vz?: number; public fx?: number; public fy?: number; public fz?: number; constructor(graph?: Graph) { super(0, graph); this.neighbors = []; this.links = []; } public setType(typeId: number) { const newType = this.graph.nameToObjectGroup.get(String(typeId)); // TODO // Exists? if (newType === undefined) { return; } this.type = newType; } public delete() { return this.graph.deleteNode(this.id); } /** * Connects this node to a given node. 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) { throw new Error("The connected nodes are not on the same graph!"); } return this.graph.createLink(this.id, node.id); } public toJSONSerializableObject(): NodeData { return { id: this.id, name: this.name, description: this.description, icon: this.icon, banner: this.banner, video: this.video, references: this.references, type: this.type.name, }; } public toHistorySerializableObject(): SimNodeData { return { ...this.toJSONSerializableObject(), index: this.index, x: this.x, y: this.y, vx: this.vx, vy: this.vy, fx: this.fx, fy: this.fy, }; } public fromSerializedObject(data: NodeData | SimNodeData): Node { Object.assign(this, data); this.type = undefined; // Remove string type again if undefined as it may be a string. return this; } public toString(): string { return this.name; } }