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!

 

most graph problems are NP complete.

ahah. 

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

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

 

https://www.redblobgames.com/

 

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!

Made with Slides.com