| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import LayeringError from "../../errors/graph/layering/LayeringError.js";
- import Edge from "../Edge.js";
- import Node from "../Node.js";
- import Layer from "./Layer.js";
- export default class Layering<TNode extends Node, TEdge extends Edge<TNode>> {
- private readonly _layers: Map<number, Layer<TNode>>;
- public constructor() {
- this._layers = new Map();
- }
- public assign(node: TNode, layerIndex: number) : this {
- if(!this._layers.has(layerIndex))
- this._layers.set(layerIndex, new Layer(layerIndex));
- this._layers.get(layerIndex)!.addNodes([node.id]);
- return this;
- }
- public getLayers(): Layer<TNode>[] {
- return Array.from(this._layers.values()).sort((a, b) => a.index - b.index);
- }
- public getLayerOf(nodeId: TNode["id"]) : number | null {
- for(const [layerIndex, layer] of this._layers)
- if(layer.nodes.some((id) => id == nodeId))
- return layerIndex;
- return null;
- }
- public setLayerOf(nodeId: TNode["id"], newLayerIndex: number) : this {
- const oldIndex = this.getLayerOf(nodeId);
- if(oldIndex !== null) {
- const oldLayer = this._layers.get(oldIndex);
- oldLayer?.removeNodes([nodeId])
- }
- if(!this._layers.has(newLayerIndex))
- this._layers.set(newLayerIndex, new Layer(newLayerIndex));
- this._layers.get(newLayerIndex)!.addNodes([nodeId]);
- return this;
- }
- public isEdgeTight(edge: TEdge) : boolean {
- const { from, to } = edge;
- const fromLayerIndex = this.getLayerOf(from), toLayerIndex = this.getLayerOf(to);
- if(fromLayerIndex == null || toLayerIndex == null)
- throw new LayeringError(`Node from edge ${edge.id} is not assigned to any layer`);
- return Math.abs(fromLayerIndex - toLayerIndex) === 1;
- }
- public getEdgeSpan(edge: TEdge) : number {
- const fromLayer = this.getLayerOf(edge.from);
- const toLayer = this.getLayerOf(edge.to);
- if(fromLayer === null || toLayer === null)
- throw new LayeringError(`Node from edge ${edge.id} is not assigned to any layer`);
- return Math.abs(fromLayer - toLayer);
- }
- public normalize() : this {
- const minLayerIndex = Math.min(...Array.from(this._layers.keys()));
- if(minLayerIndex === 0)
- return this;
- const newLayers = new Map<number, Layer<TNode>>();
- for(const [index, layer] of this._layers) {
- const newLayerIndex = index - minLayerIndex;
- const newLayer = new Layer<TNode>(newLayerIndex);
- newLayer.addNodes(layer.nodes);
- newLayers.set(newLayerIndex, newLayer);
- }
- this._layers.clear();
- newLayers.forEach((layer, index) => this._layers.set(index, layer));
-
- return this;
- }
- public get height() : number {
- return this._layers.size;
- }
- public get width() : number {
- return Math.max(...Array.from(this._layers.values()).map((layer) => layer.width));
- }
- }
|