2 Commits b7dd145cdb ... 9a238f1913

Author SHA1 Message Date
  icestormikk 9a238f1913 grid 2 weeks ago
  icestormikk b7dd145cdb grid 2 weeks ago

+ 20 - 13
src/graph/grid/Grid.ts

@@ -27,23 +27,18 @@ export class Grid<TElement> {
 		this._cells = Array.from({ length: height }, () => new Array(width));
 	}
 
+	/**
+     * Поместить элемент в ячейку сетки
+     * @param row Индекс строки ячейки
+     * @param col Индекс стобца сетки
+     * @param value Элемент, который необходимо разместить
+     */
 	public set(row: number, col: number, value: TElement) : this {
 		this.validate(row, col);
 
-		if(row >= this._cells.length)
-			this._cells.length = row + 1;
-
-		if(this._cells[row] === undefined)
-			this._cells[row] = [];
-
-		const r = this._cells[row]!;
-
-		if(col >= r.length)
-			r.length = col + 1;
+        this._cells[row]![col] = value;
 
-		r[col] = value;
-
-		return this;
+        return this;
 	}
 
 	public get(row: number, col: number) : TElement | undefined {
@@ -51,6 +46,18 @@ export class Grid<TElement> {
 		return this._cells[row]![col];
 	}
 
+	public getPositionOf(element: TElement) : ({ row: number, column: number }) | null {
+		for(let i = 0; i < this._cells.length; i++) {
+			const row = this._cells[i]!;
+
+			for(let j = 0; j < row.length; j++)
+				if(row[j] === element)
+					return { row: i, column: j };
+		}
+
+		return null;
+	}
+
 	public delete(row: number, col: number) : this {
 		this.validate(row, col);
 

+ 14 - 0
src/graph/grid/NodeGrid.ts

@@ -1,5 +1,6 @@
 import {Grid} from "./Grid.js";
 import Node from "../node/Node.js";
+import DummyNode from "../node/DummyNode.js";
 
 export default class NodeGrid<TNode extends Node> extends Grid<TNode> {
 	public getHeight(row: number, col: number) : number {
@@ -33,4 +34,17 @@ export default class NodeGrid<TNode extends Node> extends Grid<TNode> {
 	public getCellSize(row: number, col: number) : { width: number, height: number } {
 		return { width: this.getWidth(row, col), height: this.getHeight(row, col) };
 	}
+
+	public toString() : string {
+		let result = "";
+
+		for(const r of this._cells) {
+			for(const cell of r) {
+				result += cell ? `[${cell instanceof DummyNode ? 'dn' : 'node'}(${cell.getX()}, ${cell.getY()})]` : '[]';
+			}
+			result += "\n";
+		}
+
+		return result;
+	}
 }

+ 19 - 14
src/optimizer/steps/CoordinateAssignmentStep.ts

@@ -46,7 +46,9 @@ export default class CoordinateAssignmentStep extends AlgorithmStep<SiguiyamaCon
 			throw new Error("Layering of graph was not found!");
 
 		const grid = this.buildGrid(layering);
-		this.assignCoordinates(layering);
+		this.assignCoordinatesByGrid(grid);
+
+		context.grid = grid;
 	}
 
 	/**
@@ -83,14 +85,14 @@ export default class CoordinateAssignmentStep extends AlgorithmStep<SiguiyamaCon
 	}
 
 	private buildGrid(layering: Layering<Node, Edge<Node>>) : NodeGrid<Node> {
-		const grid = new NodeGrid(0,0);
 		const layers = layering.getLayers().toReversed();
+		const grid = new NodeGrid(layers.length, Math.max(...layers.map((l) => l.getNodes().length)))
 
 		for(let i = 0; i < layers.length; i++) {
 			const layer = layers[i]!, nodes = layer.getNodes();
 
 			for(let j = 0; j < nodes.length; j++) {
-				grid.set(i, j, nodes[j]!);
+				grid.set(j, i, nodes[j]!);
 			}
 		}
 
@@ -98,21 +100,24 @@ export default class CoordinateAssignmentStep extends AlgorithmStep<SiguiyamaCon
 	}
 
 	private assignCoordinatesByGrid(grid: NodeGrid<Node>) : void {
-		const { width, height } = grid.getSize();
+		const gridSize = grid.getSize();
+
+		let yOffset = 0.0;
+		for(let r = 0; r < gridSize.height; r++) {
+			const rowHeight = grid.getHeight(r, 0);
+			let xOffset = 0.0;
 
-		const xOffset = 0.0;
-		for(let i = 0; i < height; i++) {
-			const yOffset = 0.0;
+			for(let c = 0; c < gridSize.width; c++) {
+				const cellSize = grid.getCellSize(r, c);
+				const node = grid.get(r, c);
 
-			for(let j = 0; j < width; j++) {
-				const node = grid.get(i, j);
-				const cellSize = grid.getCellSize(j, j);
+				if(node)
+					node.setX(xOffset + cellSize.width / 2 - node.getWidth() / 2).setY(yOffset + cellSize.height / 2 - node.getHeight() / 2);
 
-				if(node) {
-					const nodeWidth = node.getWidth(), nodeHeight = node.getHeight();
-					node.setX(xOffset + );
-				}
+				xOffset += cellSize.width + this._padding;
 			}
+
+			yOffset += rowHeight + this._layerGap;
 		}
 	}
 }

+ 20 - 54
src/optimizer/steps/EdgeRoutingStep.ts

@@ -1,12 +1,12 @@
 import AlgorithmStep from "../AlgorithmStep.js";
 import {EdgeSubdivisions, SiguiyamaContext} from "../siguiyama/SiguiyamaContext.js";
 import EdgeRoutingStepError from "../../errors/optimizer/EdgeRoutingStepError.js";
+import Graph from "../../graph/Graph.js";
 import Node from "../../graph/node/Node.js";
 import Edge from "../../graph/edge/Edge.js";
+import NodeGrid from "../../graph/grid/NodeGrid.js";
 import DummyNode from "../../graph/node/DummyNode.js";
 import DummyEdge from "../../graph/edge/DummyEdge.js";
-import Graph from "../../graph/Graph.js";
-import Layering from "../../graph/layering/Layering.js";
 
 export default class EdgeRoutingStep extends AlgorithmStep<SiguiyamaContext> {
 	public constructor() {
@@ -14,77 +14,43 @@ export default class EdgeRoutingStep extends AlgorithmStep<SiguiyamaContext> {
 	}
 
 	public run(context: SiguiyamaContext) : void {
-		const { layering, graph, edgeSubdivisions } = context;
+		const { graph, grid, edgeSubdivisions } = context;
 
-		if(!layering)
-			throw new EdgeRoutingStepError("Layering is null or undefined");
 		if(!graph)
 			throw new EdgeRoutingStepError("Graph is null or undefined");
+		if(!grid)
+			throw new EdgeRoutingStepError("Grid is null or undefined");
 		if(!edgeSubdivisions)
-			throw new EdgeRoutingStepError("Edge Subdivisions are null or undefined");
+			throw new EdgeRoutingStepError("Edge subdivisions information is null or undefined");
 
-		this.routeEdges(graph, layering, edgeSubdivisions);
+		this.manhattanEdgeRouting(graph, grid, edgeSubdivisions);
 	}
 
-	private routeEdges(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>, edgeSubdivisions: EdgeSubdivisions<Node, Edge<Node>>): void {
+	private manhattanEdgeRouting(graph: Graph<Node, Edge<Node>>, grid: NodeGrid<Node>, edgeSubdivisions: EdgeSubdivisions<Node, Edge<Node>>) : void {
 		const edges = graph.getEdges();
 
 		for(const edge of edges) {
-			const from = edge.getFrom();
-			const to = edge.getTo();
-			const fromNodeIndex = this.getNodeIndex(layering, from);
-			const toNodeIndex = this.getNodeIndex(layering, to);
+			const from = edge.getFrom(), to = edge.getTo();
+			const fromPosition = grid.getPositionOf(from), toPosition = grid.getPositionOf(to);
 
-			if(fromNodeIndex === -1 || toNodeIndex === -1 || fromNodeIndex === toNodeIndex)
+			if(!fromPosition || !toPosition || fromPosition.row === toPosition.row)
 				continue;
 
-			const fromLayerIndex = layering.getNodeLayerIndex(from);
-			if(fromLayerIndex === -1)
-				continue;
+			const fromRow = fromPosition.row, fromColumn = fromPosition.column;
+			const toRow = toPosition.row, toColumn = toPosition.column;
 
-			const targetRowIndex = fromNodeIndex > toNodeIndex ? fromNodeIndex - 1 : fromNodeIndex + 1;
-			const neighborRowCenter = this.getRowCenter(layering, targetRowIndex);
-			if(neighborRowCenter === null)
-				continue;
+			const targetCellPosition: { row: number, column: number } = toRow > fromRow ? { row: toRow, column: fromColumn } : { row: fromRow, column: toColumn };
 
-			const fromCenterY = from.getY() + from.getHeight() / 2;
-			const routedNode = new DummyNode(
-				from.getX() + from.getWidth() / 2,
-				(fromCenterY + neighborRowCenter) / 2
-			);
+			const cellSize = grid.getCellSize(targetCellPosition.row, targetCellPosition.column);
+			const dummyNode = new DummyNode(cellSize.width / 2,cellSize.height / 2);
+			graph.addNode(dummyNode);
+			grid.set(targetCellPosition.row, targetCellPosition.column, dummyNode);
 
-			layering.addToLayer(fromLayerIndex, routedNode);
-			graph.addNode(routedNode);
-
-			const left = new DummyEdge(from, routedNode);
-			const right = new DummyEdge(routedNode, to);
-
-			graph.addEdge(left);
-			graph.addEdge(right);
-			graph.removeEdge(edge.getId());
+			const left = new DummyEdge(from, dummyNode), right = new DummyEdge(dummyNode, to);
+			graph.addEdge(left).addEdge(right).removeEdge(edge.getId());
 
 			edgeSubdivisions.set(edge, { left, right });
-		}
-	}
-
-	private getRowCenter(layering: Layering<Node, Edge<Node>>, rowIndex: number): number | null {
-		if(rowIndex < 0)
-			return null;
 
-		for(const layer of layering.getLayers()) {
-			const node = layer.getNodes().at(rowIndex);
-			if(node)
-				return node.getY() + node.getHeight() / 2;
 		}
-
-		return null;
-	}
-
-	private getNodeIndex(layering: Layering<Node, Edge<Node>>, node: Node) : number {
-		const layerIndex = layering.getNodeLayerIndex(node);
-		if(layerIndex === -1)
-			return -1;
-
-		return layering.getLayers()[layerIndex]!.getNodes().indexOf(node);
 	}
 }