Add weighted cross-chord edges: 100x weaker than regular edges
This commit is contained in:
parent
ab7e949f07
commit
7259cd67bd
|
|
@ -46,18 +46,23 @@
|
|||
});
|
||||
});
|
||||
|
||||
const edgeList = edges.map(e => ({ s: e.source().id(), t: e.target().id() }));
|
||||
const edgeList = edges.map(e => ({
|
||||
s: e.source().id(),
|
||||
t: e.target().id(),
|
||||
isCrossChord: e.data('isCrossChord')
|
||||
}));
|
||||
|
||||
const iter = (i) => {
|
||||
state.forEach(s => s.fx = 0);
|
||||
|
||||
edgeList.forEach(({s,t})=>{
|
||||
edgeList.forEach(({s, t, isCrossChord})=>{
|
||||
const a = state.get(s), b = state.get(t);
|
||||
if(!a || !b) return;
|
||||
const dx = b.x - a.x;
|
||||
const dist = Math.abs(dx) || 0.0001;
|
||||
const dir = dx / dist;
|
||||
const spring = opts.linkStrength * (dist - opts.linkDistance);
|
||||
const strength = isCrossChord ? (opts.crossChordStrength || 0.001) : opts.linkStrength;
|
||||
const spring = strength * (dist - opts.linkDistance);
|
||||
a.fx += spring * dir;
|
||||
b.fx -= spring * dir;
|
||||
});
|
||||
|
|
@ -350,8 +355,8 @@
|
|||
{
|
||||
selector: 'edge',
|
||||
style: {
|
||||
'width': 1.5,
|
||||
'line-color': '#555555',
|
||||
'width': 2.5,
|
||||
'line-color': '#ffffff',
|
||||
'curve-style': 'straight',
|
||||
'target-arrow-shape': 'none',
|
||||
'label': 'data(ratio)',
|
||||
|
|
@ -364,6 +369,17 @@
|
|||
'text-background-padding': '2px',
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: 'edge[isCrossChord = "true"]',
|
||||
style: {
|
||||
'width': 1,
|
||||
'line-color': '#aaaaaa',
|
||||
'line-style': 'dashed',
|
||||
'curve-style': 'straight',
|
||||
'target-arrow-shape': 'none',
|
||||
'label': '',
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: ':selected',
|
||||
style: {
|
||||
|
|
@ -479,6 +495,33 @@
|
|||
// Build elements array for all chords
|
||||
let elements = [];
|
||||
|
||||
// Collect cross-chord edges (same hs_array between adjacent chords)
|
||||
const crossChordEdges = [];
|
||||
for (let chordIdx = 1; chordIdx < allGraphsData.graphs.length; chordIdx++) {
|
||||
const prevGraph = allGraphsData.graphs[chordIdx - 1];
|
||||
const currGraph = allGraphsData.graphs[chordIdx];
|
||||
if (!prevGraph || !prevGraph.nodes || !currGraph || !currGraph.nodes) continue;
|
||||
|
||||
currGraph.nodes.forEach(n => {
|
||||
const prevNode = prevGraph.nodes.find(pn =>
|
||||
JSON.stringify(pn.hs_array) === JSON.stringify(n.hs_array)
|
||||
);
|
||||
if (prevNode) {
|
||||
const prevNodeId = `c${chordIdx - 1}_${prevNode.id}`;
|
||||
const currNodeId = `c${chordIdx}_${n.id}`;
|
||||
crossChordEdges.push({
|
||||
group: 'edges',
|
||||
data: {
|
||||
source: prevNodeId,
|
||||
target: currNodeId,
|
||||
ratio: "1/1",
|
||||
isCrossChord: "true"
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
allGraphsData.graphs.forEach((graph, chordIdx) => {
|
||||
if (!graph || !graph.nodes) return;
|
||||
|
||||
|
|
@ -527,6 +570,9 @@
|
|||
|
||||
if (elements.length === 0) return;
|
||||
|
||||
// Add cross-chord edges to elements BEFORE layout (so xforce considers them)
|
||||
elements.push(...crossChordEdges);
|
||||
|
||||
// Add all elements
|
||||
cy.add(elements);
|
||||
console.log('Added', elements.length, 'elements');
|
||||
|
|
@ -544,16 +590,19 @@
|
|||
});
|
||||
|
||||
// Run xforce layout to optimize x positions while keeping y fixed
|
||||
cy.layout({
|
||||
const layout = cy.layout({
|
||||
name: 'xforce',
|
||||
linkDistance: 60,
|
||||
linkStrength: 0.1,
|
||||
crossChordStrength: 0.00005,
|
||||
charge: -60,
|
||||
collisionDistance: 35,
|
||||
damping: 0.7,
|
||||
iterations: 250,
|
||||
bounds: bounds,
|
||||
}).run();
|
||||
});
|
||||
|
||||
layout.run();
|
||||
|
||||
// Set canvas size
|
||||
cy.style().json()[0].value = graphWidth;
|
||||
|
|
|
|||
Loading…
Reference in a new issue