fix: distribute document clusters across canvas instead of clumping

- Exclude 'extends' edges from force simulation (visual-only, no pull)
- Apply same filter in update() to prevent re-adding extends on refresh
- Stronger derives link strength (0.35) to keep memories near parent doc
- Each document forms its own mini-cluster with orbiting memories
- Clusters spread evenly across the entire canvas
This commit is contained in:
Vorflux AI 2026-03-28 22:58:59 +00:00
parent 056dda2720
commit 46d851a2f8
2 changed files with 16 additions and 12 deletions

View file

@ -9,6 +9,11 @@ export class ForceSimulation {
this.destroy()
try {
// Only use structural edges (derives, updates) for the force layout.
// "extends" edges are visual-only -- they connect documents sharing a
// spaceId but should not pull documents together into a single mass.
const structuralEdges = edges.filter((e) => e.edgeType !== "extends")
this.sim = d3
.forceSimulation<GraphNode>(nodes)
.alphaDecay(FORCE_CONFIG.alphaDecay)
@ -18,7 +23,7 @@ export class ForceSimulation {
this.sim.force(
"link",
d3
.forceLink<GraphNode, GraphEdge>(edges)
.forceLink<GraphNode, GraphEdge>(structuralEdges)
.id((d) => d.id)
.distance((link) =>
link.edgeType === "derives"
@ -30,8 +35,6 @@ export class ForceSimulation {
return FORCE_CONFIG.linkStrength.docMemory
if (link.edgeType === "updates")
return FORCE_CONFIG.linkStrength.version
if (link.edgeType === "extends")
return FORCE_CONFIG.linkStrength.docDocBase
return FORCE_CONFIG.linkStrength.fallback
}),
)
@ -70,7 +73,8 @@ export class ForceSimulation {
if (!this.sim) return
this.sim.nodes(nodes)
const linkForce = this.sim.force<d3.ForceLink<GraphNode, GraphEdge>>("link")
if (linkForce) linkForce.links(edges)
if (linkForce)
linkForce.links(edges.filter((e) => e.edgeType !== "extends"))
}
reheat(): void {

View file

@ -9,22 +9,22 @@ export const MEMORY_BORDER_KEYS = {
export const FORCE_CONFIG = {
linkStrength: {
docMemory: 0.12,
version: 0.5,
docDocBase: 0.08,
fallback: 0.08,
docMemory: 0.35,
version: 0.6,
docDocBase: 0.0,
fallback: 0.05,
},
linkDistance: 300,
docMemoryDistance: 220,
chargeStrength: -2500,
docMemoryDistance: 180,
chargeStrength: -2000,
collisionRadius: { document: 70, memory: 35 },
collisionStrength: 0.7,
centeringStrength: 0.08,
centeringStrength: 0.06,
alphaDecay: 0.025,
alphaMin: 0.001,
velocityDecay: 0.45,
alphaTarget: 0.3,
preSettleTicks: 250,
preSettleTicks: 150,
}
export const GRAPH_SETTINGS = {