2016-01-12 01:30:32 +00:00
# Graphoon
2016-01-14 17:02:51 +00:00
[![Version ](https://img.shields.io/badge/Version-1.0.1-blue.svg )](https://github.com/rm-code/Graphoon/releases/latest)
[![License ](http://img.shields.io/badge/Licence-MIT-brightgreen.svg )](LICENSE.md)
2016-01-12 01:30:32 +00:00
2016-01-12 01:34:48 +00:00
A force directed graph algorithm written in Lua.
2016-01-12 01:30:32 +00:00
2016-02-08 22:18:26 +00:00
[![example ](https://cloud.githubusercontent.com/assets/11627131/12313149/44ea06a0-ba65-11e5-82d0-4867022fbdf5.gif )](http://rm-code.github.io/Graphoon/)
2016-01-12 02:23:13 +00:00
2016-01-12 01:34:48 +00:00
## Introduction
_Graphoon_ emerged from the graph calculation code used in both [LoGiVi ](https://github.com/rm-code/logivi ) and [LoFiVi ](https://github.com/rm-code/lofivi ).
A force directed graph layout is achieved by simulating physical forces, which push and pull each node in the graph until a nice layout is found.
2016-01-12 01:30:32 +00:00
## Basic Usage
The basic idea is that you create a new graph object, to which you can then add nodes and edges.
2016-01-12 01:34:48 +00:00
```lua
2016-01-12 01:30:32 +00:00
local GraphLibrary = require('Graphoon').Graph
graph = GraphLibrary.new()
graph:addNode( "Ash Williams" )
graph:addNode( "Necronomicon" )
graph:connectIDs( "Ash Williams", "Necronomicon" )
```
By itself Graphoon only provides functionality for creating the graph and calculating the layout based on physical attraction and repulsion forces.
It provides a ```draw``` and ```update``` function, which can be used to easily write your own rendering code.
2016-01-12 01:34:48 +00:00
The ```draw``` function should be called with two callback functions. The first callback will be used for all nodes and the second one for all the edges.
2016-01-12 01:30:32 +00:00
2016-01-12 01:34:48 +00:00
```lua
2016-01-12 01:30:32 +00:00
graph:draw( function( node )
local x, y = node:getPosition()
drawCircle( 'fill', x, y, 10 )
end,
function( edge )
local ox, oy = edge.origin:getPosition()
local tx, ty = edge.target:getPosition()
drawLine( ox, oy, tx, ty )
end)
```
At its simplest the force calculations can be updated via ```graph:update( dt )```, but the ```update``` function also can receive optional callbacks for both nodes and edges.
## Advanced usage
### Using anchors
Anchors can be used to attach a node to a certain position on the screen. This can be useful if you want to center a certain node for example.
This can either be done directly via the constructor of the node:
2016-01-12 01:34:48 +00:00
```lua
2016-01-12 01:30:32 +00:00
-- Anchor the node to the center of the screen.
graph:addNode( "Ash Williams", screenX * 0.5, screenY * 0.5, true )
```
Or by using the ```setAnchor``` function:
2016-01-12 01:34:48 +00:00
```lua
2016-01-12 01:30:32 +00:00
-- Invert anchor status
2016-01-12 02:19:28 +00:00
node:setAnchor( not node:isAnchor(), mouseX, mouseY )
2016-01-12 01:30:32 +00:00
```
2016-01-12 02:37:03 +00:00
### Using custom classes for Nodes and Edges
If you prefer to not touch the default classes, you can simply inherit from them and tell Graphoon to use your custom classes instead.
```lua
local GraphLibraryNode = require('lib.libfdgraph.fd').Node
local CustomNodeClass = {}
-- You can pass additional arguments to your custom class. Just make sure the
-- default parameters ar in the right order.
function CustomNodeClass.new( id, x, y, anchor, ... )
local self = GraphLibraryNode.new( id, x, y, anchor )
-- ... Custom code
end
return CustomNodeClass
```
```lua
local GraphLibrary = require('Graphoon').Graph
GraphLibrary.setNodeClass( require('CustomNodeClass') )
```