@antv/layout
Version:
graph layout algorithm
95 lines (86 loc) • 2.5 kB
text/typescript
import type { ID } from '../../../types';
import { partition } from '../util';
import { ConflictEntry } from './resolve-conflicts';
export const sort = (
entries: ConflictEntry[],
biasRight?: boolean,
usePrev?: boolean,
keepNodeOrder?: boolean,
) => {
const parts = partition(entries, (entry) => {
const hasFixOrder =
entry.hasOwnProperty('fixorder') && !isNaN(entry.fixorder!);
if (keepNodeOrder) {
return !hasFixOrder && entry.hasOwnProperty('barycenter');
}
// NOTE: 有fixorder的也可以排
return hasFixOrder || entry.hasOwnProperty('barycenter');
});
const sortable = parts.lhs;
const unsortable = parts.rhs.sort((a, b) => -a.i - -b.i);
const vs: ID[][] = [];
let sum = 0;
let weight = 0;
let vsIndex = 0;
sortable?.sort(compareWithBias(!!biasRight, !!usePrev));
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
sortable?.forEach((entry) => {
vsIndex += entry.vs?.length;
vs.push(entry.vs);
sum += entry.barycenter! * entry.weight!;
weight += entry.weight!;
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
});
const result: { vs: ID[]; barycenter?: number; weight?: number } = {
vs: vs.flat(),
};
if (weight) {
result.barycenter = sum / weight;
result.weight = weight;
}
return result;
};
const consumeUnsortable = (
vs: ID[][],
unsortable: ConflictEntry[],
index: number,
) => {
let iindex = index;
let last;
while (
unsortable.length &&
(last = unsortable[unsortable.length - 1]).i <= iindex
) {
unsortable.pop();
vs?.push(last.vs);
iindex++;
}
return iindex;
};
/**
* 配置是否考虑使用之前的布局结果
*/
const compareWithBias = (bias: boolean, usePrev: boolean) => {
return (entryV: ConflictEntry, entryW: ConflictEntry) => {
// 排序的时候先判断fixorder,不行再判断重心
if (entryV.fixorder !== undefined && entryW.fixorder !== undefined) {
return entryV.fixorder - entryW.fixorder;
}
if (entryV.barycenter! < entryW.barycenter!) {
return -1;
}
if (entryV.barycenter! > entryW.barycenter!) {
return 1;
}
// 重心相同,考虑之前排好的顺序
if (usePrev && entryV.order !== undefined && entryW.order !== undefined) {
if (entryV.order < entryW.order) {
return -1;
}
if (entryV.order > entryW.order) {
return 1;
}
}
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
};
};