瀏覽代碼

documentation + rework 2 (layer assignment update)

icestormikk 1 月之前
父節點
當前提交
c53450848a
共有 1 個文件被更改,包括 43 次插入2 次删除
  1. 43 2
      src/v1/optimizer/steps/LayerAssignmentStep.ts

+ 43 - 2
src/v1/optimizer/steps/LayerAssignmentStep.ts

@@ -5,6 +5,7 @@ import Layering from "../../graph/layering/Layering.js";
 import Node from "../../graph/node/Node.js";
 import AlgorithmStep from "../AlgorithmStep.js";
 import {SiguiyamaContext} from "../siguiyama/SiguiyamaContext.js";
+import DummyNode from "../../graph/node/DummyNode.js";
 
 /**
  * Шаг алгоритма Sugiyama для присвоения слоёв вершинам графа.
@@ -36,7 +37,11 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
 		if(!graph.isAcyclic())
 			throw new LayerAssignmentStepError("Graph is acyclic, can not assign layers to an acyclic graph!");
 
-		context.layering = this.longestPathAlgorithm(graph);
+		const layering = this.longestPathAlgorithm(graph);
+
+		this.divideLongEdges(graph, layering);
+
+		context.layering = layering;
 	}
 
 	/**
@@ -73,4 +78,40 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
 
 		return layering;
 	}
-}
+
+	/**
+	 * Разбивает длинные рёбра (span >= 2) добавлением dummy-вершин между слоями.
+	 *
+	 * Для каждого ребра, у которого {@link Layering.getEdgeSpan} возвращает значение больше 1:
+	 * - создаётся цепочка из `span - 1` вершин {@link DummyNode};
+	 * - каждая dummy-вершина добавляется в промежуточный слой;
+	 * - исходная вершина/последняя dummy соединяется новым сегментом {@link Edge}.
+	 *
+	 * @param graph Граф, в который добавляются dummy-вершины и сегменты рёбер.
+	 * @param layering Текущее разбиение графа на слои, используемое для вычисления span и вставки dummy-вершин.
+	 */
+	private divideLongEdges(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>) : void {
+		const edges = graph.getEdges();
+
+		for(const edge of edges) {
+			const span = layering.getEdgeSpan(edge);
+			if(span < 2)
+				continue;
+
+			const from = edge.getFrom();
+			const fromLayer = layering.getNodeLayerIndex(from);
+
+			let currentNode = from;
+			for(let i = 1; i < span; i++) {
+				const dummyNode = new DummyNode(0, 0, edge.getId());
+				layering.addToLayer(fromLayer - i, dummyNode);
+				graph.addNode(dummyNode);
+
+				const dummyEdge = new Edge(currentNode, dummyNode);
+				graph.addEdge(dummyEdge);
+
+				currentNode = dummyNode;
+			}
+		}
+	}
+}