|
|
|
|
@ -233,36 +233,17 @@ export function enhanceGraphWithTags(
@@ -233,36 +233,17 @@ export function enhanceGraphWithTags(
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Custom force for tag anchor gravity |
|
|
|
|
* Applies a gentle pull on each node toward its tag anchors. |
|
|
|
|
* |
|
|
|
|
* @param nodes - The array of network nodes to update. |
|
|
|
|
* @param nodeToAnchors - A map from node IDs to their tag anchor nodes. |
|
|
|
|
* @param alpha - The current simulation alpha (cooling factor). |
|
|
|
|
*/ |
|
|
|
|
export function createTagGravityForce( |
|
|
|
|
export function applyTagGravity( |
|
|
|
|
nodes: NetworkNode[], |
|
|
|
|
links: NetworkLink[], |
|
|
|
|
): any { |
|
|
|
|
// Build a map of nodes to their tag anchors
|
|
|
|
|
const nodeToAnchors = new Map<string, NetworkNode[]>(); |
|
|
|
|
|
|
|
|
|
links.forEach((link) => { |
|
|
|
|
const source = link.source as NetworkNode; |
|
|
|
|
const target = link.target as NetworkNode; |
|
|
|
|
|
|
|
|
|
if (source.isTagAnchor && !target.isTagAnchor) { |
|
|
|
|
if (!nodeToAnchors.has(target.id)) { |
|
|
|
|
nodeToAnchors.set(target.id, []); |
|
|
|
|
} |
|
|
|
|
nodeToAnchors.get(target.id)!.push(source); |
|
|
|
|
} else if (target.isTagAnchor && !source.isTagAnchor) { |
|
|
|
|
if (!nodeToAnchors.has(source.id)) { |
|
|
|
|
nodeToAnchors.set(source.id, []); |
|
|
|
|
} |
|
|
|
|
nodeToAnchors.get(source.id)!.push(target); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
debug("Creating tag gravity force"); |
|
|
|
|
|
|
|
|
|
// Custom force function
|
|
|
|
|
function force(alpha: number) { |
|
|
|
|
nodeToAnchors: Map<string, NetworkNode[]>, |
|
|
|
|
alpha: number |
|
|
|
|
): void { |
|
|
|
|
nodes.forEach((node) => { |
|
|
|
|
if (node.isTagAnchor) return; // Tag anchors don't move
|
|
|
|
|
|
|
|
|
|
@ -290,6 +271,39 @@ export function createTagGravityForce(
@@ -290,6 +271,39 @@ export function createTagGravityForce(
|
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Custom force for tag anchor gravity |
|
|
|
|
*/ |
|
|
|
|
export function createTagGravityForce( |
|
|
|
|
nodes: NetworkNode[], |
|
|
|
|
links: NetworkLink[], |
|
|
|
|
): any { |
|
|
|
|
// Build a map of nodes to their tag anchors
|
|
|
|
|
const nodeToAnchors = new Map<string, NetworkNode[]>(); |
|
|
|
|
|
|
|
|
|
links.forEach((link) => { |
|
|
|
|
const source = link.source as NetworkNode; |
|
|
|
|
const target = link.target as NetworkNode; |
|
|
|
|
|
|
|
|
|
if (source.isTagAnchor && !target.isTagAnchor) { |
|
|
|
|
if (!nodeToAnchors.has(target.id)) { |
|
|
|
|
nodeToAnchors.set(target.id, []); |
|
|
|
|
} |
|
|
|
|
nodeToAnchors.get(target.id)!.push(source); |
|
|
|
|
} else if (target.isTagAnchor && !source.isTagAnchor) { |
|
|
|
|
if (!nodeToAnchors.has(source.id)) { |
|
|
|
|
nodeToAnchors.set(source.id, []); |
|
|
|
|
} |
|
|
|
|
nodeToAnchors.get(source.id)!.push(target); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
debug("Creating tag gravity force"); |
|
|
|
|
|
|
|
|
|
function force(alpha: number) { |
|
|
|
|
applyTagGravity(nodes, nodeToAnchors, alpha); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
force.initialize = function (_: NetworkNode[]) { |
|
|
|
|
|