forceHelper.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. var vec2 = require("zrender/lib/core/vector");
  20. /*
  21. * Licensed to the Apache Software Foundation (ASF) under one
  22. * or more contributor license agreements. See the NOTICE file
  23. * distributed with this work for additional information
  24. * regarding copyright ownership. The ASF licenses this file
  25. * to you under the Apache License, Version 2.0 (the
  26. * "License"); you may not use this file except in compliance
  27. * with the License. You may obtain a copy of the License at
  28. *
  29. * http://www.apache.org/licenses/LICENSE-2.0
  30. *
  31. * Unless required by applicable law or agreed to in writing,
  32. * software distributed under the License is distributed on an
  33. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  34. * KIND, either express or implied. See the License for the
  35. * specific language governing permissions and limitations
  36. * under the License.
  37. */
  38. /*
  39. * A third-party license is embeded for some of the code in this file:
  40. * Some formulas were originally copied from "d3.js" with some
  41. * modifications made for this project.
  42. * (See more details in the comment of the method "step" below.)
  43. * The use of the source code of this file is also subject to the terms
  44. * and consitions of the license of "d3.js" (BSD-3Clause, see
  45. * </licenses/LICENSE-d3>).
  46. */
  47. var scaleAndAdd = vec2.scaleAndAdd; // function adjacentNode(n, e) {
  48. // return e.n1 === n ? e.n2 : e.n1;
  49. // }
  50. function forceLayout(nodes, edges, opts) {
  51. var rect = opts.rect;
  52. var width = rect.width;
  53. var height = rect.height;
  54. var center = [rect.x + width / 2, rect.y + height / 2]; // var scale = opts.scale || 1;
  55. var gravity = opts.gravity == null ? 0.1 : opts.gravity; // for (var i = 0; i < edges.length; i++) {
  56. // var e = edges[i];
  57. // var n1 = e.n1;
  58. // var n2 = e.n2;
  59. // n1.edges = n1.edges || [];
  60. // n2.edges = n2.edges || [];
  61. // n1.edges.push(e);
  62. // n2.edges.push(e);
  63. // }
  64. // Init position
  65. for (var i = 0; i < nodes.length; i++) {
  66. var n = nodes[i];
  67. if (!n.p) {
  68. n.p = vec2.create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]);
  69. }
  70. n.pp = vec2.clone(n.p);
  71. n.edges = null;
  72. } // Formula in 'Graph Drawing by Force-directed Placement'
  73. // var k = scale * Math.sqrt(width * height / nodes.length);
  74. // var k2 = k * k;
  75. var initialFriction = opts.friction == null ? 0.6 : opts.friction;
  76. var friction = initialFriction;
  77. return {
  78. warmUp: function () {
  79. friction = initialFriction * 0.8;
  80. },
  81. setFixed: function (idx) {
  82. nodes[idx].fixed = true;
  83. },
  84. setUnfixed: function (idx) {
  85. nodes[idx].fixed = false;
  86. },
  87. /**
  88. * Some formulas were originally copied from "d3.js"
  89. * https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/layout/force.js
  90. * with some modifications made for this project.
  91. * See the license statement at the head of this file.
  92. */
  93. step: function (cb) {
  94. var v12 = [];
  95. var nLen = nodes.length;
  96. for (var i = 0; i < edges.length; i++) {
  97. var e = edges[i];
  98. if (e.ignoreForceLayout) {
  99. continue;
  100. }
  101. var n1 = e.n1;
  102. var n2 = e.n2;
  103. vec2.sub(v12, n2.p, n1.p);
  104. var d = vec2.len(v12) - e.d;
  105. var w = n2.w / (n1.w + n2.w);
  106. if (isNaN(w)) {
  107. w = 0;
  108. }
  109. vec2.normalize(v12, v12);
  110. !n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction);
  111. !n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction);
  112. } // Gravity
  113. for (var i = 0; i < nLen; i++) {
  114. var n = nodes[i];
  115. if (!n.fixed) {
  116. vec2.sub(v12, center, n.p); // var d = vec2.len(v12);
  117. // vec2.scale(v12, v12, 1 / d);
  118. // var gravityFactor = gravity;
  119. scaleAndAdd(n.p, n.p, v12, gravity * friction);
  120. }
  121. } // Repulsive
  122. // PENDING
  123. for (var i = 0; i < nLen; i++) {
  124. var n1 = nodes[i];
  125. for (var j = i + 1; j < nLen; j++) {
  126. var n2 = nodes[j];
  127. vec2.sub(v12, n2.p, n1.p);
  128. var d = vec2.len(v12);
  129. if (d === 0) {
  130. // Random repulse
  131. vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5);
  132. d = 1;
  133. }
  134. var repFact = (n1.rep + n2.rep) / d / d;
  135. !n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact);
  136. !n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact);
  137. }
  138. }
  139. var v = [];
  140. for (var i = 0; i < nLen; i++) {
  141. var n = nodes[i];
  142. if (!n.fixed) {
  143. vec2.sub(v, n.p, n.pp);
  144. scaleAndAdd(n.p, n.p, v, friction);
  145. vec2.copy(n.pp, n.p);
  146. }
  147. }
  148. friction = friction * 0.992;
  149. cb && cb(nodes, edges, friction < 0.01);
  150. }
  151. };
  152. }
  153. exports.forceLayout = forceLayout;