diff options
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index 4acc507..ba2b893 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -552,7 +552,10 @@ function edges() { function idealLength(count, width, height) { return Math.min(width, height) / Math.max(2, Math.sqrt(count) * 1.5); } -// `pairs`: [a, b, length], the length the link pulls towards (else `idealLength`). +// `pairs`: [a, b, length, loose], the length the link pulls towards (else +// `idealLength`), and whether it is loose (`lengths`). +// How hard a loose link pulls, against a measured one. +const LOOSE = .1; // `only`, if given: the nodes laid out; the others stay where they are. function layout(nodes, pairs, width, height, only) { for (const id of nodes) { @@ -580,11 +583,13 @@ function relax(nodes, pairs, width, height, gain, most, only) { force.get(nodes[j]).x -= dx * push / 10; force.get(nodes[j]).y -= dy * push / 10; } } - for (const [a, b, length] of pairs) { + for (const [a, b, length, loose] of pairs) { const p = positions.get(a), q = positions.get(b); if (!p || !q) continue; const dx = q.x - p.x, dy = q.y - p.y, d = Math.max(Math.hypot(dx, dy), 1); - const pull = (d - (length || ideal)) / d / 4; + const stretch = d - (length || ideal); + // A loose link pulls a little, and never pushes. + const pull = loose ? Math.max(0, stretch) / d / 4 * LOOSE : stretch / d / 4; force.get(a).x += dx * pull; force.get(a).y += dy * pull; force.get(b).x -= dx * pull; force.get(b).y -= dy * pull; } @@ -609,19 +614,21 @@ function relax(nodes, pairs, width, height, gain, most, only) { // them a little every frame (`settle`), not at once. let byRtt = false; try { byRtt = localStorage.getItem("continuum-by-rtt") === "1"; } catch (_) {} -// One spring per pair of nodes, intended or measured or both, all pulling alike: a pair -// both intended and measured doesn't pull twice as hard as one only intended. +// One spring per pair of nodes, intended or measured or both: [a, b, length, loose]. +// Measured links shape the map; a link only intended (nothing measured backs it) is +// `loose`: it gives way to them, pulling only a little where stretched and never pushing +// where they hold its ends closer (`LOOSE`). function lengths(intended, measured, count, width, height) { const ideal = idealLength(count, width, height); const rtts = [...measured.values()].map(edge => edge.link.rttMs) .filter(rtt => typeof rtt === "number" && rtt > 0).sort((x, y) => x - y); const median = rtts[Math.floor(rtts.length / 2)]; - const pairs = new Map([...intended].map(([key, [a, b]]) => [key, [a, b, ideal]])); + const pairs = new Map([...intended].map(([key, [a, b]]) => [key, [a, b, ideal, true]])); for (const [key, { a, b, link }] of measured) { const rtt = link.rttMs; const length = byRtt && median && typeof rtt === "number" && rtt > 0 ? ideal * Math.min(2.5, Math.max(.4, Math.sqrt(rtt / median))) : ideal; - pairs.set(key, [a, b, Math.round(length)]); + pairs.set(key, [a, b, Math.round(length), false]); } return [...pairs.values()]; } |
