123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608 |
- //
- // 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 k = window.location.protocol == "file:" && navigator.userAgent.toLowerCase().indexOf("chrome") > -1;
- var a = (window.Worker !== undefined && !k);
- var i = null;
- var c = null;
- var f = [];
- f.last = new Date();
- var l = null;
- var e = null;
- var d = 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 m = b.parameters();
- if (a) {
- trace("using web workers");
- l = setInterval(j.screenUpdate, m.timeout);
- i = new Worker(arbor_path() + "arbor.js");
- i.onmessage = j.workerMsg;
- i.onerror = function (n) {
- trace("physics:", n)
- };
- i.postMessage({type: "physics", physics: objmerge(m, {timeout: Math.ceil(m.timeout)})})
- } else {
- trace("couldn't use web workers, be careful...");
- i = Physics(m.dt, m.stiffness, m.repulsion, m.friction, j.system._updateGeometry);
- j.start()
- }
- return j
- },
- graphChanged: function (m) {
- if (a) {
- i.postMessage({type: "changes", changes: m})
- } else {
- i._update(m)
- }
- j.start()
- },
- particleModified: function (n, m) {
- if (a) {
- i.postMessage({type: "modify", id: n, mods: m})
- } else {
- i.modifyNode(n, m)
- }
- j.start()
- },
- physicsModified: function (m) {
- if (!isNaN(m.timeout)) {
- if (a) {
- clearInterval(l);
- l = setInterval(j.screenUpdate, m.timeout)
- } else {
- clearInterval(d);
- d = null
- }
- }
- if (a) {
- i.postMessage({type: "sys", param: m})
- } else {
- i.modifyPhysics(m)
- }
- j.start()
- },
- workerMsg: function (n) {
- var m = n.data.type;
- if (m == "geometry") {
- j.workerUpdate(n.data)
- } else {
- trace("physics:", n.data)
- }
- },
- _lastPositions: null,
- workerUpdate: function (m) {
- j._lastPositions = m;
- j._lastBounds = m.bounds
- },
- _lastFrametime: new Date().valueOf(),
- _lastBounds: null,
- _currentRenderer: null,
- screenUpdate: function () {
- var n = new Date().valueOf();
- var m = false;
- if (j._lastPositions !== null) {
- j.system._updateGeometry(j._lastPositions);
- j._lastPositions = null;
- m = true
- }
- if (c && c.busy()) {
- m = true
- }
- if (j.system._updateBounds(j._lastBounds)) {
- m = true
- }
- if (m) {
- var o = j.system.renderer;
- if (o !== undefined) {
- if (o !== e) {
- o.init(j.system);
- e = o
- }
- if (c) {
- c.tick()
- }
- o.redraw();
- var p = f.last;
- f.last = new Date();
- f.push(f.last - p);
- if (f.length > 50) {
- f.shift()
- }
- }
- }
- },
- physicsUpdate: function () {
- if (c) {
- c.tick()
- }
- i.tick();
- var n = j.system._updateBounds();
- if (c && c.busy()) {
- n = true
- }
- var o = j.system.renderer;
- var m = new Date();
- var o = j.system.renderer;
- if (o !== undefined) {
- if (o !== e) {
- o.init(j.system);
- e = o
- }
- o.redraw({timestamp: m})
- }
- var q = f.last;
- f.last = m;
- f.push(f.last - q);
- if (f.length > 50) {
- f.shift()
- }
- var p = i.systemEnergy();
- if ((p.mean + p.max) / 2 < 0.05) {
- if (h === null) {
- h = new Date().valueOf()
- }
- if (new Date().valueOf() - h > 1000) {
- clearInterval(d);
- d = null
- } else {
- }
- } else {
- h = null
- }
- },
- fps: function (n) {
- if (n !== undefined) {
- var q = 1000 / Math.max(1, targetFps);
- j.physicsModified({timeout: q})
- }
- var r = 0;
- for (var p = 0, o = f.length; p < o; p++) {
- r += f[p]
- }
- var m = r / Math.max(1, f.length);
- if (!isNaN(m)) {
- return Math.round(1000 / m)
- } else {
- return 0
- }
- },
- start: function (m) {
- if (d !== null) {
- return
- }
- if (g && !m) {
- return
- }
- g = false;
- if (a) {
- i.postMessage({type: "start"})
- } else {
- h = null;
- d = setInterval(j.physicsUpdate, j.system.parameters().timeout)
- }
- },
- stop: function () {
- g = true;
- if (a) {
- i.postMessage({type: "stop"})
- } else {
- if (d !== null) {
- clearInterval(d);
- d = 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 (w, B) {
- B = B || {};
- var C = c.names[w];
- if (C) {
- C.data = B;
- return C
- } else {
- if (w != undefined) {
- var v = (B.x != undefined) ? B.x : null;
- var D = (B.y != undefined) ? B.y : null;
- var A = (B.fixed) ? 1 : 0;
- var z = new Node(B);
- z.name = w;
- c.names[w] = z;
- c.nodes[z._id] = z;
- j.push({t: "addNode", id: z._id, m: z.mass, x: v, y: D, f: A});
- g._notify();
- return z
- }
- }
- }, 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 == undefined) {
- return {size: (u) ? objcopy(u) : undefined, padding: i.concat(), step: m}
- }
- 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((u.x != null) ? u.x : g.topleft.x + p * Math.random(), (u.y != null) ? u.y : g.topleft.y + s * Math.random());
- c.particles[t] = new Particle(r, q);
- c.particles[t].connections = 0;
- c.particles[t].fixed = (u.f === 1);
- 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)
|