in src/sankeyDiagram.ts [980:1087]
private computePositions(sankeyDiagramDataView: SankeyDiagramDataView): void {
let maxXPosition: number,
maxColumn: SankeyDiagramColumn,
columns: SankeyDiagramColumn[];
maxXPosition = SankeyDiagram.computeXPositions(sankeyDiagramDataView);
SankeyDiagram.sortNodesByX(sankeyDiagramDataView.nodes);
let scaleShift: number = 0;
let minWeight: number = 1;
let minHeight: number = 1;
let scaleStepCount: number = 0;
let minWeigthShift: number = 0;
let minWeigthLink = _.minBy(sankeyDiagramDataView.links, "weigth");
if (minWeigthLink) {
minWeigthShift = minWeigthLink.weigth;
}
if (minWeigthShift > 0) {
minWeigthShift = 0;
}
let minWeightInData: number = minWeigthShift;
minWeigthShift = Math.abs(minWeigthShift) + minWeight;
let maxWeightInData: number = 0;
let maxWeigthLink = _.maxBy(sankeyDiagramDataView.links, "weigth");
if (maxWeigthLink) {
maxWeightInData = maxWeigthLink.weigth;
}
let minRangeOfScale: number = sankeyDiagramDataView.settings.scaleSettings.provideMinHeight ? SankeyDiagram.DefaultMinRangeOfScale : SankeyDiagram.MinRangeOfScale;
while (minHeight <= SankeyDiagram.MinHeightOfNode && scaleStepCount < SankeyDiagram.ScaleStepLimit) {
let weightScale: any;
if (sankeyDiagramDataView.settings.scaleSettings.lnScale) {
weightScale = d3.scaleLog()
.base(Math.E)
.domain([Math.exp(SankeyDiagram.MinDomainOfScale + scaleShift), Math.exp(SankeyDiagram.MaxDomainOfScale + scaleShift)])
.range([minRangeOfScale, SankeyDiagram.DefaultMaxRangeOfScale]);
} else {
weightScale = d3.scaleLinear()
.domain([minWeightInData + scaleShift, maxWeightInData + scaleShift])
.range([minRangeOfScale, SankeyDiagram.DefaultMaxRangeOfScale]);
}
sankeyDiagramDataView.links.forEach((l) => {
l.weigth = weightScale(l.weigth + minWeigthShift);
if (Number.NEGATIVE_INFINITY === l.weigth || Number.POSITIVE_INFINITY === l.weigth || isNaN(l.weigth)) {
l.weigth = 0;
}
});
if (sankeyDiagramDataView.links.some((link: SankeyDiagramLink) => link.weigth <= SankeyDiagram.NegativeValueRange)) {
let minWeight: number = sankeyDiagramDataView.links[0].weigth;
sankeyDiagramDataView.links.forEach((link: SankeyDiagramLink) => {
if (link.weigth <= minWeight) {
minWeight = link.weigth;
}
});
minWeight = Math.abs(minWeight);
// shift weight values to eliminate negative values
sankeyDiagramDataView.links.forEach((link: SankeyDiagramLink) => {
link.weigth += minWeight;
});
}
sankeyDiagramDataView.nodes.forEach((node: SankeyDiagramNode) => {
SankeyDiagram.updateValueOfNode(node);
});
columns = this.getColumns(sankeyDiagramDataView.nodes);
maxColumn = SankeyDiagram.getMaxColumn(columns);
minWeight = d3.min(sankeyDiagramDataView.nodes.filter((n) => Math.max(n.inputWeight, n.outputWeight) > 0).map((n) => Math.max(n.inputWeight, n.outputWeight)));
minWeight = minWeight || SankeyDiagram.DefaultWeightOfLink;
sankeyDiagramDataView.settings._scale.y = this.getScaleByAxisY(maxColumn.sumValueOfNodes);
minHeight = minWeight * sankeyDiagramDataView.settings._scale.y;
scaleShift += SankeyDiagram.ScaleStep;
scaleStepCount++;
}
sankeyDiagramDataView.settings._scale.x = this.getScaleByAxisX(maxXPosition);
SankeyDiagram.scalePositionsByAxes(
sankeyDiagramDataView.settings.sort,
sankeyDiagramDataView.nodes,
columns,
sankeyDiagramDataView.settings._scale,
this.viewport.height,
sankeyDiagramDataView.settings.cyclesLinks.selfLinksWeight && sankeyDiagramDataView.settings.cyclesLinks.drawCycles === CyclesDrawType.Backward
);
this.computeYPosition(
sankeyDiagramDataView.nodes,
sankeyDiagramDataView.settings._scale.y,
sankeyDiagramDataView.settings.cyclesLinks.selfLinksWeight && sankeyDiagramDataView.settings.cyclesLinks.drawCycles === CyclesDrawType.Backward
);
this.applySavedPositions(sankeyDiagramDataView);
this.computeBordersOfTheNode(sankeyDiagramDataView);
SankeyDiagram.computeIntersections(sankeyDiagramDataView);
}