vis-rails 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/vis.js +26 -26
  4. metadata +16 -85
  5. data/vendor/assets/vis/DataSet.js +0 -926
  6. data/vendor/assets/vis/DataView.js +0 -283
  7. data/vendor/assets/vis/graph/Edge.js +0 -957
  8. data/vendor/assets/vis/graph/Graph.js +0 -2291
  9. data/vendor/assets/vis/graph/Groups.js +0 -80
  10. data/vendor/assets/vis/graph/Images.js +0 -41
  11. data/vendor/assets/vis/graph/Node.js +0 -966
  12. data/vendor/assets/vis/graph/Popup.js +0 -132
  13. data/vendor/assets/vis/graph/css/graph-manipulation.css +0 -128
  14. data/vendor/assets/vis/graph/css/graph-navigation.css +0 -66
  15. data/vendor/assets/vis/graph/dotparser.js +0 -829
  16. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +0 -1143
  17. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +0 -311
  18. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +0 -576
  19. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +0 -199
  20. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +0 -205
  21. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +0 -552
  22. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +0 -648
  23. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +0 -398
  24. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +0 -64
  25. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +0 -697
  26. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +0 -66
  27. data/vendor/assets/vis/graph/img/acceptDeleteIcon.png +0 -0
  28. data/vendor/assets/vis/graph/img/addNodeIcon.png +0 -0
  29. data/vendor/assets/vis/graph/img/backIcon.png +0 -0
  30. data/vendor/assets/vis/graph/img/connectIcon.png +0 -0
  31. data/vendor/assets/vis/graph/img/cross.png +0 -0
  32. data/vendor/assets/vis/graph/img/cross2.png +0 -0
  33. data/vendor/assets/vis/graph/img/deleteIcon.png +0 -0
  34. data/vendor/assets/vis/graph/img/downArrow.png +0 -0
  35. data/vendor/assets/vis/graph/img/editIcon.png +0 -0
  36. data/vendor/assets/vis/graph/img/leftArrow.png +0 -0
  37. data/vendor/assets/vis/graph/img/minus.png +0 -0
  38. data/vendor/assets/vis/graph/img/plus.png +0 -0
  39. data/vendor/assets/vis/graph/img/rightArrow.png +0 -0
  40. data/vendor/assets/vis/graph/img/upArrow.png +0 -0
  41. data/vendor/assets/vis/graph/img/zoomExtends.png +0 -0
  42. data/vendor/assets/vis/graph/shapes.js +0 -225
  43. data/vendor/assets/vis/graph3d/Graph3d.js +0 -3306
  44. data/vendor/assets/vis/module/exports.js +0 -65
  45. data/vendor/assets/vis/module/header.js +0 -24
  46. data/vendor/assets/vis/module/imports.js +0 -31
  47. data/vendor/assets/vis/shim.js +0 -252
  48. data/vendor/assets/vis/timeline/Range.js +0 -532
  49. data/vendor/assets/vis/timeline/TimeStep.js +0 -466
  50. data/vendor/assets/vis/timeline/Timeline.js +0 -851
  51. data/vendor/assets/vis/timeline/component/Component.js +0 -52
  52. data/vendor/assets/vis/timeline/component/CurrentTime.js +0 -128
  53. data/vendor/assets/vis/timeline/component/CustomTime.js +0 -182
  54. data/vendor/assets/vis/timeline/component/Group.js +0 -470
  55. data/vendor/assets/vis/timeline/component/ItemSet.js +0 -1332
  56. data/vendor/assets/vis/timeline/component/TimeAxis.js +0 -389
  57. data/vendor/assets/vis/timeline/component/css/animation.css +0 -33
  58. data/vendor/assets/vis/timeline/component/css/currenttime.css +0 -5
  59. data/vendor/assets/vis/timeline/component/css/customtime.css +0 -6
  60. data/vendor/assets/vis/timeline/component/css/item.css +0 -107
  61. data/vendor/assets/vis/timeline/component/css/itemset.css +0 -33
  62. data/vendor/assets/vis/timeline/component/css/labelset.css +0 -36
  63. data/vendor/assets/vis/timeline/component/css/panel.css +0 -71
  64. data/vendor/assets/vis/timeline/component/css/timeaxis.css +0 -48
  65. data/vendor/assets/vis/timeline/component/css/timeline.css +0 -2
  66. data/vendor/assets/vis/timeline/component/item/Item.js +0 -139
  67. data/vendor/assets/vis/timeline/component/item/ItemBox.js +0 -230
  68. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +0 -190
  69. data/vendor/assets/vis/timeline/component/item/ItemRange.js +0 -262
  70. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +0 -57
  71. data/vendor/assets/vis/timeline/img/delete.png +0 -0
  72. data/vendor/assets/vis/timeline/stack.js +0 -112
  73. data/vendor/assets/vis/util.js +0 -990
@@ -1,80 +0,0 @@
1
- /**
2
- * @class Groups
3
- * This class can store groups and properties specific for groups.
4
- */
5
- function Groups() {
6
- this.clear();
7
- this.defaultIndex = 0;
8
- }
9
-
10
-
11
- /**
12
- * default constants for group colors
13
- */
14
- Groups.DEFAULT = [
15
- {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}}, // blue
16
- {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}}, // yellow
17
- {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}}, // red
18
- {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}}, // green
19
- {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}}, // magenta
20
- {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}}, // purple
21
- {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}}, // orange
22
- {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}}, // darkblue
23
- {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}}, // pink
24
- {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}} // mint
25
- ];
26
-
27
-
28
- /**
29
- * Clear all groups
30
- */
31
- Groups.prototype.clear = function () {
32
- this.groups = {};
33
- this.groups.length = function()
34
- {
35
- var i = 0;
36
- for ( var p in this ) {
37
- if (this.hasOwnProperty(p)) {
38
- i++;
39
- }
40
- }
41
- return i;
42
- }
43
- };
44
-
45
-
46
- /**
47
- * get group properties of a groupname. If groupname is not found, a new group
48
- * is added.
49
- * @param {*} groupname Can be a number, string, Date, etc.
50
- * @return {Object} group The created group, containing all group properties
51
- */
52
- Groups.prototype.get = function (groupname) {
53
- var group = this.groups[groupname];
54
-
55
- if (group == undefined) {
56
- // create new group
57
- var index = this.defaultIndex % Groups.DEFAULT.length;
58
- this.defaultIndex++;
59
- group = {};
60
- group.color = Groups.DEFAULT[index];
61
- this.groups[groupname] = group;
62
- }
63
-
64
- return group;
65
- };
66
-
67
- /**
68
- * Add a custom group style
69
- * @param {String} groupname
70
- * @param {Object} style An object containing borderColor,
71
- * backgroundColor, etc.
72
- * @return {Object} group The created group object
73
- */
74
- Groups.prototype.add = function (groupname, style) {
75
- this.groups[groupname] = style;
76
- if (style.color) {
77
- style.color = util.parseColor(style.color);
78
- }
79
- return style;
80
- };
@@ -1,41 +0,0 @@
1
- /**
2
- * @class Images
3
- * This class loads images and keeps them stored.
4
- */
5
- function Images() {
6
- this.images = {};
7
-
8
- this.callback = undefined;
9
- }
10
-
11
- /**
12
- * Set an onload callback function. This will be called each time an image
13
- * is loaded
14
- * @param {function} callback
15
- */
16
- Images.prototype.setOnloadCallback = function(callback) {
17
- this.callback = callback;
18
- };
19
-
20
- /**
21
- *
22
- * @param {string} url Url of the image
23
- * @return {Image} img The image object
24
- */
25
- Images.prototype.load = function(url) {
26
- var img = this.images[url];
27
- if (img == undefined) {
28
- // create the image
29
- var images = this;
30
- img = new Image();
31
- this.images[url] = img;
32
- img.onload = function() {
33
- if (images.callback) {
34
- images.callback(this);
35
- }
36
- };
37
- img.src = url;
38
- }
39
-
40
- return img;
41
- };
@@ -1,966 +0,0 @@
1
- /**
2
- * @class Node
3
- * A node. A node can be connected to other nodes via one or multiple edges.
4
- * @param {object} properties An object containing properties for the node. All
5
- * properties are optional, except for the id.
6
- * {number} id Id of the node. Required
7
- * {string} label Text label for the node
8
- * {number} x Horizontal position of the node
9
- * {number} y Vertical position of the node
10
- * {string} shape Node shape, available:
11
- * "database", "circle", "ellipse",
12
- * "box", "image", "text", "dot",
13
- * "star", "triangle", "triangleDown",
14
- * "square"
15
- * {string} image An image url
16
- * {string} title An title text, can be HTML
17
- * {anytype} group A group name or number
18
- * @param {Graph.Images} imagelist A list with images. Only needed
19
- * when the node has an image
20
- * @param {Graph.Groups} grouplist A list with groups. Needed for
21
- * retrieving group properties
22
- * @param {Object} constants An object with default values for
23
- * example for the color
24
- *
25
- */
26
- function Node(properties, imagelist, grouplist, constants) {
27
- this.selected = false;
28
- this.hover = false;
29
-
30
- this.edges = []; // all edges connected to this node
31
- this.dynamicEdges = [];
32
- this.reroutedEdges = {};
33
-
34
- this.group = constants.nodes.group;
35
- this.fontSize = Number(constants.nodes.fontSize);
36
- this.fontFace = constants.nodes.fontFace;
37
- this.fontColor = constants.nodes.fontColor;
38
- this.fontDrawThreshold = 3;
39
-
40
- this.color = constants.nodes.color;
41
-
42
- // set defaults for the properties
43
- this.id = undefined;
44
- this.shape = constants.nodes.shape;
45
- this.image = constants.nodes.image;
46
- this.x = null;
47
- this.y = null;
48
- this.xFixed = false;
49
- this.yFixed = false;
50
- this.horizontalAlignLeft = true; // these are for the navigation controls
51
- this.verticalAlignTop = true; // these are for the navigation controls
52
- this.radius = constants.nodes.radius;
53
- this.baseRadiusValue = constants.nodes.radius;
54
- this.radiusFixed = false;
55
- this.radiusMin = constants.nodes.radiusMin;
56
- this.radiusMax = constants.nodes.radiusMax;
57
- this.level = -1;
58
- this.preassignedLevel = false;
59
-
60
-
61
- this.imagelist = imagelist;
62
- this.grouplist = grouplist;
63
-
64
- // physics properties
65
- this.fx = 0.0; // external force x
66
- this.fy = 0.0; // external force y
67
- this.vx = 0.0; // velocity x
68
- this.vy = 0.0; // velocity y
69
- this.minForce = constants.minForce;
70
- this.damping = constants.physics.damping;
71
- this.mass = 1; // kg
72
- this.fixedData = {x:null,y:null};
73
-
74
- this.setProperties(properties, constants);
75
-
76
- // creating the variables for clustering
77
- this.resetCluster();
78
- this.dynamicEdgesLength = 0;
79
- this.clusterSession = 0;
80
- this.clusterSizeWidthFactor = constants.clustering.nodeScaling.width;
81
- this.clusterSizeHeightFactor = constants.clustering.nodeScaling.height;
82
- this.clusterSizeRadiusFactor = constants.clustering.nodeScaling.radius;
83
- this.maxNodeSizeIncrements = constants.clustering.maxNodeSizeIncrements;
84
- this.growthIndicator = 0;
85
-
86
- // variables to tell the node about the graph.
87
- this.graphScaleInv = 1;
88
- this.graphScale = 1;
89
- this.canvasTopLeft = {"x": -300, "y": -300};
90
- this.canvasBottomRight = {"x": 300, "y": 300};
91
- this.parentEdgeId = null;
92
- }
93
-
94
- /**
95
- * (re)setting the clustering variables and objects
96
- */
97
- Node.prototype.resetCluster = function() {
98
- // clustering variables
99
- this.formationScale = undefined; // this is used to determine when to open the cluster
100
- this.clusterSize = 1; // this signifies the total amount of nodes in this cluster
101
- this.containedNodes = {};
102
- this.containedEdges = {};
103
- this.clusterSessions = [];
104
- };
105
-
106
- /**
107
- * Attach a edge to the node
108
- * @param {Edge} edge
109
- */
110
- Node.prototype.attachEdge = function(edge) {
111
- if (this.edges.indexOf(edge) == -1) {
112
- this.edges.push(edge);
113
- }
114
- if (this.dynamicEdges.indexOf(edge) == -1) {
115
- this.dynamicEdges.push(edge);
116
- }
117
- this.dynamicEdgesLength = this.dynamicEdges.length;
118
- };
119
-
120
- /**
121
- * Detach a edge from the node
122
- * @param {Edge} edge
123
- */
124
- Node.prototype.detachEdge = function(edge) {
125
- var index = this.edges.indexOf(edge);
126
- if (index != -1) {
127
- this.edges.splice(index, 1);
128
- this.dynamicEdges.splice(index, 1);
129
- }
130
- this.dynamicEdgesLength = this.dynamicEdges.length;
131
- };
132
-
133
-
134
- /**
135
- * Set or overwrite properties for the node
136
- * @param {Object} properties an object with properties
137
- * @param {Object} constants and object with default, global properties
138
- */
139
- Node.prototype.setProperties = function(properties, constants) {
140
- if (!properties) {
141
- return;
142
- }
143
- this.originalLabel = undefined;
144
- // basic properties
145
- if (properties.id !== undefined) {this.id = properties.id;}
146
- if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;}
147
- if (properties.title !== undefined) {this.title = properties.title;}
148
- if (properties.group !== undefined) {this.group = properties.group;}
149
- if (properties.x !== undefined) {this.x = properties.x;}
150
- if (properties.y !== undefined) {this.y = properties.y;}
151
- if (properties.value !== undefined) {this.value = properties.value;}
152
- if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;}
153
-
154
-
155
- // physics
156
- if (properties.mass !== undefined) {this.mass = properties.mass;}
157
-
158
- // navigation controls properties
159
- if (properties.horizontalAlignLeft !== undefined) {this.horizontalAlignLeft = properties.horizontalAlignLeft;}
160
- if (properties.verticalAlignTop !== undefined) {this.verticalAlignTop = properties.verticalAlignTop;}
161
- if (properties.triggerFunction !== undefined) {this.triggerFunction = properties.triggerFunction;}
162
-
163
- if (this.id === undefined) {
164
- throw "Node must have an id";
165
- }
166
-
167
- // copy group properties
168
- if (this.group) {
169
- var groupObj = this.grouplist.get(this.group);
170
- for (var prop in groupObj) {
171
- if (groupObj.hasOwnProperty(prop)) {
172
- this[prop] = groupObj[prop];
173
- }
174
- }
175
- }
176
-
177
- // individual shape properties
178
- if (properties.shape !== undefined) {this.shape = properties.shape;}
179
- if (properties.image !== undefined) {this.image = properties.image;}
180
- if (properties.radius !== undefined) {this.radius = properties.radius;}
181
- if (properties.color !== undefined) {this.color = util.parseColor(properties.color);}
182
-
183
- if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;}
184
- if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;}
185
- if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;}
186
-
187
- if (this.image !== undefined && this.image != "") {
188
- if (this.imagelist) {
189
- this.imageObj = this.imagelist.load(this.image);
190
- }
191
- else {
192
- throw "No imagelist provided";
193
- }
194
- }
195
-
196
- this.xFixed = this.xFixed || (properties.x !== undefined && !properties.allowedToMoveX);
197
- this.yFixed = this.yFixed || (properties.y !== undefined && !properties.allowedToMoveY);
198
- this.radiusFixed = this.radiusFixed || (properties.radius !== undefined);
199
-
200
- if (this.shape == 'image') {
201
- this.radiusMin = constants.nodes.widthMin;
202
- this.radiusMax = constants.nodes.widthMax;
203
- }
204
-
205
- // choose draw method depending on the shape
206
- switch (this.shape) {
207
- case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break;
208
- case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break;
209
- case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break;
210
- case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break;
211
- // TODO: add diamond shape
212
- case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break;
213
- case 'text': this.draw = this._drawText; this.resize = this._resizeText; break;
214
- case 'dot': this.draw = this._drawDot; this.resize = this._resizeShape; break;
215
- case 'square': this.draw = this._drawSquare; this.resize = this._resizeShape; break;
216
- case 'triangle': this.draw = this._drawTriangle; this.resize = this._resizeShape; break;
217
- case 'triangleDown': this.draw = this._drawTriangleDown; this.resize = this._resizeShape; break;
218
- case 'star': this.draw = this._drawStar; this.resize = this._resizeShape; break;
219
- default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break;
220
- }
221
- // reset the size of the node, this can be changed
222
- this._reset();
223
- };
224
-
225
- /**
226
- * select this node
227
- */
228
- Node.prototype.select = function() {
229
- this.selected = true;
230
- this._reset();
231
- };
232
-
233
- /**
234
- * unselect this node
235
- */
236
- Node.prototype.unselect = function() {
237
- this.selected = false;
238
- this._reset();
239
- };
240
-
241
-
242
- /**
243
- * Reset the calculated size of the node, forces it to recalculate its size
244
- */
245
- Node.prototype.clearSizeCache = function() {
246
- this._reset();
247
- };
248
-
249
- /**
250
- * Reset the calculated size of the node, forces it to recalculate its size
251
- * @private
252
- */
253
- Node.prototype._reset = function() {
254
- this.width = undefined;
255
- this.height = undefined;
256
- };
257
-
258
- /**
259
- * get the title of this node.
260
- * @return {string} title The title of the node, or undefined when no title
261
- * has been set.
262
- */
263
- Node.prototype.getTitle = function() {
264
- return typeof this.title === "function" ? this.title() : this.title;
265
- };
266
-
267
- /**
268
- * Calculate the distance to the border of the Node
269
- * @param {CanvasRenderingContext2D} ctx
270
- * @param {Number} angle Angle in radians
271
- * @returns {number} distance Distance to the border in pixels
272
- */
273
- Node.prototype.distanceToBorder = function (ctx, angle) {
274
- var borderWidth = 1;
275
-
276
- if (!this.width) {
277
- this.resize(ctx);
278
- }
279
-
280
- switch (this.shape) {
281
- case 'circle':
282
- case 'dot':
283
- return this.radius + borderWidth;
284
-
285
- case 'ellipse':
286
- var a = this.width / 2;
287
- var b = this.height / 2;
288
- var w = (Math.sin(angle) * a);
289
- var h = (Math.cos(angle) * b);
290
- return a * b / Math.sqrt(w * w + h * h);
291
-
292
- // TODO: implement distanceToBorder for database
293
- // TODO: implement distanceToBorder for triangle
294
- // TODO: implement distanceToBorder for triangleDown
295
-
296
- case 'box':
297
- case 'image':
298
- case 'text':
299
- default:
300
- if (this.width) {
301
- return Math.min(
302
- Math.abs(this.width / 2 / Math.cos(angle)),
303
- Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
304
- // TODO: reckon with border radius too in case of box
305
- }
306
- else {
307
- return 0;
308
- }
309
-
310
- }
311
- // TODO: implement calculation of distance to border for all shapes
312
- };
313
-
314
- /**
315
- * Set forces acting on the node
316
- * @param {number} fx Force in horizontal direction
317
- * @param {number} fy Force in vertical direction
318
- */
319
- Node.prototype._setForce = function(fx, fy) {
320
- this.fx = fx;
321
- this.fy = fy;
322
- };
323
-
324
- /**
325
- * Add forces acting on the node
326
- * @param {number} fx Force in horizontal direction
327
- * @param {number} fy Force in vertical direction
328
- * @private
329
- */
330
- Node.prototype._addForce = function(fx, fy) {
331
- this.fx += fx;
332
- this.fy += fy;
333
- };
334
-
335
- /**
336
- * Perform one discrete step for the node
337
- * @param {number} interval Time interval in seconds
338
- */
339
- Node.prototype.discreteStep = function(interval) {
340
- if (!this.xFixed) {
341
- var dx = this.damping * this.vx; // damping force
342
- var ax = (this.fx - dx) / this.mass; // acceleration
343
- this.vx += ax * interval; // velocity
344
- this.x += this.vx * interval; // position
345
- }
346
-
347
- if (!this.yFixed) {
348
- var dy = this.damping * this.vy; // damping force
349
- var ay = (this.fy - dy) / this.mass; // acceleration
350
- this.vy += ay * interval; // velocity
351
- this.y += this.vy * interval; // position
352
- }
353
- };
354
-
355
-
356
-
357
- /**
358
- * Perform one discrete step for the node
359
- * @param {number} interval Time interval in seconds
360
- * @param {number} maxVelocity The speed limit imposed on the velocity
361
- */
362
- Node.prototype.discreteStepLimited = function(interval, maxVelocity) {
363
- if (!this.xFixed) {
364
- var dx = this.damping * this.vx; // damping force
365
- var ax = (this.fx - dx) / this.mass; // acceleration
366
- this.vx += ax * interval; // velocity
367
- this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx;
368
- this.x += this.vx * interval; // position
369
- }
370
- else {
371
- this.fx = 0;
372
- }
373
-
374
- if (!this.yFixed) {
375
- var dy = this.damping * this.vy; // damping force
376
- var ay = (this.fy - dy) / this.mass; // acceleration
377
- this.vy += ay * interval; // velocity
378
- this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy;
379
- this.y += this.vy * interval; // position
380
- }
381
- else {
382
- this.fy = 0;
383
- }
384
- };
385
-
386
- /**
387
- * Check if this node has a fixed x and y position
388
- * @return {boolean} true if fixed, false if not
389
- */
390
- Node.prototype.isFixed = function() {
391
- return (this.xFixed && this.yFixed);
392
- };
393
-
394
- /**
395
- * Check if this node is moving
396
- * @param {number} vmin the minimum velocity considered as "moving"
397
- * @return {boolean} true if moving, false if it has no velocity
398
- */
399
- // TODO: replace this method with calculating the kinetic energy
400
- Node.prototype.isMoving = function(vmin) {
401
- return (Math.abs(this.vx) > vmin || Math.abs(this.vy) > vmin);
402
- };
403
-
404
- /**
405
- * check if this node is selecte
406
- * @return {boolean} selected True if node is selected, else false
407
- */
408
- Node.prototype.isSelected = function() {
409
- return this.selected;
410
- };
411
-
412
- /**
413
- * Retrieve the value of the node. Can be undefined
414
- * @return {Number} value
415
- */
416
- Node.prototype.getValue = function() {
417
- return this.value;
418
- };
419
-
420
- /**
421
- * Calculate the distance from the nodes location to the given location (x,y)
422
- * @param {Number} x
423
- * @param {Number} y
424
- * @return {Number} value
425
- */
426
- Node.prototype.getDistance = function(x, y) {
427
- var dx = this.x - x,
428
- dy = this.y - y;
429
- return Math.sqrt(dx * dx + dy * dy);
430
- };
431
-
432
-
433
- /**
434
- * Adjust the value range of the node. The node will adjust it's radius
435
- * based on its value.
436
- * @param {Number} min
437
- * @param {Number} max
438
- */
439
- Node.prototype.setValueRange = function(min, max) {
440
- if (!this.radiusFixed && this.value !== undefined) {
441
- if (max == min) {
442
- this.radius = (this.radiusMin + this.radiusMax) / 2;
443
- }
444
- else {
445
- var scale = (this.radiusMax - this.radiusMin) / (max - min);
446
- this.radius = (this.value - min) * scale + this.radiusMin;
447
- }
448
- }
449
- this.baseRadiusValue = this.radius;
450
- };
451
-
452
- /**
453
- * Draw this node in the given canvas
454
- * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
455
- * @param {CanvasRenderingContext2D} ctx
456
- */
457
- Node.prototype.draw = function(ctx) {
458
- throw "Draw method not initialized for node";
459
- };
460
-
461
- /**
462
- * Recalculate the size of this node in the given canvas
463
- * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
464
- * @param {CanvasRenderingContext2D} ctx
465
- */
466
- Node.prototype.resize = function(ctx) {
467
- throw "Resize method not initialized for node";
468
- };
469
-
470
- /**
471
- * Check if this object is overlapping with the provided object
472
- * @param {Object} obj an object with parameters left, top, right, bottom
473
- * @return {boolean} True if location is located on node
474
- */
475
- Node.prototype.isOverlappingWith = function(obj) {
476
- return (this.left < obj.right &&
477
- this.left + this.width > obj.left &&
478
- this.top < obj.bottom &&
479
- this.top + this.height > obj.top);
480
- };
481
-
482
- Node.prototype._resizeImage = function (ctx) {
483
- // TODO: pre calculate the image size
484
-
485
- if (!this.width || !this.height) { // undefined or 0
486
- var width, height;
487
- if (this.value) {
488
- this.radius = this.baseRadiusValue;
489
- var scale = this.imageObj.height / this.imageObj.width;
490
- if (scale !== undefined) {
491
- width = this.radius || this.imageObj.width;
492
- height = this.radius * scale || this.imageObj.height;
493
- }
494
- else {
495
- width = 0;
496
- height = 0;
497
- }
498
- }
499
- else {
500
- width = this.imageObj.width;
501
- height = this.imageObj.height;
502
- }
503
- this.width = width;
504
- this.height = height;
505
-
506
- this.growthIndicator = 0;
507
- if (this.width > 0 && this.height > 0) {
508
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor;
509
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor;
510
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor;
511
- this.growthIndicator = this.width - width;
512
- }
513
- }
514
-
515
- };
516
-
517
- Node.prototype._drawImage = function (ctx) {
518
- this._resizeImage(ctx);
519
-
520
- this.left = this.x - this.width / 2;
521
- this.top = this.y - this.height / 2;
522
-
523
- var yLabel;
524
- if (this.imageObj.width != 0 ) {
525
- // draw the shade
526
- if (this.clusterSize > 1) {
527
- var lineWidth = ((this.clusterSize > 1) ? 10 : 0.0);
528
- lineWidth *= this.graphScaleInv;
529
- lineWidth = Math.min(0.2 * this.width,lineWidth);
530
-
531
- ctx.globalAlpha = 0.5;
532
- ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth);
533
- }
534
-
535
- // draw the image
536
- ctx.globalAlpha = 1.0;
537
- ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height);
538
- yLabel = this.y + this.height / 2;
539
- }
540
- else {
541
- // image still loading... just draw the label for now
542
- yLabel = this.y;
543
- }
544
-
545
- this._label(ctx, this.label, this.x, yLabel, undefined, "top");
546
- };
547
-
548
-
549
- Node.prototype._resizeBox = function (ctx) {
550
- if (!this.width) {
551
- var margin = 5;
552
- var textSize = this.getTextSize(ctx);
553
- this.width = textSize.width + 2 * margin;
554
- this.height = textSize.height + 2 * margin;
555
-
556
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor;
557
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor;
558
- this.growthIndicator = this.width - (textSize.width + 2 * margin);
559
- // this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor;
560
-
561
- }
562
- };
563
-
564
- Node.prototype._drawBox = function (ctx) {
565
- this._resizeBox(ctx);
566
-
567
- this.left = this.x - this.width / 2;
568
- this.top = this.y - this.height / 2;
569
-
570
- var clusterLineWidth = 2.5;
571
- var selectionLineWidth = 2;
572
-
573
- ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
574
-
575
- // draw the outer border
576
- if (this.clusterSize > 1) {
577
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
578
- ctx.lineWidth *= this.graphScaleInv;
579
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
580
-
581
- ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.radius);
582
- ctx.stroke();
583
- }
584
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
585
- ctx.lineWidth *= this.graphScaleInv;
586
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
587
-
588
- ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background;
589
-
590
- ctx.roundRect(this.left, this.top, this.width, this.height, this.radius);
591
- ctx.fill();
592
- ctx.stroke();
593
-
594
- this._label(ctx, this.label, this.x, this.y);
595
- };
596
-
597
-
598
- Node.prototype._resizeDatabase = function (ctx) {
599
- if (!this.width) {
600
- var margin = 5;
601
- var textSize = this.getTextSize(ctx);
602
- var size = textSize.width + 2 * margin;
603
- this.width = size;
604
- this.height = size;
605
-
606
- // scaling used for clustering
607
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor;
608
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor;
609
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor;
610
- this.growthIndicator = this.width - size;
611
- }
612
- };
613
-
614
- Node.prototype._drawDatabase = function (ctx) {
615
- this._resizeDatabase(ctx);
616
- this.left = this.x - this.width / 2;
617
- this.top = this.y - this.height / 2;
618
-
619
- var clusterLineWidth = 2.5;
620
- var selectionLineWidth = 2;
621
-
622
- ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
623
-
624
- // draw the outer border
625
- if (this.clusterSize > 1) {
626
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
627
- ctx.lineWidth *= this.graphScaleInv;
628
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
629
-
630
- ctx.database(this.x - this.width/2 - 2*ctx.lineWidth, this.y - this.height*0.5 - 2*ctx.lineWidth, this.width + 4*ctx.lineWidth, this.height + 4*ctx.lineWidth);
631
- ctx.stroke();
632
- }
633
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
634
- ctx.lineWidth *= this.graphScaleInv;
635
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
636
-
637
- ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
638
- ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height);
639
- ctx.fill();
640
- ctx.stroke();
641
-
642
- this._label(ctx, this.label, this.x, this.y);
643
- };
644
-
645
-
646
- Node.prototype._resizeCircle = function (ctx) {
647
- if (!this.width) {
648
- var margin = 5;
649
- var textSize = this.getTextSize(ctx);
650
- var diameter = Math.max(textSize.width, textSize.height) + 2 * margin;
651
- this.radius = diameter / 2;
652
-
653
- this.width = diameter;
654
- this.height = diameter;
655
-
656
- // scaling used for clustering
657
- // this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor;
658
- // this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor;
659
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor;
660
- this.growthIndicator = this.radius - 0.5*diameter;
661
- }
662
- };
663
-
664
- Node.prototype._drawCircle = function (ctx) {
665
- this._resizeCircle(ctx);
666
- this.left = this.x - this.width / 2;
667
- this.top = this.y - this.height / 2;
668
-
669
- var clusterLineWidth = 2.5;
670
- var selectionLineWidth = 2;
671
-
672
- ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
673
-
674
- // draw the outer border
675
- if (this.clusterSize > 1) {
676
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
677
- ctx.lineWidth *= this.graphScaleInv;
678
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
679
-
680
- ctx.circle(this.x, this.y, this.radius+2*ctx.lineWidth);
681
- ctx.stroke();
682
- }
683
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
684
- ctx.lineWidth *= this.graphScaleInv;
685
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
686
-
687
- ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
688
- ctx.circle(this.x, this.y, this.radius);
689
- ctx.fill();
690
- ctx.stroke();
691
-
692
- this._label(ctx, this.label, this.x, this.y);
693
- };
694
-
695
- Node.prototype._resizeEllipse = function (ctx) {
696
- if (!this.width) {
697
- var textSize = this.getTextSize(ctx);
698
-
699
- this.width = textSize.width * 1.5;
700
- this.height = textSize.height * 2;
701
- if (this.width < this.height) {
702
- this.width = this.height;
703
- }
704
- var defaultSize = this.width;
705
-
706
- // scaling used for clustering
707
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor;
708
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor;
709
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor;
710
- this.growthIndicator = this.width - defaultSize;
711
- }
712
- };
713
-
714
- Node.prototype._drawEllipse = function (ctx) {
715
- this._resizeEllipse(ctx);
716
- this.left = this.x - this.width / 2;
717
- this.top = this.y - this.height / 2;
718
-
719
- var clusterLineWidth = 2.5;
720
- var selectionLineWidth = 2;
721
-
722
- ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
723
-
724
- // draw the outer border
725
- if (this.clusterSize > 1) {
726
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
727
- ctx.lineWidth *= this.graphScaleInv;
728
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
729
-
730
- ctx.ellipse(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth);
731
- ctx.stroke();
732
- }
733
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
734
- ctx.lineWidth *= this.graphScaleInv;
735
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
736
-
737
- ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
738
-
739
- ctx.ellipse(this.left, this.top, this.width, this.height);
740
- ctx.fill();
741
- ctx.stroke();
742
- this._label(ctx, this.label, this.x, this.y);
743
- };
744
-
745
- Node.prototype._drawDot = function (ctx) {
746
- this._drawShape(ctx, 'circle');
747
- };
748
-
749
- Node.prototype._drawTriangle = function (ctx) {
750
- this._drawShape(ctx, 'triangle');
751
- };
752
-
753
- Node.prototype._drawTriangleDown = function (ctx) {
754
- this._drawShape(ctx, 'triangleDown');
755
- };
756
-
757
- Node.prototype._drawSquare = function (ctx) {
758
- this._drawShape(ctx, 'square');
759
- };
760
-
761
- Node.prototype._drawStar = function (ctx) {
762
- this._drawShape(ctx, 'star');
763
- };
764
-
765
- Node.prototype._resizeShape = function (ctx) {
766
- if (!this.width) {
767
- this.radius = this.baseRadiusValue;
768
- var size = 2 * this.radius;
769
- this.width = size;
770
- this.height = size;
771
-
772
- // scaling used for clustering
773
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor;
774
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor;
775
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor;
776
- this.growthIndicator = this.width - size;
777
- }
778
- };
779
-
780
- Node.prototype._drawShape = function (ctx, shape) {
781
- this._resizeShape(ctx);
782
-
783
- this.left = this.x - this.width / 2;
784
- this.top = this.y - this.height / 2;
785
-
786
- var clusterLineWidth = 2.5;
787
- var selectionLineWidth = 2;
788
- var radiusMultiplier = 2;
789
-
790
- // choose draw method depending on the shape
791
- switch (shape) {
792
- case 'dot': radiusMultiplier = 2; break;
793
- case 'square': radiusMultiplier = 2; break;
794
- case 'triangle': radiusMultiplier = 3; break;
795
- case 'triangleDown': radiusMultiplier = 3; break;
796
- case 'star': radiusMultiplier = 4; break;
797
- }
798
-
799
- ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
800
-
801
- // draw the outer border
802
- if (this.clusterSize > 1) {
803
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
804
- ctx.lineWidth *= this.graphScaleInv;
805
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
806
-
807
- ctx[shape](this.x, this.y, this.radius + radiusMultiplier * ctx.lineWidth);
808
- ctx.stroke();
809
- }
810
- ctx.lineWidth = (this.selected ? selectionLineWidth : 1.0) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0);
811
- ctx.lineWidth *= this.graphScaleInv;
812
- ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
813
-
814
- ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
815
- ctx[shape](this.x, this.y, this.radius);
816
- ctx.fill();
817
- ctx.stroke();
818
-
819
- if (this.label) {
820
- this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top');
821
- }
822
- };
823
-
824
- Node.prototype._resizeText = function (ctx) {
825
- if (!this.width) {
826
- var margin = 5;
827
- var textSize = this.getTextSize(ctx);
828
- this.width = textSize.width + 2 * margin;
829
- this.height = textSize.height + 2 * margin;
830
-
831
- // scaling used for clustering
832
- this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor;
833
- this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor;
834
- this.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor;
835
- this.growthIndicator = this.width - (textSize.width + 2 * margin);
836
- }
837
- };
838
-
839
- Node.prototype._drawText = function (ctx) {
840
- this._resizeText(ctx);
841
- this.left = this.x - this.width / 2;
842
- this.top = this.y - this.height / 2;
843
-
844
- this._label(ctx, this.label, this.x, this.y);
845
- };
846
-
847
-
848
- Node.prototype._label = function (ctx, text, x, y, align, baseline) {
849
- if (text && this.fontSize * this.graphScale > this.fontDrawThreshold) {
850
- ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace;
851
- ctx.fillStyle = this.fontColor || "black";
852
- ctx.textAlign = align || "center";
853
- ctx.textBaseline = baseline || "middle";
854
-
855
- var lines = text.split('\n'),
856
- lineCount = lines.length,
857
- fontSize = (this.fontSize + 4),
858
- yLine = y + (1 - lineCount) / 2 * fontSize;
859
-
860
- for (var i = 0; i < lineCount; i++) {
861
- ctx.fillText(lines[i], x, yLine);
862
- yLine += fontSize;
863
- }
864
- }
865
- };
866
-
867
-
868
- Node.prototype.getTextSize = function(ctx) {
869
- if (this.label !== undefined) {
870
- ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace;
871
-
872
- var lines = this.label.split('\n'),
873
- height = (this.fontSize + 4) * lines.length,
874
- width = 0;
875
-
876
- for (var i = 0, iMax = lines.length; i < iMax; i++) {
877
- width = Math.max(width, ctx.measureText(lines[i]).width);
878
- }
879
-
880
- return {"width": width, "height": height};
881
- }
882
- else {
883
- return {"width": 0, "height": 0};
884
- }
885
- };
886
-
887
- /**
888
- * this is used to determine if a node is visible at all. this is used to determine when it needs to be drawn.
889
- * there is a safety margin of 0.3 * width;
890
- *
891
- * @returns {boolean}
892
- */
893
- Node.prototype.inArea = function() {
894
- if (this.width !== undefined) {
895
- return (this.x + this.width *this.graphScaleInv >= this.canvasTopLeft.x &&
896
- this.x - this.width *this.graphScaleInv < this.canvasBottomRight.x &&
897
- this.y + this.height*this.graphScaleInv >= this.canvasTopLeft.y &&
898
- this.y - this.height*this.graphScaleInv < this.canvasBottomRight.y);
899
- }
900
- else {
901
- return true;
902
- }
903
- };
904
-
905
- /**
906
- * checks if the core of the node is in the display area, this is used for opening clusters around zoom
907
- * @returns {boolean}
908
- */
909
- Node.prototype.inView = function() {
910
- return (this.x >= this.canvasTopLeft.x &&
911
- this.x < this.canvasBottomRight.x &&
912
- this.y >= this.canvasTopLeft.y &&
913
- this.y < this.canvasBottomRight.y);
914
- };
915
-
916
- /**
917
- * This allows the zoom level of the graph to influence the rendering
918
- * We store the inverted scale and the coordinates of the top left, and bottom right points of the canvas
919
- *
920
- * @param scale
921
- * @param canvasTopLeft
922
- * @param canvasBottomRight
923
- */
924
- Node.prototype.setScaleAndPos = function(scale,canvasTopLeft,canvasBottomRight) {
925
- this.graphScaleInv = 1.0/scale;
926
- this.graphScale = scale;
927
- this.canvasTopLeft = canvasTopLeft;
928
- this.canvasBottomRight = canvasBottomRight;
929
- };
930
-
931
-
932
- /**
933
- * This allows the zoom level of the graph to influence the rendering
934
- *
935
- * @param scale
936
- */
937
- Node.prototype.setScale = function(scale) {
938
- this.graphScaleInv = 1.0/scale;
939
- this.graphScale = scale;
940
- };
941
-
942
-
943
-
944
- /**
945
- * set the velocity at 0. Is called when this node is contained in another during clustering
946
- */
947
- Node.prototype.clearVelocity = function() {
948
- this.vx = 0;
949
- this.vy = 0;
950
- };
951
-
952
-
953
- /**
954
- * Basic preservation of (kinectic) energy
955
- *
956
- * @param massBeforeClustering
957
- */
958
- Node.prototype.updateVelocity = function(massBeforeClustering) {
959
- var energyBefore = this.vx * this.vx * massBeforeClustering;
960
- //this.vx = (this.vx < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass);
961
- this.vx = Math.sqrt(energyBefore/this.mass);
962
- energyBefore = this.vy * this.vy * massBeforeClustering;
963
- //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass);
964
- this.vy = Math.sqrt(energyBefore/this.mass);
965
- };
966
-