arbor.js 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608
  1. //
  2. // arbor.js - version 0.91
  3. // a graph vizualization toolkit
  4. //
  5. // Copyright (c) 2011 Samizdat Drafting Co.
  6. // Physics code derived from springy.js, copyright (c) 2010 Dennis Hotson
  7. //
  8. // Permission is hereby granted, free of charge, to any person
  9. // obtaining a copy of this software and associated documentation
  10. // files (the "Software"), to deal in the Software without
  11. // restriction, including without limitation the rights to use,
  12. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the
  14. // Software is furnished to do so, subject to the following
  15. // conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  22. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  24. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  25. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27. // OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. (function ($) {
  30. /* etc.js */
  31. var trace = function (msg) {
  32. if (typeof (window) == "undefined" || !window.console) {
  33. return
  34. }
  35. var len = arguments.length;
  36. var args = [];
  37. for (var i = 0; i < len; i++) {
  38. args.push("arguments[" + i + "]")
  39. }
  40. eval("console.log(" + args.join(",") + ")")
  41. };
  42. var dirname = function (a) {
  43. var b = a.replace(/^\/?(.*?)\/?$/, "$1").split("/");
  44. b.pop();
  45. return "/" + b.join("/")
  46. };
  47. var basename = function (b) {
  48. var c = b.replace(/^\/?(.*?)\/?$/, "$1").split("/");
  49. var a = c.pop();
  50. if (a == "") {
  51. return null
  52. } else {
  53. return a
  54. }
  55. };
  56. var _ordinalize_re = /(\d)(?=(\d\d\d)+(?!\d))/g;
  57. var ordinalize = function (a) {
  58. var b = "" + a;
  59. if (a < 11000) {
  60. b = ("" + a).replace(_ordinalize_re, "$1,")
  61. } else {
  62. if (a < 1000000) {
  63. b = Math.floor(a / 1000) + "k"
  64. } else {
  65. if (a < 1000000000) {
  66. b = ("" + Math.floor(a / 1000)).replace(_ordinalize_re, "$1,") + "m"
  67. }
  68. }
  69. }
  70. return b
  71. };
  72. var nano = function (a, b) {
  73. return a.replace(/\{([\w\-\.]*)}/g, function (f, c) {
  74. var d = c.split("."), e = b[d.shift()];
  75. $.each(d, function () {
  76. if (e.hasOwnProperty(this)) {
  77. e = e[this]
  78. } else {
  79. e = f
  80. }
  81. });
  82. return e
  83. })
  84. };
  85. var objcopy = function (a) {
  86. if (a === undefined) {
  87. return undefined
  88. }
  89. if (a === null) {
  90. return null
  91. }
  92. if (a.parentNode) {
  93. return a
  94. }
  95. switch (typeof a) {
  96. case"string":
  97. return a.substring(0);
  98. break;
  99. case"number":
  100. return a + 0;
  101. break;
  102. case"boolean":
  103. return a === true;
  104. break
  105. }
  106. var b = ($.isArray(a)) ? [] : {};
  107. $.each(a, function (d, c) {
  108. b[d] = objcopy(c)
  109. });
  110. return b
  111. };
  112. var objmerge = function (d, b) {
  113. d = d || {};
  114. b = b || {};
  115. var c = objcopy(d);
  116. for (var a in b) {
  117. c[a] = b[a]
  118. }
  119. return c
  120. };
  121. var objcmp = function (e, c, d) {
  122. if (!e || !c) {
  123. return e === c
  124. }
  125. if (typeof e != typeof c) {
  126. return false
  127. }
  128. if (typeof e != "object") {
  129. return e === c
  130. } else {
  131. if ($.isArray(e)) {
  132. if (!($.isArray(c))) {
  133. return false
  134. }
  135. if (e.length != c.length) {
  136. return false
  137. }
  138. } else {
  139. var h = [];
  140. for (var f in e) {
  141. if (e.hasOwnProperty(f)) {
  142. h.push(f)
  143. }
  144. }
  145. var g = [];
  146. for (var f in c) {
  147. if (c.hasOwnProperty(f)) {
  148. g.push(f)
  149. }
  150. }
  151. if (!d) {
  152. h.sort();
  153. g.sort()
  154. }
  155. if (h.join(",") !== g.join(",")) {
  156. return false
  157. }
  158. }
  159. var i = true;
  160. $.each(e, function (a) {
  161. var b = objcmp(e[a], c[a]);
  162. i = i && b;
  163. if (!i) {
  164. return false
  165. }
  166. });
  167. return i
  168. }
  169. };
  170. var objkeys = function (b) {
  171. var a = [];
  172. $.each(b, function (d, c) {
  173. if (b.hasOwnProperty(d)) {
  174. a.push(d)
  175. }
  176. });
  177. return a
  178. };
  179. var objcontains = function (c) {
  180. if (!c || typeof c != "object") {
  181. return false
  182. }
  183. for (var b = 1, a = arguments.length; b < a; b++) {
  184. if (c.hasOwnProperty(arguments[b])) {
  185. return true
  186. }
  187. }
  188. return false
  189. };
  190. var uniq = function (b) {
  191. var a = b.length;
  192. var d = {};
  193. for (var c = 0; c < a; c++) {
  194. d[b[c]] = true
  195. }
  196. return objkeys(d)
  197. };
  198. var arbor_path = function () {
  199. var a = $("script").map(function (b) {
  200. var c = $(this).attr("src");
  201. if (!c) {
  202. return
  203. }
  204. if (c.match(/arbor[^\/\.]*.js|dev.js/)) {
  205. return c.match(/.*\//) || "/"
  206. }
  207. });
  208. if (a.length > 0) {
  209. return a[0]
  210. } else {
  211. return null
  212. }
  213. };
  214. /* kernel.js */
  215. var Kernel = function (b) {
  216. var k = window.location.protocol == "file:" && navigator.userAgent.toLowerCase().indexOf("chrome") > -1;
  217. var a = (window.Worker !== undefined && !k);
  218. var i = null;
  219. var c = null;
  220. var f = [];
  221. f.last = new Date();
  222. var l = null;
  223. var e = null;
  224. var d = null;
  225. var h = null;
  226. var g = false;
  227. var j = {
  228. system: b,
  229. tween: null,
  230. nodes: {},
  231. init: function () {
  232. if (typeof (Tween) != "undefined") {
  233. c = Tween()
  234. } else {
  235. if (typeof (arbor.Tween) != "undefined") {
  236. c = arbor.Tween()
  237. } else {
  238. c = {
  239. busy: function () {
  240. return false
  241. }, tick: function () {
  242. return true
  243. }, to: function () {
  244. trace("Please include arbor-tween.js to enable tweens");
  245. c.to = function () {
  246. };
  247. return
  248. }
  249. }
  250. }
  251. }
  252. j.tween = c;
  253. var m = b.parameters();
  254. if (a) {
  255. trace("using web workers");
  256. l = setInterval(j.screenUpdate, m.timeout);
  257. i = new Worker(arbor_path() + "arbor.js");
  258. i.onmessage = j.workerMsg;
  259. i.onerror = function (n) {
  260. trace("physics:", n)
  261. };
  262. i.postMessage({type: "physics", physics: objmerge(m, {timeout: Math.ceil(m.timeout)})})
  263. } else {
  264. trace("couldn't use web workers, be careful...");
  265. i = Physics(m.dt, m.stiffness, m.repulsion, m.friction, j.system._updateGeometry);
  266. j.start()
  267. }
  268. return j
  269. },
  270. graphChanged: function (m) {
  271. if (a) {
  272. i.postMessage({type: "changes", changes: m})
  273. } else {
  274. i._update(m)
  275. }
  276. j.start()
  277. },
  278. particleModified: function (n, m) {
  279. if (a) {
  280. i.postMessage({type: "modify", id: n, mods: m})
  281. } else {
  282. i.modifyNode(n, m)
  283. }
  284. j.start()
  285. },
  286. physicsModified: function (m) {
  287. if (!isNaN(m.timeout)) {
  288. if (a) {
  289. clearInterval(l);
  290. l = setInterval(j.screenUpdate, m.timeout)
  291. } else {
  292. clearInterval(d);
  293. d = null
  294. }
  295. }
  296. if (a) {
  297. i.postMessage({type: "sys", param: m})
  298. } else {
  299. i.modifyPhysics(m)
  300. }
  301. j.start()
  302. },
  303. workerMsg: function (n) {
  304. var m = n.data.type;
  305. if (m == "geometry") {
  306. j.workerUpdate(n.data)
  307. } else {
  308. trace("physics:", n.data)
  309. }
  310. },
  311. _lastPositions: null,
  312. workerUpdate: function (m) {
  313. j._lastPositions = m;
  314. j._lastBounds = m.bounds
  315. },
  316. _lastFrametime: new Date().valueOf(),
  317. _lastBounds: null,
  318. _currentRenderer: null,
  319. screenUpdate: function () {
  320. var n = new Date().valueOf();
  321. var m = false;
  322. if (j._lastPositions !== null) {
  323. j.system._updateGeometry(j._lastPositions);
  324. j._lastPositions = null;
  325. m = true
  326. }
  327. if (c && c.busy()) {
  328. m = true
  329. }
  330. if (j.system._updateBounds(j._lastBounds)) {
  331. m = true
  332. }
  333. if (m) {
  334. var o = j.system.renderer;
  335. if (o !== undefined) {
  336. if (o !== e) {
  337. o.init(j.system);
  338. e = o
  339. }
  340. if (c) {
  341. c.tick()
  342. }
  343. o.redraw();
  344. var p = f.last;
  345. f.last = new Date();
  346. f.push(f.last - p);
  347. if (f.length > 50) {
  348. f.shift()
  349. }
  350. }
  351. }
  352. },
  353. physicsUpdate: function () {
  354. if (c) {
  355. c.tick()
  356. }
  357. i.tick();
  358. var n = j.system._updateBounds();
  359. if (c && c.busy()) {
  360. n = true
  361. }
  362. var o = j.system.renderer;
  363. var m = new Date();
  364. var o = j.system.renderer;
  365. if (o !== undefined) {
  366. if (o !== e) {
  367. o.init(j.system);
  368. e = o
  369. }
  370. o.redraw({timestamp: m})
  371. }
  372. var q = f.last;
  373. f.last = m;
  374. f.push(f.last - q);
  375. if (f.length > 50) {
  376. f.shift()
  377. }
  378. var p = i.systemEnergy();
  379. if ((p.mean + p.max) / 2 < 0.05) {
  380. if (h === null) {
  381. h = new Date().valueOf()
  382. }
  383. if (new Date().valueOf() - h > 1000) {
  384. clearInterval(d);
  385. d = null
  386. } else {
  387. }
  388. } else {
  389. h = null
  390. }
  391. },
  392. fps: function (n) {
  393. if (n !== undefined) {
  394. var q = 1000 / Math.max(1, targetFps);
  395. j.physicsModified({timeout: q})
  396. }
  397. var r = 0;
  398. for (var p = 0, o = f.length; p < o; p++) {
  399. r += f[p]
  400. }
  401. var m = r / Math.max(1, f.length);
  402. if (!isNaN(m)) {
  403. return Math.round(1000 / m)
  404. } else {
  405. return 0
  406. }
  407. },
  408. start: function (m) {
  409. if (d !== null) {
  410. return
  411. }
  412. if (g && !m) {
  413. return
  414. }
  415. g = false;
  416. if (a) {
  417. i.postMessage({type: "start"})
  418. } else {
  419. h = null;
  420. d = setInterval(j.physicsUpdate, j.system.parameters().timeout)
  421. }
  422. },
  423. stop: function () {
  424. g = true;
  425. if (a) {
  426. i.postMessage({type: "stop"})
  427. } else {
  428. if (d !== null) {
  429. clearInterval(d);
  430. d = null
  431. }
  432. }
  433. }
  434. };
  435. return j.init()
  436. };
  437. /* atoms.js */
  438. var Node = function (a) {
  439. this._id = _nextNodeId++;
  440. this.data = a || {};
  441. this._mass = (a.mass !== undefined) ? a.mass : 1;
  442. this._fixed = (a.fixed === true) ? true : false;
  443. this._p = new Point((typeof (a.x) == "number") ? a.x : null, (typeof (a.y) == "number") ? a.y : null);
  444. delete this.data.x;
  445. delete this.data.y;
  446. delete this.data.mass;
  447. delete this.data.fixed
  448. };
  449. var _nextNodeId = 1;
  450. var Edge = function (b, c, a) {
  451. this._id = _nextEdgeId--;
  452. this.source = b;
  453. this.target = c;
  454. this.length = (a.length !== undefined) ? a.length : 1;
  455. this.data = (a !== undefined) ? a : {};
  456. delete this.data.length
  457. };
  458. var _nextEdgeId = -1;
  459. var Particle = function (a, b) {
  460. this.p = a;
  461. this.m = b;
  462. this.v = new Point(0, 0);
  463. this.f = new Point(0, 0)
  464. };
  465. Particle.prototype.applyForce = function (a) {
  466. this.f = this.f.add(a.divide(this.m))
  467. };
  468. var Spring = function (c, b, d, a) {
  469. this.point1 = c;
  470. this.point2 = b;
  471. this.length = d;
  472. this.k = a
  473. };
  474. Spring.prototype.distanceToParticle = function (a) {
  475. var c = that.point2.p.subtract(that.point1.p).normalize().normal();
  476. var b = a.p.subtract(that.point1.p);
  477. return Math.abs(b.x * c.x + b.y * c.y)
  478. };
  479. var Point = function (a, b) {
  480. if (a && a.hasOwnProperty("y")) {
  481. b = a.y;
  482. a = a.x
  483. }
  484. this.x = a;
  485. this.y = b
  486. };
  487. Point.random = function (a) {
  488. a = (a !== undefined) ? a : 5;
  489. return new Point(2 * a * (Math.random() - 0.5), 2 * a * (Math.random() - 0.5))
  490. };
  491. Point.prototype = {
  492. exploded: function () {
  493. return (isNaN(this.x) || isNaN(this.y))
  494. }, add: function (a) {
  495. return new Point(this.x + a.x, this.y + a.y)
  496. }, subtract: function (a) {
  497. return new Point(this.x - a.x, this.y - a.y)
  498. }, multiply: function (a) {
  499. return new Point(this.x * a, this.y * a)
  500. }, divide: function (a) {
  501. return new Point(this.x / a, this.y / a)
  502. }, magnitude: function () {
  503. return Math.sqrt(this.x * this.x + this.y * this.y)
  504. }, normal: function () {
  505. return new Point(-this.y, this.x)
  506. }, normalize: function () {
  507. return this.divide(this.magnitude())
  508. }
  509. };
  510. /* system.js */
  511. var ParticleSystem = function (d, p, e, f, t, l, q) {
  512. var j = [];
  513. var h = null;
  514. var k = 0;
  515. var u = null;
  516. var m = 0.04;
  517. var i = [20, 20, 20, 20];
  518. var n = null;
  519. var o = null;
  520. if (typeof p == "object") {
  521. var s = p;
  522. e = s.friction;
  523. d = s.repulsion;
  524. t = s.fps;
  525. l = s.dt;
  526. p = s.stiffness;
  527. f = s.gravity;
  528. q = s.precision
  529. }
  530. e = isNaN(e) ? 0.5 : e;
  531. d = isNaN(d) ? 1000 : d;
  532. t = isNaN(t) ? 55 : t;
  533. p = isNaN(p) ? 600 : p;
  534. l = isNaN(l) ? 0.02 : l;
  535. q = isNaN(q) ? 0.6 : q;
  536. f = (f === true);
  537. var r = (t !== undefined) ? 1000 / t : 1000 / 50;
  538. var b = {repulsion: d, stiffness: p, friction: e, dt: l, gravity: f, precision: q, timeout: r};
  539. var a;
  540. var c = {renderer: null, tween: null, nodes: {}, edges: {}, adjacency: {}, names: {}, kernel: null};
  541. var g = {
  542. parameters: function (v) {
  543. if (v !== undefined) {
  544. if (!isNaN(v.precision)) {
  545. v.precision = Math.max(0, Math.min(1, v.precision))
  546. }
  547. $.each(b, function (x, w) {
  548. if (v[x] !== undefined) {
  549. b[x] = v[x]
  550. }
  551. });
  552. c.kernel.physicsModified(v)
  553. }
  554. return b
  555. }, fps: function (v) {
  556. if (v === undefined) {
  557. return c.kernel.fps()
  558. } else {
  559. g.parameters({timeout: 1000 / (v || 50)})
  560. }
  561. }, start: function () {
  562. c.kernel.start()
  563. }, stop: function () {
  564. c.kernel.stop()
  565. }, addNode: function (w, B) {
  566. B = B || {};
  567. var C = c.names[w];
  568. if (C) {
  569. C.data = B;
  570. return C
  571. } else {
  572. if (w != undefined) {
  573. var v = (B.x != undefined) ? B.x : null;
  574. var D = (B.y != undefined) ? B.y : null;
  575. var A = (B.fixed) ? 1 : 0;
  576. var z = new Node(B);
  577. z.name = w;
  578. c.names[w] = z;
  579. c.nodes[z._id] = z;
  580. j.push({t: "addNode", id: z._id, m: z.mass, x: v, y: D, f: A});
  581. g._notify();
  582. return z
  583. }
  584. }
  585. }, pruneNode: function (w) {
  586. var v = g.getNode(w);
  587. if (typeof (c.nodes[v._id]) !== "undefined") {
  588. delete c.nodes[v._id];
  589. delete c.names[v.name]
  590. }
  591. $.each(c.edges, function (y, x) {
  592. if (x.source._id === v._id || x.target._id === v._id) {
  593. g.pruneEdge(x)
  594. }
  595. });
  596. j.push({t: "dropNode", id: v._id});
  597. g._notify()
  598. }, getNode: function (v) {
  599. if (v._id !== undefined) {
  600. return v
  601. } else {
  602. if (typeof v == "string" || typeof v == "number") {
  603. return c.names[v]
  604. }
  605. }
  606. }, eachNode: function (v) {
  607. $.each(c.nodes, function (y, x) {
  608. if (x._p.x == null || x._p.y == null) {
  609. return
  610. }
  611. var w = (u !== null) ? g.toScreen(x._p) : x._p;
  612. v.call(g, x, w)
  613. })
  614. }, addEdge: function (z, A, y) {
  615. z = g.getNode(z) || g.addNode(z);
  616. A = g.getNode(A) || g.addNode(A);
  617. y = y || {};
  618. var x = new Edge(z, A, y);
  619. var B = z._id;
  620. var C = A._id;
  621. c.adjacency[B] = c.adjacency[B] || {};
  622. c.adjacency[B][C] = c.adjacency[B][C] || [];
  623. var w = (c.adjacency[B][C].length > 0);
  624. if (w) {
  625. $.extend(c.adjacency[B][C].data, x.data);
  626. return
  627. } else {
  628. c.edges[x._id] = x;
  629. c.adjacency[B][C].push(x);
  630. var v = (x.length !== undefined) ? x.length : 1;
  631. j.push({t: "addSpring", id: x._id, fm: B, to: C, l: v});
  632. g._notify()
  633. }
  634. return x
  635. }, pruneEdge: function (A) {
  636. j.push({t: "dropSpring", id: A._id});
  637. delete c.edges[A._id];
  638. for (var v in c.adjacency) {
  639. for (var B in c.adjacency[v]) {
  640. var w = c.adjacency[v][B];
  641. for (var z = w.length - 1; z >= 0; z--) {
  642. if (c.adjacency[v][B][z]._id === A._id) {
  643. c.adjacency[v][B].splice(z, 1)
  644. }
  645. }
  646. }
  647. }
  648. g._notify()
  649. }, getEdges: function (w, v) {
  650. w = g.getNode(w);
  651. v = g.getNode(v);
  652. if (!w || !v) {
  653. return []
  654. }
  655. if (typeof (c.adjacency[w._id]) !== "undefined" && typeof (c.adjacency[w._id][v._id]) !== "undefined") {
  656. return c.adjacency[w._id][v._id]
  657. }
  658. return []
  659. }, getEdgesFrom: function (v) {
  660. v = g.getNode(v);
  661. if (!v) {
  662. return []
  663. }
  664. if (typeof (c.adjacency[v._id]) !== "undefined") {
  665. var w = [];
  666. $.each(c.adjacency[v._id], function (y, x) {
  667. w = w.concat(x)
  668. });
  669. return w
  670. }
  671. return []
  672. }, getEdgesTo: function (v) {
  673. v = g.getNode(v);
  674. if (!v) {
  675. return []
  676. }
  677. var w = [];
  678. $.each(c.edges, function (y, x) {
  679. if (x.target == v) {
  680. w.push(x)
  681. }
  682. });
  683. return w
  684. }, eachEdge: function (v) {
  685. $.each(c.edges, function (z, x) {
  686. var y = c.nodes[x.source._id]._p;
  687. var w = c.nodes[x.target._id]._p;
  688. if (y.x == null || w.x == null) {
  689. return
  690. }
  691. y = (u !== null) ? g.toScreen(y) : y;
  692. w = (u !== null) ? g.toScreen(w) : w;
  693. if (y && w) {
  694. v.call(g, x, y, w)
  695. }
  696. })
  697. }, prune: function (w) {
  698. var v = {dropped: {nodes: [], edges: []}};
  699. if (w === undefined) {
  700. $.each(c.nodes, function (y, x) {
  701. v.dropped.nodes.push(x);
  702. g.pruneNode(x)
  703. })
  704. } else {
  705. g.eachNode(function (y) {
  706. var x = w.call(g, y, {from: g.getEdgesFrom(y), to: g.getEdgesTo(y)});
  707. if (x) {
  708. v.dropped.nodes.push(y);
  709. g.pruneNode(y)
  710. }
  711. })
  712. }
  713. return v
  714. }, graft: function (w) {
  715. var v = {added: {nodes: [], edges: []}};
  716. if (w.nodes) {
  717. $.each(w.nodes, function (y, x) {
  718. var z = g.getNode(y);
  719. if (z) {
  720. z.data = x
  721. } else {
  722. v.added.nodes.push(g.addNode(y, x))
  723. }
  724. c.kernel.start()
  725. })
  726. }
  727. if (w.edges) {
  728. $.each(w.edges, function (z, x) {
  729. var y = g.getNode(z);
  730. if (!y) {
  731. v.added.nodes.push(g.addNode(z, {}))
  732. }
  733. $.each(x, function (D, A) {
  734. var C = g.getNode(D);
  735. if (!C) {
  736. v.added.nodes.push(g.addNode(D, {}))
  737. }
  738. var B = g.getEdges(z, D);
  739. if (B.length > 0) {
  740. B[0].data = A
  741. } else {
  742. v.added.edges.push(g.addEdge(z, D, A))
  743. }
  744. })
  745. })
  746. }
  747. return v
  748. }, merge: function (w) {
  749. var v = {added: {nodes: [], edges: []}, dropped: {nodes: [], edges: []}};
  750. $.each(c.edges, function (A, z) {
  751. if ((w.edges[z.source.name] === undefined || w.edges[z.source.name][z.target.name] === undefined)) {
  752. g.pruneEdge(z);
  753. v.dropped.edges.push(z)
  754. }
  755. });
  756. var y = g.prune(function (A, z) {
  757. if (w.nodes[A.name] === undefined) {
  758. v.dropped.nodes.push(A);
  759. return true
  760. }
  761. });
  762. var x = g.graft(w);
  763. v.added.nodes = v.added.nodes.concat(x.added.nodes);
  764. v.added.edges = v.added.edges.concat(x.added.edges);
  765. v.dropped.nodes = v.dropped.nodes.concat(y.dropped.nodes);
  766. v.dropped.edges = v.dropped.edges.concat(y.dropped.edges);
  767. return v
  768. }, tweenNode: function (y, v, x) {
  769. var w = g.getNode(y);
  770. if (w) {
  771. c.tween.to(w, v, x)
  772. }
  773. }, tweenEdge: function (w, v, z, y) {
  774. if (y === undefined) {
  775. g._tweenEdge(w, v, z)
  776. } else {
  777. var x = g.getEdges(w, v);
  778. $.each(x, function (A, B) {
  779. g._tweenEdge(B, z, y)
  780. })
  781. }
  782. }, _tweenEdge: function (w, v, x) {
  783. if (w && w._id !== undefined) {
  784. c.tween.to(w, v, x)
  785. }
  786. }, _updateGeometry: function (y) {
  787. if (y != undefined) {
  788. var v = (y.epoch < k);
  789. a = y.energy;
  790. var z = y.geometry;
  791. if (z !== undefined) {
  792. for (var x = 0, w = z.length / 3; x < w; x++) {
  793. var A = z[3 * x];
  794. if (v && c.nodes[A] == undefined) {
  795. continue
  796. }
  797. c.nodes[A]._p.x = z[3 * x + 1];
  798. c.nodes[A]._p.y = z[3 * x + 2]
  799. }
  800. }
  801. }
  802. }, screen: function (v) {
  803. if (v == undefined) {
  804. return {size: (u) ? objcopy(u) : undefined, padding: i.concat(), step: m}
  805. }
  806. if (v.size !== undefined) {
  807. g.screenSize(v.size.width, v.size.height)
  808. }
  809. if (!isNaN(v.step)) {
  810. g.screenStep(v.step)
  811. }
  812. if (v.padding !== undefined) {
  813. g.screenPadding(v.padding)
  814. }
  815. }, screenSize: function (v, w) {
  816. u = {width: v, height: w};
  817. g._updateBounds()
  818. }, screenPadding: function (y, z, v, w) {
  819. if ($.isArray(y)) {
  820. trbl = y
  821. } else {
  822. trbl = [y, z, v, w]
  823. }
  824. var A = trbl[0];
  825. var x = trbl[1];
  826. var B = trbl[2];
  827. if (x === undefined) {
  828. trbl = [A, A, A, A]
  829. } else {
  830. if (B == undefined) {
  831. trbl = [A, x, A, x]
  832. }
  833. }
  834. i = trbl
  835. }, screenStep: function (v) {
  836. m = v
  837. }, toScreen: function (x) {
  838. if (!n || !u) {
  839. return
  840. }
  841. var w = i || [0, 0, 0, 0];
  842. var v = n.bottomright.subtract(n.topleft);
  843. var z = w[3] + x.subtract(n.topleft).divide(v.x).x * (u.width - (w[1] + w[3]));
  844. var y = w[0] + x.subtract(n.topleft).divide(v.y).y * (u.height - (w[0] + w[2]));
  845. return arbor.Point(z, y)
  846. }, fromScreen: function (z) {
  847. if (!n || !u) {
  848. return
  849. }
  850. var y = i || [0, 0, 0, 0];
  851. var x = n.bottomright.subtract(n.topleft);
  852. var w = (z.x - y[3]) / (u.width - (y[1] + y[3])) * x.x + n.topleft.x;
  853. var v = (z.y - y[0]) / (u.height - (y[0] + y[2])) * x.y + n.topleft.y;
  854. return arbor.Point(w, v)
  855. }, _updateBounds: function (w) {
  856. if (u === null) {
  857. return
  858. }
  859. if (w) {
  860. o = w
  861. } else {
  862. o = g.bounds()
  863. }
  864. var z = new Point(o.bottomright.x, o.bottomright.y);
  865. var y = new Point(o.topleft.x, o.topleft.y);
  866. var B = z.subtract(y);
  867. var v = y.add(B.divide(2));
  868. var x = 4;
  869. var D = new Point(Math.max(B.x, x), Math.max(B.y, x));
  870. o.topleft = v.subtract(D.divide(2));
  871. o.bottomright = v.add(D.divide(2));
  872. if (!n) {
  873. if ($.isEmptyObject(c.nodes)) {
  874. return false
  875. }
  876. n = o;
  877. return true
  878. }
  879. var C = m;
  880. _newBounds = {
  881. bottomright: n.bottomright.add(o.bottomright.subtract(n.bottomright).multiply(C)),
  882. topleft: n.topleft.add(o.topleft.subtract(n.topleft).multiply(C))
  883. };
  884. var A = new Point(n.topleft.subtract(_newBounds.topleft).magnitude(), n.bottomright.subtract(_newBounds.bottomright).magnitude());
  885. if (A.x * u.width > 1 || A.y * u.height > 1) {
  886. n = _newBounds;
  887. return true
  888. } else {
  889. return false
  890. }
  891. }, energy: function () {
  892. return a
  893. }, bounds: function () {
  894. var w = null;
  895. var v = null;
  896. $.each(c.nodes, function (z, y) {
  897. if (!w) {
  898. w = new Point(y._p);
  899. v = new Point(y._p);
  900. return
  901. }
  902. var x = y._p;
  903. if (x.x === null || x.y === null) {
  904. return
  905. }
  906. if (x.x > w.x) {
  907. w.x = x.x
  908. }
  909. if (x.y > w.y) {
  910. w.y = x.y
  911. }
  912. if (x.x < v.x) {
  913. v.x = x.x
  914. }
  915. if (x.y < v.y) {
  916. v.y = x.y
  917. }
  918. });
  919. if (w && v) {
  920. return {bottomright: w, topleft: v}
  921. } else {
  922. return {topleft: new Point(-1, -1), bottomright: new Point(1, 1)}
  923. }
  924. }, nearest: function (x) {
  925. if (u !== null) {
  926. x = g.fromScreen(x)
  927. }
  928. var w = {node: null, point: null, distance: null};
  929. var v = g;
  930. $.each(c.nodes, function (B, y) {
  931. var z = y._p;
  932. if (z.x === null || z.y === null) {
  933. return
  934. }
  935. var A = z.subtract(x).magnitude();
  936. if (w.distance === null || A < w.distance) {
  937. w = {node: y, point: z, distance: A};
  938. if (u !== null) {
  939. w.screenPoint = g.toScreen(z)
  940. }
  941. }
  942. });
  943. if (w.node) {
  944. if (u !== null) {
  945. w.distance = g.toScreen(w.node.p).subtract(g.toScreen(x)).magnitude()
  946. }
  947. return w
  948. } else {
  949. return null
  950. }
  951. }, _notify: function () {
  952. if (h === null) {
  953. k++
  954. } else {
  955. clearTimeout(h)
  956. }
  957. h = setTimeout(g._synchronize, 20)
  958. }, _synchronize: function () {
  959. if (j.length > 0) {
  960. c.kernel.graphChanged(j);
  961. j = [];
  962. h = null
  963. }
  964. },
  965. };
  966. c.kernel = Kernel(g);
  967. c.tween = c.kernel.tween || null;
  968. Node.prototype.__defineGetter__("p", function () {
  969. var w = this;
  970. var v = {};
  971. v.__defineGetter__("x", function () {
  972. return w._p.x
  973. });
  974. v.__defineSetter__("x", function (x) {
  975. c.kernel.particleModified(w._id, {x: x})
  976. });
  977. v.__defineGetter__("y", function () {
  978. return w._p.y
  979. });
  980. v.__defineSetter__("y", function (x) {
  981. c.kernel.particleModified(w._id, {y: x})
  982. });
  983. v.__proto__ = Point.prototype;
  984. return v
  985. });
  986. Node.prototype.__defineSetter__("p", function (v) {
  987. this._p.x = v.x;
  988. this._p.y = v.y;
  989. c.kernel.particleModified(this._id, {x: v.x, y: v.y})
  990. });
  991. Node.prototype.__defineGetter__("mass", function () {
  992. return this._mass
  993. });
  994. Node.prototype.__defineSetter__("mass", function (v) {
  995. this._mass = v;
  996. c.kernel.particleModified(this._id, {m: v})
  997. });
  998. Node.prototype.__defineSetter__("tempMass", function (v) {
  999. c.kernel.particleModified(this._id, {_m: v})
  1000. });
  1001. Node.prototype.__defineGetter__("fixed", function () {
  1002. return this._fixed
  1003. });
  1004. Node.prototype.__defineSetter__("fixed", function (v) {
  1005. this._fixed = v;
  1006. c.kernel.particleModified(this._id, {f: v ? 1 : 0})
  1007. });
  1008. return g
  1009. };
  1010. /* barnes-hut.js */
  1011. var BarnesHutTree = function () {
  1012. var b = [];
  1013. var a = 0;
  1014. var e = null;
  1015. var d = 0.5;
  1016. var c = {
  1017. init: function (g, h, f) {
  1018. d = f;
  1019. a = 0;
  1020. e = c._newBranch();
  1021. e.origin = g;
  1022. e.size = h.subtract(g)
  1023. }, insert: function (j) {
  1024. var f = e;
  1025. var g = [j];
  1026. while (g.length) {
  1027. var h = g.shift();
  1028. var m = h._m || h.m;
  1029. var p = c._whichQuad(h, f);
  1030. if (f[p] === undefined) {
  1031. f[p] = h;
  1032. f.mass += m;
  1033. if (f.p) {
  1034. f.p = f.p.add(h.p.multiply(m))
  1035. } else {
  1036. f.p = h.p.multiply(m)
  1037. }
  1038. } else {
  1039. if ("origin" in f[p]) {
  1040. f.mass += (m);
  1041. if (f.p) {
  1042. f.p = f.p.add(h.p.multiply(m))
  1043. } else {
  1044. f.p = h.p.multiply(m)
  1045. }
  1046. f = f[p];
  1047. g.unshift(h)
  1048. } else {
  1049. var l = f.size.divide(2);
  1050. var n = new Point(f.origin);
  1051. if (p[0] == "s") {
  1052. n.y += l.y
  1053. }
  1054. if (p[1] == "e") {
  1055. n.x += l.x
  1056. }
  1057. var o = f[p];
  1058. f[p] = c._newBranch();
  1059. f[p].origin = n;
  1060. f[p].size = l;
  1061. f.mass = m;
  1062. f.p = h.p.multiply(m);
  1063. f = f[p];
  1064. if (o.p.x === h.p.x && o.p.y === h.p.y) {
  1065. var k = l.x * 0.08;
  1066. var i = l.y * 0.08;
  1067. o.p.x = Math.min(n.x + l.x, Math.max(n.x, o.p.x - k / 2 + Math.random() * k));
  1068. o.p.y = Math.min(n.y + l.y, Math.max(n.y, o.p.y - i / 2 + Math.random() * i))
  1069. }
  1070. g.push(o);
  1071. g.unshift(h)
  1072. }
  1073. }
  1074. }
  1075. }, applyForces: function (m, g) {
  1076. var f = [e];
  1077. while (f.length) {
  1078. node = f.shift();
  1079. if (node === undefined) {
  1080. continue
  1081. }
  1082. if (m === node) {
  1083. continue
  1084. }
  1085. if ("f" in node) {
  1086. var k = m.p.subtract(node.p);
  1087. var l = Math.max(1, k.magnitude());
  1088. var i = ((k.magnitude() > 0) ? k : Point.random(1)).normalize();
  1089. m.applyForce(i.multiply(g * (node._m || node.m)).divide(l * l))
  1090. } else {
  1091. var j = m.p.subtract(node.p.divide(node.mass)).magnitude();
  1092. var h = Math.sqrt(node.size.x * node.size.y);
  1093. if (h / j > d) {
  1094. f.push(node.ne);
  1095. f.push(node.nw);
  1096. f.push(node.se);
  1097. f.push(node.sw)
  1098. } else {
  1099. var k = m.p.subtract(node.p.divide(node.mass));
  1100. var l = Math.max(1, k.magnitude());
  1101. var i = ((k.magnitude() > 0) ? k : Point.random(1)).normalize();
  1102. m.applyForce(i.multiply(g * (node.mass)).divide(l * l))
  1103. }
  1104. }
  1105. }
  1106. }, _whichQuad: function (i, f) {
  1107. if (i.p.exploded()) {
  1108. return null
  1109. }
  1110. var h = i.p.subtract(f.origin);
  1111. var g = f.size.divide(2);
  1112. if (h.y < g.y) {
  1113. if (h.x < g.x) {
  1114. return "nw"
  1115. } else {
  1116. return "ne"
  1117. }
  1118. } else {
  1119. if (h.x < g.x) {
  1120. return "sw"
  1121. } else {
  1122. return "se"
  1123. }
  1124. }
  1125. }, _newBranch: function () {
  1126. if (b[a]) {
  1127. var f = b[a];
  1128. f.ne = f.nw = f.se = f.sw = undefined;
  1129. f.mass = 0;
  1130. delete f.p
  1131. } else {
  1132. f = {origin: null, size: null, nw: undefined, ne: undefined, sw: undefined, se: undefined, mass: 0};
  1133. b[a] = f
  1134. }
  1135. a++;
  1136. return f
  1137. }
  1138. };
  1139. return c
  1140. };
  1141. /* physics.js */
  1142. var Physics = function (a, m, n, e, h) {
  1143. var f = BarnesHutTree();
  1144. var c = {particles: {}, springs: {}};
  1145. var l = {particles: {}};
  1146. var o = [];
  1147. var k = [];
  1148. var d = 0;
  1149. var b = {sum: 0, max: 0, mean: 0};
  1150. var g = {topleft: new Point(-1, -1), bottomright: new Point(1, 1)};
  1151. var j = 1000;
  1152. var i = {
  1153. stiffness: (m !== undefined) ? m : 1000,
  1154. repulsion: (n !== undefined) ? n : 600,
  1155. friction: (e !== undefined) ? e : 0.3,
  1156. gravity: false,
  1157. dt: (a !== undefined) ? a : 0.02,
  1158. theta: 0.4,
  1159. init: function () {
  1160. return i
  1161. },
  1162. modifyPhysics: function (p) {
  1163. $.each(["stiffness", "repulsion", "friction", "gravity", "dt", "precision"], function (r, s) {
  1164. if (p[s] !== undefined) {
  1165. if (s == "precision") {
  1166. i.theta = 1 - p[s];
  1167. return
  1168. }
  1169. i[s] = p[s];
  1170. if (s == "stiffness") {
  1171. var q = p[s];
  1172. $.each(c.springs, function (u, t) {
  1173. t.k = q
  1174. })
  1175. }
  1176. }
  1177. })
  1178. },
  1179. addNode: function (u) {
  1180. var t = u.id;
  1181. var q = u.m;
  1182. var p = g.bottomright.x - g.topleft.x;
  1183. var s = g.bottomright.y - g.topleft.y;
  1184. 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());
  1185. c.particles[t] = new Particle(r, q);
  1186. c.particles[t].connections = 0;
  1187. c.particles[t].fixed = (u.f === 1);
  1188. l.particles[t] = c.particles[t];
  1189. o.push(c.particles[t])
  1190. },
  1191. dropNode: function (s) {
  1192. var r = s.id;
  1193. var q = c.particles[r];
  1194. var p = $.inArray(q, o);
  1195. if (p > -1) {
  1196. o.splice(p, 1)
  1197. }
  1198. delete c.particles[r];
  1199. delete l.particles[r]
  1200. },
  1201. modifyNode: function (r, p) {
  1202. if (r in c.particles) {
  1203. var q = c.particles[r];
  1204. if ("x" in p) {
  1205. q.p.x = p.x
  1206. }
  1207. if ("y" in p) {
  1208. q.p.y = p.y
  1209. }
  1210. if ("m" in p) {
  1211. q.m = p.m
  1212. }
  1213. if ("f" in p) {
  1214. q.fixed = (p.f === 1)
  1215. }
  1216. if ("_m" in p) {
  1217. if (q._m === undefined) {
  1218. q._m = q.m
  1219. }
  1220. q.m = p._m
  1221. }
  1222. }
  1223. },
  1224. addSpring: function (t) {
  1225. var s = t.id;
  1226. var p = t.l;
  1227. var r = c.particles[t.fm];
  1228. var q = c.particles[t.to];
  1229. if (r !== undefined && q !== undefined) {
  1230. c.springs[s] = new Spring(r, q, p, i.stiffness);
  1231. k.push(c.springs[s]);
  1232. r.connections++;
  1233. q.connections++;
  1234. delete l.particles[t.fm];
  1235. delete l.particles[t.to]
  1236. }
  1237. },
  1238. dropSpring: function (s) {
  1239. var r = s.id;
  1240. var q = c.springs[r];
  1241. q.point1.connections--;
  1242. q.point2.connections--;
  1243. var p = $.inArray(q, k);
  1244. if (p > -1) {
  1245. k.splice(p, 1)
  1246. }
  1247. delete c.springs[r]
  1248. },
  1249. _update: function (p) {
  1250. d++;
  1251. $.each(p, function (q, r) {
  1252. if (r.t in i) {
  1253. i[r.t](r)
  1254. }
  1255. });
  1256. return d
  1257. },
  1258. tick: function () {
  1259. i.tendParticles();
  1260. i.eulerIntegrator(i.dt);
  1261. i.tock()
  1262. },
  1263. tock: function () {
  1264. var p = [];
  1265. $.each(c.particles, function (r, q) {
  1266. p.push(r);
  1267. p.push(q.p.x);
  1268. p.push(q.p.y)
  1269. });
  1270. if (h) {
  1271. h({geometry: p, epoch: d, energy: b, bounds: g})
  1272. }
  1273. },
  1274. tendParticles: function () {
  1275. $.each(c.particles, function (q, p) {
  1276. if (p._m !== undefined) {
  1277. if (Math.abs(p.m - p._m) < 1) {
  1278. p.m = p._m;
  1279. delete p._m
  1280. } else {
  1281. p.m *= 0.98
  1282. }
  1283. }
  1284. p.v.x = p.v.y = 0
  1285. })
  1286. },
  1287. eulerIntegrator: function (p) {
  1288. if (i.repulsion > 0) {
  1289. if (i.theta > 0) {
  1290. i.applyBarnesHutRepulsion()
  1291. } else {
  1292. i.applyBruteForceRepulsion()
  1293. }
  1294. }
  1295. if (i.stiffness > 0) {
  1296. i.applySprings()
  1297. }
  1298. i.applyCenterDrift();
  1299. if (i.gravity) {
  1300. i.applyCenterGravity()
  1301. }
  1302. i.updateVelocity(p);
  1303. i.updatePosition(p)
  1304. },
  1305. applyBruteForceRepulsion: function () {
  1306. $.each(c.particles, function (q, p) {
  1307. $.each(c.particles, function (s, r) {
  1308. if (p !== r) {
  1309. var u = p.p.subtract(r.p);
  1310. var v = Math.max(1, u.magnitude());
  1311. var t = ((u.magnitude() > 0) ? u : Point.random(1)).normalize();
  1312. p.applyForce(t.multiply(i.repulsion * (r._m || r.m) * 0.5).divide(v * v * 0.5));
  1313. r.applyForce(t.multiply(i.repulsion * (p._m || p.m) * 0.5).divide(v * v * -0.5))
  1314. }
  1315. })
  1316. })
  1317. },
  1318. applyBarnesHutRepulsion: function () {
  1319. if (!g.topleft || !g.bottomright) {
  1320. return
  1321. }
  1322. var q = new Point(g.bottomright);
  1323. var p = new Point(g.topleft);
  1324. f.init(p, q, i.theta);
  1325. $.each(c.particles, function (s, r) {
  1326. f.insert(r)
  1327. });
  1328. $.each(c.particles, function (s, r) {
  1329. f.applyForces(r, i.repulsion)
  1330. })
  1331. },
  1332. applySprings: function () {
  1333. $.each(c.springs, function (t, p) {
  1334. var s = p.point2.p.subtract(p.point1.p);
  1335. var q = p.length - s.magnitude();
  1336. var r = ((s.magnitude() > 0) ? s : Point.random(1)).normalize();
  1337. p.point1.applyForce(r.multiply(p.k * q * -0.5));
  1338. p.point2.applyForce(r.multiply(p.k * q * 0.5))
  1339. })
  1340. },
  1341. applyCenterDrift: function () {
  1342. var q = 0;
  1343. var r = new Point(0, 0);
  1344. $.each(c.particles, function (t, s) {
  1345. r.add(s.p);
  1346. q++
  1347. });
  1348. if (q == 0) {
  1349. return
  1350. }
  1351. var p = r.divide(-q);
  1352. $.each(c.particles, function (t, s) {
  1353. s.applyForce(p)
  1354. })
  1355. },
  1356. applyCenterGravity: function () {
  1357. $.each(c.particles, function (r, p) {
  1358. var q = p.p.multiply(-1);
  1359. p.applyForce(q.multiply(i.repulsion / 100))
  1360. })
  1361. },
  1362. updateVelocity: function (p) {
  1363. $.each(c.particles, function (t, q) {
  1364. if (q.fixed) {
  1365. q.v = new Point(0, 0);
  1366. q.f = new Point(0, 0);
  1367. return
  1368. }
  1369. var s = q.v.magnitude();
  1370. q.v = q.v.add(q.f.multiply(p)).multiply(1 - i.friction);
  1371. q.f.x = q.f.y = 0;
  1372. var r = q.v.magnitude();
  1373. if (r > j) {
  1374. q.v = q.v.divide(r * r)
  1375. }
  1376. })
  1377. },
  1378. updatePosition: function (q) {
  1379. var r = 0, p = 0, u = 0;
  1380. var t = null;
  1381. var s = null;
  1382. $.each(c.particles, function (w, v) {
  1383. v.p = v.p.add(v.v.multiply(q));
  1384. var x = v.v.magnitude();
  1385. var z = x * x;
  1386. r += z;
  1387. p = Math.max(z, p);
  1388. u++;
  1389. if (!t) {
  1390. t = new Point(v.p.x, v.p.y);
  1391. s = new Point(v.p.x, v.p.y);
  1392. return
  1393. }
  1394. var y = v.p;
  1395. if (y.x === null || y.y === null) {
  1396. return
  1397. }
  1398. if (y.x > t.x) {
  1399. t.x = y.x
  1400. }
  1401. if (y.y > t.y) {
  1402. t.y = y.y
  1403. }
  1404. if (y.x < s.x) {
  1405. s.x = y.x
  1406. }
  1407. if (y.y < s.y) {
  1408. s.y = y.y
  1409. }
  1410. });
  1411. b = {sum: r, max: p, mean: r / u, n: u};
  1412. g = {topleft: s || new Point(-1, -1), bottomright: t || new Point(1, 1)}
  1413. },
  1414. systemEnergy: function (p) {
  1415. return b
  1416. }
  1417. };
  1418. return i.init()
  1419. };
  1420. var _nearParticle = function (b, c) {
  1421. var c = c || 0;
  1422. var a = b.x;
  1423. var f = b.y;
  1424. var e = c * 2;
  1425. return new Point(a - c + Math.random() * e, f - c + Math.random() * e)
  1426. };
  1427. // if called as a worker thread, set up a run loop for the Physics object and bail out
  1428. if (typeof (window) == 'undefined') return (function () {
  1429. /* hermetic.js */
  1430. $ = {
  1431. each: function (d, e) {
  1432. if ($.isArray(d)) {
  1433. for (var c = 0, b = d.length; c < b; c++) {
  1434. e(c, d[c])
  1435. }
  1436. } else {
  1437. for (var a in d) {
  1438. e(a, d[a])
  1439. }
  1440. }
  1441. }, map: function (a, c) {
  1442. var b = [];
  1443. $.each(a, function (f, e) {
  1444. var d = c(e);
  1445. if (d !== undefined) {
  1446. b.push(d)
  1447. }
  1448. });
  1449. return b
  1450. }, extend: function (c, b) {
  1451. if (typeof b != "object") {
  1452. return c
  1453. }
  1454. for (var a in b) {
  1455. if (b.hasOwnProperty(a)) {
  1456. c[a] = b[a]
  1457. }
  1458. }
  1459. return c
  1460. }, isArray: function (a) {
  1461. if (!a) {
  1462. return false
  1463. }
  1464. return (a.constructor.toString().indexOf("Array") != -1)
  1465. }, inArray: function (c, a) {
  1466. for (var d = 0, b = a.length; d < b; d++) {
  1467. if (a[d] === c) {
  1468. return d
  1469. }
  1470. }
  1471. return -1
  1472. }, isEmptyObject: function (a) {
  1473. if (typeof a !== "object") {
  1474. return false
  1475. }
  1476. var b = true;
  1477. $.each(a, function (c, d) {
  1478. b = false
  1479. });
  1480. return b
  1481. },
  1482. };
  1483. /* worker.js */
  1484. var PhysicsWorker = function () {
  1485. var b = 20;
  1486. var a = null;
  1487. var d = null;
  1488. var c = null;
  1489. var g = [];
  1490. var f = new Date().valueOf();
  1491. var e = {
  1492. init: function (h) {
  1493. e.timeout(h.timeout);
  1494. a = Physics(h.dt, h.stiffness, h.repulsion, h.friction, e.tock);
  1495. return e
  1496. }, timeout: function (h) {
  1497. if (h != b) {
  1498. b = h;
  1499. if (d !== null) {
  1500. e.stop();
  1501. e.go()
  1502. }
  1503. }
  1504. }, go: function () {
  1505. if (d !== null) {
  1506. return
  1507. }
  1508. c = null;
  1509. d = setInterval(e.tick, b)
  1510. }, stop: function () {
  1511. if (d === null) {
  1512. return
  1513. }
  1514. clearInterval(d);
  1515. d = null
  1516. }, tick: function () {
  1517. a.tick();
  1518. var h = a.systemEnergy();
  1519. if ((h.mean + h.max) / 2 < 0.05) {
  1520. if (c === null) {
  1521. c = new Date().valueOf()
  1522. }
  1523. if (new Date().valueOf() - c > 1000) {
  1524. e.stop()
  1525. } else {
  1526. }
  1527. } else {
  1528. c = null
  1529. }
  1530. }, tock: function (h) {
  1531. h.type = "geometry";
  1532. postMessage(h)
  1533. }, modifyNode: function (i, h) {
  1534. a.modifyNode(i, h);
  1535. e.go()
  1536. }, modifyPhysics: function (h) {
  1537. a.modifyPhysics(h)
  1538. }, update: function (h) {
  1539. var i = a._update(h)
  1540. }
  1541. };
  1542. return e
  1543. };
  1544. var physics = PhysicsWorker();
  1545. onmessage = function (a) {
  1546. if (!a.data.type) {
  1547. postMessage("¿kérnèl?");
  1548. return
  1549. }
  1550. if (a.data.type == "physics") {
  1551. var b = a.data.physics;
  1552. physics.init(a.data.physics);
  1553. return
  1554. }
  1555. switch (a.data.type) {
  1556. case"modify":
  1557. physics.modifyNode(a.data.id, a.data.mods);
  1558. break;
  1559. case"changes":
  1560. physics.update(a.data.changes);
  1561. physics.go();
  1562. break;
  1563. case"start":
  1564. physics.go();
  1565. break;
  1566. case"stop":
  1567. physics.stop();
  1568. break;
  1569. case"sys":
  1570. var b = a.data.param || {};
  1571. if (!isNaN(b.timeout)) {
  1572. physics.timeout(b.timeout)
  1573. }
  1574. physics.modifyPhysics(b);
  1575. physics.go();
  1576. break
  1577. }
  1578. };
  1579. })()
  1580. arbor = (typeof (arbor) !== 'undefined') ? arbor : {}
  1581. $.extend(arbor, {
  1582. // object constructors (don't use ‘new’, just call them)
  1583. ParticleSystem: ParticleSystem,
  1584. Point: function (x, y) {
  1585. return new Point(x, y)
  1586. },
  1587. // immutable object with useful methods
  1588. etc: {
  1589. trace: trace, // ƒ(msg) -> safe console logging
  1590. dirname: dirname, // ƒ(path) -> leading part of path
  1591. basename: basename, // ƒ(path) -> trailing part of path
  1592. ordinalize: ordinalize, // ƒ(num) -> abbrev integers (and add commas)
  1593. objcopy: objcopy, // ƒ(old) -> clone an object
  1594. objcmp: objcmp, // ƒ(a, b, strict_ordering) -> t/f comparison
  1595. objkeys: objkeys, // ƒ(obj) -> array of all keys in obj
  1596. objmerge: objmerge, // ƒ(dst, src) -> like $.extend but non-destructive
  1597. uniq: uniq, // ƒ(arr) -> array of unique items in arr
  1598. arbor_path: arbor_path, // ƒ() -> guess the directory of the lib code
  1599. }
  1600. })
  1601. })(this.jQuery)