@antv/util
Version:
> AntV 底层依赖的工具库,不建议在自己业务中使用。
92 lines (82 loc) • 2.72 kB
text/typescript
import type { CurveArray, PathArray } from '../types';
import { midPoint } from './mid-point';
import { segmentCubicFactory } from './segment-cubic-factory';
type SplitArray = [number, number, number, number, number, number, number, number, number];
function splitCubic(pts: SplitArray, t = 0.5): [CurveArray, CurveArray] {
const p0 = pts.slice(0, 2) as [number, number];
const p1 = pts.slice(2, 4) as [number, number];
const p2 = pts.slice(4, 6) as [number, number];
const p3 = pts.slice(6, 8) as [number, number];
const p4 = midPoint(p0, p1, t);
const p5 = midPoint(p1, p2, t);
const p6 = midPoint(p2, p3, t);
const p7 = midPoint(p4, p5, t);
const p8 = midPoint(p5, p6, t);
const p9 = midPoint(p7, p8, t);
return [
// @ts-ignore
['C'].concat(p4, p7, p9),
// @ts-ignore
['C'].concat(p8, p6, p3),
];
}
function getCurveArray(segments: PathArray) {
return segments.map((segment, i, pathArray) => {
// @ts-ignore
const segmentData = i && (pathArray[i - 1].slice(-2).concat(segment.slice(1)) as SplitArray);
// @ts-ignore
const curveLength = i
? segmentCubicFactory(
segmentData[0],
segmentData[1],
segmentData[2],
segmentData[3],
segmentData[4],
segmentData[5],
segmentData[6],
segmentData[7],
segmentData[8],
{ bbox: false },
).length
: 0;
let subsegs;
if (i) {
// must be [segment,segment]
subsegs = curveLength ? splitCubic(segmentData) : [segment, segment];
} else {
subsegs = [segment];
}
return {
s: segment,
ss: subsegs,
l: curveLength,
};
});
}
export function equalizeSegments(path1: PathArray, path2: PathArray, TL?: number): CurveArray[] {
const c1 = getCurveArray(path1);
const c2 = getCurveArray(path2);
const L1 = c1.length;
const L2 = c2.length;
const l1 = c1.filter((x) => x.l).length;
const l2 = c2.filter((x) => x.l).length;
const m1 = c1.filter((x) => x.l).reduce((a, { l }) => a + l, 0) / l1 || 0;
const m2 = c2.filter((x) => x.l).reduce((a, { l }) => a + l, 0) / l2 || 0;
const tl = TL || Math.max(L1, L2);
const mm = [m1, m2];
const dif = [tl - L1, tl - L2];
let canSplit: number | boolean = 0;
const result = [c1, c2].map((x, i) =>
// @ts-ignore
x.l === tl
? x.map((y) => y.s)
: x
.map((y, j) => {
canSplit = j && dif[i] && y.l >= mm[i];
dif[i] -= canSplit ? 1 : 0;
return canSplit ? y.ss : [y.s];
})
.flat(),
) as CurveArray[];
return result[0].length === result[1].length ? result : equalizeSegments(result[0], result[1], tl);
}