From f8c505efff3bca2db499ced7344aff30c712c244 Mon Sep 17 00:00:00 2001 From: Matthias Konitzny <konitzny@ibr.cs.tu-bs.de> Date: Fri, 9 Sep 2022 09:41:42 +0200 Subject: [PATCH] Simplified node, link and nodetype creation --- src/common/graph.ts | 155 ++++++++++++++++------------------------- src/common/link.ts | 4 +- src/common/node.ts | 13 +--- src/common/nodetype.ts | 8 +++ 4 files changed, 74 insertions(+), 106 deletions(-) diff --git a/src/common/graph.ts b/src/common/graph.ts index ee23da5..8399ce6 100644 --- a/src/common/graph.ts +++ b/src/common/graph.ts @@ -55,25 +55,29 @@ export class Graph this.initialized = false; return; } + this.reset(); Object.assign(this, data); - this.nameToObjectGroup = new Map<string, NodeType>(); this.objectGroups.forEach((group) => this.nameToObjectGroup.set(group.name, group) ); - - this.idToNode = new Map<number, Node>(); this.nodes.forEach((node) => { this.idToNode.set(node.id, node); }); - - this.idToLink = new Map<number, Link>(); this.links.forEach((link) => { this.idToLink.set(link.id, link); }); } + private reset() { + this.nodes = []; + this.links = []; + this.nameToObjectGroup = new Map<string, NodeType>(); + this.idToNode = new Map<number, Node>(); + this.idToLink = new Map<number, Link>(); + } + public toJSONSerializableObject(): GraphData { return { nodes: this.nodes.map((node) => node.toJSONSerializableObject()), @@ -95,57 +99,24 @@ export class Graph } public fromSerializedObject(data: GraphData | SimGraphData): Graph { - let objectGroups: Array<NodeType>; + this.reset(); if (data.objectGroups === undefined) { - objectGroups = this.createObjectGroupsFromStrings(data.nodes); + this.createObjectGroupsFromStrings(data.nodes); } else { - objectGroups = this.createObjectGroupsFromObjects( - data.objectGroups + data.objectGroups.forEach((group) => + this.createObjectGroup(group.name, group.color) ); } - this.nameToObjectGroup = new Map<string, NodeType>(); - objectGroups.forEach((group) => - this.nameToObjectGroup.set(group.name, group) - ); - - this.nodes = this.createNodes(data.nodes); - this.idToNode = new Map<number, Node>(); - this.nodes.forEach((node) => { - this.idToNode.set(node.id, node); - }); - - this.links = data.links.map((link, i) => { - const l = new Link(); - l.id = i; - l.source = this.idToNode.get(link.source); - l.target = this.idToNode.get(link.target); - return l; - }); - this.idToLink = new Map<number, Link>(); - this.links.forEach((link) => { - this.idToLink.set(link.id, link); - }); + data.nodes.forEach((node) => this.createNode(node)); + data.links.forEach((link) => this.createLink(link.source, link.target)); this.updateNodeData(); return this; } - private createNodes(nodeJSONData: NodeData[]): Array<Node> { - const nodes: Array<Node> = []; - for (const nodeData of nodeJSONData) { - const node = new Node(); - node.fromSerializedObject(nodeData); - node.type = this.nameToObjectGroup.get(nodeData.type); - node.neighbors = []; - node.links = []; - nodes.push(node); - } - return nodes; - } - private createObjectGroupsFromStrings(nodes: NodeData[]): Array<NodeType> { const objectGroups: NodeType[] = []; const nodeClasses: string[] = []; @@ -153,26 +124,14 @@ export class Graph const nodeTypes = [...new Set(nodeClasses)].map((c) => String(c)); for (let i = 0; i < nodeTypes.length; i++) { - const nodeType = new NodeType(); - nodeType.fromSerializedObject({ - id: i, - name: nodeTypes[i], - color: Config.COLOR_PALETTE[i % Config.COLOR_PALETTE.length], - }); + this.createObjectGroup( + nodeTypes[i], + Config.COLOR_PALETTE[i % Config.COLOR_PALETTE.length] + ); } return objectGroups; } - private createObjectGroupsFromObjects( - groups: NodeTypeData[] - ): Array<NodeType> { - return groups.map((group) => { - const t = new NodeType(); - t.fromSerializedObject(group); - return t; - }); - } - /** * Updates the graph data structure to contain additional values. * Creates a 'neighbors' and 'links' array for each node object. @@ -197,53 +156,61 @@ export class Graph return this.idToNode.get(id); } - private checkNode(node: Node) { - for (const neighbor of node.neighbors) { - if (this.idToNode.get(neighbor.id) === undefined) { - return false; - } - } - - for (const link of node.links) { - if (this.idToLink.get(link.id) === undefined) { - return false; - } - } - return node.isInitialized(); + private addNode(node: Node) { + node.id = this.nodes.length; + this.nodes.push(node); + this.idToNode.set(node.id, node); } - private checkLink(link: Link) { - return ( - link.isInitialized() && - !( - this.idToNode.get(link.source.id) === undefined || - this.idToNode.get(link.target.id) === undefined - ) - ); + public createNode(data?: NodeData): Node { + const node = new Node(this); + node.fromSerializedObject(data); + node.type = this.nameToObjectGroup.get(data.type); + node.neighbors = []; + node.links = []; + this.addNode(node); + return node; } - public addNode(node: Node) { - node.id = this.nodes.length; + public createLink(source: number, target: number): Link { + if (source === target) { + console.warn( + "Attempting to create a link where source equals target" + ); + return; + } - if (!this.checkNode(node)) { - return false; + const sourceNode = this.idToNode.get(source); + const targetNode = this.idToNode.get(target); + + if (sourceNode === undefined || targetNode === undefined) { + console.warn("Tried to create a link between nonexisting nodes!"); + return; } - this.nodes.push(node); - this.idToNode.set(node.id, node); - return true; + const link = new Link(sourceNode, targetNode, this); + sourceNode.links.push(link); + targetNode.links.push(link); + this.addLink(link); + return link; } - public addLink(link: Link) { - link.id = this.links.length; + public createObjectGroup(name?: string, color?: string): NodeType { + const group = new NodeType(name, color, this); + this.addObjectGroup(group); + return group; + } - if (!this.checkLink(link)) { - return false; - } + private addObjectGroup(group: NodeType) { + group.id = this.objectGroups.length; + this.objectGroups.push(group); + this.nameToObjectGroup.set(group.name, group); // TODO: Replace with id + } + private addLink(link: Link) { + link.id = this.links.length; this.links.push(link); this.idToLink.set(link.id, link); - return true; } public deleteLink(id: number) { diff --git a/src/common/link.ts b/src/common/link.ts index 78d6324..100894e 100644 --- a/src/common/link.ts +++ b/src/common/link.ts @@ -35,8 +35,10 @@ export class Link // These parameters will be added by the force graph implementation public index?: number; - constructor(graph: Graph = undefined) { + constructor(source?: Node, target?: Node, graph?: Graph) { super(0, graph); + this.source = source; + this.target = target; } /** diff --git a/src/common/node.ts b/src/common/node.ts index 076293d..fa06cf2 100644 --- a/src/common/node.ts +++ b/src/common/node.ts @@ -82,7 +82,7 @@ export class Node public fx?: number; public fy?: number; - constructor(graph: Graph = undefined) { + constructor(graph?: Graph) { super(0, graph); this.neighbors = []; this.links = []; @@ -127,16 +127,7 @@ export class Node throw new Error("The connected nodes are not on the same graph!"); } - const link = new Link(this.graph); - - link.source = this; - link.target = node; - - if (this.graph.addLink(link)) { - this.neighbors.push(node); - node.neighbors.push(this); - return link; - } + return this.graph.createLink(this.id, node.id); } public toJSONSerializableObject(): NodeData { diff --git a/src/common/nodetype.ts b/src/common/nodetype.ts index c160ec0..c9be115 100644 --- a/src/common/nodetype.ts +++ b/src/common/nodetype.ts @@ -1,4 +1,6 @@ import { GraphElement } from "./graphelement"; +import { Node } from "./node"; +import { Graph } from "./graph"; export interface NodeTypeData { id: number; @@ -14,6 +16,12 @@ export class NodeType public name: string; public color: string; + constructor(name?: string, color?: string, graph?: Graph) { + super(0, graph); + this.name = name; + this.color = color; + } + toJSONSerializableObject(): NodeTypeData { return { id: this.id, name: this.name, color: this.color }; } -- GitLab