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) => {
|
const iter = (i) => {
|
||||||
state.forEach(s => s.fx = 0);
|
state.forEach(s => s.fx = 0);
|
||||||
|
|
||||||
edgeList.forEach(({s,t})=>{
|
edgeList.forEach(({s, t, isCrossChord})=>{
|
||||||
const a = state.get(s), b = state.get(t);
|
const a = state.get(s), b = state.get(t);
|
||||||
if(!a || !b) return;
|
if(!a || !b) return;
|
||||||
const dx = b.x - a.x;
|
const dx = b.x - a.x;
|
||||||
const dist = Math.abs(dx) || 0.0001;
|
const dist = Math.abs(dx) || 0.0001;
|
||||||
const dir = dx / dist;
|
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;
|
a.fx += spring * dir;
|
||||||
b.fx -= spring * dir;
|
b.fx -= spring * dir;
|
||||||
});
|
});
|
||||||
|
|
@ -350,8 +355,8 @@
|
||||||
{
|
{
|
||||||
selector: 'edge',
|
selector: 'edge',
|
||||||
style: {
|
style: {
|
||||||
'width': 1.5,
|
'width': 2.5,
|
||||||
'line-color': '#555555',
|
'line-color': '#ffffff',
|
||||||
'curve-style': 'straight',
|
'curve-style': 'straight',
|
||||||
'target-arrow-shape': 'none',
|
'target-arrow-shape': 'none',
|
||||||
'label': 'data(ratio)',
|
'label': 'data(ratio)',
|
||||||
|
|
@ -364,6 +369,17 @@
|
||||||
'text-background-padding': '2px',
|
'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',
|
selector: ':selected',
|
||||||
style: {
|
style: {
|
||||||
|
|
@ -479,6 +495,33 @@
|
||||||
// Build elements array for all chords
|
// Build elements array for all chords
|
||||||
let elements = [];
|
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) => {
|
allGraphsData.graphs.forEach((graph, chordIdx) => {
|
||||||
if (!graph || !graph.nodes) return;
|
if (!graph || !graph.nodes) return;
|
||||||
|
|
||||||
|
|
@ -527,6 +570,9 @@
|
||||||
|
|
||||||
if (elements.length === 0) return;
|
if (elements.length === 0) return;
|
||||||
|
|
||||||
|
// Add cross-chord edges to elements BEFORE layout (so xforce considers them)
|
||||||
|
elements.push(...crossChordEdges);
|
||||||
|
|
||||||
// Add all elements
|
// Add all elements
|
||||||
cy.add(elements);
|
cy.add(elements);
|
||||||
console.log('Added', elements.length, 'elements');
|
console.log('Added', elements.length, 'elements');
|
||||||
|
|
@ -544,16 +590,19 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
// Run xforce layout to optimize x positions while keeping y fixed
|
// Run xforce layout to optimize x positions while keeping y fixed
|
||||||
cy.layout({
|
const layout = cy.layout({
|
||||||
name: 'xforce',
|
name: 'xforce',
|
||||||
linkDistance: 60,
|
linkDistance: 60,
|
||||||
linkStrength: 0.1,
|
linkStrength: 0.1,
|
||||||
|
crossChordStrength: 0.00005,
|
||||||
charge: -60,
|
charge: -60,
|
||||||
collisionDistance: 35,
|
collisionDistance: 35,
|
||||||
damping: 0.7,
|
damping: 0.7,
|
||||||
iterations: 250,
|
iterations: 250,
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
}).run();
|
});
|
||||||
|
|
||||||
|
layout.run();
|
||||||
|
|
||||||
// Set canvas size
|
// Set canvas size
|
||||||
cy.style().json()[0].value = graphWidth;
|
cy.style().json()[0].value = graphWidth;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue