| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- var vec2 = require("zrender/lib/core/vector");
- var scaleAndAdd = vec2.scaleAndAdd; // function adjacentNode(n, e) {
- // return e.n1 === n ? e.n2 : e.n1;
- // }
- function forceLayout(nodes, edges, opts) {
- var rect = opts.rect;
- var width = rect.width;
- var height = rect.height;
- var center = [rect.x + width / 2, rect.y + height / 2]; // var scale = opts.scale || 1;
- var gravity = opts.gravity == null ? 0.1 : opts.gravity; // for (var i = 0; i < edges.length; i++) {
- // var e = edges[i];
- // var n1 = e.n1;
- // var n2 = e.n2;
- // n1.edges = n1.edges || [];
- // n2.edges = n2.edges || [];
- // n1.edges.push(e);
- // n2.edges.push(e);
- // }
- // Init position
- for (var i = 0; i < nodes.length; i++) {
- var n = nodes[i];
- if (!n.p) {
- // Use the position from first adjecent node with defined position
- // Or use a random position
- // From d3
- // if (n.edges) {
- // var j = -1;
- // while (++j < n.edges.length) {
- // var e = n.edges[j];
- // var other = adjacentNode(n, e);
- // if (other.p) {
- // n.p = vec2.clone(other.p);
- // break;
- // }
- // }
- // }
- // if (!n.p) {
- n.p = vec2.create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]); // }
- }
- n.pp = vec2.clone(n.p);
- n.edges = null;
- } // Formula in 'Graph Drawing by Force-directed Placement'
- // var k = scale * Math.sqrt(width * height / nodes.length);
- // var k2 = k * k;
- var friction = 0.6;
- return {
- warmUp: function () {
- friction = 0.5;
- },
- setFixed: function (idx) {
- nodes[idx].fixed = true;
- },
- setUnfixed: function (idx) {
- nodes[idx].fixed = false;
- },
- step: function (cb) {
- var v12 = [];
- var nLen = nodes.length;
- for (var i = 0; i < edges.length; i++) {
- var e = edges[i];
- var n1 = e.n1;
- var n2 = e.n2;
- vec2.sub(v12, n2.p, n1.p);
- var d = vec2.len(v12) - e.d;
- var w = n2.w / (n1.w + n2.w);
- if (isNaN(w)) {
- w = 0;
- }
- vec2.normalize(v12, v12);
- !n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction);
- !n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction);
- } // Gravity
- for (var i = 0; i < nLen; i++) {
- var n = nodes[i];
- if (!n.fixed) {
- vec2.sub(v12, center, n.p); // var d = vec2.len(v12);
- // vec2.scale(v12, v12, 1 / d);
- // var gravityFactor = gravity;
- scaleAndAdd(n.p, n.p, v12, gravity * friction);
- }
- } // Repulsive
- // PENDING
- for (var i = 0; i < nLen; i++) {
- var n1 = nodes[i];
- for (var j = i + 1; j < nLen; j++) {
- var n2 = nodes[j];
- vec2.sub(v12, n2.p, n1.p);
- var d = vec2.len(v12);
- if (d === 0) {
- // Random repulse
- vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5);
- d = 1;
- }
- var repFact = (n1.rep + n2.rep) / d / d;
- !n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact);
- !n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact);
- }
- }
- var v = [];
- for (var i = 0; i < nLen; i++) {
- var n = nodes[i];
- if (!n.fixed) {
- vec2.sub(v, n.p, n.pp);
- scaleAndAdd(n.p, n.p, v, friction);
- vec2.copy(n.pp, n.p);
- }
- }
- friction = friction * 0.992;
- cb && cb(nodes, edges, friction < 0.01);
- }
- };
- }
- exports.forceLayout = forceLayout;
|