|
@@ -5,10 +5,11 @@ import Graph from "../../graph/Graph.js";
|
|
|
import Layering from "../../graph/layering/Layering.js";
|
|
import Layering from "../../graph/layering/Layering.js";
|
|
|
import Node from "../../graph/node/Node.js";
|
|
import Node from "../../graph/node/Node.js";
|
|
|
import AlgorithmStep from "../AlgorithmStep.js";
|
|
import AlgorithmStep from "../AlgorithmStep.js";
|
|
|
-import { FeedbackSet, SiguiyamaContext } from "../siguiyama/SiguiyamaContext.js";
|
|
|
|
|
|
|
+import {EdgeSubdivision, FeedbackSet, SiguiyamaContext} from "../siguiyama/SiguiyamaContext.js";
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Network simplex algorithm
|
|
* Network simplex algorithm
|
|
|
|
|
+ * TODO fix it
|
|
|
*/
|
|
*/
|
|
|
export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext> {
|
|
export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext> {
|
|
|
public constructor() {
|
|
public constructor() {
|
|
@@ -16,16 +17,18 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public run(context: SiguiyamaContext): void {
|
|
public run(context: SiguiyamaContext): void {
|
|
|
- const { graph, feedbackSet } = context;
|
|
|
|
|
|
|
+ const { graph, feedbackSet, edgeSubdivisions } = context;
|
|
|
|
|
|
|
|
if(!graph)
|
|
if(!graph)
|
|
|
throw new LayerAssignmentStepError("Graph was not found!");
|
|
throw new LayerAssignmentStepError("Graph was not found!");
|
|
|
if(!feedbackSet)
|
|
if(!feedbackSet)
|
|
|
throw new LayerAssignmentStepError("Feedback set is undefined!");
|
|
throw new LayerAssignmentStepError("Feedback set is undefined!");
|
|
|
|
|
+ if(!edgeSubdivisions)
|
|
|
|
|
+ throw new LayerAssignmentStepError("Edge subdivisions information is undefined!")
|
|
|
|
|
|
|
|
const layering = this.longestPathAlgorithm(graph);
|
|
const layering = this.longestPathAlgorithm(graph);
|
|
|
|
|
|
|
|
- this.subdivideLongEdges(graph, layering, feedbackSet);
|
|
|
|
|
|
|
+ this.subdivideLongEdges(graph, layering, feedbackSet, context.edgeSubdivisions!);
|
|
|
|
|
|
|
|
context.layering = layering;
|
|
context.layering = layering;
|
|
|
}
|
|
}
|
|
@@ -63,10 +66,17 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const maxLayer = currentLayerIndex;
|
|
|
|
|
+
|
|
|
|
|
+ for(const node of nodes) {
|
|
|
|
|
+ const layer = layering.getLayerOf(node)!;
|
|
|
|
|
+ layering.assign(node, maxLayer - layer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return layering;
|
|
return layering;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private subdivideLongEdges(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>, feedbackSet: FeedbackSet) : void {
|
|
|
|
|
|
|
+ private subdivideLongEdges(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>, feedbackSet: FeedbackSet, edgeSubdivisions: EdgeSubdivision<Node>[]) : void {
|
|
|
const edges = graph.getEdges();
|
|
const edges = graph.getEdges();
|
|
|
|
|
|
|
|
for(const edge of edges) {
|
|
for(const edge of edges) {
|
|
@@ -75,11 +85,11 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
|
|
|
if(edgeSpan <= 1)
|
|
if(edgeSpan <= 1)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- this.subdivideLongEdge(graph, layering, edge, feedbackSet, edgeSpan);
|
|
|
|
|
|
|
+ this.subdivideLongEdge(graph, layering, edge, feedbackSet, edgeSubdivisions, edgeSpan);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private subdivideLongEdge(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>, edge: Edge<Node>, feedbackSet: FeedbackSet, span: number) : void {
|
|
|
|
|
|
|
+ private subdivideLongEdge(graph: Graph<Node, Edge<Node>>, layering: Layering<Node, Edge<Node>>, edge: Edge<Node>, feedbackSet: FeedbackSet, edgeSubdivisions: EdgeSubdivision<Node>[], span: number) : void {
|
|
|
if(span <= 1)
|
|
if(span <= 1)
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
@@ -88,25 +98,30 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
|
|
|
const edgeReversedIndex = feedbackSet.findIndex((e) => e.getId() == edgeId);
|
|
const edgeReversedIndex = feedbackSet.findIndex((e) => e.getId() == edgeId);
|
|
|
const isReversed = edgeReversedIndex !== -1;
|
|
const isReversed = edgeReversedIndex !== -1;
|
|
|
|
|
|
|
|
- if(isReversed)
|
|
|
|
|
- feedbackSet.splice(edgeReversedIndex, 1);
|
|
|
|
|
-
|
|
|
|
|
- graph.removeEdge(edge.getId());
|
|
|
|
|
-
|
|
|
|
|
const fromLayer = layering.getLayerOf(edgeFrom)!;
|
|
const fromLayer = layering.getLayerOf(edgeFrom)!;
|
|
|
|
|
+ const toLayer = layering.getLayerOf(edgeTo)!;
|
|
|
|
|
+ const direction = Math.sign(toLayer - fromLayer);
|
|
|
|
|
+ const subdivision: EdgeSubdivision<Node> = {
|
|
|
|
|
+ originalEdge: edge,
|
|
|
|
|
+ chainNodes: [edgeFrom],
|
|
|
|
|
+ chainEdges: []
|
|
|
|
|
+ };
|
|
|
let previousNode = edgeFrom;
|
|
let previousNode = edgeFrom;
|
|
|
|
|
|
|
|
for(let i = 1; i < span; i++) {
|
|
for(let i = 1; i < span; i++) {
|
|
|
const dummyId = `dummy-${edgeId}-${i}`;
|
|
const dummyId = `dummy-${edgeId}-${i}`;
|
|
|
- const node = new DummyNode(0, 0, dummyId);
|
|
|
|
|
- const dummyLayerIndex = fromLayer - i;
|
|
|
|
|
|
|
+ const node = new DummyNode(0, 0, edgeId, dummyId);
|
|
|
|
|
+
|
|
|
|
|
+ const dummyLayerIndex = fromLayer + direction * i;
|
|
|
|
|
|
|
|
graph.addNode(node);
|
|
graph.addNode(node);
|
|
|
|
|
+ subdivision.chainNodes.push(node);
|
|
|
layering.assign(node, dummyLayerIndex);
|
|
layering.assign(node, dummyLayerIndex);
|
|
|
|
|
|
|
|
const newEdge = new Edge(previousNode, node, [], `${edgeId}_segment_${i}`);
|
|
const newEdge = new Edge(previousNode, node, [], `${edgeId}_segment_${i}`);
|
|
|
|
|
|
|
|
graph.addEdge(newEdge);
|
|
graph.addEdge(newEdge);
|
|
|
|
|
+ subdivision.chainEdges.push(newEdge);
|
|
|
|
|
|
|
|
if(isReversed)
|
|
if(isReversed)
|
|
|
feedbackSet.push(newEdge);
|
|
feedbackSet.push(newEdge);
|
|
@@ -116,7 +131,13 @@ export default class LayerAssignmentStep extends AlgorithmStep<SiguiyamaContext>
|
|
|
|
|
|
|
|
const lastEdge = new Edge(previousNode, edgeTo, [], `${edgeId}_segment_${span}`);
|
|
const lastEdge = new Edge(previousNode, edgeTo, [], `${edgeId}_segment_${span}`);
|
|
|
graph.addEdge(lastEdge);
|
|
graph.addEdge(lastEdge);
|
|
|
|
|
+
|
|
|
|
|
+ subdivision.chainEdges.push(lastEdge);
|
|
|
|
|
+ subdivision.chainNodes.push(edgeTo);
|
|
|
|
|
+
|
|
|
if(isReversed)
|
|
if(isReversed)
|
|
|
feedbackSet.push(lastEdge);
|
|
feedbackSet.push(lastEdge);
|
|
|
|
|
+
|
|
|
|
|
+ edgeSubdivisions.push(subdivision);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|