sigma-rails 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +37 -0
  4. data/lib/sigma/rails.rb +8 -0
  5. data/lib/sigma/rails/version.rb +5 -0
  6. data/vendor/assets/javascripts/sigma.js +8723 -0
  7. data/vendor/assets/javascripts/sigma.layout.forceAtlas2/README.md +12 -0
  8. data/vendor/assets/javascripts/sigma.layout.forceAtlas2/sigma.layout.forceAtlas2.js +1051 -0
  9. data/vendor/assets/javascripts/sigma.parsers.gexf/README.md +29 -0
  10. data/vendor/assets/javascripts/sigma.parsers.gexf/gexf-parser.js +548 -0
  11. data/vendor/assets/javascripts/sigma.parsers.gexf/sigma.parsers.gexf.js +108 -0
  12. data/vendor/assets/javascripts/sigma.parsers.json/README.md +29 -0
  13. data/vendor/assets/javascripts/sigma.parsers.json/sigma.parsers.json.js +88 -0
  14. data/vendor/assets/javascripts/sigma.plugins.animate/README.md +8 -0
  15. data/vendor/assets/javascripts/sigma.plugins.animate/sigma.plugins.animate.js +165 -0
  16. data/vendor/assets/javascripts/sigma.plugins.dragNodes/README.md +8 -0
  17. data/vendor/assets/javascripts/sigma.plugins.dragNodes/sigma.plugins.dragNodes.js +135 -0
  18. data/vendor/assets/javascripts/sigma.plugins.neighborhoods/README.md +24 -0
  19. data/vendor/assets/javascripts/sigma.plugins.neighborhoods/sigma.plugins.neighborhoods.js +186 -0
  20. data/vendor/assets/javascripts/sigma.renderers.customShapes/README.md +55 -0
  21. data/vendor/assets/javascripts/sigma.renderers.customShapes/shape-library.js +145 -0
  22. data/vendor/assets/javascripts/sigma.renderers.customShapes/sigma.renderers.customShapes.js +112 -0
  23. metadata +121 -0
@@ -0,0 +1,24 @@
1
+ sigma.plugins.neighborhood
2
+ ==========================
3
+
4
+ Plugin developed by [Alexis Jacomy](https://github.com/jacomyal).
5
+
6
+ ---
7
+
8
+ This plugin provides a method to retrieve the neighborhood of a node. Basically, it loads a graph and stores it in a headless `sigma.classes.graph` instance, that you can query to retrieve neighborhoods.
9
+
10
+ It is useful for people who want to provide a neighborhoods navigation inside a big graph instead of just displaying it, and without having to deploy an API or the list of every neighborhoods. But please note that this plugin is here as an example of what you can do with the graph model, and do not hesitate to try customizing your navigation through graphs.
11
+
12
+ This plugin also adds to the graph model a method called "neighborhood". Check the code for more information.
13
+
14
+ Here is how to use it:
15
+
16
+ ````javascript
17
+ var db = new sigma.plugins.neighborhoods();
18
+ db.load('path/to/my/graph.json', function() {
19
+ var nodeId = 'anyNodeID';
20
+ mySigmaInstance
21
+ .read(db.neighborhood(nodeId))
22
+ .refresh();
23
+ });
24
+ ````
@@ -0,0 +1,186 @@
1
+ /**
2
+ * This plugin provides a method to retrieve the neighborhood of a node.
3
+ * Basically, it loads a graph and stores it in a headless sigma.classes.graph
4
+ * instance, that you can query to retrieve neighborhoods.
5
+ *
6
+ * It is useful for people who want to provide a neighborhoods navigation
7
+ * inside a big graph instead of just displaying it, and without having to
8
+ * deploy an API or the list of every neighborhoods.
9
+ *
10
+ * This plugin also adds to the graph model a method called "neighborhood".
11
+ * Check the code for more information.
12
+ *
13
+ * Here is how to use it:
14
+ *
15
+ * > var db = new sigma.plugins.neighborhoods();
16
+ * > db.load('path/to/my/graph.json', function() {
17
+ * > var nodeId = 'anyNodeID';
18
+ * > mySigmaInstance
19
+ * > .read(db.neighborhood(nodeId))
20
+ * > .refresh();
21
+ * > });
22
+ */
23
+ (function() {
24
+ 'use strict';
25
+
26
+ if (typeof sigma === 'undefined')
27
+ throw 'sigma is not declared';
28
+
29
+ /**
30
+ * This method takes the ID of node as argument and returns the graph of the
31
+ * specified node, with every other nodes that are connected to it and every
32
+ * edges that connect two of the previously cited nodes. It uses the built-in
33
+ * indexes from sigma's graph model to search in the graph.
34
+ *
35
+ * @param {string} centerId The ID of the center node.
36
+ * @return {object} The graph, as a simple descriptive object, in
37
+ * the format required by the "read" graph method.
38
+ */
39
+ sigma.classes.graph.addMethod(
40
+ 'neighborhood',
41
+ function(centerId) {
42
+ var k1,
43
+ k2,
44
+ k3,
45
+ node,
46
+ center,
47
+ // Those two local indexes are here just to avoid duplicates:
48
+ localNodesIndex = {},
49
+ localEdgesIndex = {},
50
+ // And here is the resulted graph, empty at the moment:
51
+ graph = {
52
+ nodes: [],
53
+ edges: []
54
+ };
55
+
56
+ // Check that the exists:
57
+ if (!this.nodes(centerId))
58
+ return graph;
59
+
60
+ // Add center. It has to be cloned to add it the "center" attribute
61
+ // without altering the current graph:
62
+ node = this.nodes(centerId);
63
+ center = {};
64
+ center.center = true;
65
+ for (k1 in node)
66
+ center[k1] = node[k1];
67
+
68
+ localNodesIndex[centerId] = true;
69
+ graph.nodes.push(center);
70
+
71
+ // Add neighbors and edges between the center and the neighbors:
72
+ for (k1 in this.allNeighborsIndex[centerId]) {
73
+ if (!localNodesIndex[k1]) {
74
+ localNodesIndex[k1] = true;
75
+ graph.nodes.push(this.nodesIndex[k1]);
76
+ }
77
+
78
+ for (k2 in this.allNeighborsIndex[centerId][k1])
79
+ if (!localEdgesIndex[k2]) {
80
+ localEdgesIndex[k2] = true;
81
+ graph.edges.push(this.edgesIndex[k2]);
82
+ }
83
+ }
84
+
85
+ // Add edges connecting two neighbors:
86
+ for (k1 in localNodesIndex)
87
+ if (k1 !== centerId)
88
+ for (k2 in localNodesIndex)
89
+ if (
90
+ k2 !== centerId &&
91
+ k1 !== k2 &&
92
+ this.allNeighborsIndex[k1][k2]
93
+ )
94
+ for (k3 in this.allNeighborsIndex[k1][k2])
95
+ if (!localEdgesIndex[k3]) {
96
+ localEdgesIndex[k3] = true;
97
+ graph.edges.push(this.edgesIndex[k3]);
98
+ }
99
+
100
+ // Finally, let's return the final graph:
101
+ return graph;
102
+ }
103
+ );
104
+
105
+ sigma.utils.pkg('sigma.plugins');
106
+
107
+ /**
108
+ * sigma.plugins.neighborhoods constructor.
109
+ */
110
+ sigma.plugins.neighborhoods = function() {
111
+ var ready = false,
112
+ readyCallbacks = [],
113
+ graph = new sigma.classes.graph();
114
+
115
+ /**
116
+ * This method just returns the neighborhood of a node.
117
+ *
118
+ * @param {string} centerNodeID The ID of the center node.
119
+ * @return {object} Returns the neighborhood.
120
+ */
121
+ this.neighborhood = function(centerNodeID) {
122
+ return graph.neighborhood(centerNodeID);
123
+ };
124
+
125
+ /**
126
+ * This method loads the JSON graph at "path", stores it in the local graph
127
+ * instance, and executes the callback.
128
+ *
129
+ * @param {string} path The path of the JSON graph file.
130
+ * @param {?function} callback Eventually a callback to execute.
131
+ */
132
+ this.load = function(path, callback) {
133
+ // Quick XHR polyfill:
134
+ var xhr = (function() {
135
+ if (window.XMLHttpRequest)
136
+ return new XMLHttpRequest();
137
+
138
+ var names,
139
+ i;
140
+
141
+ if (window.ActiveXObject) {
142
+ names = [
143
+ 'Msxml2.XMLHTTP.6.0',
144
+ 'Msxml2.XMLHTTP.3.0',
145
+ 'Msxml2.XMLHTTP',
146
+ 'Microsoft.XMLHTTP'
147
+ ];
148
+
149
+ for (i in names)
150
+ try {
151
+ return new ActiveXObject(names[i]);
152
+ } catch (e) {}
153
+ }
154
+
155
+ return null;
156
+ })();
157
+
158
+ if (!xhr)
159
+ throw 'XMLHttpRequest not supported, cannot load the data.';
160
+
161
+ xhr.open('GET', path, true);
162
+ xhr.onreadystatechange = function() {
163
+ if (xhr.readyState === 4) {
164
+ graph.clear().read(JSON.parse(xhr.responseText));
165
+
166
+ if (callback)
167
+ callback();
168
+ }
169
+ };
170
+
171
+ // Start loading the file:
172
+ xhr.send();
173
+
174
+ return this;
175
+ };
176
+
177
+ /**
178
+ * This method cleans the graph instance "reads" a graph into it.
179
+ *
180
+ * @param {object} g The graph object to read.
181
+ */
182
+ this.read = function(g) {
183
+ graph.clear().read(g);
184
+ };
185
+ };
186
+ }).call(window);
@@ -0,0 +1,55 @@
1
+ sigma.renderers.customShapes
2
+ ==================
3
+
4
+ Plugin developed by [Ron Peleg](https://github.com/rpeleg1970).
5
+
6
+ ---
7
+ ## General
8
+ This plugin registers custom node shape renderers, and allows adding scaled images on top of them. See the following [example code](../../examples/plugin-customShapes.html) for full usage.
9
+
10
+ To use, include all .js files under this folder.
11
+
12
+ The plugin implements the `node.borderColor` property to allow control of the (surprise) border color.
13
+
14
+ ## Shapes
15
+ The plugin implements the following shapes. To set a shape renderer, you simply set `node.type='shape-name'` e.g. `node.type='star'`. The default renderer implemented by sigma.js is named `def` - see also [generic custom node renderer example](../../examples/custom-node-renderer.html)
16
+ * `circle`: similar to the `def` renderer, but also allows images
17
+ * `square`
18
+ * `diamond`
19
+ * `equilateral`: equilateral polygon. you can control additional properties in this polygon by setting more values as follows:
20
+ ````javascript
21
+ node.equilateral = {
22
+ rotate: /* rotate right, value in deg */,
23
+ numPoints: /* default 5, integer */
24
+ }
25
+ ````
26
+ * `star`: you can control additional properties in this star by setting more as follows:
27
+ ````javascript
28
+ node.star = {
29
+ numPoints: /* default 5, integer */,
30
+ innerRatio: /* ratio of inner radius in star, compared to node.size */
31
+ }
32
+ ````
33
+ * `pacman`: an example of a more exotic renderer
34
+
35
+ The list of available renderer types can be obtained by calling `ShapeLibrary.enumerate()`
36
+
37
+ ## Images
38
+ You can add an image to any node, simply by adding `node.image` property, with the following content:
39
+ ````javascript
40
+ node.image = {
41
+ url: /* mandatory image URL */,
42
+ clip: /* Ratio of image clipping disk compared to node size (def 1.0) - see example to how we adapt this to differenmt shapes */,
43
+ scale: /* Ratio of how to scale the image, compared to node size, default 1.0 */,
44
+ w: /* numeric width - important for correct scaling if w/h ratio is not 1.0 */,
45
+ h: /* numeric height - important for correct scaling if w/h ratio is not 1.0 */
46
+ }
47
+ ````
48
+ Because the plug-in calls the sigma instance `refresh()` method on image loading, you MUST init as follows or you will not see rendered images:
49
+ ````javascript
50
+ s = new sigma({
51
+ ...
52
+ });
53
+ CustomShapes.init(s);
54
+ s.refresh();
55
+ ````
@@ -0,0 +1,145 @@
1
+ ;(function(undefined) {
2
+ 'use strict';
3
+
4
+ var shapes = [];
5
+ var register = function(name,drawShape,drawBorder) {
6
+ shapes.push({
7
+ 'name': name,
8
+ 'drawShape': drawShape,
9
+ 'drawBorder': drawBorder
10
+ });
11
+ }
12
+
13
+ var enumerateShapes = function() {
14
+ return shapes;
15
+ }
16
+
17
+ /**
18
+ * For the standard closed shapes - the shape fill and border are drawn the
19
+ * same, with some minor differences for fill and border. To facilitate this we
20
+ * create the generic draw functions, that take a shape drawing func and
21
+ * return a shape-renderer/border-renderer
22
+ * ----------
23
+ */
24
+ var genericDrawShape = function(shapeFunc) {
25
+ return function(node,x,y,size,color,context) {
26
+ context.fillStyle = color;
27
+ context.beginPath();
28
+ shapeFunc(node,x,y,size,context);
29
+ context.closePath();
30
+ context.fill();
31
+ };
32
+ }
33
+
34
+ var genericDrawBorder = function(shapeFunc) {
35
+ return function(node,x,y,size,color,context) {
36
+ context.strokeStyle = color;
37
+ context.lineWidth = size / 5;
38
+ context.beginPath();
39
+ shapeFunc(node,x,y,size,context);
40
+ context.closePath();
41
+ context.stroke();
42
+ };
43
+ }
44
+
45
+ /**
46
+ * We now proced to use the generics to define our standard shape/border
47
+ * drawers: square, diamond, equilateral (polygon), and star
48
+ * ----------
49
+ */
50
+ var drawSquare = function(node,x,y,size,context) {
51
+ var rotate = Math.PI*45/180; // 45 deg rotation of a diamond shape
52
+ context.moveTo(x+size*Math.sin(rotate), y-size*Math.cos(rotate)); // first point on outer radius, dwangle 'rotate'
53
+ for(var i=1; i<4; i++) {
54
+ context.lineTo(x+Math.sin(rotate+2*Math.PI*i/4)*size, y-Math.cos(rotate+2*Math.PI*i/4)*size);
55
+ }
56
+ }
57
+ register("square",genericDrawShape(drawSquare),genericDrawBorder(drawSquare));
58
+
59
+ var drawCircle = function(node,x,y,size,context) {
60
+ context.arc(x,y,size,0,Math.PI*2,true);
61
+ }
62
+ register("circle",genericDrawShape(drawCircle),genericDrawBorder(drawCircle));
63
+
64
+ var drawDiamond = function(node,x,y,size,context) {
65
+ context.moveTo(x-size, y);
66
+ context.lineTo(x, y-size);
67
+ context.lineTo(x+size, y);
68
+ context.lineTo(x, y+size);
69
+ }
70
+ register("diamond",genericDrawShape(drawDiamond),genericDrawBorder(drawDiamond));
71
+
72
+ var drawEquilateral = function(node,x,y,size,context) {
73
+ var pcount = (node.equilateral && node.equilateral.numPoints) || 5;
74
+ var rotate = ((node.equilateral && node.equilateral.rotate) || 0)*Math.PI/180;
75
+ var radius = size;
76
+ context.moveTo(x+radius*Math.sin(rotate), y-radius*Math.cos(rotate)); // first point on outer radius, angle 'rotate'
77
+ for(var i=1; i<pcount; i++) {
78
+ context.lineTo(x+Math.sin(rotate+2*Math.PI*i/pcount)*radius, y-Math.cos(rotate+2*Math.PI*i/pcount)*radius);
79
+ }
80
+ }
81
+ register("equilateral",genericDrawShape(drawEquilateral),genericDrawBorder(drawEquilateral));
82
+
83
+
84
+ var starShape = function(node,x,y,size,context) {
85
+ var pcount = (node.star && node.star.numPoints) || 5,
86
+ inRatio = (node.star && node.star.innerRatio) || 0.5,
87
+ outR = size,
88
+ inR = size*inRatio,
89
+ angleOffset = Math.PI/pcount;
90
+ context.moveTo(x, y-size); // first point on outer radius, top
91
+ for(var i=0; i<pcount; i++) {
92
+ context.lineTo(x+Math.sin(angleOffset+2*Math.PI*i/pcount)*inR,
93
+ y-Math.cos(angleOffset+2*Math.PI*i/pcount)*inR);
94
+ context.lineTo(x+Math.sin(2*Math.PI*(i+1)/pcount)*outR,
95
+ y-Math.cos(2*Math.PI*(i+1)/pcount)*outR);
96
+ }
97
+ }
98
+ register("star",genericDrawShape(starShape),genericDrawBorder(starShape));
99
+
100
+ /**
101
+ * An example of a non standard shape (pacman). Here we WILL NOT use the
102
+ * genericDraw functions, but rather register a full custom node renderer for
103
+ * fill, and skip the border renderer which is irrelevant for this shape
104
+ * ----------
105
+ */
106
+ var drawPacman = function(node,x,y,size,color,context) {
107
+ context.fillStyle = 'yellow';
108
+ context.beginPath();
109
+ context.arc(x,y,size,1.25*Math.PI,0,false);
110
+ context.arc(x,y,size,0,0.75*Math.PI,false);
111
+ context.lineTo(x,y);
112
+ context.closePath();
113
+ context.fill();
114
+
115
+ context.fillStyle = 'white';
116
+ context.strokeStyle = 'black';
117
+ context.beginPath();
118
+ context.arc(x+size/3,y-size/3,size/4,0,2*Math.PI,false);
119
+ context.closePath();
120
+ context.fill();
121
+ context.stroke();
122
+
123
+ context.fillStyle = 'black';
124
+ context.beginPath();
125
+ context.arc(x+4*size/9,y-size/3,size/8,0,2*Math.PI,false);
126
+ context.closePath();
127
+ context.fill();
128
+ }
129
+ register("pacman",drawPacman,null);
130
+
131
+ /**
132
+ * Exporting
133
+ * ----------
134
+ */
135
+ this.ShapeLibrary = {
136
+
137
+ // Functions
138
+ enumerate: enumerateShapes,
139
+ // add: addShape,
140
+
141
+ // Version
142
+ version: '0.1'
143
+ };
144
+
145
+ }).call(this);
@@ -0,0 +1,112 @@
1
+ ;(function(undefined) {
2
+ 'use strict';
3
+
4
+ if (typeof sigma === 'undefined')
5
+ throw 'sigma is not declared';
6
+
7
+ if (typeof ShapeLibrary === 'undefined')
8
+ throw 'ShapeLibrary is not declared';
9
+
10
+
11
+ // Initialize package:
12
+ sigma.utils.pkg('sigma.canvas.nodes');
13
+
14
+ var sigInst = undefined;
15
+ var imgCache = {};
16
+
17
+ var initPlugin = function(inst) {
18
+ sigInst = inst;
19
+ }
20
+
21
+ var drawImage = function (node,x,y,size,context) {
22
+ if(sigInst && node.image && node.image.url) {
23
+ var url = node.image.url;
24
+ var ih = node.image.h || 1; // 1 is arbitrary, anyway only the ratio counts
25
+ var iw = node.image.w || 1;
26
+ var scale = node.image.scale || 1;
27
+ var clip = node.image.clip || 1;
28
+
29
+ // create new IMG or get from imgCache
30
+ var image = imgCache[url];
31
+ if(!image) {
32
+ image = document.createElement('IMG');
33
+ image.src = url;
34
+ image.onload = function(){
35
+ // TODO see how we redraw on load
36
+ // need to provide the siginst as a parameter to the library
37
+ console.log("redraw on image load");
38
+ sigInst.refresh();
39
+ };
40
+ imgCache[url] = image;
41
+ }
42
+
43
+ // calculate position and draw
44
+ var xratio = (iw<ih) ? (iw/ih) : 1;
45
+ var yratio = (ih<iw) ? (ih/iw) : 1;
46
+ var r = size*scale;
47
+
48
+ // Draw the clipping disc:
49
+ context.save(); // enter clipping mode
50
+ context.beginPath();
51
+ context.arc(x,y,size*clip,0,Math.PI*2,true);
52
+ context.closePath();
53
+ context.clip();
54
+
55
+ // Draw the actual image
56
+ context.drawImage(image,
57
+ x+Math.sin(-3.142/4)*r*xratio,
58
+ y-Math.cos(-3.142/4)*r*yratio,
59
+ r*xratio*2*Math.sin(-3.142/4)*(-1),
60
+ r*yratio*2*Math.cos(-3.142/4));
61
+ context.restore(); // exit clipping mode
62
+ }
63
+ }
64
+
65
+
66
+ var register = function(name,drawShape,drawBorder) {
67
+ sigma.canvas.nodes[name] = function(node, context, settings) {
68
+ var args = arguments,
69
+ prefix = settings('prefix') || '',
70
+ size = node[prefix + 'size'],
71
+ color = node.color || settings('defaultNodeColor'),
72
+ borderColor = node.borderColor || color,
73
+ x = node[prefix + 'x'],
74
+ y = node[prefix + 'y'];
75
+
76
+ context.save();
77
+
78
+ if(drawShape) {
79
+ drawShape(node,x,y,size,color,context);
80
+ }
81
+
82
+ if(drawBorder) {
83
+ drawBorder(node,x,y,size,borderColor,context);
84
+ }
85
+
86
+ drawImage(node,x,y,size,context);
87
+
88
+ context.restore();
89
+ };
90
+ }
91
+
92
+ ShapeLibrary.enumerate().forEach(function(shape) {
93
+ register(shape.name,shape.drawShape,shape.drawBorder);
94
+ });
95
+
96
+ /**
97
+ * Exporting
98
+ * ----------
99
+ */
100
+ this.CustomShapes = {
101
+
102
+ // Functions
103
+ init: initPlugin,
104
+ // add pre-cache images
105
+
106
+ // Version
107
+ version: '0.1'
108
+ };
109
+
110
+
111
+
112
+ }).call(this);