Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // arbor.js - version 0.91
- // a graph vizualization toolkit
- //
- // Copyright (c) 2011 Samizdat Drafting Co.
- // Physics code derived from springy.js, copyright (c) 2010 Dennis Hotson
- //
- // Permission is hereby granted, free of charge, to any person
- // obtaining a copy of this software and associated documentation
- // files (the "Software"), to deal in the Software without
- // restriction, including without limitation the rights to use,
- // copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the
- // Software is furnished to do so, subject to the following
- // conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- // OTHER DEALINGS IN THE SOFTWARE.
- //
- (function ($) {
- /* etc.js */
- var trace = function (msg) {
- if (typeof (window) == "undefined" || !window.console) {
- return
- }
- var len = arguments.length;
- var args = [];
- for (var i = 0; i < len; i++) {
- args.push("arguments[" + i + "]")
- }
- eval("console.log(" + args.join(",") + ")")
- };
- var dirname = function (a) {
- var b = a.replace(/^\/?(.*?)\/?$/, "$1").split("/");
- b.pop();
- return "/" + b.join("/")
- };
- var basename = function (b) {
- var c = b.replace(/^\/?(.*?)\/?$/, "$1").split("/");
- var a = c.pop();
- if (a == "") {
- return null
- } else {
- return a
- }
- };
- var _ordinalize_re = /(\d)(?=(\d\d\d)+(?!\d))/g;
- var ordinalize = function (a) {
- var b = "" + a;
- if (a < 11000) {
- b = ("" + a).replace(_ordinalize_re, "$1,")
- } else {
- if (a < 1000000) {
- b = Math.floor(a / 1000) + "k"
- } else {
- if (a < 1000000000) {
- b = ("" + Math.floor(a / 1000)).replace(_ordinalize_re, "$1,") + "m"
- }
- }
- }
- return b
- };
- var nano = function (a, b) {
- return a.replace(/\{([\w\-\.]*)}/g, function (f, c) {
- var d = c.split("."),
- e = b[d.shift()];
- $.each(d, function () {
- if (e.hasOwnProperty(this)) {
- e = e[this]
- } else {
- e = f
- }
- });
- return e
- })
- };
- var objcopy = function (a) {
- if (a === undefined) {
- return undefined
- }
- if (a === null) {
- return null
- }
- if (a.parentNode) {
- return a
- }
- switch (typeof a) {
- case "string":
- return a.substring(0);
- break;
- case "number":
- return a + 0;
- break;
- case "boolean":
- return a === true;
- break
- }
- var b = ($.isArray(a)) ? [] : {};
- $.each(a, function (d, c) {
- b[d] = objcopy(c)
- });
- return b
- };
- var objmerge = function (d, b) {
- d = d || {};
- b = b || {};
- var c = objcopy(d);
- for (var a in b) {
- c[a] = b[a]
- }
- return c
- };
- var objcmp = function (e, c, d) {
- if (!e || !c) {
- return e === c
- }
- if (typeof e != typeof c) {
- return false
- }
- if (typeof e != "object") {
- return e === c
- } else {
- if ($.isArray(e)) {
- if (!($.isArray(c))) {
- return false
- }
- if (e.length != c.length) {
- return false
- }
- } else {
- var h = [];
- for (var f in e) {
- if (e.hasOwnProperty(f)) {
- h.push(f)
- }
- }
- var g = [];
- for (var f in c) {
- if (c.hasOwnProperty(f)) {
- g.push(f)
- }
- }
- if (!d) {
- h.sort();
- g.sort()
- }
- if (h.join(",") !== g.join(",")) {
- return false
- }
- }
- var i = true;
- $.each(e, function (a) {
- var b = objcmp(e[a], c[a]);
- i = i && b;
- if (!i) {
- return false
- }
- });
- return i
- }
- };
- var objkeys = function (b) {
- var a = [];
- $.each(b, function (d, c) {
- if (b.hasOwnProperty(d)) {
- a.push(d)
- }
- });
- return a
- };
- var objcontains = function (c) {
- if (!c || typeof c != "object") {
- return false
- }
- for (var b = 1, a = arguments.length; b < a; b++) {
- if (c.hasOwnProperty(arguments[b])) {
- return true
- }
- }
- return false
- };
- var uniq = function (b) {
- var a = b.length;
- var d = {};
- for (var c = 0; c < a; c++) {
- d[b[c]] = true
- }
- return objkeys(d)
- };
- var arbor_path = function () {
- var a = $("script").map(function (b) {
- var c = $(this).attr("src");
- if (!c) {
- return
- }
- if (c.match(/arbor[^\/\.]*.js|dev.js/)) {
- return c.match(/.*\//) || "/"
- }
- });
- if (a.length > 0) {
- return a[0]
- } else {
- return null
- }
- }; /* kernel.js */
- var Kernel = function (b) {
- var a = (window.Worker !== undefined);
- var i = null;
- var c = null;
- var f = [];
- f.last = new Date();
- var k = null;
- var d = null;
- var e = null;
- var h = null;
- var g = false;
- var j = {
- system: b,
- tween: null,
- nodes: {},
- init: function () {
- if (typeof (Tween) != "undefined") {
- c = Tween()
- } else {
- if (typeof (arbor.Tween) != "undefined") {
- c = arbor.Tween()
- } else {
- c = {
- busy: function () {
- return false
- },
- tick: function () {
- return true
- },
- to: function () {
- trace("Please include arbor-tween.js to enable tweens");
- c.to = function () {};
- return
- }
- }
- }
- }
- j.tween = c;
- var l = b.parameters();
- if (a) {
- trace("using web workers");
- k = setInterval(j.screenUpdate, l.timeout);
- i = new Worker("js/arbor.js");
- //i = new Worker(arbor_path() + "arbor.js");
- i.onmessage = j.workerMsg;
- i.onerror = function (m) {
- trace("physics:", m)
- };
- i.postMessage({
- type: "physics",
- physics: objmerge(l, {
- timeout: Math.ceil(l.timeout)
- })
- })
- } else {
- trace("couldn't use web workers, be careful...");
- i = Physics(l.dt, l.stiffness, l.repulsion, l.friction, j.system._updateGeometry);
- j.start()
- }
- return j
- },
- graphChanged: function (l) {
- if (a) {
- i.postMessage({
- type: "changes",
- changes: l
- })
- } else {
- i._update(l)
- }
- j.start()
- },
- particleModified: function (m, l) {
- if (a) {
- i.postMessage({
- type: "modify",
- id: m,
- mods: l
- })
- } else {
- i.modifyNode(m, l)
- }
- j.start()
- },
- physicsModified: function (l) {
- if (!isNaN(l.timeout)) {
- if (a) {
- clearInterval(k);
- k = setInterval(j.screenUpdate, l.timeout)
- } else {
- clearInterval(e);
- e = null
- }
- }
- if (a) {
- i.postMessage({
- type: "sys",
- param: l
- })
- } else {
- i.modifyPhysics(l)
- }
- j.start()
- },
- workerMsg: function (m) {
- var l = m.data.type;
- if (l == "geometry") {
- j.workerUpdate(m.data)
- } else {
- trace("physics:", m.data)
- }
- },
- _lastPositions: null,
- workerUpdate: function (l) {
- j._lastPositions = l;
- j._lastBounds = l.bounds
- },
- _lastFrametime: new Date().valueOf(),
- _lastBounds: null,
- _currentRenderer: null,
- screenUpdate: function () {
- var m = new Date().valueOf();
- var l = false;
- if (j._lastPositions !== null) {
- j.system._updateGeometry(j._lastPositions);
- j._lastPositions = null;
- l = true
- }
- if (c && c.busy()) {
- l = true
- }
- if (j.system._updateBounds(j._lastBounds)) {
- l = true
- }
- if (l) {
- var n = j.system.renderer;
- if (n !== undefined) {
- if (n !== d) {
- n.init(j.system);
- d = n
- }
- if (c) {
- c.tick()
- }
- n.redraw();
- var o = f.last;
- f.last = new Date();
- f.push(f.last - o);
- if (f.length > 50) {
- f.shift()
- }
- }
- }
- },
- physicsUpdate: function () {
- if (c) {
- c.tick()
- }
- i.tick();
- var m = j.system._updateBounds();
- if (c && c.busy()) {
- m = true
- }
- var n = j.system.renderer;
- var l = new Date();
- var n = j.system.renderer;
- if (n !== undefined) {
- if (n !== d) {
- n.init(j.system);
- d = n
- }
- n.redraw({
- timestamp: l
- })
- }
- var p = f.last;
- f.last = l;
- f.push(f.last - p);
- if (f.length > 50) {
- f.shift()
- }
- var o = i.systemEnergy();
- if ((o.mean + o.max) / 2 < 0.05) {
- if (h === null) {
- h = new Date().valueOf()
- }
- if (new Date().valueOf() - h > 1000) {
- clearInterval(e);
- e = null
- } else {}
- } else {
- h = null
- }
- },
- fps: function (m) {
- if (m !== undefined) {
- var p = 1000 / Math.max(1, targetFps);
- j.physicsModified({
- timeout: p
- })
- }
- var q = 0;
- for (var o = 0, n = f.length; o < n; o++) {
- q += f[o]
- }
- var l = q / Math.max(1, f.length);
- if (!isNaN(l)) {
- return Math.round(1000 / l)
- } else {
- return 0
- }
- },
- start: function (l) {
- if (e !== null) {
- return
- }
- if (g && !l) {
- return
- }
- g = false;
- if (a) {
- i.postMessage({
- type: "start"
- })
- } else {
- h = null;
- e = setInterval(j.physicsUpdate, j.system.parameters().timeout)
- }
- },
- stop: function () {
- g = true;
- if (a) {
- i.postMessage({
- type: "stop"
- })
- } else {
- if (e !== null) {
- clearInterval(e);
- e = null
- }
- }
- }
- };
- return j.init()
- }; /* atoms.js */
- var Node = function (a) {
- this._id = _nextNodeId++;
- this.data = a || {};
- this._mass = (a.mass !== undefined) ? a.mass : 1;
- this._fixed = (a.fixed === true) ? true : false;
- this._p = new Point((typeof (a.x) == "number") ? a.x : null, (typeof (a.y) == "number") ? a.y : null);
- delete this.data.x;
- delete this.data.y;
- delete this.data.mass;
- delete this.data.fixed
- };
- var _nextNodeId = 1;
- var Edge = function (b, c, a) {
- this._id = _nextEdgeId--;
- this.source = b;
- this.target = c;
- this.length = (a.length !== undefined) ? a.length : 1;
- this.data = (a !== undefined) ? a : {};
- delete this.data.length
- };
- var _nextEdgeId = -1;
- var Particle = function (a, b) {
- this.p = a;
- this.m = b;
- this.v = new Point(0, 0);
- this.f = new Point(0, 0)
- };
- Particle.prototype.applyForce = function (a) {
- this.f = this.f.add(a.divide(this.m))
- };
- var Spring = function (c, b, d, a) {
- this.point1 = c;
- this.point2 = b;
- this.length = d;
- this.k = a
- };
- Spring.prototype.distanceToParticle = function (a) {
- var c = that.point2.p.subtract(that.point1.p).normalize().normal();
- var b = a.p.subtract(that.point1.p);
- return Math.abs(b.x * c.x + b.y * c.y)
- };
- var Point = function (a, b) {
- if (a && a.hasOwnProperty("y")) {
- b = a.y;
- a = a.x
- }
- this.x = a;
- this.y = b
- };
- Point.random = function (a) {
- a = (a !== undefined) ? a : 5;
- return new Point(2 * a * (Math.random() - 0.5), 2 * a * (Math.random() - 0.5))
- };
- Point.prototype = {
- exploded: function () {
- return (isNaN(this.x) || isNaN(this.y))
- },
- add: function (a) {
- return new Point(this.x + a.x, this.y + a.y)
- },
- subtract: function (a) {
- return new Point(this.x - a.x, this.y - a.y)
- },
- multiply: function (a) {
- return new Point(this.x * a, this.y * a)
- },
- divide: function (a) {
- return new Point(this.x / a, this.y / a)
- },
- magnitude: function () {
- return Math.sqrt(this.x * this.x + this.y * this.y)
- },
- normal: function () {
- return new Point(-this.y, this.x)
- },
- normalize: function () {
- return this.divide(this.magnitude())
- }
- }; /* system.js */
- var ParticleSystem = function (d, p, e, f, t, l, q) {
- var j = [];
- var h = null;
- var k = 0;
- var u = null;
- var m = 0.04;
- var i = [20, 20, 20, 20];
- var n = null;
- var o = null;
- if (typeof p == "object") {
- var s = p;
- e = s.friction;
- d = s.repulsion;
- t = s.fps;
- l = s.dt;
- p = s.stiffness;
- f = s.gravity;
- q = s.precision
- }
- e = isNaN(e) ? 0.5 : e;
- d = isNaN(d) ? 1000 : d;
- t = isNaN(t) ? 55 : t;
- p = isNaN(p) ? 600 : p;
- l = isNaN(l) ? 0.02 : l;
- q = isNaN(q) ? 0.6 : q;
- f = (f === true);
- var r = (t !== undefined) ? 1000 / t : 1000 / 50;
- var b = {
- repulsion: d,
- stiffness: p,
- friction: e,
- dt: l,
- gravity: f,
- precision: q,
- timeout: r
- };
- var a;
- var c = {
- renderer: null,
- tween: null,
- nodes: {},
- edges: {},
- adjacency: {},
- names: {},
- kernel: null
- };
- var g = {
- parameters: function (v) {
- if (v !== undefined) {
- if (!isNaN(v.precision)) {
- v.precision = Math.max(0, Math.min(1, v.precision))
- }
- $.each(b, function (x, w) {
- if (v[x] !== undefined) {
- b[x] = v[x]
- }
- });
- c.kernel.physicsModified(v)
- }
- return b
- },
- fps: function (v) {
- if (v === undefined) {
- return c.kernel.fps()
- } else {
- g.parameters({
- timeout: 1000 / (v || 50)
- })
- }
- },
- start: function () {
- c.kernel.start()
- },
- stop: function () {
- c.kernel.stop()
- },
- addNode: function (v, x) {
- x = x || {};
- var y = c.names[v];
- if (y) {
- y.data = x;
- return y
- } else {
- if (v != undefined) {
- var w = new Node(x);
- w.name = v;
- c.names[v] = w;
- c.nodes[w._id] = w;
- j.push({
- t: "addNode",
- id: w._id,
- m: w.mass
- });
- g._notify();
- return w
- }
- }
- },
- pruneNode: function (w) {
- var v = g.getNode(w);
- if (typeof (c.nodes[v._id]) !== "undefined") {
- delete c.nodes[v._id];
- delete c.names[v.name]
- }
- $.each(c.edges, function (y, x) {
- if (x.source._id === v._id || x.target._id === v._id) {
- g.pruneEdge(x)
- }
- });
- j.push({
- t: "dropNode",
- id: v._id
- });
- g._notify()
- },
- getNode: function (v) {
- if (v._id !== undefined) {
- return v
- } else {
- if (typeof v == "string" || typeof v == "number") {
- return c.names[v]
- }
- }
- },
- eachNode: function (v) {
- $.each(c.nodes, function (y, x) {
- if (x._p.x == null || x._p.y == null) {
- return
- }
- var w = (u !== null) ? g.toScreen(x._p) : x._p;
- v.call(g, x, w)
- })
- },
- addEdge: function (z, A, y) {
- z = g.getNode(z) || g.addNode(z);
- A = g.getNode(A) || g.addNode(A);
- y = y || {};
- var x = new Edge(z, A, y);
- var B = z._id;
- var C = A._id;
- c.adjacency[B] = c.adjacency[B] || {};
- c.adjacency[B][C] = c.adjacency[B][C] || [];
- var w = (c.adjacency[B][C].length > 0);
- if (w) {
- $.extend(c.adjacency[B][C].data, x.data);
- return
- } else {
- c.edges[x._id] = x;
- c.adjacency[B][C].push(x);
- var v = (x.length !== undefined) ? x.length : 1;
- j.push({
- t: "addSpring",
- id: x._id,
- fm: B,
- to: C,
- l: v
- });
- g._notify()
- }
- return x
- },
- pruneEdge: function (A) {
- j.push({
- t: "dropSpring",
- id: A._id
- });
- delete c.edges[A._id];
- for (var v in c.adjacency) {
- for (var B in c.adjacency[v]) {
- var w = c.adjacency[v][B];
- for (var z = w.length - 1; z >= 0; z--) {
- if (c.adjacency[v][B][z]._id === A._id) {
- c.adjacency[v][B].splice(z, 1)
- }
- }
- }
- }
- g._notify()
- },
- getEdges: function (w, v) {
- w = g.getNode(w);
- v = g.getNode(v);
- if (!w || !v) {
- return []
- }
- if (typeof (c.adjacency[w._id]) !== "undefined" && typeof (c.adjacency[w._id][v._id]) !== "undefined") {
- return c.adjacency[w._id][v._id]
- }
- return []
- },
- getEdgesFrom: function (v) {
- v = g.getNode(v);
- if (!v) {
- return []
- }
- if (typeof (c.adjacency[v._id]) !== "undefined") {
- var w = [];
- $.each(c.adjacency[v._id], function (y, x) {
- w = w.concat(x)
- });
- return w
- }
- return []
- },
- getEdgesTo: function (v) {
- v = g.getNode(v);
- if (!v) {
- return []
- }
- var w = [];
- $.each(c.edges, function (y, x) {
- if (x.target == v) {
- w.push(x)
- }
- });
- return w
- },
- eachEdge: function (v) {
- $.each(c.edges, function (z, x) {
- var y = c.nodes[x.source._id]._p;
- var w = c.nodes[x.target._id]._p;
- if (y.x == null || w.x == null) {
- return
- }
- y = (u !== null) ? g.toScreen(y) : y;
- w = (u !== null) ? g.toScreen(w) : w;
- if (y && w) {
- v.call(g, x, y, w)
- }
- })
- },
- prune: function (w) {
- var v = {
- dropped: {
- nodes: [],
- edges: []
- }
- };
- if (w === undefined) {
- $.each(c.nodes, function (y, x) {
- v.dropped.nodes.push(x);
- g.pruneNode(x)
- })
- } else {
- g.eachNode(function (y) {
- var x = w.call(g, y, {
- from: g.getEdgesFrom(y),
- to: g.getEdgesTo(y)
- });
- if (x) {
- v.dropped.nodes.push(y);
- g.pruneNode(y)
- }
- })
- }
- return v
- },
- graft: function (w) {
- var v = {
- added: {
- nodes: [],
- edges: []
- }
- };
- if (w.nodes) {
- $.each(w.nodes, function (y, x) {
- var z = g.getNode(y);
- if (z) {
- z.data = x
- } else {
- v.added.nodes.push(g.addNode(y, x))
- }
- c.kernel.start()
- })
- }
- if (w.edges) {
- $.each(w.edges, function (z, x) {
- var y = g.getNode(z);
- if (!y) {
- v.added.nodes.push(g.addNode(z, {}))
- }
- $.each(x, function (D, A) {
- var C = g.getNode(D);
- if (!C) {
- v.added.nodes.push(g.addNode(D, {}))
- }
- var B = g.getEdges(z, D);
- if (B.length > 0) {
- B[0].data = A
- } else {
- v.added.edges.push(g.addEdge(z, D, A))
- }
- })
- })
- }
- return v
- },
- merge: function (w) {
- var v = {
- added: {
- nodes: [],
- edges: []
- },
- dropped: {
- nodes: [],
- edges: []
- }
- };
- $.each(c.edges, function (A, z) {
- if ((w.edges[z.source.name] === undefined || w.edges[z.source.name][z.target.name] === undefined)) {
- g.pruneEdge(z);
- v.dropped.edges.push(z)
- }
- });
- var y = g.prune(function (A, z) {
- if (w.nodes[A.name] === undefined) {
- v.dropped.nodes.push(A);
- return true
- }
- });
- var x = g.graft(w);
- v.added.nodes = v.added.nodes.concat(x.added.nodes);
- v.added.edges = v.added.edges.concat(x.added.edges);
- v.dropped.nodes = v.dropped.nodes.concat(y.dropped.nodes);
- v.dropped.edges = v.dropped.edges.concat(y.dropped.edges);
- return v
- },
- tweenNode: function (y, v, x) {
- var w = g.getNode(y);
- if (w) {
- c.tween.to(w, v, x)
- }
- },
- tweenEdge: function (w, v, z, y) {
- if (y === undefined) {
- g._tweenEdge(w, v, z)
- } else {
- var x = g.getEdges(w, v);
- $.each(x, function (A, B) {
- g._tweenEdge(B, z, y)
- })
- }
- },
- _tweenEdge: function (w, v, x) {
- if (w && w._id !== undefined) {
- c.tween.to(w, v, x)
- }
- },
- _updateGeometry: function (y) {
- if (y != undefined) {
- var v = (y.epoch < k);
- a = y.energy;
- var z = y.geometry;
- if (z !== undefined) {
- for (var x = 0, w = z.length / 3; x < w; x++) {
- var A = z[3 * x];
- if (v && c.nodes[A] == undefined) {
- continue
- }
- c.nodes[A]._p.x = z[3 * x + 1];
- c.nodes[A]._p.y = z[3 * x + 2]
- }
- }
- }
- },
- screen: function (v) {
- if (v.size !== undefined) {
- g.screenSize(v.size.width, v.size.height)
- }
- if (!isNaN(v.step)) {
- g.screenStep(v.step)
- }
- if (v.padding !== undefined) {
- g.screenPadding(v.padding)
- }
- },
- screenSize: function (v, w) {
- u = {
- width: v,
- height: w
- };
- g._updateBounds()
- },
- screenPadding: function (y, z, v, w) {
- if ($.isArray(y)) {
- trbl = y
- } else {
- trbl = [y, z, v, w]
- }
- var A = trbl[0];
- var x = trbl[1];
- var B = trbl[2];
- if (x === undefined) {
- trbl = [A, A, A, A]
- } else {
- if (B == undefined) {
- trbl = [A, x, A, x]
- }
- }
- i = trbl
- },
- screenStep: function (v) {
- m = v
- },
- toScreen: function (x) {
- if (!n || !u) {
- return
- }
- var w = i || [0, 0, 0, 0];
- var v = n.bottomright.subtract(n.topleft);
- var z = w[3] + x.subtract(n.topleft).divide(v.x).x * (u.width - (w[1] + w[3]));
- var y = w[0] + x.subtract(n.topleft).divide(v.y).y * (u.height - (w[0] + w[2]));
- return arbor.Point(z, y)
- },
- fromScreen: function (z) {
- if (!n || !u) {
- return
- }
- var y = i || [0, 0, 0, 0];
- var x = n.bottomright.subtract(n.topleft);
- var w = (z.x - y[3]) / (u.width - (y[1] + y[3])) * x.x + n.topleft.x;
- var v = (z.y - y[0]) / (u.height - (y[0] + y[2])) * x.y + n.topleft.y;
- return arbor.Point(w, v)
- },
- _updateBounds: function (w) {
- if (u === null) {
- return
- }
- if (w) {
- o = w
- } else {
- o = g.bounds()
- }
- var z = new Point(o.bottomright.x, o.bottomright.y);
- var y = new Point(o.topleft.x, o.topleft.y);
- var B = z.subtract(y);
- var v = y.add(B.divide(2));
- var x = 4;
- var D = new Point(Math.max(B.x, x), Math.max(B.y, x));
- o.topleft = v.subtract(D.divide(2));
- o.bottomright = v.add(D.divide(2));
- if (!n) {
- if ($.isEmptyObject(c.nodes)) {
- return false
- }
- n = o;
- return true
- }
- var C = m;
- _newBounds = {
- bottomright: n.bottomright.add(o.bottomright.subtract(n.bottomright).multiply(C)),
- topleft: n.topleft.add(o.topleft.subtract(n.topleft).multiply(C))
- };
- var A = new Point(n.topleft.subtract(_newBounds.topleft).magnitude(), n.bottomright.subtract(_newBounds.bottomright).magnitude());
- if (A.x * u.width > 1 || A.y * u.height > 1) {
- n = _newBounds;
- return true
- } else {
- return false
- }
- },
- energy: function () {
- return a
- },
- bounds: function () {
- var w = null;
- var v = null;
- $.each(c.nodes, function (z, y) {
- if (!w) {
- w = new Point(y._p);
- v = new Point(y._p);
- return
- }
- var x = y._p;
- if (x.x === null || x.y === null) {
- return
- }
- if (x.x > w.x) {
- w.x = x.x
- }
- if (x.y > w.y) {
- w.y = x.y
- }
- if (x.x < v.x) {
- v.x = x.x
- }
- if (x.y < v.y) {
- v.y = x.y
- }
- });
- if (w && v) {
- return {
- bottomright: w,
- topleft: v
- }
- } else {
- return {
- topleft: new Point(-1, -1),
- bottomright: new Point(1, 1)
- }
- }
- },
- nearest: function (x) {
- if (u !== null) {
- x = g.fromScreen(x)
- }
- var w = {
- node: null,
- point: null,
- distance: null
- };
- var v = g;
- $.each(c.nodes, function (B, y) {
- var z = y._p;
- if (z.x === null || z.y === null) {
- return
- }
- var A = z.subtract(x).magnitude();
- if (w.distance === null || A < w.distance) {
- w = {
- node: y,
- point: z,
- distance: A
- };
- if (u !== null) {
- w.screenPoint = g.toScreen(z)
- }
- }
- });
- if (w.node) {
- if (u !== null) {
- w.distance = g.toScreen(w.node.p).subtract(g.toScreen(x)).magnitude()
- }
- return w
- } else {
- return null
- }
- },
- _notify: function () {
- if (h === null) {
- k++
- } else {
- clearTimeout(h)
- }
- h = setTimeout(g._synchronize, 20)
- },
- _synchronize: function () {
- if (j.length > 0) {
- c.kernel.graphChanged(j);
- j = [];
- h = null
- }
- },
- };
- c.kernel = Kernel(g);
- c.tween = c.kernel.tween || null;
- Node.prototype.__defineGetter__("p", function () {
- var w = this;
- var v = {};
- v.__defineGetter__("x", function () {
- return w._p.x
- });
- v.__defineSetter__("x", function (x) {
- c.kernel.particleModified(w._id, {
- x: x
- })
- });
- v.__defineGetter__("y", function () {
- return w._p.y
- });
- v.__defineSetter__("y", function (x) {
- c.kernel.particleModified(w._id, {
- y: x
- })
- });
- v.__proto__ = Point.prototype;
- return v
- });
- Node.prototype.__defineSetter__("p", function (v) {
- this._p.x = v.x;
- this._p.y = v.y;
- c.kernel.particleModified(this._id, {
- x: v.x,
- y: v.y
- })
- });
- Node.prototype.__defineGetter__("mass", function () {
- return this._mass
- });
- Node.prototype.__defineSetter__("mass", function (v) {
- this._mass = v;
- c.kernel.particleModified(this._id, {
- m: v
- })
- });
- Node.prototype.__defineSetter__("tempMass", function (v) {
- c.kernel.particleModified(this._id, {
- _m: v
- })
- });
- Node.prototype.__defineGetter__("fixed", function () {
- return this._fixed
- });
- Node.prototype.__defineSetter__("fixed", function (v) {
- this._fixed = v;
- c.kernel.particleModified(this._id, {
- f: v ? 1 : 0
- })
- });
- return g
- }; /* barnes-hut.js */
- var BarnesHutTree = function () {
- var b = [];
- var a = 0;
- var e = null;
- var d = 0.5;
- var c = {
- init: function (g, h, f) {
- d = f;
- a = 0;
- e = c._newBranch();
- e.origin = g;
- e.size = h.subtract(g)
- },
- insert: function (j) {
- var f = e;
- var g = [j];
- while (g.length) {
- var h = g.shift();
- var m = h._m || h.m;
- var p = c._whichQuad(h, f);
- if (f[p] === undefined) {
- f[p] = h;
- f.mass += m;
- if (f.p) {
- f.p = f.p.add(h.p.multiply(m))
- } else {
- f.p = h.p.multiply(m)
- }
- } else {
- if ("origin" in f[p]) {
- f.mass += (m);
- if (f.p) {
- f.p = f.p.add(h.p.multiply(m))
- } else {
- f.p = h.p.multiply(m)
- }
- f = f[p];
- g.unshift(h)
- } else {
- var l = f.size.divide(2);
- var n = new Point(f.origin);
- if (p[0] == "s") {
- n.y += l.y
- }
- if (p[1] == "e") {
- n.x += l.x
- }
- var o = f[p];
- f[p] = c._newBranch();
- f[p].origin = n;
- f[p].size = l;
- f.mass = m;
- f.p = h.p.multiply(m);
- f = f[p];
- if (o.p.x === h.p.x && o.p.y === h.p.y) {
- var k = l.x * 0.08;
- var i = l.y * 0.08;
- o.p.x = Math.min(n.x + l.x, Math.max(n.x, o.p.x - k / 2 + Math.random() * k));
- o.p.y = Math.min(n.y + l.y, Math.max(n.y, o.p.y - i / 2 + Math.random() * i))
- }
- g.push(o);
- g.unshift(h)
- }
- }
- }
- },
- applyForces: function (m, g) {
- var f = [e];
- while (f.length) {
- node = f.shift();
- if (node === undefined) {
- continue
- }
- if (m === node) {
- continue
- }
- if ("f" in node) {
- var k = m.p.subtract(node.p);
- var l = Math.max(1, k.magnitude());
- var i = ((k.magnitude() > 0) ? k : Point.random(1)).normalize();
- m.applyForce(i.multiply(g * (node._m || node.m)).divide(l * l))
- } else {
- var j = m.p.subtract(node.p.divide(node.mass)).magnitude();
- var h = Math.sqrt(node.size.x * node.size.y);
- if (h / j > d) {
- f.push(node.ne);
- f.push(node.nw);
- f.push(node.se);
- f.push(node.sw)
- } else {
- var k = m.p.subtract(node.p.divide(node.mass));
- var l = Math.max(1, k.magnitude());
- var i = ((k.magnitude() > 0) ? k : Point.random(1)).normalize();
- m.applyForce(i.multiply(g * (node.mass)).divide(l * l))
- }
- }
- }
- },
- _whichQuad: function (i, f) {
- if (i.p.exploded()) {
- return null
- }
- var h = i.p.subtract(f.origin);
- var g = f.size.divide(2);
- if (h.y < g.y) {
- if (h.x < g.x) {
- return "nw"
- } else {
- return "ne"
- }
- } else {
- if (h.x < g.x) {
- return "sw"
- } else {
- return "se"
- }
- }
- },
- _newBranch: function () {
- if (b[a]) {
- var f = b[a];
- f.ne = f.nw = f.se = f.sw = undefined;
- f.mass = 0;
- delete f.p
- } else {
- f = {
- origin: null,
- size: null,
- nw: undefined,
- ne: undefined,
- sw: undefined,
- se: undefined,
- mass: 0
- };
- b[a] = f
- }
- a++;
- return f
- }
- };
- return c
- }; /* physics.js */
- var Physics = function (a, m, n, e, h) {
- var f = BarnesHutTree();
- var c = {
- particles: {},
- springs: {}
- };
- var l = {
- particles: {}
- };
- var o = [];
- var k = [];
- var d = 0;
- var b = {
- sum: 0,
- max: 0,
- mean: 0
- };
- var g = {
- topleft: new Point(-1, -1),
- bottomright: new Point(1, 1)
- };
- var j = 1000;
- var i = {
- stiffness: (m !== undefined) ? m : 1000,
- repulsion: (n !== undefined) ? n : 600,
- friction: (e !== undefined) ? e : 0.3,
- gravity: false,
- dt: (a !== undefined) ? a : 0.02,
- theta: 0.4,
- init: function () {
- return i
- },
- modifyPhysics: function (p) {
- $.each(["stiffness", "repulsion", "friction", "gravity", "dt", "precision"], function (r, s) {
- if (p[s] !== undefined) {
- if (s == "precision") {
- i.theta = 1 - p[s];
- return
- }
- i[s] = p[s];
- if (s == "stiffness") {
- var q = p[s];
- $.each(c.springs, function (u, t) {
- t.k = q
- })
- }
- }
- })
- },
- addNode: function (u) {
- var t = u.id;
- var q = u.m;
- var p = g.bottomright.x - g.topleft.x;
- var s = g.bottomright.y - g.topleft.y;
- var r = new Point(g.topleft.x + p * Math.random(), g.topleft.y + s * Math.random());
- c.particles[t] = new Particle(r, q);
- c.particles[t].connections = 0;
- l.particles[t] = c.particles[t];
- o.push(c.particles[t])
- },
- dropNode: function (s) {
- var r = s.id;
- var q = c.particles[r];
- var p = $.inArray(q, o);
- if (p > -1) {
- o.splice(p, 1)
- }
- delete c.particles[r];
- delete l.particles[r]
- },
- modifyNode: function (r, p) {
- if (r in c.particles) {
- var q = c.particles[r];
- if ("x" in p) {
- q.p.x = p.x
- }
- if ("y" in p) {
- q.p.y = p.y
- }
- if ("m" in p) {
- q.m = p.m
- }
- if ("f" in p) {
- q.fixed = (p.f === 1)
- }
- if ("_m" in p) {
- if (q._m === undefined) {
- q._m = q.m
- }
- q.m = p._m
- }
- }
- },
- addSpring: function (t) {
- var s = t.id;
- var p = t.l;
- var r = c.particles[t.fm];
- var q = c.particles[t.to];
- if (r !== undefined && q !== undefined) {
- c.springs[s] = new Spring(r, q, p, i.stiffness);
- k.push(c.springs[s]);
- r.connections++;
- q.connections++;
- delete l.particles[t.fm];
- delete l.particles[t.to]
- }
- },
- dropSpring: function (s) {
- var r = s.id;
- var q = c.springs[r];
- q.point1.connections--;
- q.point2.connections--;
- var p = $.inArray(q, k);
- if (p > -1) {
- k.splice(p, 1)
- }
- delete c.springs[r]
- },
- _update: function (p) {
- d++;
- $.each(p, function (q, r) {
- if (r.t in i) {
- i[r.t](r)
- }
- });
- return d
- },
- tick: function () {
- i.tendParticles();
- i.eulerIntegrator(i.dt);
- i.tock()
- },
- tock: function () {
- var p = [];
- $.each(c.particles, function (r, q) {
- p.push(r);
- p.push(q.p.x);
- p.push(q.p.y)
- });
- if (h) {
- h({
- geometry: p,
- epoch: d,
- energy: b,
- bounds: g
- })
- }
- },
- tendParticles: function () {
- $.each(c.particles, function (q, p) {
- if (p._m !== undefined) {
- if (Math.abs(p.m - p._m) < 1) {
- p.m = p._m;
- delete p._m
- } else {
- p.m *= 0.98
- }
- }
- p.v.x = p.v.y = 0
- })
- },
- eulerIntegrator: function (p) {
- if (i.repulsion > 0) {
- if (i.theta > 0) {
- i.applyBarnesHutRepulsion()
- } else {
- i.applyBruteForceRepulsion()
- }
- }
- if (i.stiffness > 0) {
- i.applySprings()
- }
- i.applyCenterDrift();
- if (i.gravity) {
- i.applyCenterGravity()
- }
- i.updateVelocity(p);
- i.updatePosition(p)
- },
- applyBruteForceRepulsion: function () {
- $.each(c.particles, function (q, p) {
- $.each(c.particles, function (s, r) {
- if (p !== r) {
- var u = p.p.subtract(r.p);
- var v = Math.max(1, u.magnitude());
- var t = ((u.magnitude() > 0) ? u : Point.random(1)).normalize();
- p.applyForce(t.multiply(i.repulsion * (r._m || r.m) * 0.5).divide(v * v * 0.5));
- r.applyForce(t.multiply(i.repulsion * (p._m || p.m) * 0.5).divide(v * v * -0.5))
- }
- })
- })
- },
- applyBarnesHutRepulsion: function () {
- if (!g.topleft || !g.bottomright) {
- return
- }
- var q = new Point(g.bottomright);
- var p = new Point(g.topleft);
- f.init(p, q, i.theta);
- $.each(c.particles, function (s, r) {
- f.insert(r)
- });
- $.each(c.particles, function (s, r) {
- f.applyForces(r, i.repulsion)
- })
- },
- applySprings: function () {
- $.each(c.springs, function (t, p) {
- var s = p.point2.p.subtract(p.point1.p);
- var q = p.length - s.magnitude();
- var r = ((s.magnitude() > 0) ? s : Point.random(1)).normalize();
- p.point1.applyForce(r.multiply(p.k * q * -0.5));
- p.point2.applyForce(r.multiply(p.k * q * 0.5))
- })
- },
- applyCenterDrift: function () {
- var q = 0;
- var r = new Point(0, 0);
- $.each(c.particles, function (t, s) {
- r.add(s.p);
- q++
- });
- if (q == 0) {
- return
- }
- var p = r.divide(-q);
- $.each(c.particles, function (t, s) {
- s.applyForce(p)
- })
- },
- applyCenterGravity: function () {
- $.each(c.particles, function (r, p) {
- var q = p.p.multiply(-1);
- p.applyForce(q.multiply(i.repulsion / 100))
- })
- },
- updateVelocity: function (p) {
- $.each(c.particles, function (t, q) {
- if (q.fixed) {
- q.v = new Point(0, 0);
- q.f = new Point(0, 0);
- return
- }
- var s = q.v.magnitude();
- q.v = q.v.add(q.f.multiply(p)).multiply(1 - i.friction);
- q.f.x = q.f.y = 0;
- var r = q.v.magnitude();
- if (r > j) {
- q.v = q.v.divide(r * r)
- }
- })
- },
- updatePosition: function (q) {
- var r = 0,
- p = 0,
- u = 0;
- var t = null;
- var s = null;
- $.each(c.particles, function (w, v) {
- v.p = v.p.add(v.v.multiply(q));
- var x = v.v.magnitude();
- var z = x * x;
- r += z;
- p = Math.max(z, p);
- u++;
- if (!t) {
- t = new Point(v.p.x, v.p.y);
- s = new Point(v.p.x, v.p.y);
- return
- }
- var y = v.p;
- if (y.x === null || y.y === null) {
- return
- }
- if (y.x > t.x) {
- t.x = y.x
- }
- if (y.y > t.y) {
- t.y = y.y
- }
- if (y.x < s.x) {
- s.x = y.x
- }
- if (y.y < s.y) {
- s.y = y.y
- }
- });
- b = {
- sum: r,
- max: p,
- mean: r / u,
- n: u
- };
- g = {
- topleft: s || new Point(-1, -1),
- bottomright: t || new Point(1, 1)
- }
- },
- systemEnergy: function (p) {
- return b
- }
- };
- return i.init()
- };
- var _nearParticle = function (b, c) {
- var c = c || 0;
- var a = b.x;
- var f = b.y;
- var e = c * 2;
- return new Point(a - c + Math.random() * e, f - c + Math.random() * e)
- };
- // if called as a worker thread, set up a run loop for the Physics object and bail out
- if (typeof (window) == 'undefined') return (function () { /* hermetic.js */
- $ = {
- each: function (d, e) {
- if ($.isArray(d)) {
- for (var c = 0, b = d.length; c < b; c++) {
- e(c, d[c])
- }
- } else {
- for (var a in d) {
- e(a, d[a])
- }
- }
- },
- map: function (a, c) {
- var b = [];
- $.each(a, function (f, e) {
- var d = c(e);
- if (d !== undefined) {
- b.push(d)
- }
- });
- return b
- },
- extend: function (c, b) {
- if (typeof b != "object") {
- return c
- }
- for (var a in b) {
- if (b.hasOwnProperty(a)) {
- c[a] = b[a]
- }
- }
- return c
- },
- isArray: function (a) {
- if (!a) {
- return false
- }
- return (a.constructor.toString().indexOf("Array") != -1)
- },
- inArray: function (c, a) {
- for (var d = 0, b = a.length; d < b; d++) {
- if (a[d] === c) {
- return d
- }
- }
- return -1
- },
- isEmptyObject: function (a) {
- if (typeof a !== "object") {
- return false
- }
- var b = true;
- $.each(a, function (c, d) {
- b = false
- });
- return b
- },
- }; /* worker.js */
- var PhysicsWorker = function () {
- var b = 20;
- var a = null;
- var d = null;
- var c = null;
- var g = [];
- var f = new Date().valueOf();
- var e = {
- init: function (h) {
- e.timeout(h.timeout);
- a = Physics(h.dt, h.stiffness, h.repulsion, h.friction, e.tock);
- return e
- },
- timeout: function (h) {
- if (h != b) {
- b = h;
- if (d !== null) {
- e.stop();
- e.go()
- }
- }
- },
- go: function () {
- if (d !== null) {
- return
- }
- c = null;
- d = setInterval(e.tick, b)
- },
- stop: function () {
- if (d === null) {
- return
- }
- clearInterval(d);
- d = null
- },
- tick: function () {
- a.tick();
- var h = a.systemEnergy();
- if ((h.mean + h.max) / 2 < 0.05) {
- if (c === null) {
- c = new Date().valueOf()
- }
- if (new Date().valueOf() - c > 1000) {
- e.stop()
- } else {}
- } else {
- c = null
- }
- },
- tock: function (h) {
- h.type = "geometry";
- postMessage(h)
- },
- modifyNode: function (i, h) {
- a.modifyNode(i, h);
- e.go()
- },
- modifyPhysics: function (h) {
- a.modifyPhysics(h)
- },
- update: function (h) {
- var i = a._update(h)
- }
- };
- return e
- };
- var physics = PhysicsWorker();
- onmessage = function (a) {
- if (!a.data.type) {
- postMessage("¿kérnèl?");
- return
- }
- if (a.data.type == "physics") {
- var b = a.data.physics;
- physics.init(a.data.physics);
- return
- }
- switch (a.data.type) {
- case "modify":
- physics.modifyNode(a.data.id, a.data.mods);
- break;
- case "changes":
- physics.update(a.data.changes);
- physics.go();
- break;
- case "start":
- physics.go();
- break;
- case "stop":
- physics.stop();
- break;
- case "sys":
- var b = a.data.param || {};
- if (!isNaN(b.timeout)) {
- physics.timeout(b.timeout)
- }
- physics.modifyPhysics(b);
- physics.go();
- break
- }
- };
- })()
- arbor = (typeof (arbor) !== 'undefined') ? arbor : {}
- $.extend(arbor, {
- // object constructors (don't use ‘new’, just call them)
- ParticleSystem: ParticleSystem,
- Point: function (x, y) {
- return new Point(x, y)
- },
- // immutable object with useful methods
- etc: {
- trace: trace,
- // ƒ(msg) -> safe console logging
- dirname: dirname,
- // ƒ(path) -> leading part of path
- basename: basename,
- // ƒ(path) -> trailing part of path
- ordinalize: ordinalize,
- // ƒ(num) -> abbrev integers (and add commas)
- objcopy: objcopy,
- // ƒ(old) -> clone an object
- objcmp: objcmp,
- // ƒ(a, b, strict_ordering) -> t/f comparison
- objkeys: objkeys,
- // ƒ(obj) -> array of all keys in obj
- objmerge: objmerge,
- // ƒ(dst, src) -> like $.extend but non-destructive
- uniq: uniq,
- // ƒ(arr) -> array of unique items in arr
- arbor_path: arbor_path,
- // ƒ() -> guess the directory of the lib code
- }
- })
- })(this.jQuery)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement