1import { GNode, MINIMUM_EDGE_SEPARATION } from "./node"; 2import { Edge } from "./edge"; 3 4export class Graph { 5 nodeMap: Array<GNode>; 6 minGraphX: number; 7 maxGraphX: number; 8 minGraphY: number; 9 maxGraphY: number; 10 maxGraphNodeX: number; 11 maxBackEdgeNumber: number; 12 width: number; 13 height: number; 14 15 constructor(data: any) { 16 this.nodeMap = []; 17 18 this.minGraphX = 0; 19 this.maxGraphX = 1; 20 this.minGraphY = 0; 21 this.maxGraphY = 1; 22 this.width = 1; 23 this.height = 1; 24 25 data.nodes.forEach((jsonNode: any) => { 26 this.nodeMap[jsonNode.id] = new GNode(jsonNode.nodeLabel); 27 }); 28 29 data.edges.forEach((e: any) => { 30 const t = this.nodeMap[e.target]; 31 const s = this.nodeMap[e.source]; 32 const newEdge = new Edge(t, e.index, s, e.type); 33 t.inputs.push(newEdge); 34 s.outputs.push(newEdge); 35 if (e.type == 'control') { 36 // Every source of a control edge is a CFG node. 37 s.cfg = true; 38 } 39 }); 40 41 } 42 43 *nodes(p = (n: GNode) => true) { 44 for (const node of this.nodeMap) { 45 if (!node || !p(node)) continue; 46 yield node; 47 } 48 } 49 50 *filteredEdges(p: (e: Edge) => boolean) { 51 for (const node of this.nodes()) { 52 for (const edge of node.inputs) { 53 if (p(edge)) yield edge; 54 } 55 } 56 } 57 58 forEachEdge(p: (e: Edge) => void) { 59 for (const node of this.nodeMap) { 60 if (!node) continue; 61 for (const edge of node.inputs) { 62 p(edge); 63 } 64 } 65 } 66 67 redetermineGraphBoundingBox(showTypes: boolean): [[number, number], [number, number]] { 68 this.minGraphX = 0; 69 this.maxGraphNodeX = 1; 70 this.maxGraphX = undefined; // see below 71 this.minGraphY = 0; 72 this.maxGraphY = 1; 73 74 for (const node of this.nodes()) { 75 if (!node.visible) { 76 continue; 77 } 78 79 if (node.x < this.minGraphX) { 80 this.minGraphX = node.x; 81 } 82 if ((node.x + node.getTotalNodeWidth()) > this.maxGraphNodeX) { 83 this.maxGraphNodeX = node.x + node.getTotalNodeWidth(); 84 } 85 if ((node.y - 50) < this.minGraphY) { 86 this.minGraphY = node.y - 50; 87 } 88 if ((node.y + node.getNodeHeight(showTypes) + 50) > this.maxGraphY) { 89 this.maxGraphY = node.y + node.getNodeHeight(showTypes) + 50; 90 } 91 } 92 93 this.maxGraphX = this.maxGraphNodeX + 94 this.maxBackEdgeNumber * MINIMUM_EDGE_SEPARATION; 95 96 this.width = this.maxGraphX - this.minGraphX; 97 this.height = this.maxGraphY - this.minGraphY; 98 99 const extent: [[number, number], [number, number]] = [ 100 [this.minGraphX - this.width / 2, this.minGraphY - this.height / 2], 101 [this.maxGraphX + this.width / 2, this.maxGraphY + this.height / 2] 102 ]; 103 104 return extent; 105 } 106 107} 108