Skip to content

Commit f5e87bf

Browse files
committed
Merge branch 'release/1.0.1'
2 parents ee8885a + abfaac9 commit f5e87bf

File tree

5 files changed

+68
-18
lines changed

5 files changed

+68
-18
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
## Version 1.0.1 ( 2016-01-12 )
2+
- Fix [#1](https://github.com/rm-code/Graphoon/issues/1) - Adjusted force calculation and hopefully made it more stable
3+
14
## Version 1.0.0 ( 2016-01-12 )
25
- Initial Release

Graphoon/Graph.lua

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,10 @@ function Graph.new()
3636
---
3737
-- Updates the boundaries of the graph.
3838
-- This represents the rectangular area in which all nodes are contained.
39-
-- @param minX - The current minimum x position.
40-
-- @param maxX - The current maximum y position.
41-
-- @param minY - The current minimum x position.
42-
-- @param maxY - The current maximum y position.
4339
-- @param nx - The new x position to check.
4440
-- @param ny - The new y position to check.
4541
--
46-
local function updateBoundaries( minX, maxX, minY, maxY, nx, ny )
42+
local function updateBoundaries( nx, ny )
4743
return math.min( minX or nx, nx ), math.max( maxX or nx, nx ), math.min( minY or ny, ny ), math.max( maxY or ny, ny );
4844
end
4945

@@ -158,7 +154,7 @@ function Graph.new()
158154
nodeCallback( nodeA );
159155
end
160156

161-
minX, maxX, minY, maxY = updateBoundaries( minX, maxX, minY, maxY, nodeA:getPosition() );
157+
minX, maxX, minY, maxY = updateBoundaries( nodeA:getPosition() );
162158
end
163159
end
164160

Graphoon/Node.lua

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ local current = (...):gsub('%.[^%.]+$', '');
22

33
local Node = {};
44

5-
local FORCE_SPRING = -0.01;
6-
local FORCE_CHARGE = 100000;
5+
local FORCE_SPRING = 0.005;
6+
local FORCE_CHARGE = 200;
77

88
local FORCE_MAX = 4;
9-
local NODE_SPEED = 8;
9+
local NODE_SPEED = 128;
1010
local DAMPING_FACTOR = 0.95;
1111

12-
local DEFAULT_MASS = 0.05;
12+
local DEFAULT_MASS = 3;
1313

1414
---
1515
-- @param id - A unique id which will be used to reference this node.
1616
-- @param x - The x coordinate the Node should be spawned at (optional).
1717
-- @param y - The y coordinate the Node should be spawned at (optional).
1818
-- @param anchor - Wether the node should be locked in place or not (optional).
1919
--
20-
function Node.new( id, x, y, anchor, ... )
20+
function Node.new( id, x, y, anchor )
2121
local self = {};
2222

2323
local px, py = x or 0, y or 0;
@@ -46,17 +46,37 @@ function Node.new( id, x, y, anchor, ... )
4646
ay = clamp( -FORCE_MAX, ay + fy, FORCE_MAX );
4747
end
4848

49+
---
50+
-- Calculates the manhattan distance from the node's coordinates to the
51+
-- target coordinates.
52+
-- @param tx - The target coordinate in x-direction.
53+
-- @param ty - The target coordinate in y-direction.
54+
--
55+
local function getManhattanDistance( tx, ty )
56+
return px - tx, py - ty;
57+
end
58+
59+
---
60+
-- Calculates the actual distance vector between the node's current
61+
-- coordinates and the target coordinates based on the manhattan distance.
62+
-- @param dx - The horizontal distance.
63+
-- @param dy - The vertical distance.
64+
--
65+
local function getRealDistance( dx, dy )
66+
return math.sqrt( dx * dx + dy * dy ) + 0.1;
67+
end
68+
4969
---
5070
-- Attract this node to another node.
5171
-- @param node - The node to use for force calculation.
5272
--
5373
function self:attractTo( node )
54-
local dx, dy = px - node:getX(), py - node:getY();
55-
local distance = math.sqrt(dx * dx + dy * dy);
74+
local dx, dy = getManhattanDistance( node:getPosition() );
75+
local distance = getRealDistance( dx, dy );
5676
dx = dx / distance;
5777
dy = dy / distance;
5878

59-
local strength = FORCE_SPRING * distance;
79+
local strength = -1 * FORCE_SPRING * distance * 0.5;
6080
applyForce( dx * strength, dy * strength );
6181
end
6282

@@ -65,12 +85,12 @@ function Node.new( id, x, y, anchor, ... )
6585
-- @param node - The node to use for force calculation.
6686
--
6787
function self:repelFrom( node )
68-
local dx, dy = px - node:getX(), py - node:getY();
69-
local distance = math.sqrt(dx * dx + dy * dy);
88+
local dx, dy = getManhattanDistance( node:getPosition() );
89+
local distance = getRealDistance( dx, dy );
7090
dx = dx / distance;
7191
dy = dy / distance;
7292

73-
local strength = FORCE_CHARGE * ( mass / ( distance * distance ));
93+
local strength = FORCE_CHARGE * (( mass * node:getMass() ) / ( distance * distance ));
7494
applyForce(dx * strength, dy * strength);
7595
end
7696

@@ -119,6 +139,10 @@ function Node.new( id, x, y, anchor, ... )
119139
mass = nmass;
120140
end
121141

142+
function self:getMass()
143+
return mass;
144+
end
145+
122146
return self;
123147
end
124148

Graphoon/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
return {
2-
_VERSION = 'Graphoon v1.0.0',
2+
_VERSION = 'Graphoon v1.0.1',
33
_DESCRIPTION = 'A force directed graph algorithm written in Lua.',
44
_URL = 'https://github.com/rm-code/Graphoon',
55
_LICENSE = [[

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
A force directed graph algorithm written in Lua.
44

5+
![example](https://cloud.githubusercontent.com/assets/11627131/12252902/a5190d90-b8db-11e5-9199-a9fdb61416ac.png)
6+
57
## Introduction
68

79
_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).
@@ -60,3 +62,28 @@ Or by using the ```setAnchor``` function:
6062
-- Invert anchor status
6163
node:setAnchor( not node:isAnchor(), mouseX, mouseY )
6264
```
65+
66+
### Using custom classes for Nodes and Edges
67+
68+
If you prefer to not touch the default classes, you can simply inherit from them and tell Graphoon to use your custom classes instead.
69+
70+
```lua
71+
local GraphLibraryNode = require('lib.libfdgraph.fd').Node
72+
73+
local CustomNodeClass = {}
74+
75+
-- You can pass additional arguments to your custom class. Just make sure the
76+
-- default parameters ar in the right order.
77+
function CustomNodeClass.new( id, x, y, anchor, ... )
78+
local self = GraphLibraryNode.new( id, x, y, anchor )
79+
80+
-- ... Custom code
81+
end
82+
83+
return CustomNodeClass
84+
```
85+
86+
```lua
87+
local GraphLibrary = require('Graphoon').Graph
88+
GraphLibrary.setNodeClass( require('CustomNodeClass') )
89+
```

0 commit comments

Comments
 (0)