Graph database Analysis of the Steam Network
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
5.4 KiB

  1. ;(function(undefined) {
  2. 'use strict';
  3. if (typeof sigma === 'undefined')
  4. throw 'sigma is not declared';
  5. // Initialize packages:
  6. sigma.utils.pkg('sigma.middlewares');
  7. sigma.utils.pkg('sigma.utils');
  8. /**
  9. * This middleware will rescale the graph such that it takes an optimal space
  10. * on the renderer.
  11. *
  12. * As each middleware, this function is executed in the scope of the sigma
  13. * instance.
  14. *
  15. * @param {?string} readPrefix The read prefix.
  16. * @param {?string} writePrefix The write prefix.
  17. * @param {object} options The parameters.
  18. */
  19. sigma.middlewares.rescale = function(readPrefix, writePrefix, options) {
  20. var i,
  21. l,
  22. a,
  23. b,
  24. c,
  25. d,
  26. scale,
  27. margin,
  28. n = this.graph.nodes(),
  29. e = this.graph.edges(),
  30. settings = this.settings.embedObjects(options || {}),
  31. bounds = settings('bounds') || sigma.utils.getBoundaries(
  32. this.graph,
  33. readPrefix,
  34. true
  35. ),
  36. minX = bounds.minX,
  37. minY = bounds.minY,
  38. maxX = bounds.maxX,
  39. maxY = bounds.maxY,
  40. sizeMax = bounds.sizeMax,
  41. weightMax = bounds.weightMax,
  42. w = settings('width') || 1,
  43. h = settings('height') || 1,
  44. rescaleSettings = settings('autoRescale'),
  45. validSettings = {
  46. nodePosition: 1,
  47. nodeSize: 1,
  48. edgeSize: 1
  49. };
  50. /**
  51. * What elements should we rescale?
  52. */
  53. if (!(rescaleSettings instanceof Array))
  54. rescaleSettings = ['nodePosition', 'nodeSize', 'edgeSize'];
  55. for (i = 0, l = rescaleSettings.length; i < l; i++)
  56. if (!validSettings[rescaleSettings[i]])
  57. throw new Error(
  58. 'The rescale setting "' + rescaleSettings[i] + '" is not recognized.'
  59. );
  60. var np = ~rescaleSettings.indexOf('nodePosition'),
  61. ns = ~rescaleSettings.indexOf('nodeSize'),
  62. es = ~rescaleSettings.indexOf('edgeSize');
  63. /**
  64. * First, we compute the scaling ratio, without considering the sizes
  65. * of the nodes : Each node will have its center in the canvas, but might
  66. * be partially out of it.
  67. */
  68. scale = settings('scalingMode') === 'outside' ?
  69. Math.max(
  70. w / Math.max(maxX - minX, 1),
  71. h / Math.max(maxY - minY, 1)
  72. ) :
  73. Math.min(
  74. w / Math.max(maxX - minX, 1),
  75. h / Math.max(maxY - minY, 1)
  76. );
  77. /**
  78. * Then, we correct that scaling ratio considering a margin, which is
  79. * basically the size of the biggest node.
  80. * This has to be done as a correction since to compare the size of the
  81. * biggest node to the X and Y values, we have to first get an
  82. * approximation of the scaling ratio.
  83. **/
  84. margin =
  85. (
  86. settings('rescaleIgnoreSize') ?
  87. 0 :
  88. (settings('maxNodeSize') || sizeMax) / scale
  89. ) +
  90. (settings('sideMargin') || 0);
  91. maxX += margin;
  92. minX -= margin;
  93. maxY += margin;
  94. minY -= margin;
  95. // Fix the scaling with the new extrema:
  96. scale = settings('scalingMode') === 'outside' ?
  97. Math.max(
  98. w / Math.max(maxX - minX, 1),
  99. h / Math.max(maxY - minY, 1)
  100. ) :
  101. Math.min(
  102. w / Math.max(maxX - minX, 1),
  103. h / Math.max(maxY - minY, 1)
  104. );
  105. // Size homothetic parameters:
  106. if (!settings('maxNodeSize') && !settings('minNodeSize')) {
  107. a = 1;
  108. b = 0;
  109. } else if (settings('maxNodeSize') === settings('minNodeSize')) {
  110. a = 0;
  111. b = +settings('maxNodeSize');
  112. } else {
  113. a = (settings('maxNodeSize') - settings('minNodeSize')) / sizeMax;
  114. b = +settings('minNodeSize');
  115. }
  116. if (!settings('maxEdgeSize') && !settings('minEdgeSize')) {
  117. c = 1;
  118. d = 0;
  119. } else if (settings('maxEdgeSize') === settings('minEdgeSize')) {
  120. c = 0;
  121. d = +settings('minEdgeSize');
  122. } else {
  123. c = (settings('maxEdgeSize') - settings('minEdgeSize')) / weightMax;
  124. d = +settings('minEdgeSize');
  125. }
  126. // Rescale the nodes and edges:
  127. for (i = 0, l = e.length; i < l; i++)
  128. e[i][writePrefix + 'size'] =
  129. e[i][readPrefix + 'size'] * (es ? c : 1) + (es ? d : 0);
  130. for (i = 0, l = n.length; i < l; i++) {
  131. n[i][writePrefix + 'size'] =
  132. n[i][readPrefix + 'size'] * (ns ? a : 1) + (ns ? b : 0);
  133. n[i][writePrefix + 'x'] =
  134. (n[i][readPrefix + 'x'] - (maxX + minX) / 2) * (np ? scale : 1);
  135. n[i][writePrefix + 'y'] =
  136. (n[i][readPrefix + 'y'] - (maxY + minY) / 2) * (np ? scale : 1);
  137. }
  138. };
  139. sigma.utils.getBoundaries = function(graph, prefix, doEdges) {
  140. var i,
  141. l,
  142. e = graph.edges(),
  143. n = graph.nodes(),
  144. weightMax = -Infinity,
  145. sizeMax = -Infinity,
  146. minX = Infinity,
  147. minY = Infinity,
  148. maxX = -Infinity,
  149. maxY = -Infinity;
  150. if (doEdges)
  151. for (i = 0, l = e.length; i < l; i++)
  152. weightMax = Math.max(e[i][prefix + 'size'], weightMax);
  153. for (i = 0, l = n.length; i < l; i++) {
  154. sizeMax = Math.max(n[i][prefix + 'size'], sizeMax);
  155. maxX = Math.max(n[i][prefix + 'x'], maxX);
  156. minX = Math.min(n[i][prefix + 'x'], minX);
  157. maxY = Math.max(n[i][prefix + 'y'], maxY);
  158. minY = Math.min(n[i][prefix + 'y'], minY);
  159. }
  160. weightMax = weightMax || 1;
  161. sizeMax = sizeMax || 1;
  162. return {
  163. weightMax: weightMax,
  164. sizeMax: sizeMax,
  165. minX: minX,
  166. minY: minY,
  167. maxX: maxX,
  168. maxY: maxY
  169. };
  170. };
  171. }).call(this);