hm
This commit is contained in:
parent
7455d630fc
commit
4d3fc2cd47
84 changed files with 3429 additions and 3480 deletions
|
|
@ -21,15 +21,59 @@ function lineagePathFromPoints(points) {
|
|||
return `M ${points[0][0].toFixed(1)} ${points[0][1].toFixed(1)} ` + points.slice(1).map(p => `L ${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' ');
|
||||
}
|
||||
|
||||
function lineageCrossGenerationPartnerPath(a, b, nodeW, nodeH, unionY) {
|
||||
function lineageNodeRectsBetween(positions, nodeW, nodeH, y1, y2, excludeIds = new Set(), pad = 10) {
|
||||
const top = Math.min(y1, y2) - pad;
|
||||
const bottom = Math.max(y1, y2) + pad;
|
||||
const rects = [];
|
||||
for (const pos of positions?.values?.() || []) {
|
||||
const id = pos?.node?.id;
|
||||
if (!pos || (id && excludeIds.has(id))) continue;
|
||||
const rectTop = pos.y - pad;
|
||||
const rectBottom = pos.y + nodeH + pad;
|
||||
if (rectBottom < top || rectTop > bottom) continue;
|
||||
rects.push({ left: pos.x - pad, right: pos.x + nodeW + pad, top: rectTop, bottom: rectBottom });
|
||||
}
|
||||
return rects;
|
||||
}
|
||||
|
||||
function lineageVerticalLaneClear(x, y1, y2, rects) {
|
||||
const top = Math.min(y1, y2);
|
||||
const bottom = Math.max(y1, y2);
|
||||
return !(rects || []).some(r => x > r.left && x < r.right && Math.max(top, r.top) < Math.min(bottom, r.bottom));
|
||||
}
|
||||
|
||||
function lineageCrossGenerationPartnerLane(a, b, nodeW, nodeH, context = {}) {
|
||||
const ay = a.y + nodeH / 2;
|
||||
const by = b.y + nodeH / 2;
|
||||
const exclude = new Set([a.node?.id, b.node?.id].filter(Boolean));
|
||||
const rects = lineageNodeRectsBetween(context.positions, nodeW, nodeH, ay, by, exclude, 12);
|
||||
const ax = a.x + nodeW / 2;
|
||||
const bx = b.x + nodeW / 2;
|
||||
const ay = a.y + nodeH;
|
||||
const by = b.y + nodeH;
|
||||
const y = Math.max(unionY, ay + 12, by + 12);
|
||||
const unionX = Math.abs(ax - bx) < 18 ? Math.max(ax, bx) + 30 : (ax + bx) / 2;
|
||||
const points = [[ax, ay], [ax, y], [unionX, y], [bx, y], [bx, by]];
|
||||
return { d: lineagePathFromPoints(points), segments: lineageSegmentsFromPoints(points), unionX, unionY: y };
|
||||
const directX = Math.abs(ax - bx) < 18 ? Math.max(ax, bx) + 30 : (ax + bx) / 2;
|
||||
if (lineageVerticalLaneClear(directX, ay, by, rects)) return directX;
|
||||
const minLeft = Math.min(a.x, b.x, ...rects.map(r => r.left));
|
||||
const maxRight = Math.max(a.x + nodeW, b.x + nodeW, ...rects.map(r => r.right));
|
||||
const width = Number(context.width || 0) || Infinity;
|
||||
const candidates = [
|
||||
maxRight + 18,
|
||||
minLeft - 18,
|
||||
Math.max(a.x + nodeW, b.x + nodeW) + 18,
|
||||
Math.min(a.x, b.x) - 18,
|
||||
].filter(x => Number.isFinite(x) && x >= 12 && x <= width - 12);
|
||||
const clear = candidates.filter(x => lineageVerticalLaneClear(x, ay, by, rects));
|
||||
const pool = clear.length ? clear : candidates;
|
||||
if (pool.length) return pool.sort((x, y) => Math.abs(x - directX) - Math.abs(y - directX))[0];
|
||||
return directX;
|
||||
}
|
||||
|
||||
function lineageCrossGenerationPartnerPath(a, b, nodeW, nodeH, unionY, context = {}) {
|
||||
const railX = lineageCrossGenerationPartnerLane(a, b, nodeW, nodeH, context);
|
||||
const aMidY = a.y + nodeH / 2;
|
||||
const bMidY = b.y + nodeH / 2;
|
||||
const aSideX = railX >= a.x + nodeW / 2 ? a.x + nodeW : a.x;
|
||||
const bSideX = railX >= b.x + nodeW / 2 ? b.x + nodeW : b.x;
|
||||
const points = [[aSideX, aMidY], [railX, aMidY], [railX, bMidY], [bSideX, bMidY]];
|
||||
return { d: lineagePathFromPoints(points), segments: lineageSegmentsFromPoints(points), unionX: railX, unionY: Math.max(aMidY, bMidY) };
|
||||
}
|
||||
|
||||
function lineageSameGenerationPartnerPath(a, b, nodeW, nodeH, unionY, attachOffsetA = 0, attachOffsetB = 0) {
|
||||
|
|
@ -54,8 +98,8 @@ function lineageSameGenerationPartnerPath(a, b, nodeW, nodeH, unionY, attachOffs
|
|||
return { d: lineagePathFromPoints(points), segments: lineageSegmentsFromPoints(points), unionX: (x1 + x2) / 2, unionY: y };
|
||||
}
|
||||
|
||||
function lineagePartnerPathFromPositions(a, b, nodeW, nodeH, unionY, attachOffsetA = 0, attachOffsetB = 0) {
|
||||
if (a.rowIndex !== b.rowIndex) return lineageCrossGenerationPartnerPath(a, b, nodeW, nodeH, unionY);
|
||||
function lineagePartnerPathFromPositions(a, b, nodeW, nodeH, unionY, attachOffsetA = 0, attachOffsetB = 0, context = {}) {
|
||||
if (a.rowIndex !== b.rowIndex) return lineageCrossGenerationPartnerPath(a, b, nodeW, nodeH, unionY, context);
|
||||
return lineageSameGenerationPartnerPath(a, b, nodeW, nodeH, unionY, attachOffsetA, attachOffsetB);
|
||||
}
|
||||
|
||||
|
|
@ -298,7 +342,7 @@ function lineageBuildLinks(nodes, idSet, layout) {
|
|||
const attachA = 0;
|
||||
const attachB = 0;
|
||||
const partnerY = ((left.y + nodeH / 2) + (right.y + nodeH / 2)) / 2;
|
||||
const partner = lineagePartnerPathFromPositions(left, right, nodeW, nodeH, partnerY, attachA, attachB);
|
||||
const partner = lineagePartnerPathFromPositions(left, right, nodeW, nodeH, partnerY, attachA, attachB, layout);
|
||||
if (Number.isFinite(partner.unionX)) group.joinX = partner.unionX;
|
||||
const unionY = Number.isFinite(partner.unionY) ? partner.unionY : partnerY;
|
||||
const clearY = clamp(group.parentBottom + 22 + i * 2, unionY + 10, group.childTop - 36);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue