Skip to content

Commit

Permalink
updated heuristics for cluster boundary spacing
Browse files Browse the repository at this point in the history
  • Loading branch information
shaswat-indian committed Aug 19, 2023
1 parent ba23f60 commit b5456ea
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
48 changes: 48 additions & 0 deletions docs/assets/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,54 @@ export const clusterNodes: GraphNode[] =
}
});

export const singleNodeClusterNodes: GraphNode[] =
range(2).map(i => {

const idx = i
const type = i;

return {
id: `n-${i}`,
label: `${type} ${i}`,
fill: colors[idx],
data: {
type
}
}
});

export const imbalancedClusterNodes: GraphNode[] =
range(20).map(i => {
const idx = (i == 0) ? 2: (i % 2);
const type = types[idx];

return {
id: `n-${i}`,
label: `${type} ${i}`,
fill: colors[idx],
data: {
type
}
}
});

const manyTypes = ['IPV4', 'URL', 'Email', 'MD5', 'SHA256', 'Domain', 'IPV6', 'CRC32', 'SHA512'];

export const manyClusterNodes: GraphNode[] =
range(500).map(i => {
const idx = random(0, manyTypes.length);
const type = manyTypes[idx];

return {
id: `n-${i}`,
label: `${type} ${i}`,
fill: colors[idx%colors.length],
data: {
type
}
}
});

export const clusterEdges: GraphEdge[] = range(random(5, 25)).map(i => ({
id: `e-${i}`,
source: `n-${i}`,
Expand Down
14 changes: 13 additions & 1 deletion docs/demos/Cluster.story.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { GraphCanvas, lightTheme } from '../../src';
import { clusterNodes, clusterEdges, random } from '../assets/demo';
import { clusterNodes, clusterEdges, random, singleNodeClusterNodes, imbalancedClusterNodes, manyClusterNodes } from '../assets/demo';

export default {
title: 'Demos/Cluster',
Expand All @@ -20,6 +20,18 @@ export const Sizes = () => (
<GraphCanvas nodes={clusterNodesWithSizes} draggable edges={[]} clusterAttribute="type" />
);

export const SingleNodeClusters = () => (
<GraphCanvas nodes={singleNodeClusterNodes} draggable edges={[]} clusterAttribute="type" />
);

export const ImbalancedClusters = () => (
<GraphCanvas nodes={imbalancedClusterNodes} draggable edges={[]} clusterAttribute="type" />
);

export const LargeDataset = () => (
<GraphCanvas nodes={manyClusterNodes} draggable edges={[]} clusterAttribute="type" />
);

export const Edges = () => (
<GraphCanvas nodes={clusterNodes} draggable edges={clusterEdges} clusterAttribute="type" />
);
Expand Down
27 changes: 18 additions & 9 deletions src/utils/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,28 @@ export function caluculateCenters({

if (clusterAttribute) {
const groups = buildClusterGroups(nodes, clusterAttribute);
const count = groups.size;
const numGroups = groups.size;
const numNodes = nodes?.length;

// Heuristics to adjust spacing between clusters
const nodeStrengthMultiplier = nodes?.length / 100;
const adjustedCenterStrength =
(Math.max(nodeStrengthMultiplier, 2) + Math.max(count / 2, 2)) *
Math.abs(strength);
const [maxCap, numGroupsFactor] =
numGroups < 6 ? [8, 10 * numGroups] : [20, 20 * numGroups];

let idx = 0;
for (const [key] of groups) {
const radiant = ((2 * Math.PI) / count) * idx;
const x = Math.cos(radiant) * adjustedCenterStrength;
const y = Math.sin(radiant) * adjustedCenterStrength;
for (const [key, value] of groups) {
const radiant = ((2 * Math.PI) / numGroups) * idx;
const groupSize = value.length;

// Heuristics to adjust spacing between clusters
const factor = (groupSize * numGroupsFactor) / numNodes;
const cappedFactor =
groupSize < 10 && numGroups < 8
? numGroups / 2
: Math.max(2, Math.min(maxCap, factor));

const x = Math.cos(radiant) * strength * cappedFactor;
const y = Math.sin(radiant) * strength * cappedFactor;

idx++;

centers.set(key, {
Expand Down

0 comments on commit b5456ea

Please sign in to comment.