fix: avoid paths corssing each other

This commit is contained in:
2026-04-13 12:56:39 +08:00
parent 17dca6303c
commit fe361dc877
2 changed files with 128 additions and 32 deletions
@@ -86,4 +86,70 @@ describe('generatePointCrawlMap', () => {
}
}
});
it('should only connect nodes to nearby nodes to avoid crossing paths', () => {
const map = generatePointCrawlMap(42);
// Check each edge between consecutive layers
for (let i = 0; i < map.layers.length - 1; i++) {
const sourceLayer = map.layers[i];
const targetLayer = map.layers[i + 1];
for (const srcId of sourceLayer.nodeIds) {
const srcNode = map.nodes.get(srcId);
expect(srcNode).toBeDefined();
const srcIndex = sourceLayer.nodeIds.indexOf(srcId);
for (const tgtId of srcNode!.childIds) {
const tgtIndex = targetLayer.nodeIds.indexOf(tgtId);
// Calculate the "scaled" source index to compare with target index
// This accounts for layers with different widths
const scaledSrcIndex = srcIndex * (targetLayer.nodeIds.length / sourceLayer.nodeIds.length);
const distance = Math.abs(tgtIndex - scaledSrcIndex);
// The distance should be within a reasonable radius
// Allow some tolerance for edge cases when covering uncovered targets
const maxAllowedDistance = Math.max(2, Math.floor(targetLayer.nodeIds.length / 2));
expect(distance).toBeLessThanOrEqual(maxAllowedDistance);
}
}
}
});
it('should not have crossing edges between consecutive layers', () => {
const map = generatePointCrawlMap(12345);
// Check each pair of consecutive layers for crossing edges
for (let i = 0; i < map.layers.length - 1; i++) {
const sourceLayer = map.layers[i];
const targetLayer = map.layers[i + 1];
// Collect all edges as pairs of indices
const edges: Array<{ srcIndex: number; tgtIndex: number }> = [];
for (let s = 0; s < sourceLayer.nodeIds.length; s++) {
const srcNode = map.nodes.get(sourceLayer.nodeIds[s]);
for (const tgtId of srcNode!.childIds) {
const t = targetLayer.nodeIds.indexOf(tgtId);
edges.push({ srcIndex: s, tgtIndex: t });
}
}
// Check for crossings: edge (s1, t1) and (s2, t2) cross if
// s1 < s2 but t1 > t2 (or vice versa)
for (let e1 = 0; e1 < edges.length; e1++) {
for (let e2 = e1 + 1; e2 < edges.length; e2++) {
const { srcIndex: s1, tgtIndex: t1 } = edges[e1];
const { srcIndex: s2, tgtIndex: t2 } = edges[e2];
// Skip if they share a source (not a crossing)
if (s1 === s2) continue;
const crosses = (s1 < s2 && t1 > t2) || (s1 > s2 && t1 < t2);
expect(crosses).toBe(false);
}
}
}
});
});