2 Commits 07072e7d8a ... a70f39c4ee

Author SHA1 Message Date
  Pavel Zhigalov a70f39c4ee ok 1 month ago
  Pavel Zhigalov 07072e7d8a ok 1 month ago
4 changed files with 102 additions and 24 deletions
  1. 4 2
      src/index.ts
  2. 0 22
      src/v1/io/dzwf/DZWFData.ts
  3. 27 0
      src/v1/io/dzwf/DzwfData.ts
  4. 71 0
      src/v1/optimizer/steps/EdgeRoutingStep.ts

+ 4 - 2
src/index.ts

@@ -11,6 +11,7 @@ import SiguiyamaAlgorithm from "./v1/optimizer/siguiyama/SiguiyamaAlgorithm.js";
 import { SiguiyamaContext } from "./v1/optimizer/siguiyama/SiguiyamaContext.js";
 import DzwfJsonDeserializer from "./v1/io/deserialize/json/DzwfJsonDeserializer.js";
 import DzwfJsonSerializer from "./v1/io/serialize/json/DzwfJsonSerializer.js";
+import EdgeRoutingStep from "./v1/optimizer/steps/EdgeRoutingStep.js";
 
 export class BPMNOptimizer {
 	private _optimizationAlgorithm?: SiguiyamaAlgorithm;
@@ -32,10 +33,11 @@ const algorithm = new SiguiyamaAlgorithm()
 	.addStep(new LayerAssignmentStep())
 	.addStep(new NodeOrderingStep())
 	.addStep(new CoordinateAssignmentStep(60, 100))
+	.addStep(new EdgeRoutingStep());
 const optimizer = new BPMNOptimizer().setOptimizationAlgorithm(algorithm);
 
-const data = readFileSync("./data/1.json").toString();
+const data = readFileSync("./data/bpmn-graph.json").toString();
 const { dzwfData, graph } = new DzwfJsonDeserializer().deserialize(data);
 const result = optimizer.run(graph);
 
-writeFileSync(`./data/graph-${Date.now()}.json`, new DzwfJsonSerializer().serialize({ dzwfData, graph: result.graph }));
+writeFileSync(`./data/document.dzwf`, new DzwfJsonSerializer().serialize({ dzwfData, graph: result.graph }));

+ 0 - 22
src/v1/io/dzwf/DZWFData.ts

@@ -1,22 +0,0 @@
-export type DZWFData = object & {
-	elements: { 
-		diagram: { 
-			position: { x: number, y: number }
-		},
-		outs: unknown[],
-		ins: unknown[],
-		variables: unknown[],
-		stages: unknown[],
-		name: string,
-		type: string,
-		id: string
-	}[], 
-	links: {
-		sourceId: string,
-		targetId: string,
-		id: string,
-		diagram?: {
-			vertices: { x: number, y: number }[]
-		}
-	}[] 
-};

+ 27 - 0
src/v1/io/dzwf/DzwfData.ts

@@ -0,0 +1,27 @@
+export type DzwfElement = {
+	diagram: {
+		position: { x: number, y: number },
+		size: { width: number, height: number }
+	},
+	outs: unknown[],
+	ins: unknown[],
+	variables: unknown[],
+	stages: unknown[],
+	name: string,
+	type: string,
+	id: string
+}
+
+export type DzwfLink = {
+	sourceId: string,
+	targetId: string,
+	id: string,
+	diagram?: {
+		vertices: { x: number, y: number }[]
+	}
+}
+
+export type DzwfData = object & {
+	elements: DzwfElement[],
+	links: DzwfLink[]
+};

+ 71 - 0
src/v1/optimizer/steps/EdgeRoutingStep.ts

@@ -0,0 +1,71 @@
+import AlgorithmStep from "../AlgorithmStep.js";
+import {SiguiyamaContext} from "../siguiyama/SiguiyamaContext.js";
+import EdgeRoutingStepError from "../../errors/optimizer/EdgeRoutingStepError.js";
+import Node from "../../graph/node/Node.js";
+import Edge from "../../graph/edge/Edge.js";
+import DummyNode from "../../graph/node/DummyNode.js";
+import DummyEdge from "../../graph/edge/DummyEdge.js";
+
+export default class EdgeRoutingStep extends AlgorithmStep<SiguiyamaContext> {
+	public constructor() {
+		super(EdgeRoutingStep.name);
+	}
+
+	public run(context: SiguiyamaContext) : void {
+		const { layering, graph } = context;
+
+		if(!layering)
+			throw new EdgeRoutingStepError("Layering is null or undefined");
+		if(!graph)
+			throw new EdgeRoutingStepError("Graph is null or undefined");
+
+		this.routeEdges(graph.getEdges(), layering, graph);
+	}
+
+	private routeEdges(edges: Edge<Node>[], layering: NonNullable<SiguiyamaContext["layering"]>, graph: NonNullable<SiguiyamaContext["graph"]>): void {
+		const layers = layering.getLayers();
+
+		for(const edge of edges) {
+			const from = edge.getFrom();
+			const to = edge.getTo();
+
+			const fromLayerIndex = layering.getNodeLayerIndex(from);
+			const toLayerIndex = layering.getNodeLayerIndex(to);
+
+			if(fromLayerIndex < 0 || toLayerIndex < 0)
+				continue;
+
+			const fromRowIndex = layers[fromLayerIndex]?.getNodes().findIndex(node => node === from) ?? -1;
+			const toRowIndex = layers[toLayerIndex]?.getNodes().findIndex(node => node === to) ?? -1;
+
+			if(fromRowIndex < 0 || toRowIndex < 0 || fromRowIndex === toRowIndex)
+				continue;
+
+			const rightLayer = layers[fromLayerIndex - 1];
+			if(!rightLayer)
+				continue;
+
+			const rightLayerNodes = rightLayer.getNodes();
+			if(rightLayerNodes.length === 0)
+				continue;
+
+			const anchorNode = rightLayerNodes[0]!;
+			const routedNode = new DummyNode(
+				anchorNode.getX() + anchorNode.getWidth() / 2,
+				from.getY() + from.getHeight() / 2,
+				edge.getId()
+			);
+
+			layering.addToLayer(fromLayerIndex - 1, routedNode);
+			graph.addNode(routedNode);
+
+			const firstSegment = new DummyEdge(from, routedNode, []);
+			const secondSegment = new DummyEdge(routedNode, to, []);
+
+			graph.addEdge(firstSegment);
+			graph.addEdge(secondSegment);
+			graph.removeEdge(edge.getId());
+		}
+
+	}
+}