From 407d07723df7d2e472d0928f79227ed4cb5dc218 Mon Sep 17 00:00:00 2001 From: emkael Date: Thu, 19 Feb 2015 10:46:55 +0100 Subject: * initial commit --- _img/foto_02.jpg | Bin 0 -> 1977 bytes _img/foto_03.jpg | Bin 0 -> 4021 bytes _img/foto_04.jpg | Bin 0 -> 3834 bytes _img/foto_05.jpg | Bin 0 -> 4992 bytes _img/foto_06.jpg | Bin 0 -> 1335 bytes arbor.js | 67 +++++++++++++++ graph.json | 17 ++++ index.html | 21 +++++ main.js | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 6 ++ 10 files changed, 363 insertions(+) create mode 100644 _img/foto_02.jpg create mode 100644 _img/foto_03.jpg create mode 100644 _img/foto_04.jpg create mode 100644 _img/foto_05.jpg create mode 100644 _img/foto_06.jpg create mode 100644 arbor.js create mode 100644 graph.json create mode 100644 index.html create mode 100644 main.js create mode 100644 style.css diff --git a/_img/foto_02.jpg b/_img/foto_02.jpg new file mode 100644 index 0000000..79c3f7e Binary files /dev/null and b/_img/foto_02.jpg differ diff --git a/_img/foto_03.jpg b/_img/foto_03.jpg new file mode 100644 index 0000000..bfb0cfa Binary files /dev/null and b/_img/foto_03.jpg differ diff --git a/_img/foto_04.jpg b/_img/foto_04.jpg new file mode 100644 index 0000000..1b350c9 Binary files /dev/null and b/_img/foto_04.jpg differ diff --git a/_img/foto_05.jpg b/_img/foto_05.jpg new file mode 100644 index 0000000..9583a72 Binary files /dev/null and b/_img/foto_05.jpg differ diff --git a/_img/foto_06.jpg b/_img/foto_06.jpg new file mode 100644 index 0000000..efa819b Binary files /dev/null and b/_img/foto_06.jpg differ diff --git a/arbor.js b/arbor.js new file mode 100644 index 0000000..87ad4d0 --- /dev/null +++ b/arbor.js @@ -0,0 +1,67 @@ +// +// arbor.js - version 0.91 +// a graph vizualization toolkit +// +// Copyright (c) 2012 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;i0){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("arbor.js/web-workers",m);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("arbor.js/single-threaded",m);i=Physics(m.dt,m.stiffness,m.repulsion,m.friction,j.system._updateGeometry,m.integrator);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;p0);if(x){$.extend(d.adjacency[C][D].data,y.data);return}else{d.edges[y._id]=y;d.adjacency[C][D].push(y);var w=(y.length!==undefined)?y.length:1;k.push({t:"addSpring",id:y._id,fm:C,to:D,l:w});h._notify()}return y},pruneEdge:function(B){k.push({t:"dropSpring",id:B._id});delete d.edges[B._id];for(var w in d.adjacency){for(var C in d.adjacency[w]){var z=d.adjacency[w][C];for(var A=z.length-1;A>=0;A--){if(d.adjacency[w][C][A]._id===B._id){d.adjacency[w][C].splice(A,1)}}}}h._notify()},getEdges:function(x,w){x=h.getNode(x);w=h.getNode(w);if(!x||!w){return[]}if(typeof(d.adjacency[x._id])!=="undefined"&&typeof(d.adjacency[x._id][w._id])!=="undefined"){return d.adjacency[x._id][w._id]}return[]},getEdgesFrom:function(w){w=h.getNode(w);if(!w){return[]}if(typeof(d.adjacency[w._id])!=="undefined"){var x=[];$.each(d.adjacency[w._id],function(z,y){x=x.concat(y)});return x}return[]},getEdgesTo:function(w){w=h.getNode(w);if(!w){return[]}var x=[];$.each(d.edges,function(z,y){if(y.target==w){x.push(y)}});return x},eachEdge:function(w){$.each(d.edges,function(A,y){var z=d.nodes[y.source._id]._p;var x=d.nodes[y.target._id]._p;if(z.x==null||x.x==null){return}z=(v!==null)?h.toScreen(z):z;x=(v!==null)?h.toScreen(x):x;if(z&&x){w.call(h,y,z,x)}})},prune:function(x){var w={dropped:{nodes:[],edges:[]}};if(x===undefined){$.each(d.nodes,function(z,y){w.dropped.nodes.push(y);h.pruneNode(y)})}else{h.eachNode(function(z){var y=x.call(h,z,{from:h.getEdgesFrom(z),to:h.getEdgesTo(z)});if(y){w.dropped.nodes.push(z);h.pruneNode(z)}})}return w},graft:function(x){var w={added:{nodes:[],edges:[]}};if(x.nodes){$.each(x.nodes,function(z,y){var A=h.getNode(z);if(A){A.data=y}else{w.added.nodes.push(h.addNode(z,y))}d.kernel.start()})}if(x.edges){$.each(x.edges,function(A,y){var z=h.getNode(A);if(!z){w.added.nodes.push(h.addNode(A,{}))}$.each(y,function(E,B){var D=h.getNode(E);if(!D){w.added.nodes.push(h.addNode(E,{}))}var C=h.getEdges(A,E);if(C.length>0){C[0].data=B}else{w.added.edges.push(h.addEdge(A,E,B))}})})}return w},merge:function(x){var w={added:{nodes:[],edges:[]},dropped:{nodes:[],edges:[]}};$.each(d.edges,function(B,A){if((x.edges[A.source.name]===undefined||x.edges[A.source.name][A.target.name]===undefined)){h.pruneEdge(A);w.dropped.edges.push(A)}});var z=h.prune(function(B,A){if(x.nodes[B.name]===undefined){w.dropped.nodes.push(B);return true}});var y=h.graft(x);w.added.nodes=w.added.nodes.concat(y.added.nodes);w.added.edges=w.added.edges.concat(y.added.edges);w.dropped.nodes=w.dropped.nodes.concat(z.dropped.nodes);w.dropped.edges=w.dropped.edges.concat(z.dropped.edges);return w},tweenNode:function(z,w,y){var x=h.getNode(z);if(x){d.tween.to(x,w,y)}},tweenEdge:function(x,w,A,z){if(z===undefined){h._tweenEdge(x,w,A)}else{var y=h.getEdges(x,w);$.each(y,function(B,C){h._tweenEdge(C,A,z)})}},_tweenEdge:function(x,w,y){if(x&&x._id!==undefined){d.tween.to(x,w,y)}},_updateGeometry:function(z){if(z!=undefined){var w=(z.epoch1||B.y*v.height>1){o=_newBounds;return true}else{return false}},energy:function(){return b},bounds:function(){var x=null;var w=null;$.each(d.nodes,function(A,z){if(!x){x=new Point(z._p);w=new Point(z._p);return}var y=z._p;if(y.x===null||y.y===null){return}if(y.x>x.x){x.x=y.x}if(y.y>x.y){x.y=y.y}if(y.x0){d.kernel.graphChanged(k);k=[];i=null}},};d.kernel=Kernel(h);d.tween=d.kernel.tween||null;Node.prototype.__defineGetter__("p",function(){var x=this;var w={};w.__defineGetter__("x",function(){return x._p.x});w.__defineSetter__("x",function(y){d.kernel.particleModified(x._id,{x:y})});w.__defineGetter__("y",function(){return x._p.y});w.__defineSetter__("y",function(y){d.kernel.particleModified(x._id,{y:y})});w.__proto__=Point.prototype;return w});Node.prototype.__defineSetter__("p",function(w){this._p.x=w.x;this._p.y=w.y;d.kernel.particleModified(this._id,{x:w.x,y:w.y})});Node.prototype.__defineGetter__("mass",function(){return this._mass});Node.prototype.__defineSetter__("mass",function(w){this._mass=w;d.kernel.particleModified(this._id,{m:w})});Node.prototype.__defineSetter__("tempMass",function(w){d.kernel.particleModified(this._id,{_m:w})});Node.prototype.__defineGetter__("fixed",function(){return this._fixed});Node.prototype.__defineSetter__("fixed",function(w){this._fixed=w;d.kernel.particleModified(this._id,{f:w?1:0})});return h}; + /* 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=0?o:"verlet",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(q){$.each(["stiffness","repulsion","friction","gravity","dt","precision","integrator"],function(s,t){if(q[t]!==undefined){if(t=="precision"){i.theta=1-q[t];return}i[t]=q[t];if(t=="stiffness"){var r=q[t];$.each(c.springs,function(v,u){u.k=r})}}})},addNode:function(v){var u=v.id;var r=v.m;var q=g.bottomright.x-g.topleft.x;var t=g.bottomright.y-g.topleft.y;var s=new Point((v.x!=null)?v.x:g.topleft.x+q*Math.random(),(v.y!=null)?v.y:g.topleft.y+t*Math.random());c.particles[u]=new Particle(s,r);c.particles[u].connections=0;c.particles[u].fixed=(v.f===1);l.particles[u]=c.particles[u];p.push(c.particles[u])},dropNode:function(t){var s=t.id;var r=c.particles[s];var q=$.inArray(r,p);if(q>-1){p.splice(q,1)}delete c.particles[s];delete l.particles[s]},modifyNode:function(s,q){if(s in c.particles){var r=c.particles[s];if("x" in q){r.p.x=q.x}if("y" in q){r.p.y=q.y}if("m" in q){r.m=q.m}if("f" in q){r.fixed=(q.f===1)}if("_m" in q){if(r._m===undefined){r._m=r.m}r.m=q._m}}},addSpring:function(u){var t=u.id;var q=u.l;var s=c.particles[u.fm];var r=c.particles[u.to];if(s!==undefined&&r!==undefined){c.springs[t]=new Spring(s,r,q,i.stiffness);k.push(c.springs[t]);s.connections++;r.connections++;delete l.particles[u.fm];delete l.particles[u.to]}},dropSpring:function(t){var s=t.id;var r=c.springs[s];r.point1.connections--;r.point2.connections--;var q=$.inArray(r,k);if(q>-1){k.splice(q,1)}delete c.springs[s]},_update:function(q){d++;$.each(q,function(r,s){if(s.t in i){i[s.t](s)}});return d},tick:function(){i.tendParticles();if(i.integrator=="euler"){i.updateForces();i.updateVelocity(i.dt);i.updatePosition(i.dt)}else{i.updateForces();i.cacheForces();i.updatePosition(i.dt);i.updateForces();i.updateVelocity(i.dt)}i.tock()},tock:function(){var q=[];$.each(c.particles,function(s,r){q.push(s);q.push(r.p.x);q.push(r.p.y)});if(h){h({geometry:q,epoch:d,energy:b,bounds:g})}},tendParticles:function(){$.each(c.particles,function(r,q){if(q._m!==undefined){if(Math.abs(q.m-q._m)<1){q.m=q._m;delete q._m}else{q.m*=0.98}}q.v.x=q.v.y=0})},updateForces:function(){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()}},cacheForces:function(){$.each(c.particles,function(r,q){q._F=q.f})},applyBruteForceRepulsion:function(){$.each(c.particles,function(r,q){$.each(c.particles,function(t,s){if(q!==s){var v=q.p.subtract(s.p);var w=Math.max(1,v.magnitude());var u=((v.magnitude()>0)?v:Point.random(1)).normalize();q.applyForce(u.multiply(i.repulsion*(s._m||s.m)*0.5).divide(w*w*0.5));s.applyForce(u.multiply(i.repulsion*(q._m||q.m)*0.5).divide(w*w*-0.5))}})})},applyBarnesHutRepulsion:function(){if(!g.topleft||!g.bottomright){return}var r=new Point(g.bottomright);var q=new Point(g.topleft);f.init(q,r,i.theta);$.each(c.particles,function(t,s){f.insert(s)});$.each(c.particles,function(t,s){f.applyForces(s,i.repulsion)})},applySprings:function(){$.each(c.springs,function(u,q){var t=q.point2.p.subtract(q.point1.p);var r=q.length-t.magnitude();var s=((t.magnitude()>0)?t:Point.random(1)).normalize();q.point1.applyForce(s.multiply(q.k*r*-0.5));q.point2.applyForce(s.multiply(q.k*r*0.5))})},applyCenterDrift:function(){var r=0;var s=new Point(0,0);$.each(c.particles,function(u,t){s.add(t.p);r++});if(r==0){return}var q=s.divide(-r);$.each(c.particles,function(u,t){t.applyForce(q)})},applyCenterGravity:function(){$.each(c.particles,function(s,q){var r=q.p.multiply(-1);q.applyForce(r.multiply(i.repulsion/100))})},updateVelocity:function(r){var s=0,q=0,t=0;$.each(c.particles,function(x,u){if(u.fixed){u.v=new Point(0,0);u.f=new Point(0,0);return}if(i.integrator=="euler"){u.v=u.v.add(u.f.multiply(r)).multiply(1-i.friction)}else{u.v=u.v.add(u.f.add(u._F.divide(u._m)).multiply(r*0.5)).multiply(1-i.friction)}u.f.x=u.f.y=0;var v=u.v.magnitude();if(v>j){u.v=u.v.divide(v*v)}var v=u.v.magnitude();var w=v*v;s+=w;q=Math.max(w,q);t++});b={sum:s,max:q,mean:s/t,n:t}},updatePosition:function(q){var s=null;var r=null;$.each(c.particles,function(v,u){if(i.integrator=="euler"){u.p=u.p.add(u.v.multiply(q))}else{var t=u.f.multiply(0.5*q*q).divide(u.m);u.p=u.p.add(u.v.multiply(q)).add(t)}if(!s){s=new Point(u.p.x,u.p.y);r=new Point(u.p.x,u.p.y);return}var w=u.p;if(w.x===null||w.y===null){return}if(w.x>s.x){s.x=w.x}if(w.y>s.y){s.y=w.y}if(w.x1000){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) \ No newline at end of file diff --git a/graph.json b/graph.json new file mode 100644 index 0000000..cbac5ad --- /dev/null +++ b/graph.json @@ -0,0 +1,17 @@ +{ + "nodes": { + "a": { "image": "foto_02.jpg" }, + "b": { "image": "foto_03.jpg" }, + "c": { "image": "foto_04.jpg" }, + "d": { "image": "foto_05.jpg" }, + "e": { "image": "foto_06.jpg" } + }, + "edges": { + "a": { + "b": { "style": "red" }, + "c": { "width": 5, "dash": [10, 10] }, + "d": { "style": "black", "width": 5, "arrow": 20, "dash": [10, 10] }, + "e": { } + } + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..585214d --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + arbor.js project template + + + + + + + + + + + + + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..bc488f4 --- /dev/null +++ b/main.js @@ -0,0 +1,252 @@ +// +// main.js +// +// A project template for using arbor.js +// + +(function($){ + + var Renderer = function(canvas){ + var canvas = $(canvas).get(0) + var ctx = canvas.getContext("2d"); + var particleSystem + + var that = { + init:function(system){ + // + // the particle system will call the init function once, right before the + // first frame is to be drawn. it's a good place to set up the canvas and + // to pass the canvas size to the particle system + // + // save a reference to the particle system for use in the .redraw() loop + particleSystem = system + + // inform the system of the screen dimensions so it can map coords for us. + // if the canvas is ever resized, screenSize should be called again with + // the new dimensions + particleSystem.screenSize(canvas.width, canvas.height) + particleSystem.screenPadding(50) // leave an extra 80px of whitespace per side + + // set up some event handlers to allow for node-dragging + that.initMouseHandling() + }, + + redraw:function(){ + // + // redraw will be called repeatedly during the run whenever the node positions + // change. the new positions for the nodes can be accessed by looking at the + // .p attribute of a given node. however the p.x & p.y values are in the coordinates + // of the particle system rather than the screen. you can either map them to + // the screen yourself, or use the convenience iterators .eachNode (and .eachEdge) + // which allow you to step through the actual node objects but also pass an + // x,y point in the screen's coordinate system + // + ctx.fillStyle = "white" + ctx.fillRect(0,0, canvas.width, canvas.height) + + // JESTEM BOGIEM PRZEKSZTAŁCEŃ 2D :O + var drawArrow = function(pt1, pt2, length, style) { + var angle = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); + ctx.fillStyle = style; + ctx.setLineDash([]); + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(pt2.x, pt2.y); + ctx.lineTo(pt2.x - length * Math.cos(angle - Math.PI/6), pt2.y - length * Math.sin(angle - Math.PI/6)); + ctx.lineTo(pt2.x - length * (Math.cos(angle + Math.PI/6) + Math.cos(angle - Math.PI/6))/3, + pt2.y - length * (Math.sin(angle - Math.PI/6) + Math.sin(angle + Math.PI/6))/3); + ctx.lineTo(pt2.x - length * Math.cos(angle + Math.PI/6), pt2.y - length * Math.sin(angle + Math.PI/6)); + ctx.lineTo(pt2.x, pt2.y); + ctx.stroke(); + ctx.fill(); + } + + particleSystem.eachEdge(function(edge, pt1, pt2){ + // edge: {source:Node, target:Node, length:#, data:{}} + // pt1: {x:#, y:#} source position in screen coords + // pt2: {x:#, y:#} target position in screen coords + + ctx.strokeStyle = edge.data.style || "rgba(0,0,0, .333)" + ctx.lineWidth = edge.data.width || 1 + ctx.setLineDash(edge.data.dash || []) + + // draw a line from pt1 to pt2 + ctx.beginPath() + ctx.moveTo(pt1.x, pt1.y) + + if (edge.data.arrow) { + if (edge.target.data.imageObject) { + var destination = {}; + var intersectingSegment = undefined; + if (pt1.x != pt2.x) { + var lineSlope = (pt1.y - pt2.y) / (pt1.x - pt2.x); + var width = edge.target.data.imageObject.width; + var height = edge.target.data.imageObject.height; + if ((-height / 2 <= lineSlope * width / 2) + && (lineSlope * width / 2 <= height / 2)) { + if (pt1.x > pt2.x) { + intersectingSegment = [ + { x: pt2.x + width / 2, + y: pt2.y - height / 2 }, + { x: pt2.x + width / 2, + y: pt2.y + height / 2 } + ]; + } + else { + intersectingSegment = [ + { x: pt2.x - width / 2, + y: pt2.y - height / 2 }, + { x: pt2.x - width / 2, + y: pt2.y + height / 2 } + ]; + } + } + if ((-width / 2 <= (height / 2) / lineSlope) + && ((height / 2) / lineSlope <= width / 2)) { + if (pt1.y > pt2.y) { + intersectingSegment = [ + { x: pt2.x - width / 2, + y: pt2.y + height / 2 }, + { x: pt2.x + width / 2, + y: pt2.y + height / 2 } + ]; + } + else { + intersectingSegment = [ + { x: pt2.x - width / 2, + y: pt2.y - height / 2 }, + { x: pt2.x + width / 2, + y: pt2.y - height / 2 } + ]; + } + } + } + else { + intersectingSegment = (pt1.y > pt2.y) ? [ + { x: pt2.x - width / 2, + y: pt2.y - height / 2 }, + { x: pt2.x + width / 2, + y: pt2.y - height / 2 } + ] : [ + { x: pt2.x - width / 2, + y: pt2.y + height / 2 }, + { x: pt2.x + width / 2, + y: pt2.y + height / 2 } + ]; + } + if (intersectingSegment) { + var intersectAngle = ((intersectingSegment[1].y - intersectingSegment[0].y) * (pt2.x - pt1.x)) + - ((intersectingSegment[1].x - intersectingSegment[0].x) * (pt2.y - pt1.y)); + var aSlope = pt1.y - intersectingSegment[0].y; + var bSlope = pt1.x - intersectingSegment[0].x; + var numerator1 = ((intersectingSegment[1].x - intersectingSegment[0].x) * aSlope) + - ((intersectingSegment[1].y - intersectingSegment[0].y) * bSlope); + var intersectSlope = numerator1 / intersectAngle; + destination = { x: pt1.x + (intersectSlope * (pt2.x - pt1.x)), + y: pt1.y + (intersectSlope * (pt2.y - pt1.y)) }; + } + } + } + + if (destination) { + pt2 = destination; + } + ctx.lineTo(pt2.x, pt2.y); + ctx.stroke(); + if (edge.data.arrow) { + drawArrow(pt1, pt2, edge.data.arrow, ctx.strokeStyle); + } + }) + + var drawImage = function(image, coords) { + ctx.drawImage(image, + coords.x - image.width / 2, + coords.y - image.height / 2); + }; + + + particleSystem.eachNode(function(node, pt){ + // node: {mass:#, p:{x,y}, name:"", data:{}} + // pt: {x:#, y:#} node position in screen coords + + + if (node.data.imageObject) { + drawImage(node.data.imageObject, pt); + } + else { + var img = new Image(); + img.onload = function() { + node.data.imageObject = img; + drawImage(node.data.imageObject, pt); + }; + img.src = '_img/' + node.data.image; + } + }) + }, + + initMouseHandling:function(){ + // no-nonsense drag and drop (thanks springy.js) + var dragged = null; + + // set up a handler object that will initially listen for mousedowns then + // for moves and mouseups while dragging + var handler = { + clicked:function(e){ + var pos = $(canvas).offset(); + _mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top) + dragged = particleSystem.nearest(_mouseP); + + if (dragged && dragged.node !== null){ + // while we're dragging, don't let physics move the node + dragged.node.fixed = true + } + + $(canvas).bind('mousemove', handler.dragged) + $(window).bind('mouseup', handler.dropped) + + return false + }, + dragged:function(e){ + var pos = $(canvas).offset(); + var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top) + + if (dragged && dragged.node !== null){ + var p = particleSystem.fromScreen(s) + dragged.node.p = p + } + + return false + }, + + dropped:function(e){ + if (dragged===null || dragged.node===undefined) return + if (dragged.node !== null) dragged.node.fixed = false + dragged.node.tempMass = 1000 + dragged = null + $(canvas).unbind('mousemove', handler.dragged) + $(window).unbind('mouseup', handler.dropped) + _mouseP = null + return false + } + } + + // start listening + $(canvas).mousedown(handler.clicked); + + }, + + } + return that + } + + $(document).ready(function() { + var sys = arbor.ParticleSystem(500, 2000, 0.7); // create the system with sensible repulsion/stiffness/friction + sys.parameters({gravity:true}); // use center-gravity to make the graph settle nicely (ymmv) + sys.renderer = Renderer("#viewport"); // our newly created renderer will have its .init() method called shortly by sys... + + $.getJSON('graph.json', function(graph) { + sys.graft(graph); + }); + }) + +})(this.jQuery) diff --git a/style.css b/style.css new file mode 100644 index 0000000..c02f01e --- /dev/null +++ b/style.css @@ -0,0 +1,6 @@ +body{ + margin:0; + padding:20px; + font:12px/17px Arial, sans-serif; + background:#f9f9f9; +} -- cgit v1.2.3