how I learned to stop worrying and optimize my Force Directed Graphs
graph,
WHO ARE YOU?
or
fun facts
CW
CCW
'winding'
non orientable manifold, lol!
fun fact
funny properties
funny things to do
Half-Edge
Dijkstra, A*...
Minimum Spanning Tree
normal unifomisation
Delaunay, Voronoi, "navmeshes"
2D visibility
funny things to do
wow, such ALIVE!
GRAPH !
dead penguin ->
funny Force Directed Graph
a funny algorithm
// define the rest length
const restLength = 50;
// update loop
graph.vertices.forEach(function (a) {
//attraction
a.neighbours.forEach(function (b) {
const dx = b.x - a.x;
const dy = b.y - a.y;
const d = Math.sqrt(dx * dx + dy * dy);
const diff = restLength / a.neighbours.length - d;
const offx = ((diff * dx) / d) * 0.5;
const offy = ((diff * dy) / d) * 0.5;
a.x -= offx;
a.y -= offy;
b.x += offx;
b.y += offy;
});
//repulsion
graph.vertices.forEach(function (b) {
if (a == b) return;
const dx = b.x - a.x;
const dy = b.y - a.y;
const d = Math.sqrt(dx * dx + dy * dy);
const diff = restLength - d;
const offx = ((diff * dx) / d) * 0.01;
const offy = ((diff * dy) / d) * 0.01;
a.x -= offx;
a.y -= offy;
b.x += offx;
b.y += offy;
});
});
attract
repel
R: desired edge length
a funny example
funny libs
3D Force-Directed Graph
a funny sample
import ForceGraph3D from "3d-force-graph";
//1 create a FDG simulation
const FDG = ForceGraph3D({
logarithmicDepthBuffer: true, // three.js renderer settings
})(this.container); //<- add renderer to DOM
const data = {nodes:[], links:[]};//get the data from a graph
graph.nodes.forEach((node) => {//create the nodes
data.nodes.push({ x: node.x, y: node.y, z: node.z,
data:'whatever you want this node to hold' });
});
graph.edges.forEach((link) => { //create the edges
data.links.push({ source: link[0], target: link[1], });
});
FDG.graphData(data);//feed the graph data to the FDG
funny helpers
//set some useful helper
FDG.onNodeHover((node) => {}); //get node on roll over
FDG.onNodeClick((node) => {}); //get node on click
FDG.onLinkHover((link) => {}); // same for links
FDG.onLinkClick((link) => {});
FDG.nodeHoverPrecision(10); //click & hover precision (in pixels)
FDG.linkHoverPrecision(10);
//for DAG (Directed Acyclic Graph) only: render presets
FDG.dagLevelDistance(100);
FDG.dagMode("tr");
FDG.warmupTicks(50); //precomputes the layout for X iterations
FDG.cooldownTicks(100); //ticks before calling "onEngineStop"
FDG.onEngineTick(() => {}); //on FDG update
FDG.onEngineStop(() => {}); //called when the FDG has cooled down
funny optimisation
edge = { a : G.nodes[x], b : G.nodes[y] }
G.edges = [ edge, ... ]
ahah silly!
cunning!
G.edges = [ [x, y], [y, z], ... ]
=> G.edges = [ x,y,y,z... ]
funny optimisation
cunning!
funny further reading
all manners of graphs, from theory to practice to actually useful stuffs for game dev and more
PARAGRAPHL
https://nblintao.github.io/ParaGraphL/
(shameless plug) Graph, a hidden hero
https://barradeau.com/blog/?p=651
funny Machine Learning take on graphs encoding
funny Machine Learning take on graphs encoding
"half edge data structure | unreal"
"a graph is a data strcuture | vray"
THAT'S ALL FOLKS!
american pie graph
By nicolas barradeau
american pie graph
- 810