Skip to content

Commit d5f4244

Browse files
fix(graph): keep settling resistance responsive
1 parent 1e05eb5 commit d5f4244

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

engraphis/dashboard_assets/engraphis-graph-every-worker.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@
338338
/* A tight per-pass step cap keeps the settle from smearing district boundaries. */
339339
const resistance = Number.isFinite(Number(settings.damping))
340340
? Math.max(0, Math.min(15, Number(settings.damping))) : 1;
341-
const damp = Math.max(0.2, Math.min(0.95, 0.8 / (0.75 + 0.25 * resistance)));
341+
/* Keep the full 0..15 control range responsive: the reciprocal curve reaches 0.2
342+
at resistance 13, so a 0.2 floor would make the final two slider units inert. */
343+
const damp = Math.max(0.15, Math.min(0.95, 0.8 / (0.75 + 0.25 * resistance)));
342344
const maxStep = SPACING * MAP_SCALE * 0.7;
343345
for (let index = 0; index < count; index += 1) {
344346
let vx = dx[index] * damp, vy = dy[index] * damp;

tests/test_graph_every_asset.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,41 @@ def test_worker_settings_relayout_and_reheat_move_nodes() -> None:
168168
assert report["reheated_streams"] is True
169169

170170

171+
def test_worker_settling_resistance_keeps_high_end_distinct() -> None:
172+
script = """
173+
const nodes = [
174+
{ id: 'a', community_id: 'c' },
175+
{ id: 'b', community_id: 'c' },
176+
{ id: 'c', community_id: 'c' },
177+
];
178+
send({ type: 'prepare', payload: { nodes, links: [{ source: 'a', target: 'b' }] } });
179+
const waitForLayouts = (count, callback) => {
180+
const tick = () => {
181+
if (all('layout').length >= count) return callback();
182+
setTimeout(tick, 10);
183+
};
184+
tick();
185+
};
186+
waitForLayouts(1, () => {
187+
const samples = {};
188+
const next = (resistance, callback) => {
189+
const before = all('layout').length;
190+
send({ type: 'settings', settings: { damping: resistance }, relayout: true, fit: false });
191+
// settings emits the reseeded preview immediately; wait for the first relaxed layout.
192+
waitForLayouts(before + 2, () => {
193+
samples[resistance] = latest('layout').positions;
194+
callback();
195+
});
196+
};
197+
next(13, () => next(14, () => next(15, () => console.log(JSON.stringify({ samples })))));
198+
});
199+
"""
200+
report = _run_worker(script)
201+
samples = report["samples"]
202+
assert samples["13"] != samples["14"]
203+
assert samples["14"] != samples["15"]
204+
205+
171206
def test_renderer_is_webgl2_only_without_live_simulation_or_canvas_fallback() -> None:
172207
renderer = RENDERER.read_text(encoding="utf-8")
173208
assert "getContext('webgl2'" in renderer

0 commit comments

Comments
 (0)