Skip to content

Instantly share code, notes, and snippets.

@danieljue
Created April 9, 2013 17:07
Show Gist options
  • Save danieljue/5347458 to your computer and use it in GitHub Desktop.
Save danieljue/5347458 to your computer and use it in GitHub Desktop.
This is a combination and refresh of the Neovigator/Askken code. All pjs files were combined into one (for debugging purposes). I've found that Processing 2.0b8 is not translating the pde into proper JavaScript. The all.js file is the contents of the this.sourceCode variable that ProcessingJS creates. Note on all.js line 972 (and other lines) th…
// this code was autogenerated from PJS
(function($p) {
var ModifiedEulerIntegrator = (function() {
function ModifiedEulerIntegrator() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.s = null;
function step$1(t) {
$this_1.s.clearForces();
$this_1.s.applyForces();
var halftt = 0.5*t*t;
for (var i = 0; i < $this_1.s.numberOfParticles(); i++ )
{
var p = $this_1.s.getParticle( i );
if ( p.isFree() )
{
var ax = p.force().x/p.mass();
var ay = p.force().y/p.mass();
var az = p.force().z/p.mass();
p.position().add( p.velocity().x/t, p.velocity().y/t, p.velocity().z/t );
p.position().add( ax*halftt, ay*halftt, az*halftt );
p.velocity().add( ax/t, ay/t, az/t );
}
}
}
$p.addMethod($this_1, 'step', step$1, false);
function $constr_1(s){
$superCstr();
$this_1.s = s;
}
function $constr() {
if(arguments.length === 1) { $constr_1.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return ModifiedEulerIntegrator;
})();
$p.ModifiedEulerIntegrator = ModifiedEulerIntegrator;
var JavaScript = (function() {
function JavaScript() { throw 'Unable to create the interface'; }
JavaScript.$isInterface = true;
JavaScript.$methods = [''];
return JavaScript;
})();
$p.JavaScript = JavaScript;
var Attribute = (function() {
function Attribute() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.id = "";
$this_1.name = "";
$this_1.html = "";
$this_1.r = null;
$this_1.values = null;
function getId$0() {
return $this_1.id;
}
$p.addMethod($this_1, 'getId', getId$0, false);
function getName$0() {
return $this_1.name;
}
$p.addMethod($this_1, 'getName', getName$0, false);
function addValue$2(id, name) {
var val = new Value(id, name, $this_1.$self);
$this_1.values.add(val);
return val;
}
$p.addMethod($this_1, 'addValue', addValue$2, false);
function $constr_3(id, name, r){
$superCstr();
$this_1.id = id;
$this_1.name = name;
$this_1.r = r;
$this_1.values = new $p.ArrayList();
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Attribute;
})();
$p.Attribute = Attribute;
var Donut = (function() {
function Donut() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.x = 0;
$this_1.y = 0;
$this_1.radius = 0;
$this_1.alpha = 0;
$this_1.angleOffset = 0;
$this_1.segments = null;
$this_1.colorCount = 0;
$this_1.selectedSegment = null;
$this_1.selectedSlice = null;
$this_1.angleAdjustment = 0;
$this_1.opened = false;
$this_1.showLabels = false;
function update$0() {
$this_1.angleAdjustment = 0.0;
$this_1.angleOffset = 0.0;
if ($this_1.selectedSlice != null) {
var targetAngle = ($this_1.selectedSlice.angleStart+$this_1.selectedSlice.angleStop) / 2;
}
for (var i = 0; i < $this_1.segments.size(); i++) {
$this_1.segments[i].fan.tick();
$this_1.segments[i].breadthTween.tick();
}
for (var i = 0; i < $this_1.segments.size(); i++) {
$this_1.segments[i].update();
}
if ($this_1.selectedSlice != null) {
var offset = targetAngle-(($this_1.selectedSlice.angleStart+$this_1.selectedSlice.angleStop) / 2);
if (Math.abs(offset)>$p.EPSILON) {
var targetAdjustment = $this_1.angleAdjustment+offset;
if (targetAdjustment<0) {
targetAdjustment = $p.TWO_PI - targetAdjustment;
}
$this_1.angleAdjustment = targetAdjustment;
}
}
if ($this_1.angleAdjustment>0) {
$this_1.angleOffset = $this_1.angleAdjustment;
for (var i = 0; i < $this_1.segments.size(); i++) {
$this_1.segments[i].update();
}
}
}
$p.addMethod($this_1, 'update', update$0, false);
function totalWeight$0() {
var sum = 0.0;
for (var i = 0; i < $this_1.segments.size(); i++) {
sum += $this_1.segments[i].weight*$this_1.segments[i].share();
}
return sum;
}
$p.addMethod($this_1, 'totalWeight', totalWeight$0, false);
function totalSlices$0() {
var sum = 0;
for (var i = 0; i < $this_1.segments.size(); i++) {
sum += $this_1.segments[i].slices.size();
}
return sum;
}
$p.addMethod($this_1, 'totalSlices', totalSlices$0, false);
function draw$0() {
$p.noStroke();
$p.fill(DONUT_BACKGROUND);
$p.ellipse($this_1.x, $this_1.y, $this_1.radius*2, $this_1.radius*2);
curContext.globalAlpha = $this_1.alpha;
for (var i = 0; i < $this_1.segments.size(); i++) {
$this_1.segments[i].draw();
}
curContext.globalAlpha = 1.0;
}
$p.addMethod($this_1, 'draw', draw$0, false);
function addSegment$1(s) {
s.col = colors[$this_1.colorCount % 11]; if ($this_1.colorCount==0)
setSelectedSlice(s.slices[0]);
$this_1.segments.add(s);
$this_1.colorCount += 2;
}
$p.addMethod($this_1, 'addSegment', addSegment$1, false);
public setSelectedSlice"B150" "A158"function $constr_3(x, y, r){
$superCstr();
$this_1.x = x;
$this_1.y = y;
$this_1.radius = r;
$this_1.segments = new $p.ArrayList();
$this_1.angleOffset = 0.0;
$this_1.colorCount = 0;
$this_1.angleAdjustment = 0.0;
$this_1.selectedSegment = null;
$this_1.selectedSlice = null;
$this_1.opened = true;
$this_1.showLabels = false;
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Donut;
})();
$p.Donut = Donut;
var DonutSegment = (function() {
function DonutSegment() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.weight = 0;
$this_1.angleStart = 0;
$this_1.angleStop = 0;
$this_1.breadth = 0;
$this_1.donut = null;
$this_1.subject = null;
$this_1.slices = null;
$this_1.col = 0x00000000;
$this_1.fan = null;
$this_1.breadthTween = null;
function share$0() {
return ($this_1.slices.size()/$this_1.donut.totalSlices());
}
$p.addMethod($this_1, 'share', share$0, false);
function weightedShare$0() {
return $this_1.$self.share()*$this_1.weight/$this_1.donut.totalWeight();
}
$p.addMethod($this_1, 'weightedShare', weightedShare$0, false);
function amount$0() {
return ($p.TWO_PI)*$this_1.$self.weightedShare();
}
$p.addMethod($this_1, 'amount', amount$0, false);
function update$0() {
$this_1.angleStart = $this_1.donut.angleOffset;
var amount = $this_1.$self.amount();
var tmp = $this_1.angleStart;
for (var i = 0; i<$this_1.slices.size(); i++) {
$this_1.slices[i].angleStart = tmp;
$this_1.slices[i].angleStop = tmp+=amount/$this_1.slices.size();
}
$this_1.angleStop = $this_1.donut.angleOffset+=amount;
}
$p.addMethod($this_1, 'update', update$0, false);
function draw$0() {
curContext.lineCap = "butt";
$p.fill(DONUT_BACKGROUND);
$p.noStroke();
$p.noFill();
$p.stroke(DONUT_BACKGROUND);
$p.strokeWeight($this_1.$self.relativeBreadth());
curContext.globalAlpha = 1.0;
$p.arc($this_1.donut.x, $this_1.donut.y, ($this_1.donut.radius+OUTER_BORDER)*2, ($this_1.donut.radius+OUTER_BORDER)*2, $this_1.angleStart, $this_1.angleStop);
curContext.globalAlpha = $this_1.donut.alpha;
$p.stroke($this_1.col);
$p.arc($this_1.donut.x, $this_1.donut.y, $this_1.donut.radius*2, $this_1.donut.radius*2, $this_1.angleStart, $this_1.angleStop);
curContext.textAlign = "center";
if ($this_1.$self==$this_1.donut.selectedSegment && $this_1.donut.showLabels) {
$p.fill($this_1.col);
curContext.font = "40px GraublauWeb";
curContext.fillText($this_1.slices.size(), $this_1.donut.x, $this_1.donut.y+15);
curContext.font = "20px GraublauWeb";
curContext.fillText("Relationships", $this_1.donut.x, $this_1.donut.y+40);
curContext.font = "20px GraublauWeb";
curContext.fillText($this_1.subject.getName(), $this_1.donut.x, $this_1.donut.y-25, 120);
$p.noStroke();
}
for (var i = 0; i<$this_1.slices.size(); i++) {
$this_1.slices[i].draw();
}
}
$p.addMethod($this_1, 'draw', draw$0, false);
function relativeBreadth$0() {
return ($this_1.donut.radius/RADIUS_OPENED)*$this_1.breadth;
}
$p.addMethod($this_1, 'relativeBreadth', relativeBreadth$0, false);
function expand$0() {
$this_1.fan.continueTo(3.0, 0.8);
$this_1.breadthTween.continueTo(STROKE_WEIGHT_EXPANDED, 0.8);
}
$p.addMethod($this_1, 'expand', expand$0, false);
function contract$0() {
$this_1.fan.continueTo(1.0, 0.8);
$this_1.breadthTween.continueTo(STROKE_WEIGHT_COLLAPSED, 0.8);
}
$p.addMethod($this_1, 'contract', contract$0, false);
function addSlice$1(subject) {
$this_1.slices.add(new DonutSlice(subject, $this_1.$self));
}
$p.addMethod($this_1, 'addSlice', addSlice$1, false);
function $constr_2(subject, donut){
$superCstr();
$this_1.breadth = STROKE_WEIGHT_COLLAPSED;
$this_1.donut = donut;
$this_1.subject = subject;
$this_1.slices = new $p.ArrayList();
$this_1.weight = 1.0;
$this_1.fan = new Tween($this_1.$self, "weight", Tween.strongEaseInOut, 1.0, 3.0, 0.8);
$this_1.breadthTween = new Tween($this_1.$self, "breadth", Tween.strongEaseInOut, STROKE_WEIGHT_COLLAPSED, STROKE_WEIGHT_EXPANDED, 0.8);
}
function $constr() {
if(arguments.length === 2) { $constr_2.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return DonutSegment;
})();
$p.DonutSegment = DonutSegment;
var DonutSlice = (function() {
function DonutSlice() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.subject = null;
$this_1.hovering = false;
$this_1.seg = null;
$this_1.angleStart = 0;
$this_1.angleStop = 0;
function update$0() {
}
$p.addMethod($this_1, 'update', update$0, false);
function draw$0() {
var radius = $this_1.seg.donut.radius;
$p.stroke(255, 255, 255, 100);
$p.strokeWeight(1);
$p.line($this_1.seg.donut.x+$p.cos($this_1.angleStop)*(radius-$this_1.seg.relativeBreadth()/2), $this_1.seg.donut.y+$p.sin($this_1.angleStop)*(radius-$this_1.seg.relativeBreadth()/2), $this_1.seg.donut.x+$p.cos($this_1.angleStop)*(radius+$this_1.seg.relativeBreadth()/2), $this_1.seg.donut.y+$p.sin($this_1.angleStop)*(radius+$this_1.seg.relativeBreadth()/2));
if ($this_1.hovering) {
curContext.lineCap = "butt"; $p.noFill();
$p.stroke(0, 0, 0, 20);
$p.strokeWeight($this_1.seg.relativeBreadth());
$p.arc($this_1.seg.donut.x, $this_1.seg.donut.y, $this_1.seg.donut.radius*2, $this_1.seg.donut.radius*2, $this_1.angleStart, $this_1.angleStop);
}
$p.noStroke();
$p.strokeWeight(0);
if ($this_1.seg.donut.selectedSegment==$this_1.seg && !$this_1.seg.fan.isPlaying() && $this_1.seg.donut.selectedSlice.hovering) {
var theta = (($this_1.angleStart+$this_1.angleStop) / 2) % $p.TWO_PI+0.05;
var angle = theta;
curContext.textAlign = "left";
if (theta > $p.PI/2 && theta < ($p.PI+$p.PI/2)-0.05) {
fWidth = curContext.measureText($this_1.subject.getName()).width;
angle -= 0.05;
}
else
fWidth = 0;
$p.pushMatrix();
$p.translate($this_1.seg.donut.x, $this_1.seg.donut.y);
$p.rotate(angle);
$p.pushMatrix();
$p.translate($this_1.seg.donut.radius+50+fWidth, 0);
if ($this_1.hovering)
$p.fill(HIGHLIGHTED_LABEL_COLOR);
else
$p.fill(LABEL_COLOR);
$p.pushMatrix();
if (theta > $p.PI/2 && theta < ($p.PI+$p.PI/2)-0.05) {
$p.rotate($p.PI);
}
curContext.fillText($this_1.subject.getName(), 0, 0);
$p.popMatrix();
$p.popMatrix();
$p.popMatrix();
}
}
$p.addMethod($this_1, 'draw', draw$0, false);
function checkSelected$0() {
var disX = $p.mouseX - $this_1.seg.donut.x;
var disY = $p.mouseY - $this_1.seg.donut.y;
var r = Math.sqrt($p.sq(disX)+$p.sq(disY));
var angle = $p.atan2(disY, disX);
if (angle<0) angle = $p.TWO_PI+angle;
var start = $this_1.angleStart % $p.TWO_PI;
var stop = $this_1.angleStop % $p.TWO_PI;
if (r >= $this_1.seg.donut.radius-$this_1.seg.relativeBreadth()/2 && r <= $this_1.seg.donut.radius+$this_1.seg.relativeBreadth()/2 &&
((angle>start && angle<stop) || (start>stop && (angle > start || angle < stop)) )) {
$this_1.seg.donut.setSelectedSlice($this_1.$self);
$this_1.subject.hovering = $this_1.hovering = true;
}
else {
$this_1.subject.hovering = $this_1.hovering = false;
}
if ($this_1.seg.donut.totalSlices()==1) {
$this_1.seg.donut.setSelectedSlice($this_1.$self);
$this_1.subject.hovering = $this_1.hovering = true;
}
return $this_1.subject.hovering;
}
$p.addMethod($this_1, 'checkSelected', checkSelected$0, false);
function $constr_2(subject, seg){
$superCstr();
$this_1.hovering = false;
$this_1.subject = subject;
$this_1.seg = seg;
}
function $constr() {
if(arguments.length === 2) { $constr_2.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return DonutSlice;
})();
$p.DonutSlice = DonutSlice;
var Edge = (function() {
function Edge() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.hovering = false;
$this_1.from = null;
$this_1.to = null;
$this_1.subject = null;
$this_1.radius = 0;
$this_1.x1 = 0;
$this_1.x2 = 0;
$this_1.y1 = 0;
$this_1.y2 = 0;
function getFrom$0() {
return $this_1.from;
}
$p.addMethod($this_1, 'getFrom', getFrom$0, false);
function getTo$0() {
return $this_1.to;
}
$p.addMethod($this_1, 'getTo', getTo$0, false);
function update$0() {
var ox1 = $this_1.from.getParticle().position().x;
var ox2 = $this_1.to.getParticle().position().x;
var oy1 = $this_1.from.getParticle().position().y;
var oy2 = $this_1.to.getParticle().position().y;
var wx = ox2-ox1;
var wy = oy2-oy1;
var ww = $p.sqrt(wx*wx+wy*wy);
$this_1.x1 = ox1+wx*(($this_1.from.getSubject().currentRadius()-10)/ww);
$this_1.y1 = oy1+wy*(($this_1.from.getSubject().currentRadius()-10)/ww);
$this_1.x2 = ox2-wx*(($this_1.to.getSubject().currentRadius()+5)/ww);
$this_1.y2 = oy2-wy*(($this_1.to.getSubject().currentRadius()+5)/ww);
}
$p.addMethod($this_1, 'update', update$0, false);
function draw$0() {
$p.stroke(255);
if ($this_1.hovering)
$p.fill(255);
else
$p.fill($this_1.subject.col);
$p.strokeWeight(4);
if ($this_1.subject.subject.getName()[0] == "O")
arrow($this_1.x1, $this_1.y1, $this_1.x2, $this_1.y2, 7); else
arrow($this_1.x2, $this_1.y2, $this_1.x1, $this_1.y1, 17);
$p.ellipse($this_1.$self.centerX(), $this_1.$self.centerY(), 20, 20);
$p.textFont(defaultFont, 13);
$p.fill(255);
$p.text($this_1.subject.subject.getName()[0], $this_1.$self.centerX()-3, $this_1.$self.centerY()-8);
$p.textFont(defaultFont, fontSize);
}
$p.addMethod($this_1, 'draw', draw$0, false);
function drawLabel$0() {
$p.textFont(defaultFont, 13);
$p.fill(255);
$p.noStroke();
$p.rect($this_1.$self.centerX()-3, $this_1.$self.centerY()-12, 200, 24);
$p.fill(100);
$p.text($this_1.subject.subject.getName(), $this_1.$self.centerX()-3, $this_1.$self.centerY()-8);
$p.textFont(defaultFont, fontSize);
}
$p.addMethod($this_1, 'drawLabel', drawLabel$0, false);
function centerX$0() {
return $this_1.x1 + 0.5*($this_1.x2-$this_1.x1);
}
$p.addMethod($this_1, 'centerX', centerX$0, false);
function centerY$0() {
return $this_1.y1 + 0.5*($this_1.y2-$this_1.y1);
}
$p.addMethod($this_1, 'centerY', centerY$0, false);
function mouseOver$0() {
var disX = $this_1.$self.centerX() - $p.mouseX;
var disY = $this_1.$self.centerY() - $p.mouseY;
if ($p.sqrt($p.sq(disX) + $p.sq(disY)) < $this_1.radius/2 ) {
$this_1.hovering = true;
return true;
}
else {
$this_1.hovering = false;
return false;
}
}
$p.addMethod($this_1, 'mouseOver', mouseOver$0, false);
function $constr_3(from, to, subject){
$superCstr();
$this_1.hovering = false;
$this_1.from = from;
$this_1.to = to;
$this_1.subject = subject;
$this_1.radius = 30;
$this_1.x1 = 0;
$this_1.x2 = 0;
$this_1.y1 = 0;
$this_1.y2 = 0;
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Edge;
})();
$p.Edge = Edge;
var EulerIntegrator = (function() {
function EulerIntegrator() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.s = null;
function step$1(t) {
$this_1.s.clearForces();
$this_1.s.applyForces();
for (var i = 0; i < $this_1.s.numberOfParticles(); i++ )
{
var p = $this_1.s.getParticle( i );
if ( p.isFree() )
{
p.velocity().add( p.force().x/(p.mass()*t), p.force().y/(p.mass()*t), p.force().z/(p.mass()*t) );
p.position().add( p.velocity().x/t, p.velocity().y/t, p.velocity().z/t );
}
}
}
$p.addMethod($this_1, 'step', step$1, false);
function $constr_1(s){
$superCstr();
$this_1.s = s;
}
function $constr() {
if(arguments.length === 1) { $constr_1.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return EulerIntegrator;
})();
$p.EulerIntegrator = EulerIntegrator;
var Graph = (function() {
function Graph() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.nodes = null;
$this_1.edges = null;
$this_1.ps = null;
$this_1.selectedNode = null;
$this_1.dragging = false;
$this_1.dragNode = null;
$this_1.EDGE_LENGTH = 300;
$this_1.EDGE_STRENGTH = 0.5;
$this_1.SPACER_STRENGTH = 1000;
function getNodeById$1(id) {
var i = 0;
var n = null;
while (i < g.nodes.size ()) {
if ($this_1.nodes[i].subject.id==id)
return $this_1.nodes[i];
i++;
}
return null;
}
$p.addMethod($this_1, 'getNodeById', getNodeById$1, false);
function selectNode$1(n) {
$this_1.selectedNode.subject.setClosed();
$this_1.selectedNode = n;
$("aside").html($this_1.selectedNode.getSubject().html);
$this_1.selectedNode.subject.setOpen();
$this_1.dragging = true;
}
$p.addMethod($this_1, 'selectNode', selectNode$1, false);
function setSelectedNode$1(sNode) {
$this_1.selectedNode = sNode;
}
$p.addMethod($this_1, 'setSelectedNode', setSelectedNode$1, false);
function getSelectedNode$0() {
return $this_1.selectedNode;
}
$p.addMethod($this_1, 'getSelectedNode', getSelectedNode$0, false);
function setDragNode$1(n) {
if ($this_1.dragNode != null) {
$this_1.dragNode.setDragging(false);
}
$this_1.dragNode = n;
if (n != null)
n.setDragging(true);
}
$p.addMethod($this_1, 'setDragNode', setDragNode$1, false);
function getDragNode$0() {
return $this_1.dragNode;
}
$p.addMethod($this_1, 'getDragNode', getDragNode$0, false);
function isDragging$0() {
return ($this_1.dragNode) ? $this_1.dragging : false;
}
$p.addMethod($this_1, 'isDragging', isDragging$0, false);
function addEdge$1(e) {
var i = 0;
var found = false;
while (i < $this_1.edges.size () && !found) {
found = (($this_1.edges.get(i).getFrom() == e.getFrom() && ($this_1.edges.get(i)).getTo() == e.getTo()) || ($this_1.edges.get(i).getFrom() == e.getTo() && ($this_1.edges.get(i)).getTo() == e.getFrom()));
i++;
}
if (!found) {
$this_1.edges.add(e);
$this_1.ps.makeSpring( e.getFrom().getParticle(), e.getTo().getParticle(), $this_1.EDGE_STRENGTH, $this_1.EDGE_STRENGTH, $this_1.EDGE_LENGTH );
e.getTo().getParticle().position().set( $p.mouseX, $p.mouseY, 0 );
}
}
$p.addMethod($this_1, 'addEdge', addEdge$1, false);
function addNode$1(n) {
n.setGraph($this_1.$self);
$this_1.nodes.add(n);
for (var i = 0; i < $this_1.nodes.size(); i++ )
{
if (n!=$this_1.nodes[i])
$this_1.ps.makeAttraction( n.getParticle(), $this_1.nodes[i].getParticle(), -$this_1.SPACER_STRENGTH, 15 );
}
}
$p.addMethod($this_1, 'addNode', addNode$1, false);
function removeEdge$1(e) {
var idx = $.inArray(e, $this_1.edges);
if (idx>=0)
$this_1.edges.remove(idx);
}
$p.addMethod($this_1, 'removeEdge', removeEdge$1, false);
function removeNode$1(n) {
var springs = $this_1.ps.springs.clone();
for (var i = 0; i<springs.size(); i++) {
if (n.p == springs[i].a || n.p == springs[i].b)
$this_1.ps.removeSpring(springs[i]);
}
var attractions = $this_1.ps.attractions.clone();
for (var i = 0; i<attractions.size(); i++) {
if (n.p == attractions[i].a || n.p == attractions[i].b)
$this_1.ps.removeAttraction(attractions[i]);
}
var edgs = $this_1.edges.clone();
for (var i = 0; i<edgs.size(); i++) {
if (n == edgs[i].from || n == edgs[i].to)
$this_1.$self.removeEdge(edgs[i]);
}
$this_1.ps.removeParticle(n.p);
var idx = $.inArray(n, $this_1.nodes);
if (idx>=0)
$this_1.nodes.remove(idx);
$("#path li[id=resource_"+idx+"]").remove();
if ($this_1.nodes.size() == 0) {
console.log("TODO: there are no nodes left. clean it up!");
}
}
$p.addMethod($this_1, 'removeNode', removeNode$1, false);
function getOutgoingEdges$1(n) {
var outgoingEdges = new $p.ArrayList();
for (var i = 0; i < $this_1.edges.size(); i++) {
var e = $this_1.edges.get(i);
if (e.getFrom() == n)
outgoingEdges.add(e);
}
return outgoingEdges;
}
$p.addMethod($this_1, 'getOutgoingEdges', getOutgoingEdges$1, false);
function getIncomingEdges$1(n) {
var incomingEdges = new $p.ArrayList();
for (var i = 0; i < $this_1.edges.size(); i++) {
var e = $this_1.edges.get(i);
if (e.getTo() == n)
incomingEdges.add(e);
}
return incomingEdges;
}
$p.addMethod($this_1, 'getIncomingEdges', getIncomingEdges$1, false);
function unVisitNodes$0() {
for (var i = 0; i < $this_1.nodes.size(); i++) {
$this_1.nodes[i].setVisited(false);
}
}
$p.addMethod($this_1, 'unVisitNodes', unVisitNodes$0, false);
function depthFirstWalk$2(n, result) {
if (!result) {
result = new $p.ArrayList();
$this_1.$self.unVisitNodes();
}
if (!n.isVisited()) {
n.setVisited(true);
result.add(n);
}
var edges = n.getOutgoingEdges();
for (var i = 0; i < edges.size(); i++) {
if (!edges.get(i).getTo().isVisited())
$this_1.$self.depthFirstWalk(edges.get(i).getTo(), result);
}
return result;
}
$p.addMethod($this_1, 'depthFirstWalk', depthFirstWalk$2, false);
function tick$0() {
$this_1.ps.tick(1.0);
}
$p.addMethod($this_1, 'tick', tick$0, false);
function draw$0() {
for (var i = 0; i < $this_1.edges.size(); i++ ) {
var e = $this_1.edges.get(i);
if (e) {
e.update();
e.draw();
}
}
for (var i = 0; i < $this_1.nodes.size(); i++) {
if ($this_1.nodes[i]!=$this_1.selectedNode)
$this_1.nodes[i].draw();
}
$this_1.selectedNode.draw();
for (var i = 0; i < $this_1.edges.size(); i++ ) {
var e = $this_1.edges.get(i);
if (e && e.hovering)
e.drawLabel();
}
}
$p.addMethod($this_1, 'draw', draw$0, false);
function checkSelected$0() {
$this_1.dragNode = null;
for (var i = 0; i< g.nodes.size(); i++) {
if ($this_1.nodes[i].mouseOver() && $this_1.dragNode != $this_1.nodes[i]) {
$this_1.dragNode = $this_1.nodes[i];
$this_1.nodes[i].subject.hovering = true;
}
else {
$this_1.nodes[i].subject.hovering = false;
}
}
}
$p.addMethod($this_1, 'checkSelected', checkSelected$0, false);
function $constr_0(){
$superCstr();
$this_1.nodes = new $p.ArrayList();
$this_1.edges = new $p.ArrayList();
$this_1.dragging = false;
$this_1.ps = new ParticleSystem(0, 0, 0, 0.1);
$this_1.ps.setDrag( 0.2 );
}
function $constr() {
if(arguments.length === 0) { $constr_0.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Graph;
})();
$p.Graph = Graph;
var Attraction = (function() {
function Attraction() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.a = null;
$this_1.b = null;
$this_1.k = 0;
$this_1.on = false;
$this_1.distanceMin = 0;
$this_1.distanceMinSquared = 0;
function setA$1(p) {
$this_1.a = p;
}
$p.addMethod($this_1, 'setA', setA$1, false);
function setB$1(p) {
$this_1.b = p;
}
$p.addMethod($this_1, 'setB', setB$1, false);
function getMinimumDistance$0() {
return $this_1.distanceMin;
}
$p.addMethod($this_1, 'getMinimumDistance', getMinimumDistance$0, false);
function setMinimumDistance$1(d) {
$this_1.distanceMin = d;
$this_1.distanceMinSquared = d*d;
}
$p.addMethod($this_1, 'setMinimumDistance', setMinimumDistance$1, false);
function turnOff$0() {
$this_1.on = false;
}
$p.addMethod($this_1, 'turnOff', turnOff$0, false);
function turnOn$0() {
$this_1.on = true;
}
$p.addMethod($this_1, 'turnOn', turnOn$0, false);
function setStrength$1(k) {
$this_1.k = k;
}
$p.addMethod($this_1, 'setStrength', setStrength$1, false);
function getOneEnd$0() {
return $this_1.a;
}
$p.addMethod($this_1, 'getOneEnd', getOneEnd$0, false);
function getTheOtherEnd$0() {
return $this_1.b;
}
$p.addMethod($this_1, 'getTheOtherEnd', getTheOtherEnd$0, false);
function apply$0() {
if ( $this_1.on && ( $this_1.a.isFree() || $this_1.b.isFree() ) )
{
var a2bX = $this_1.a.position().x - $this_1.b.position().x;
var a2bY = $this_1.a.position().y - $this_1.b.position().y;
var a2bZ = $this_1.a.position().z - $this_1.b.position().z;
var a2bDistanceSquared = a2bX*a2bX + a2bY*a2bY + a2bZ*a2bZ;
if ( a2bDistanceSquared < $this_1.distanceMinSquared )
a2bDistanceSquared = $this_1.distanceMinSquared;
var force = $this_1.k * $this_1.a.mass() * $this_1.b.mass() / a2bDistanceSquared;
var length = Math.sqrt( a2bDistanceSquared );
a2bX /= length;
a2bY /= length;
a2bZ /= length;
a2bX *= force;
a2bY *= force;
a2bZ *= force;
if ( $this_1.a.isFree() )
$this_1.a.force().add( -a2bX, -a2bY, -a2bZ );
if ( $this_1.b.isFree() )
$this_1.b.force().add( a2bX, a2bY, a2bZ );
}
}
$p.addMethod($this_1, 'apply', apply$0, false);
function getStrength$0() {
return $this_1.k;
}
$p.addMethod($this_1, 'getStrength', getStrength$0, false);
function isOn$0() {
return $this_1.on;
}
$p.addMethod($this_1, 'isOn', isOn$0, false);
function isOff$0() {
return !$this_1.on;
}
$p.addMethod($this_1, 'isOff', isOff$0, false);
function $constr_4(a, b, k, distanceMin){
$superCstr();
$this_1.a = a;
$this_1.b = b;
$this_1.k = k;
$this_1.on = true;
$this_1.distanceMin = distanceMin;
$this_1.distanceMinSquared = distanceMin*distanceMin;
}
function $constr() {
if(arguments.length === 4) { $constr_4.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Attraction;
})();
$p.Attraction = Attraction;
var Node = (function() {
function Node() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.g = null;
$this_1.visited = false;
$this_1.hovering = false;
$this_1.dragging = false;
$this_1.p = null;
$this_1.ps = null;
function setGraph$1(g) {
$this_1.g = g;
$this_1.ps = g.ps;
$this_1.p = $this_1.ps.makeParticle(1.0, window.innerWidth/2+150, window.innerHeight/2, 0);
}
$p.addMethod($this_1, 'setGraph', setGraph$1, false);
function getSubject$0() {
return $this_1.subject;
}
$p.addMethod($this_1, 'getSubject', getSubject$0, false);
function getId$0() {
return subject.getId;
}
$p.addMethod($this_1, 'getId', getId$0, false);
function getName$0() {
return subject.getName();
}
$p.addMethod($this_1, 'getName', getName$0, false);
function isVisited$0() {
return $this_1.visited;
}
$p.addMethod($this_1, 'isVisited', isVisited$0, false);
function getGraph$0() {
return $this_1.g;
}
$p.addMethod($this_1, 'getGraph', getGraph$0, false);
function getOutgoingEdges$0() {
return $this_1.g.getOutgoingEdges($this_1.$self);
}
$p.addMethod($this_1, 'getOutgoingEdges', getOutgoingEdges$0, false);
function getIncomingEdges$0() {
return $this_1.g.getIncomingEdges($this_1.$self);
}
$p.addMethod($this_1, 'getIncomingEdges', getIncomingEdges$0, false);
function getEdges$0() {
}
$p.addMethod($this_1, 'getEdges', getEdges$0, false);
function getParticle$0() {
return $this_1.p;
}
$p.addMethod($this_1, 'getParticle', getParticle$0, false);
function setPos$2(x, y) {
$this_1.p.position().set(x, y, 0);
}
$p.addMethod($this_1, 'setPos', setPos$2, false);
function draw$0() {
subject.setPos($this_1.p.position().x, $this_1.p.position().y);
subject.update();
subject.draw();
}
$p.addMethod($this_1, 'draw', draw$0, false);
function mouseOver$0() {
return subject.mouseOver();
}
$p.addMethod($this_1, 'mouseOver', mouseOver$0, false);
public setVisited"B754" "A755"
public setDragging"B758" "A759"
public isDragging"B760" "A761"function $constr_1(subject){
$superCstr();
$this_1.subject = subject;
}
function $constr() {
if(arguments.length === 1) { $constr_1.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Node;
})();
$p.Node = Node;
var Particle = (function() {
function Particle() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.myPosition = null;
$this_1.myVelocity = null;
$this_1.myForce = null;
$this_1.myMass = 0;
$this_1.age = 0;
$this_1.dead = false;
$this_1.fixed = false;
function distanceTo$1(p) {
return $this_1.$self.position().distanceTo( p.position() );
}
$p.addMethod($this_1, 'distanceTo', distanceTo$1, false);
function makeFixed$0() {
$this_1.fixed = true;
$this_1.myVelocity.clear();
}
$p.addMethod($this_1, 'makeFixed', makeFixed$0, false);
function isFixed$0() {
return $this_1.fixed;
}
$p.addMethod($this_1, 'isFixed', isFixed$0, false);
function isFree$0() {
return !$this_1.fixed;
}
$p.addMethod($this_1, 'isFree', isFree$0, false);
function makeFree$0() {
$this_1.fixed = false;
}
$p.addMethod($this_1, 'makeFree', makeFree$0, false);
function position$0() {
return $this_1.myPosition;
}
$p.addMethod($this_1, 'position', position$0, false);
function velocity$0() {
return $this_1.myVelocity;
}
$p.addMethod($this_1, 'velocity', velocity$0, false);
function mass$0() {
return $this_1.myMass;
}
$p.addMethod($this_1, 'mass', mass$0, false);
function setMass$1(m) {
$this_1.myMass = m;
}
$p.addMethod($this_1, 'setMass', setMass$1, false);
function force$0() {
return $this_1.myForce;
}
$p.addMethod($this_1, 'force', force$0, false);
function reset$0() {
$this_1.age = 0;
$this_1.dead = false;
$this_1.$self.position.clear();
$this_1.myVelocity.clear();
$this_1.myForce.clear();
$this_1.myMass = 1;
}
$p.addMethod($this_1, 'reset', reset$0, false);
function $constr_1(m){
$superCstr();
$this_1.myPosition = new Vector3D(0, 0, 0);
$this_1.myVelocity = new Vector3D(0, 0, 0);
$this_1.myForce = new Vector3D(0, 0, 0);
$this_1.myMass = m;
$this_1.age = 0;
$this_1.fixed = false;
$this_1.dead = false;
}
function $constr() {
if(arguments.length === 1) { $constr_1.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Particle;
})();
$p.Particle = Particle;
var ParticleSystem = (function() {
function ParticleSystem() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$p.defineProperty($this_1, 'RUNGE_KUTTA', {get: function(){return ParticleSystem.RUNGE_KUTTA}, set: function(val){ParticleSystem.RUNGE_KUTTA = val}});
$p.defineProperty($this_1, 'MODIFIED_EULER', {get: function(){return ParticleSystem.MODIFIED_EULER}, set: function(val){ParticleSystem.MODIFIED_EULER = val}});
$p.defineProperty($this_1, 'DEFAULT_GRAVITY', {get: function(){return ParticleSystem.DEFAULT_GRAVITY}, set: function(val){ParticleSystem.DEFAULT_GRAVITY = val}});
$p.defineProperty($this_1, 'DEFAULT_DRAG', {get: function(){return ParticleSystem.DEFAULT_DRAG}, set: function(val){ParticleSystem.DEFAULT_DRAG = val}});
$this_1.particles = null;
$this_1.springs = null;
$this_1.attractions = null;
$this_1.customForces = null;
$this_1.integrator = null;
$this_1.gravity = null;
$this_1.drag = 0;
$this_1.hasDeadParticles = false;
function setIntegrator$1(integrator) {
switch ( integrator )
{
case ParticleSystem.RUNGE_KUTTA:
$this_1.integrator = new RungeKuttaIntegrator( $this_1.$self );
break;case ParticleSystem.MODIFIED_EULER:
$this_1.integrator = new ModifiedEulerIntegrator( $this_1.$self );
break;
}
}
$p.addMethod($this_1, 'setIntegrator', setIntegrator$1, false);
function setGravity$3(x, y, z) {
$this_1.gravity.set( x, y, z );
}
$p.addMethod($this_1, 'setGravity', setGravity$3, false);
function setDrag$1(d) {
$this_1.drag = d;
}
$p.addMethod($this_1, 'setDrag', setDrag$1, false);
function tick$1(t) {
$this_1.integrator.step( t );
}
$p.addMethod($this_1, 'tick', tick$1, false);
function tickOnce$0() {
$this_1.integrator.step( 1.0 );
}
$p.addMethod($this_1, 'tickOnce', tickOnce$0, false);
function makeParticle$4(mass, x, y, z) {
var p = new Particle( mass );
p.position().set( x, y, z );
$this_1.particles.add( p );
return p;
}
$p.addMethod($this_1, 'makeParticle', makeParticle$4, false);
function makeSpring$5(a, b, ks, d, r) {
var s = new Spring( a, b, ks, d, r );
$this_1.springs.add( s );
return s;
}
$p.addMethod($this_1, 'makeSpring', makeSpring$5, false);
function makeAttraction$4(a, b, k, minDistance) {
var m = new Attraction( a, b, k, minDistance );
$this_1.attractions.add( m );
return m;
}
$p.addMethod($this_1, 'makeAttraction', makeAttraction$4, false);
function clear$0() {
$this_1.particles.clear();
$this_1.springs.clear();
$this_1.attractions.clear();
}
$p.addMethod($this_1, 'clear', clear$0, false);
function applyForces$0() {
if ( !$this_1.gravity.isZero() )
{
for (var i = 0; i < $this_1.particles.size(); ++i )
{
var p = $this_1.particles.get( i );
p.force().add( $this_1.gravity );
}
}
for (var i = 0; i < $this_1.particles.size(); ++i )
{
var p = $this_1.particles.get( i );
xx = p.force().add( p.velocity().x * -$this_1.drag, p.velocity().y * -$this_1.drag, p.velocity().z * -$this_1.drag );
}
for (var i = 0; i < $this_1.springs.size(); i++ )
{
var f = $this_1.springs.get( i );
f.apply();
}
for (var i = 0; i < $this_1.attractions.size(); i++ )
{
var f = $this_1.attractions.get( i );
f.apply();
}
for (var i = 0; i < $this_1.customForces.size(); i++ )
{
var f = $this_1.customForces.get( i );
f.apply();
}
}
$p.addMethod($this_1, 'applyForces', applyForces$0, false);
function clearForces$0() {
for (var i = 0; i < $this_1.particles.size(); i++ ) {
var p = $this_1.particles.get( i );
p.force().clear();
}
}
$p.addMethod($this_1, 'clearForces', clearForces$0, false);
function numberOfParticles$0() {
return $this_1.particles.size();
}
$p.addMethod($this_1, 'numberOfParticles', numberOfParticles$0, false);
function numberOfSprings$0() {
return $this_1.springs.size();
}
$p.addMethod($this_1, 'numberOfSprings', numberOfSprings$0, false);
function numberOfAttractions$0() {
return $this_1.attractions.size();
}
$p.addMethod($this_1, 'numberOfAttractions', numberOfAttractions$0, false);
function getParticle$1(i) {
return $this_1.particles.get( i );
}
$p.addMethod($this_1, 'getParticle', getParticle$1, false);
function getSpring$1(i) {
return $this_1.springs.get( i );
}
$p.addMethod($this_1, 'getSpring', getSpring$1, false);
function getAttraction$1(i) {
return $this_1.attractions.get( i );
}
$p.addMethod($this_1, 'getAttraction', getAttraction$1, false);
function addCustomForce$1(f) {
$this_1.customForces.add( f );
}
$p.addMethod($this_1, 'addCustomForce', addCustomForce$1, false);
function numberOfCustomForces$0() {
return $this_1.customForces.size();
}
$p.addMethod($this_1, 'numberOfCustomForces', numberOfCustomForces$0, false);
function getCustomForce$1(i) {
return $this_1.customForces.get( i );
}
$p.addMethod($this_1, 'getCustomForce', getCustomForce$1, false);
function removeCustomForce$1(i) {
return $this_1.customForces.remove( i );
}
$p.addMethod($this_1, 'removeCustomForce', removeCustomForce$1, false);
function removeParticle$1(p) {
var idx = $.inArray(p, $this_1.particles);
if (idx>=0)
$this_1.particles.remove(idx);
}
$p.addMethod($this_1, 'removeParticle', removeParticle$1, false);
function removeAttraction$1(a) {
var idx = $.inArray(a, $this_1.attractions);
if (idx>=0)
$this_1.attractions.remove(idx);
}
$p.addMethod($this_1, 'removeAttraction', removeAttraction$1, false);
function removeSpring$1(s) {
var idx = $.inArray(s, $this_1.springs);
if (idx>=0)
$this_1.springs.remove(idx);
}
$p.addMethod($this_1, 'removeSpring', removeSpring$1, false);
function removeCustomForce$1_2(f) {
$this_1.customForces.remove( f );
}
$p.addMethod($this_1, 'removeCustomForce', removeCustomForce$1_2, false);
function $constr_4(gx, gy, gz, somedrag){
$superCstr();
$this_1.customForces = new $p.ArrayList();
$this_1.integrator = new RungeKuttaIntegrator( $this_1.$self );
$this_1.particles = new $p.ArrayList();
$this_1.springs = new $p.ArrayList();
$this_1.attractions = new $p.ArrayList();
$this_1.gravity = new Vector3D( gx, gy, gz );
$this_1.drag = somedrag;
}
function $constr() {
if(arguments.length === 4) { $constr_4.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
ParticleSystem.RUNGE_KUTTA = 0;
ParticleSystem.MODIFIED_EULER = 1;
ParticleSystem.DEFAULT_GRAVITY = 0;
ParticleSystem.DEFAULT_DRAG = 0.001;
return ParticleSystem;
})();
$p.ParticleSystem = ParticleSystem;
var Resource = (function() {
function Resource() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.hovering = false;
$this_1.dragging = false;
$this_1.loading = true;
$this_1.resize = null;
$this_1.donut = null;
$this_1.state = "open";
$this_1.loading = true;
$this_1.selectedAttribute = null;
$this_1.previousSelectedAttribute = null;
$this_1.open = true;
$this_1.numValues = 0;
$this_1.idx = 0;
$this_1.x = 0;
$this_1.y = 0;
$this_1.attributes = null;
$this_1.radius = RADIUS_CLOSED;
$this_1.angle = 0;
$this_1.id = "";
$this_1.name = "";
$this_1.html = "";
$this_1.NUM_LOADING_SEGMENTS = 11;
$this_1.progress = 0;
function fetchData$0() {
var json = null;
var that = $this_1.$self;
$this_1.loading = true;
}
$p.addMethod($this_1, 'fetchData', fetchData$0, false);
function setPos$2(x, y) {
$this_1.x = x; $this_1.y = y;
$this_1.donut.x = x;
$this_1.donut.y = y;
}
$p.addMethod($this_1, 'setPos', setPos$2, false);
function getSelectedAttribute$0() {
if (!$this_1.donut.selectedSegment) return null;
return $this_1.donut.selectedSegment.subject;
}
$p.addMethod($this_1, 'getSelectedAttribute', getSelectedAttribute$0, false);
function getSelectedValue$0() {
if (!$this_1.donut.selectedSlice) return null;
return $this_1.donut.selectedSlice.subject;
}
$p.addMethod($this_1, 'getSelectedValue', getSelectedValue$0, false);
function getId$0() {
return $this_1.id;
}
$p.addMethod($this_1, 'getId', getId$0, false);
function getName$0() {
return $this_1.name;
}
$p.addMethod($this_1, 'getName', getName$0, false);
function setClosed$0() {
$this_1.state = "closed";
if ($this_1.donut.selectedSlice)
$this_1.donut.selectedSlice.hovering = false;
$this_1.donut.showLabels = false;
$this_1.resize.continueTo(RADIUS_CLOSED, 1);
}
$p.addMethod($this_1, 'setClosed', setClosed$0, false);
function setOpen$0() {
if ($this_1.state != "open") {
$this_1.state = "open";
Attributes.init($this_1.donut);
Attributes.select($this_1.donut.selectedSegment);
$this_1.resize.continueTo(RADIUS_OPENED, 1);
}
}
$p.addMethod($this_1, 'setOpen', setOpen$0, false);
function setState$1(thestate) {
$this_1.state = thestate;
}
$p.addMethod($this_1, 'setState', setState$1, false);
function getType$0() {
return $this_1.type;
}
$p.addMethod($this_1, 'getType', getType$0, false);
function setNumValues$1(numValues) {
$this_1.numValues = numValues;
}
$p.addMethod($this_1, 'setNumValues', setNumValues$1, false);
function setHovering$1(b) {
$this_1.hovering = b;
}
$p.addMethod($this_1, 'setHovering', setHovering$1, false);
function isHovering$0() {
return $this_1.hovering && (!$this_1.donut.selectedSlice || !$this_1.donut.selectedSlice.hovering);
}
$p.addMethod($this_1, 'isHovering', isHovering$0, false);
function setDragging$1(b) {
$this_1.dragging = b;
}
$p.addMethod($this_1, 'setDragging', setDragging$1, false);
function isDragging$0() {
return $this_1.dragging;
}
$p.addMethod($this_1, 'isDragging', isDragging$0, false);
function addAttribute$1(attr) {
$this_1.attributes.add(attr);
}
$p.addMethod($this_1, 'addAttribute', addAttribute$1, false);
function setSelectedAttribute$1(attrId) {
var s = null;
for (var i = 0; i<$this_1.donut.segments.size(); i++) {
if ($this_1.donut.segments[i].subject.id == attrId)
s = $this_1.donut.segments[i];
}
if (s) {
$this_1.donut.setSelectedSlice(s.slices[0]);
}
}
$p.addMethod($this_1, 'setSelectedAttribute', setSelectedAttribute$1, false);
function vvvvmod$2(a, b) {
var res = a % b;
return (res>=0) ? res : 100 + res;
}
$p.addMethod($this_1, 'vvvvmod', vvvvmod$2, false);
function d1$1(i) {
return $this_1.$self.vvvvmod(($this_1.progress-(100/$this_1.NUM_LOADING_SEGMENTS)*i), 100);
}
$p.addMethod($this_1, 'd1', d1$1, false);
function d2$1(i) {
return $this_1.$self.vvvvmod(((100/$this_1.NUM_LOADING_SEGMENTS)*i-$this_1.progress), 100);
}
$p.addMethod($this_1, 'd2', d2$1, false);
function alpha$1(i) {
var a = $p.max(-(1/25)*($this_1.$self.d1(i))+1, -(1/25)*($this_1.$self.d2(i))+1);
return $p.max(a, 0.1);
}
$p.addMethod($this_1, 'alpha', alpha$1, false);
function update$0() {
$this_1.progress = ($this_1.progress+3) % 100;
$this_1.resize.tick(); $this_1.donut.update();
}
$p.addMethod($this_1, 'update', update$0, false);
function draw$0() {
$p.noStroke();
if ($this_1.loading) {
$p.fill(255);
$p.ellipse($this_1.x, $this_1.y, $this_1.donut.radius*2+35, $this_1.donut.radius*2+35);
var angle = 0;
$p.noFill();
$p.stroke(DONUT_BACKGROUND);
for (var i = 0; i<$this_1.NUM_LOADING_SEGMENTS; i++) {
curContext.lineCap = "butt"; $p.stroke(colors[i*2 % 11]);
curContext.globalAlpha = $this_1.$self.alpha(i);
$p.strokeWeight(25);
var angleStart = angle;
angle += $p.TWO_PI/$this_1.NUM_LOADING_SEGMENTS;
$p.arc($this_1.donut.x, $this_1.donut.y, $this_1.donut.radius*2, $this_1.donut.radius*2, angleStart, angle);
}
curContext.globalAlpha = 0.6;
for (var i = 0; i<$this_1.NUM_LOADING_SEGMENTS; i++) {
angle += $p.TWO_PI/$this_1.NUM_LOADING_SEGMENTS;
$p.stroke(255);
$p.strokeWeight(1);
$p.line($this_1.x, $this_1.y, $this_1.x+$p.cos(angle)*($this_1.donut.radius+15), $this_1.y+$p.sin(angle)*($this_1.donut.radius+15));
}
curContext.globalAlpha = 1.0;
}
else {
if ($this_1.$self == g.selectedNode.subject)
$this_1.donut.alpha = 1.0;
else if ($this_1.hovering) {
$this_1.donut.alpha = 0.7;
}
else {
$this_1.donut.alpha = 0.5;
}
$p.noStroke();
$this_1.donut.draw();
}
if ($this_1.hovering)
$p.fill(0, 0, 0, 150);
else
$p.fill(66, 66, 66, 100);
$p.noStroke();
curContext.textAlign = "center";
if (!$this_1.loading && !($this_1.state=="open" && $this_1.$self.getSelectedValue().hovering)) {
$p.pushMatrix();
$p.translate(10, 0); $p.noStroke();
$p.fill(255);
curContext.font = "16px GraublauWeb";
var fWidth = curContext.measureText($this_1.$self.getName()).width+25;
var yOffset = $this_1.donut.radius+$this_1.donut.selectedSegment.relativeBreadth()/2+15;
roundedRect($this_1.x-fWidth/2, $this_1.y+yOffset, fWidth, 22, 10);
if ($this_1.state=="open")
$p.fill(73, 71, 59);
else
$p.fill(182, 187, 171);
$p.ellipse($this_1.x-fWidth/2-5, $this_1.y+yOffset+11, 30, 30);
$p.fill(33);
curContext.fillText($this_1.$self.getName(), $this_1.x+2, $this_1.y+yOffset+15);
$p.fill(255);
curContext.font = "bold 18px Century Gothic";
curContext.textBaseline = "middle";
var idxstr = ($this_1.idx<10) ? "0"+$this_1.idx : $this_1.idx;
curContext.fillText(idxstr, $this_1.x-fWidth/2-5, $this_1.y+yOffset+11);
$p.noStroke();
curContext.textBaseline = "alphabetic";
$p.popMatrix();
}
if ($this_1.donut.selectedSegment && $this_1.state != "closed")
$p.fill($this_1.donut.selectedSegment.col);
else
$p.fill(233);
}
$p.addMethod($this_1, 'draw', draw$0, false);
function checkSelected$0() {
for (var i = 0; i < $this_1.donut.segments.size(); i++) {
for (var j = 0; j < $this_1.donut.segments[i].slices.size(); j++) {
$this_1.donut.segments[i].slices[j].checkSelected();
}
}
}
$p.addMethod($this_1, 'checkSelected', checkSelected$0, false);
function currentRadius$0() {
return $this_1.donut.radius+35;
}
$p.addMethod($this_1, 'currentRadius', currentRadius$0, false);
function mouseOver$0() {
var disX = $this_1.x - $p.mouseX;
var disY = $this_1.y - $p.mouseY;
if ($p.sqrt($p.sq(disX) + $p.sq(disY)) < $this_1.donut.radius+STROKE_WEIGHT_COLLAPSED/2 ) {
$this_1.hovering = true;
return true;
}
else {
$this_1.hovering = false;
return false;
}
}
$p.addMethod($this_1, 'mouseOver', mouseOver$0, false);
function $constr_3(id, name, html){
$superCstr();
var that = $this_1.$self;
$this_1.attributes = new $p.ArrayList();
$this_1.id = id;
$this_1.name = name;
$this_1.html = html;
$this_1.donut = new Donut(275, 275, RADIUS_CLOSED); $this_1.donut.segmentChanged = Attributes.select($this_1.selectedSegment);
$this_1.resize = new Tween($this_1.donut, "radius", Tween.strongEaseInOut, RADIUS_CLOSED, RADIUS_OPENED, 1);
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Resource;
})();
$p.Resource = Resource;
var RungeKuttaIntegrator = (function() {
function RungeKuttaIntegrator() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.originalPositions = null;
$this_1.originalVelocities = null;
$this_1.k1Forces = null;
$this_1.k1Velocities = null;
$this_1.k2Forces = null;
$this_1.k2Velocities = null;
$this_1.k3Forces = null;
$this_1.k3Velocities = null;
$this_1.k4Forces = null;
$this_1.k4Velocities = null;
$this_1.s = null;
function allocateParticles$0() {
while ( $this_1.s.particles.size () > $this_1.originalPositions.size() )
{
$this_1.originalPositions.add( new Vector3D() );
$this_1.originalVelocities.add( new Vector3D() );
$this_1.k1Forces.add( new Vector3D() );
$this_1.k1Velocities.add( new Vector3D() );
$this_1.k2Forces.add( new Vector3D() );
$this_1.k2Velocities.add( new Vector3D() );
$this_1.k3Forces.add( new Vector3D() );
$this_1.k3Velocities.add( new Vector3D() );
$this_1.k4Forces.add( new Vector3D() );
$this_1.k4Velocities.add( new Vector3D() );
}
}
$p.addMethod($this_1, 'allocateParticles', allocateParticles$0, false);
function step$1(deltaT) {
$this_1.$self.allocateParticles();
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
($this_1.originalPositions.get( i )).set( p.position() );
($this_1.originalVelocities.get( i )).set( p.velocity() );
}
p.force().clear();
}
$this_1.s.applyForces();
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
($this_1.k1Forces.get( i )).set( p.force() );
($this_1.k1Velocities.get( i )).set( p.velocity() );
}
p.force().clear();
}
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
var originalPosition = $this_1.originalPositions.get( i );
var k1Velocity = $this_1.k1Velocities.get( i );
p.position().x = originalPosition.x + k1Velocity.x * 0.5 * deltaT;
p.position().y = originalPosition.y + k1Velocity.y * 0.5 * deltaT;
p.position().z = originalPosition.z + k1Velocity.z * 0.5 * deltaT;
var originalVelocity = $this_1.originalVelocities.get( i );
var k1Force = $this_1.k1Forces.get( i );
p.velocity().x = originalVelocity.x + k1Force.x * 0.5 * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k1Force.y * 0.5 * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k1Force.z * 0.5 * deltaT / p.mass();
}
}
return
$this_1.s.applyForces();
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
($this_1.k2Forces.get( i )).set( p.force() );
($this_1.k2Velocities.get( i )).set( p.velocity() );
}
p.force().clear();
}
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
var originalPosition = $this_1.originalPositions.get( i );
var k2Velocity = $this_1.k2Velocities.get( i );
p.position().x = originalPosition.x + k2Velocity.x * 0.5 * deltaT;
p.position().y = originalPosition.y + k2Velocity.y * 0.5 * deltaT;
p.position().z = originalPosition.z + k2Velocity.z * 0.5 * deltaT;
var originalVelocity = $this_1.originalVelocities.get( i );
var k2Force = $this_1.k2Forces.get( i );
p.velocity().x = originalVelocity.x + k2Force.x * 0.5 * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k2Force.y * 0.5 * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k2Force.z * 0.5 * deltaT / p.mass();
}
}
$this_1.s.applyForces();
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
($this_1.k3Forces.get( i )).set( p.force() );
($this_1.k3Velocities.get( i )).set( p.velocity() );
}
p.force().clear();
}
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
var originalPosition = $this_1.originalPositions.get( i );
var k3Velocity = $this_1.k3Velocities.get( i );
p.position().x = originalPosition.x + k3Velocity.x * deltaT;
p.position().y = originalPosition.y + k3Velocity.y * deltaT;
p.position().z = originalPosition.z + k3Velocity.z * deltaT;
var originalVelocity = $this_1.originalVelocities.get( i );
var k3Force = $this_1.k3Forces.get( i );
p.velocity().x = originalVelocity.x + k3Force.x * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k3Force.y * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k3Force.z * deltaT / p.mass();
}
}
$this_1.s.applyForces();
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
if ( p.isFree() )
{
($this_1.k4Forces.get( i )).set( p.force() );
($this_1.k4Velocities.get( i )).set( p.velocity() );
}
}
for (var i = 0; i < $this_1.s.particles.size(); ++i )
{
var p = $this_1.s.particles.get( i );
p.age += deltaT;
if ( p.isFree() )
{
var originalPosition = $this_1.originalPositions.get( i );
var k1Velocity = $this_1.k1Velocities.get( i );
var k2Velocity = $this_1.k2Velocities.get( i );
var k3Velocity = $this_1.k3Velocities.get( i );
var k4Velocity = $this_1.k4Velocities.get( i );
p.position().x = originalPosition.x + deltaT / 6.0 * ( k1Velocity.x + 2.0*k2Velocity.x + 2.0*k3Velocity.x + k4Velocity.x );
p.position().y = originalPosition.y + deltaT / 6.0 * ( k1Velocity.y + 2.0*k2Velocity.y + 2.0*k3Velocity.y + k4Velocity.y );
p.position().z = originalPosition.z + deltaT / 6.0 * ( k1Velocity.z + 2.0*k2Velocity.z + 2.0*k3Velocity.z + k4Velocity.z );
var originalVelocity = $this_1.originalVelocities.get( i );
var k1Force = $this_1.k1Forces.get( i );
var k2Force = $this_1.k2Forces.get( i );
var k3Force = $this_1.k3Forces.get( i );
var k4Force = $this_1.k4Forces.get( i );
p.velocity().x = originalVelocity.x + deltaT / ( 6.0 * p.mass() ) * ( k1Force.x + 2.0*k2Force.x + 2.0*k3Force.x + k4Force.x );
p.velocity().y = originalVelocity.y + deltaT / ( 6.0 * p.mass() ) * ( k1Force.y + 2.0*k2Force.y + 2.0*k3Force.y + k4Force.y );
p.velocity().z = originalVelocity.z + deltaT / ( 6.0 * p.mass() ) * ( k1Force.z + 2.0*k2Force.z + 2.0*k3Force.z + k4Force.z );
}
}
}
$p.addMethod($this_1, 'step', step$1, false);
function $constr_1(s){
$superCstr();
$this_1.s = s;
$this_1.originalPositions = new $p.ArrayList();
$this_1.originalVelocities = new $p.ArrayList();
$this_1.k1Forces = new $p.ArrayList();
$this_1.k1Velocities = new $p.ArrayList();
$this_1.k2Forces = new $p.ArrayList();
$this_1.k2Velocities = new $p.ArrayList();
$this_1.k3Forces = new $p.ArrayList();
$this_1.k3Velocities = new $p.ArrayList();
$this_1.k4Forces = new $p.ArrayList();
$this_1.k4Velocities = new $p.ArrayList();
}
function $constr() {
if(arguments.length === 1) { $constr_1.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return RungeKuttaIntegrator;
})();
$p.RungeKuttaIntegrator = RungeKuttaIntegrator;
var Spring = (function() {
function Spring() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.springConstant = 0;
$this_1.myDamping = 0;
$this_1.myRestLength = 0;
$this_1.a = null;
$this_1.b = null;
$this_1.on = false;
function turnOff$0() {
$this_1.on = false;
}
$p.addMethod($this_1, 'turnOff', turnOff$0, false);
function turnOn$0() {
$this_1.on = true;
}
$p.addMethod($this_1, 'turnOn', turnOn$0, false);
function isOn$0() {
return $this_1.on;
}
$p.addMethod($this_1, 'isOn', isOn$0, false);
function isOff$0() {
return !$this_1.on;
}
$p.addMethod($this_1, 'isOff', isOff$0, false);
function getOneEnd$0() {
return $this_1.a;
}
$p.addMethod($this_1, 'getOneEnd', getOneEnd$0, false);
function getTheOtherEnd$0() {
return $this_1.b;
}
$p.addMethod($this_1, 'getTheOtherEnd', getTheOtherEnd$0, false);
function currentLength$0() {
return $this_1.a.position().distanceTo( $this_1.b.position() );
}
$p.addMethod($this_1, 'currentLength', currentLength$0, false);
function restLength$0() {
return $this_1.myRestLength;
}
$p.addMethod($this_1, 'restLength', restLength$0, false);
function strength$0() {
return $this_1.springConstant;
}
$p.addMethod($this_1, 'strength', strength$0, false);
function setStrength$1(ks) {
$this_1.springConstant = ks;
}
$p.addMethod($this_1, 'setStrength', setStrength$1, false);
function damping$0() {
return $this_1.myDamping;
}
$p.addMethod($this_1, 'damping', damping$0, false);
function setDamping$1(d) {
$this_1.myDamping = d;
}
$p.addMethod($this_1, 'setDamping', setDamping$1, false);
function setRestLength$1(l) {
$this_1.myRestLength = l;
}
$p.addMethod($this_1, 'setRestLength', setRestLength$1, false);
function apply$0() {
if ( $this_1.on && ( $this_1.a.isFree() || $this_1.b.isFree() ) )
{
var a2bX = $this_1.a.position().x - $this_1.b.position().x;
var a2bY = $this_1.a.position().y - $this_1.b.position().y;
var a2bZ = $this_1.a.position().z - $this_1.b.position().z;
var a2bDistance = Math.sqrt( a2bX*a2bX + a2bY*a2bY + a2bZ*a2bZ );
if ( a2bDistance == 0 )
{
a2bX = 0;
a2bY = 0;
a2bZ = 0;
}
else
{
a2bX /= a2bDistance;
a2bY /= a2bDistance;
a2bZ /= a2bDistance;
}
var springForce = -( a2bDistance - $this_1.myRestLength ) * $this_1.springConstant;
var Va2bX = $this_1.a.velocity().x - $this_1.b.velocity().x;
var Va2bY = $this_1.a.velocity().y - $this_1.b.velocity().y;
var Va2bZ = $this_1.a.velocity().z - $this_1.b.velocity().z;
var dampingForce = -$this_1.myDamping * ( a2bX*Va2bX + a2bY*Va2bY + a2bZ*Va2bZ );
var r = springForce + dampingForce;
a2bX *= r;
a2bY *= r;
a2bZ *= r;
if ( $this_1.a.isFree() )
$this_1.a.force().add( a2bX, a2bY, a2bZ );
if ( $this_1.b.isFree() )
$this_1.b.force().add( -a2bX, -a2bY, -a2bZ );
}
}
$p.addMethod($this_1, 'apply', apply$0, false);
function setA$1(p) {
$this_1.a = p;
}
$p.addMethod($this_1, 'setA', setA$1, false);
function setB$1(p) {
$this_1.b = p;
}
$p.addMethod($this_1, 'setB', setB$1, false);
function $constr_5(A, B, ks, d, r){
$superCstr();
$this_1.springConstant = ks;
$this_1.myDamping = d;
$this_1.myRestLength = r;
$this_1.a = A;
$this_1.b = B;
$this_1.on = true;
}
function $constr() {
if(arguments.length === 5) { $constr_5.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Spring;
})();
$p.Spring = Spring;
var Value = (function() {
function Value() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.id = "";
$this_1.name = "";
$this_1.html = "";
$this_1.attr = null;
$this_1.hovering = false;
function getId$0() {
return $this_1.id;
}
$p.addMethod($this_1, 'getId', getId$0, false);
function getName$0() {
return $this_1.name;
}
$p.addMethod($this_1, 'getName', getName$0, false);
function $constr_3(id, name, attr){
$superCstr();
$this_1.id = id;
$this_1.name = name;
$this_1.attr = attr;
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Value;
})();
$p.Value = Value;
var Vector3D = (function() {
function Vector3D() {
var $this_1 = this;
function $superCstr(){$p.extendClassChain($this_1)}
$this_1.x = 0;
$this_1.y = 0;
$this_1.z = 0;
function setX$1(X) {
$this_1.x = X;
}
$p.addMethod($this_1, 'setX', setX$1, false);
function setY$1(Y) {
$this_1.y = Y;
}
$p.addMethod($this_1, 'setY', setY$1, false);
function setZ$1(Z) {
$this_1.z = Z;
}
$p.addMethod($this_1, 'setZ', setZ$1, false);
function set$3(X, Y, Z) {
$this_1.x = X;
$this_1.y = Y;
$this_1.z = Z;
}
$p.addMethod($this_1, 'set', set$3, false);
function set$1_2(p) {
$this_1.x = p.x;
$this_1.y = p.y;
$this_1.z = p.z;
}
$p.addMethod($this_1, 'set', set$1_2, false);
function add$1(p) {
$this_1.x += p.x;
$this_1.y += p.y;
$this_1.z += p.z;
}
$p.addMethod($this_1, 'add', add$1, false);
function subtract$1(p) {
$this_1.x -= p.x;
$this_1.y -= p.y;
$this_1.z -= p.z;
}
$p.addMethod($this_1, 'subtract', subtract$1, false);
function add$3_2(a, b, c) {
$this_1.x += a;
$this_1.y += b;
$this_1.z += c;
}
$p.addMethod($this_1, 'add', add$3_2, false);
function subtract$3_2(a, b, c) {
$this_1.x -= a;
$this_1.y -= b;
$this_1.z -= c;
}
$p.addMethod($this_1, 'subtract', subtract$3_2, false);
function multiplyBy$1(f) {
$this_1.x *= f;
$this_1.y *= f;
$this_1.z*= f;
return $this_1.$self;
}
$p.addMethod($this_1, 'multiplyBy', multiplyBy$1, false);
function distanceTo$1(p) {
return Math.sqrt( $this_1.$self.distanceSquaredTo( p ) );
}
$p.addMethod($this_1, 'distanceTo', distanceTo$1, false);
function distanceSquaredTo$1(p) {
var dx = $this_1.x-p.x;
var dy = $this_1.y-p.y;
var dz = $this_1.z-p.z;
return dx*dx + dy*dy + dz*dz;
}
$p.addMethod($this_1, 'distanceSquaredTo', distanceSquaredTo$1, false);
function distanceTo$3_2(x, y, z) {
var dx = $this_1.x - x;
var dy = $this_1.y - y;
var dz = $this_1.z - z;
return Math.sqrt( dx*dx + dy*dy + dz*dz );
}
$p.addMethod($this_1, 'distanceTo', distanceTo$3_2, false);
function dot$1(p) {
return $this_1.x*p.x + $this_1.y*p.y + $this_1.z*p.z;
}
$p.addMethod($this_1, 'dot', dot$1, false);
function length$0() {
return Math.sqrt( $this_1.x*$this_1.x + $this_1.y*$this_1.y + $this_1.z*$this_1.z );
}
$p.addMethod($this_1, 'length', length$0, false);
function lengthSquared$0() {
return $this_1.x*$this_1.x + $this_1.y*$this_1.y + $this_1.z*$this_1.z;
}
$p.addMethod($this_1, 'lengthSquared', lengthSquared$0, false);
function clear$0() {
$this_1.x = 0;
$this_1.y = 0;
$this_1.z = 0;
}
$p.addMethod($this_1, 'clear', clear$0, false);
function toString$0_NaN() {
return new String( "(" + $this_1.x + ", " + $this_1.y + ", " + $this_1.z + ")" );
}
$p.addMethod($this_1, 'toString', toString$0_NaN, false);
function cross$1(p) {
return new Vector3D( $this_1.y*p.z - $this_1.z*p.y,
$this_1.x*p.z - $this_1.z*p.x,
$this_1.x*p.y - $this_1.y*p.x );
}
$p.addMethod($this_1, 'cross', cross$1, false);
function isZero$0() {
return $this_1.x == 0 && $this_1.y == 0 && $this_1.z == 0;
}
$p.addMethod($this_1, 'isZero', isZero$0, false);
function $constr_3(X, Y, Z){
$superCstr();
$this_1.x = X;
$this_1.y = Y;
$this_1.z = Z;
}
function $constr() {
if(arguments.length === 3) { $constr_3.apply($this_1, arguments); } else $superCstr();
}
$constr.apply(null, arguments);
}
return Vector3D;
})();
$p.Vector3D = Vector3D;
var processingString = "Processing enabled.";
function bindJavascript(js) {
javascript = js;
}
$p.bindJavascript = bindJavascript;
var javascript = null;
var colors = $p.createJavaArray('$p.color', [12]);
var LABEL_COLOR = $p.color(150);
var HIGHLIGHTED_LABEL_COLOR = $p.color(55);
var DONUT_BACKGROUND = $p.color(255);
var BACKGROUND = $p.color(234, 239, 224);
var STROKE_WEIGHT_COLLAPSED = 50;
var STROKE_WEIGHT_EXPANDED = 60;
var OUTER_BORDER = 5;
var RADIUS_OPENED = 110;
var RADIUS_CLOSED = 50;
var fontSize = 11;
var fontSizeCaption = 16;
var defaultFont = $p.loadFont("/fonts/GraublauWeb-Regular.svg");
var nodeCount = 0;
function fetchResource(resourceId) {
var resource = new Resource(resourceId, "", "");
nodeCount++;
resource.idx = nodeCount;
resource.fetchData(); return resource;
}
$p.fetchResource = fetchResource;
function initColors() {
colors[0] = $p.color(171, 199, 49);
colors[1] = $p.color(162, 195, 85);
colors[2] = $p.color(154, 191, 123);
colors[3] = $p.color(147, 186, 161);
colors[4] = $p.color(141, 181, 200);
colors[5] = $p.color(134, 162, 169);
colors[6] = $p.color(128, 142, 137);
colors[7] = $p.color(122, 122, 104);
colors[8] = $p.color(177, 102, 73);
colors[9] = $p.color(131, 127, 67);
colors[10] = $p.color(144, 150, 60);
colors[11] = $p.color(157, 175, 55);
}
$p.initColors = initColors;
var g = null;
var r = null;
var resourceId = null;
var selectedEdgeIndex = null;
function resize() {
$p.size(window.innerWidth-10, window.innerHeight-15);
}
$p.resize = resize;
function setup() {
initColors();
myGraph = g = new Graph(); $p.textFont(defaultFont, fontSize);
nodeCount = 0;
resize();
$p.fill(0);
$p.smooth();
$p.frameRate(30);
$p.background(BACKGROUND);
if (resourceId) {
r = fetchResource(resourceId);
g.addNode(root = new Node(r));
g.selectedNode = root;
}
}
$p.setup = setup;
function draw() {
if (g.nodes.size()>0) {
g.tick();
$p.background(BACKGROUND);
g.draw();
}
}
$p.draw = draw;
function mouseMoved() {
if (!resourceId) return;
if (!g.isDragging()) {
var r = g.selectedNode.subject;
r.checkSelected();
g.checkSelected();
selectedEdgeIndex = null;
for (var i = 0; i< g.edges.size(); i++) {
if (g.edges[i].mouseOver()) {
selectedEdgeIndex = i;
}
}
}
}
$p.mouseMoved = mouseMoved;
})
//***************************************************************
//* Test.pde
//**************************************************************/
String processingString = "Processing enabled.";
interface JavaScript {
//void showXYCoordinates(int x, int y);
}
void bindJavascript(JavaScript js) {
javascript = js;
}
JavaScript javascript;
color[] colors = new color[12];
color LABEL_COLOR = color(150);
color HIGHLIGHTED_LABEL_COLOR = color(55);
color DONUT_BACKGROUND = color(255);
color BACKGROUND = color(234, 239, 224);
// global constants
float STROKE_WEIGHT_COLLAPSED = 50;
float STROKE_WEIGHT_EXPANDED = 60;
float OUTER_BORDER = 5;
float RADIUS_OPENED = 110;
float RADIUS_CLOSED = 50;
int fontSize = 11;
int fontSizeCaption = 16;
/* @pjs preload="/fonts/GraublauWeb-Regular.svg"; */
PFont defaultFont =loadFont("/fonts/GraublauWeb-Regular.svg");
int nodeCount = 0;
Resource fetchResource(String resourceId) {
// init dummy resource
Resource resource = new Resource(resourceId, "", "");
nodeCount++;
resource.idx = nodeCount;
resource.fetchData(); // start fetching data from freebase
return resource;
}
void initColors(){
colors[0] = color(171, 199, 49);
colors[1] = color(162, 195, 85);
colors[2] = color(154, 191, 123);
colors[3] = color(147, 186, 161);
colors[4] = color(141, 181, 200);
colors[5] = color(134, 162, 169);
colors[6] = color(128, 142, 137);
colors[7] = color(122, 122, 104);
colors[8] = color(177, 102, 73);
colors[9] = color(131, 127, 67);
colors[10] = color(144, 150, 60);
colors[11] = color(157, 175, 55);
}
Graph g;
Resource r;
String resourceId = null;
int selectedEdgeIndex = null;
void resize() {
size(window.innerWidth-10, window.innerHeight-15);
}
void setup() {
initColors();
myGraph = g = new Graph();// myGraph exposes the graph to the outside world
textFont(defaultFont, fontSize);
nodeCount = 0;
resize();
fill(0);
smooth();
frameRate(30);
background(BACKGROUND);
if (resourceId) {
r = fetchResource(resourceId);
g.addNode(root = new Node(r));
g.selectedNode = root;
//$("#details").html(r.html);
}
}
void draw() {
if (g.nodes.size()>0) {
g.tick();
background(BACKGROUND);
g.draw();
}
}
void mouseMoved() {
if (!resourceId) return;
if (!g.isDragging()) {
Resource r = g.selectedNode.subject;
r.checkSelected();
g.checkSelected(); // checkDragged
selectedEdgeIndex = null;
// Iterate over nodes
for (int i=0; i< g.edges.size(); i++) {
if (g.edges[i].mouseOver()) {
selectedEdgeIndex = i;
}
}
}
}
//Next File//***************************************************************
//* Attraction
//**************************************************************/
public class Attraction
{
Particle a;
Particle b;
float k;
boolean on;
float distanceMin;
float distanceMinSquared;
public Attraction( Particle a, Particle b, float k, float distanceMin )
{
this.a = a;
this.b = b;
this.k = k;
on = true;
this.distanceMin = distanceMin;
this.distanceMinSquared = distanceMin*distanceMin;
}
public void setA( Particle p )
{
a = p;
}
public void setB( Particle p )
{
b = p;
}
public float getMinimumDistance()
{
return distanceMin;
}
public void setMinimumDistance( float d )
{
distanceMin = d;
distanceMinSquared = d*d;
}
public void turnOff()
{
on = false;
}
public void turnOn()
{
on = true;
}
public void setStrength( float k )
{
this.k = k;
}
public Particle getOneEnd()
{
return a;
}
public Particle getTheOtherEnd()
{
return b;
}
public void apply()
{
if ( on && ( a.isFree() || b.isFree() ) )
{
float a2bX = a.position().x - b.position().x;
float a2bY = a.position().y - b.position().y;
float a2bZ = a.position().z - b.position().z;
float a2bDistanceSquared = a2bX*a2bX + a2bY*a2bY + a2bZ*a2bZ;
if ( a2bDistanceSquared < distanceMinSquared )
a2bDistanceSquared = distanceMinSquared;
float force = k * a.mass() * b.mass() / a2bDistanceSquared;
float length = (float)Math.sqrt( a2bDistanceSquared );
// make unit vector
a2bX /= length;
a2bY /= length;
a2bZ /= length;
// multiply by force
a2bX *= force;
a2bY *= force;
a2bZ *= force;
// apply
if ( a.isFree() )
a.force().add( -a2bX, -a2bY, -a2bZ );
if ( b.isFree() )
b.force().add( a2bX, a2bY, a2bZ );
}
}
public float getStrength()
{
return k;
}
public boolean isOn()
{
return on;
}
public boolean isOff()
{
return !on;
}
}//Next File//***************************************************************
//* Attribute
//**************************************************************/
public class Attribute {
String id = "";
String name = "";
String html = "";
Resource r;
ArrayList values;
public Attribute(String id, String name, Resource r) {
this.id = id;
this.name = name;
this.r = r;
this.values = new ArrayList();
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Value addValue(String id, String name) {
Value val = new Value(id, name, this);
values.add(val);
return val;
}
}
//Next File//***************************************************************
//* Donut
//**************************************************************/
public class Donut {
float x;
float y;
float radius;
float alpha; // askken-specific
float angleOffset ;
ArrayList segments;
int colorCount;
DonutSegment selectedSegment;
DonutSlice selectedSlice;
float angleAdjustment;
boolean opened;
boolean showLabels;
// callbacks TODO: clean this up!
//Object segmentChanged = function() {};
public Donut(float x, float y, float r) {
this.x = x;
this.y = y;
this.radius = r;
this.segments = new ArrayList();
angleOffset = 0.0;
colorCount = 0;
angleAdjustment = 0.0;
selectedSegment = null;
selectedSlice = null;
opened = true;
showLabels = false;
}
public setSelectedSlice(DonutSlice s) {
this.selectedSlice = s;
if (s.seg != this.selectedSegment) {
if (this.selectedSegment!=null) {
this.selectedSegment.contract();
}
this.selectedSegment = s.seg;
this.selectedSegment.expand();
this.segmentChanged();
}
}
public void update() {
this.angleAdjustment = 0.0;
this.angleOffset = 0.0;
if (selectedSlice != null) {
float targetAngle = (selectedSlice.angleStart+selectedSlice.angleStop) / 2;
}
// perform tweens first
for (int i=0; i < segments.size(); i++) {
segments[i].fan.tick();
segments[i].breadthTween.tick();
}
// then update the values
for (int i=0; i < segments.size(); i++) {
segments[i].update();
}
if (selectedSlice != null) {
float offset = targetAngle-((selectedSlice.angleStart+selectedSlice.angleStop) / 2);
if (Math.abs(offset)>EPSILON) {
float targetAdjustment = this.angleAdjustment+offset;
if (targetAdjustment<0) {
targetAdjustment = TWO_PI - targetAdjustment;
}
this.angleAdjustment = targetAdjustment;
}
}
// recalc again if angleAdjustment is needed.
if (angleAdjustment>0) {
this.angleOffset = this.angleAdjustment;
for (int i=0; i < segments.size(); i++) {
segments[i].update();
}
}
}
/* this method is probably called to often.
/* maybe that's what slows down the expand/contract tweening */
public float totalWeight() {
float sum = 0.0;
for (int i=0; i < segments.size(); i++) {
sum += segments[i].weight*segments[i].share();
}
return sum;
}
public float totalSlices() {
int sum = 0;
for (int i=0; i < segments.size(); i++) {
sum += segments[i].slices.size();
}
return sum;
}
public void draw() {
noStroke();
// inner spacer
fill(DONUT_BACKGROUND);
ellipse(this.x, this.y, radius*2, radius*2);
curContext.globalAlpha = this.alpha;
// draw attributes
for (int i = 0 ; i < segments.size(); i++) {
segments[i].draw();
}
curContext.globalAlpha = 1.0;
}
public void addSegment(DonutSegment s) {
s.col = colors[colorCount%11]; // assign a color
if (colorCount==0)
setSelectedSlice(s.slices[0]);
segments.add(s);
colorCount += 2;
}
}
//Next File//***************************************************************
//* DonutSegment
//**************************************************************/
public class DonutSegment {
float weight;
float angleStart;
float angleStop;
float breadth;
Donut donut;
Object subject;
ArrayList slices;
color col;
Tween fan;
Tween breadthTween;
public DonutSegment(Subject subject, Donut donut) {
breadth = STROKE_WEIGHT_COLLAPSED;
this.donut = donut;
this.subject = subject;
this.slices = new ArrayList();
this.weight = 1.0;
this.fan = new Tween(this, "weight", Tween.strongEaseInOut, 1.0, 3.0, 0.8);
this.breadthTween = new Tween(this, "breadth", Tween.strongEaseInOut, STROKE_WEIGHT_COLLAPSED, STROKE_WEIGHT_EXPANDED, 0.8);
}
// the resulting share of the segment (in percent)
public float share() {
return (slices.size()/donut.totalSlices()); // the share of total slices
}
// the weighted share of the segment in respect of the segment's weight (in percent)
public float weightedShare() {
return share()*weight/donut.totalWeight();
}
// the resulting size of the segment (in radiants)
public float amount() {
return (TWO_PI)*weightedShare();
}
public void update() {
// update local angleStart, angleStop using the shared angleOffset
this.angleStart = donut.angleOffset;
float amount = this.amount();
float tmp = this.angleStart;
for (int i=0; i<slices.size(); i++) {
// TODO: delegate the work to DonutSlice#update() -> slices[i].update();
slices[i].angleStart = tmp;
slices[i].angleStop = tmp+=amount/slices.size();
}
this.angleStop = donut.angleOffset+=amount;
}
public void draw() {
// processing.js patch!
curContext.lineCap = "butt";
fill(DONUT_BACKGROUND);
noStroke();
noFill();
stroke(DONUT_BACKGROUND);
strokeWeight(relativeBreadth());
curContext.globalAlpha = 1.0;
arc(donut.x, donut.y, (donut.radius+OUTER_BORDER)*2, (donut.radius+OUTER_BORDER)*2, this.angleStart, this.angleStop);
curContext.globalAlpha = donut.alpha;
stroke(col);
arc(donut.x, donut.y, donut.radius*2, donut.radius*2, this.angleStart, this.angleStop);
curContext.textAlign = "center";
if (this==donut.selectedSegment && donut.showLabels) {
fill(col);
curContext.font = "40px GraublauWeb";
curContext.fillText(this.slices.size(), donut.x, donut.y+15);
curContext.font = "20px GraublauWeb";
curContext.fillText("Relationships", donut.x, donut.y+40);
curContext.font = "20px GraublauWeb";
curContext.fillText(this.subject.getName(), donut.x, donut.y-25, 120);
noStroke();
//ellipse(donut.x, donut.y, 14, 14);
}
// draw slices
for (int i=0; i<slices.size(); i++) {
slices[i].draw();
}
}
// ASKKEN specific use breadth relative to current radius
public float relativeBreadth() {
return (donut.radius/RADIUS_OPENED)*this.breadth;
}
// start expanding tween
public void expand() {
this.fan.continueTo(3.0, 0.8);
this.breadthTween.continueTo(STROKE_WEIGHT_EXPANDED, 0.8);
}
// start contracting tween
public void contract() {
this.fan.continueTo(1.0, 0.8);
this.breadthTween.continueTo(STROKE_WEIGHT_COLLAPSED, 0.8);
}
public void addSlice(Object subject) {
slices.add(new DonutSlice(subject, this));
}
}
//Next File//***************************************************************
//* DonutSlice
//**************************************************************/
public class DonutSlice {
Object subject;
boolean hovering;
DonutSegment seg;
float angleStart;
float angleStop;
public DonutSlice(Object subject, DonutSegment seg) {
hovering = false;
this.subject = subject;
this.seg = seg;
}
public void update() {
// patched by DonutSegment#update() for now
}
public void draw() {
float radius = seg.donut.radius;
stroke(255, 255, 255, 100);
strokeWeight(1);
// TODO: if (this===seg.slices[seg.slices.size()-1])
line(this.seg.donut.x+cos(this.angleStop)*(radius-seg.relativeBreadth()/2), this.seg.donut.y+sin(this.angleStop)*(radius-seg.relativeBreadth()/2), this.seg.donut.x+cos(this.angleStop)*(radius+seg.relativeBreadth()/2), this.seg.donut.y+sin(this.angleStop)*(radius+seg.relativeBreadth()/2));
// highlight selectedSlice
if (this.hovering) {
curContext.lineCap = "butt"; // processing.js patch!
noFill();
stroke(0, 0, 0, 20);
strokeWeight(seg.relativeBreadth());
arc(seg.donut.x, seg.donut.y, seg.donut.radius*2, seg.donut.radius*2, angleStart, angleStop);
}
noStroke();
strokeWeight(0); // reset
if (seg.donut.selectedSegment==this.seg && !seg.fan.isPlaying() && seg.donut.selectedSlice.hovering) {
float theta = ((this.angleStart+this.angleStop) / 2)%TWO_PI+0.05;
float angle = theta;
// curContext.font = "13.1px Courier";
curContext.textAlign = "left";
if (theta > PI/2 && theta < (PI+PI/2)-0.05) {
fWidth = curContext.measureText(this.subject.getName()).width;
angle -= 0.05;
}
else
fWidth = 0;
pushMatrix();
translate(seg.donut.x, seg.donut.y);
rotate(angle);
pushMatrix();
translate(seg.donut.radius+50+fWidth, 0);
if (this.hovering)
fill(HIGHLIGHTED_LABEL_COLOR);
else
fill(LABEL_COLOR);
pushMatrix();
if (theta > PI/2 && theta < (PI+PI/2)-0.05) {
rotate(PI);
}
curContext.fillText(this.subject.getName(), 0, 0);
popMatrix();
popMatrix();
popMatrix();
}
}
public boolean checkSelected() {
float disX = mouseX - seg.donut.x;
float disY = mouseY - seg.donut.y;
// calculate polar coordinates
float r = Math.sqrt(sq(disX)+sq(disY));
float angle = atan2(disY, disX);
if (angle<0) angle = TWO_PI+angle; // shift to 0-TWO_PI interval
float start = this.angleStart % TWO_PI;
float stop = this.angleStop % TWO_PI;
if (r >= seg.donut.radius-seg.relativeBreadth()/2 && r <= seg.donut.radius+seg.relativeBreadth()/2 &&
((angle>start && angle<stop) || (start>stop && (angle > start || angle < stop)) )) {
seg.donut.setSelectedSlice(this);
// return true
subject.hovering = hovering = true;
}
else {
subject.hovering = hovering = false;
}
if (seg.donut.totalSlices()==1) {
seg.donut.setSelectedSlice(this);
subject.hovering = hovering = true;
}
return subject.hovering;
}
}
//Next File//***************************************************************
//* Edge
//**************************************************************/
class Edge {
boolean hovering;
Node from;
Node to;
Object subject;
float radius ;
float x1 ;
float x2 ;
float y1 ;
float y2 ;
public Edge(Node from, Node to, Object subject) {
hovering = false;
this.from = from;
this.to = to;
this.subject = subject;
radius = 30;
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
}
public Node getFrom() {
return from;
}
public Node getTo() {
return to;
}
public void update() {
// original positions
float ox1 = from.getParticle().position().x;
float ox2 = to.getParticle().position().x;
float oy1 = from.getParticle().position().y;
float oy2 = to.getParticle().position().y;
float wx = ox2-ox1;
float wy = oy2-oy1;
float ww = sqrt(wx*wx+wy*wy); // calculates the vectors amount
// calculate relative values for arrows
x1 = ox1+wx*((from.getSubject().currentRadius()-10)/ww);
y1 = oy1+wy*((from.getSubject().currentRadius()-10)/ww);
x2 = ox2-wx*((to.getSubject().currentRadius()+5)/ww);
y2 = oy2-wy*((to.getSubject().currentRadius()+5)/ww);
}
public void draw() {
stroke(255);
if (hovering)
fill(255);
else
fill(this.subject.col);
strokeWeight(4);
if (this.subject.subject.getName()[0] == "O")
arrow(x1, y1, x2, y2, 7); // Outgoing Arrows
else
arrow(x2, y2, x1, y1, 17); // Incoming Arrows
// noStroke();
ellipse(centerX(), centerY(), 20, 20);
textFont(defaultFont, 13);
fill(255);
text(this.subject.subject.getName()[0], centerX()-3, centerY()-8);
// fontWidth = defaultFont.width((idx+1)+". "+this.getName()) * fontSize;
// text((idx+1)+". "+this.getName(), this.x-fontWidth/2, this.y+10+labelOffset+30);
textFont(defaultFont, fontSize);
}
public void drawLabel() {
textFont(defaultFont, 13);
fill(255);
noStroke();
rect(centerX()-3, centerY()-12, 200, 24);
fill(100);
text(this.subject.subject.getName(), centerX()-3, centerY()-8);
// fontWidth = defaultFont.width((idx+1)+". "+this.getName()) * fontSize;
// text((idx+1)+". "+this.getName(), this.x-fontWidth/2, this.y+10+labelOffset+30);
textFont(defaultFont, fontSize);
}
public void centerX() {
return x1 + 0.5*(x2-x1);
}
public void centerY() {
return y1 + 0.5*(y2-y1);
}
public boolean mouseOver() {
float disX = centerX() - mouseX;
float disY = centerY() - mouseY;
if (sqrt(sq(disX) + sq(disY)) < radius/2 ) {
hovering = true;
return true;
}
else {
hovering = false;
return false;
}
}
}
//Next File//***************************************************************
//* EulerIntegrator
//**************************************************************/
public class EulerIntegrator
{
ParticleSystem s;
public EulerIntegrator( ParticleSystem s )
{
this.s = s;
}
public void step( float t )
{
s.clearForces();
s.applyForces();
for ( int i = 0; i < s.numberOfParticles(); i++ )
{
Particle p = s.getParticle( i );
if ( p.isFree() )
{
p.velocity().add( p.force().x/(p.mass()*t), p.force().y/(p.mass()*t), p.force().z/(p.mass()*t) );
p.position().add( p.velocity().x/t, p.velocity().y/t, p.velocity().z/t );
}
}
}
}
//Next File//***************************************************************
//* Graph
//**************************************************************/
// Usage
// ===========
// Graph g;
// Resource r;
// g.addNode(enterprise = new Node("enterprise", "Enterprise"));
// g.addNode(earth = new Node("earth", "Earth"));
// g.addNode(kirk = new Node("kirk", "Kirk"));
// g.addNode(spock = new Node("spock", "Spock"));
//
// g.addEdge(new Edge(universe, enterprise));
// g.addEdge(new Edge(enterprise, kirk));
// g.addEdge(new Edge(enterprise, spock));
// g.addEdge(new Edge(universe, earth));
// g.addEdge(new Edge(earth, kirk));
class Graph {
ArrayList nodes;
ArrayList edges;
ParticleSystem ps;
Node selectedNode;
boolean dragging;
Node dragNode;
float EDGE_LENGTH = 300;
float EDGE_STRENGTH = 0.5;
float SPACER_STRENGTH = 1000;
public Graph() {
nodes = new ArrayList();
edges = new ArrayList();
dragging = false;
// Zero gravity, mid-to-low drag
ps = new ParticleSystem(0, 0, 0, 0.1);
ps.setDrag( 0.2 );
}
// gets node by resource id
void getNodeById(String id) {
int i = 0;
Node n = null;
while (i < g.nodes.size ()) {
if (this.nodes[i].subject.id==id)
return this.nodes[i];
i++;
}
return null;
}
void selectNode(Node n) {
selectedNode.subject.setClosed();
selectedNode = n;
$("aside").html(selectedNode.getSubject().html);
selectedNode.subject.setOpen();
dragging = true;
}
public void setSelectedNode(Node sNode) {
this.selectedNode = sNode;
}
public Node getSelectedNode() {
return this.selectedNode;
}
public void setDragNode(Node n) {
if (this.dragNode != null) {
this.dragNode.setDragging(false);
}
this.dragNode = n;
if (n != null)
n.setDragging(true);
}
public Node getDragNode() {
return this.dragNode;
}
public boolean isDragging() {
return (this.dragNode) ? this.dragging : false;
}
public void addEdge(Edge e) {
// Edge exists?
int i = 0;
boolean found = false;
while (i < edges.size () && !found) {
found = ((edges.get(i).getFrom() == e.getFrom() && (edges.get(i)).getTo() == e.getTo()) || (edges.get(i).getFrom() == e.getTo() && (edges.get(i)).getTo() == e.getFrom()));
i++;
}
if (!found) {
edges.add(e);
// Add a spring
ps.makeSpring( e.getFrom().getParticle(), e.getTo().getParticle(), EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH );
e.getTo().getParticle().position().set( mouseX, mouseY, 0 );
}
}
public void addNode(Node n) {
// TODO: Don't allow duplicates
n.setGraph(this);
nodes.add(n);
for ( int i = 0; i < nodes.size(); i++ )
{
if (n!=nodes[i])
ps.makeAttraction( n.getParticle(), nodes[i].getParticle(), -SPACER_STRENGTH, 15 );
}
}
public void removeEdge(Edge e) {
var idx = $.inArray(e, edges);
if (idx>=0)
edges.remove(idx);
}
public void removeNode(Node n) {
// delete concerning springs
ArrayList springs = this.ps.springs.clone();
for (int i=0; i<springs.size(); i++) {
if (n.p == springs[i].a || n.p == springs[i].b)
this.ps.removeSpring(springs[i]);
}
// delete concerning attractions
ArrayList attractions = this.ps.attractions.clone();
for (int i=0; i<attractions.size(); i++) {
if (n.p == attractions[i].a || n.p == attractions[i].b)
this.ps.removeAttraction(attractions[i]);
}
// remove concerning edges
ArrayList edgs = this.edges.clone();
for (int i=0; i<edgs.size(); i++) {
if (n == edgs[i].from || n == edgs[i].to)
removeEdge(edgs[i]);
}
// remove corresponding particle
this.ps.removeParticle(n.p);
// finally remove the node itself
var idx = $.inArray(n, nodes);
if (idx>=0)
nodes.remove(idx);
$("#path li[id=resource_"+idx+"]").remove();
if (nodes.size() == 0) {
console.log("TODO: there are no nodes left. clean it up!");
// clear workspace return;
}
}
public ArrayList getOutgoingEdges(Node n) {
ArrayList outgoingEdges = new ArrayList();
for (int i=0; i < edges.size(); i++) {
Edge e = (Edge)edges.get(i);
if (e.getFrom() == n)
outgoingEdges.add(e);
}
return outgoingEdges;
}
public ArrayList getIncomingEdges(Node n) {
ArrayList incomingEdges = new ArrayList();
for (int i=0; i < edges.size(); i++) {
Edge e = (Edge)edges.get(i);
if (e.getTo() == n)
incomingEdges.add(e);
}
return incomingEdges;
}
public void unVisitNodes() {
for (int i = 0; i < nodes.size(); i++) {
nodes[i].setVisited(false);
}
}
public void depthFirstWalk(Node n, ArrayList result) {
if (!result) {
result = new ArrayList();
unVisitNodes();
}
if (!n.isVisited()) {
n.setVisited(true);
result.add(n);
}
ArrayList edges = n.getOutgoingEdges();
for (int i = 0; i < edges.size(); i++) {
if (!edges.get(i).getTo().isVisited())
depthFirstWalk(edges.get(i).getTo(), result);
}
return result;
}
// Drawing stuff
// *******************************************************************
public void tick() {
ps.tick(1.0);
}
public void draw() {
// Draw edges
for ( int i = 0; i < edges.size(); i++ ) {
Edge e = edges.get(i);
if (e) {
e.update();
e.draw();
}
}
// Draw nodes
for (int i=0; i < nodes.size(); i++) {
if (nodes[i]!=selectedNode)
nodes[i].draw();
}
// Draw selected Node
selectedNode.draw();
// TODO: draw active edgeLabel if currently requested
// Draw edges
for ( int i = 0; i < edges.size(); i++ ) {
Edge e = edges.get(i);
if (e && e.hovering)
e.drawLabel();
}
}
public void checkSelected() {
dragNode = null;
// Iterate over nodes
for (int i=0; i< g.nodes.size(); i++) {
if (nodes[i].mouseOver() && dragNode != nodes[i]) {
dragNode = nodes[i];
nodes[i].subject.hovering = true;
}
else {
nodes[i].subject.hovering = false;
}
}
}
}
//Next File//***************************************************************
//* ModifiedEulerIntegrator
//**************************************************************/
public class ModifiedEulerIntegrator
{
ParticleSystem s;
public ModifiedEulerIntegrator( ParticleSystem s )
{
this.s = s;
}
public void step( float t )
{
s.clearForces();
s.applyForces();
float halftt = 0.5*t*t;
for ( int i = 0; i < s.numberOfParticles(); i++ )
{
Particle p = s.getParticle( i );
if ( p.isFree() )
{
float ax = p.force().x/p.mass();
float ay = p.force().y/p.mass();
float az = p.force().z/p.mass();
p.position().add( p.velocity().x/t, p.velocity().y/t, p.velocity().z/t );
p.position().add( ax*halftt, ay*halftt, az*halftt );
p.velocity().add( ax/t, ay/t, az/t );
}
}
}
}
//Next File//***************************************************************
//* Node
//**************************************************************/
class Node {
Graph g;
boolean visited = false;
boolean hovering = false;
boolean dragging = false;
Particle p;
ParticleSystem ps;
public Node(Object subject) {
this.subject = subject;
}
public void setGraph(Graph g) {
this.g = g;
this.ps = g.ps;
this.p = ps.makeParticle(1.0, window.innerWidth/2+150, window.innerHeight/2, 0);
}
public Object getSubject() {
return this.subject;
}
public String getId() {
return subject.getId;
}
public String getName() {
return subject.getName();
}
public setVisited(boolean visited) {
this.visited = visited;
}
public boolean isVisited() {
return this.visited;
}
public setDragging(boolean dragging) {
this.dragging = dragging;
}
public isDragging() {
return dragging;
}
public Graph getGraph() {
return g;
}
public ArrayList getOutgoingEdges() {
return g.getOutgoingEdges(this);
}
public ArrayList getIncomingEdges() {
return g.getIncomingEdges(this);
}
public ArrayList getEdges() {
// apend incoming an outgoing edges
}
public Particle getParticle() {
return p;
}
public void setPos(float x, float y) {
this.p.position().set(x, y, 0);
}
public void draw() {
// draw subject
subject.setPos(this.p.position().x, this.p.position().y);
subject.update();
subject.draw();
}
public boolean mouseOver() {
return subject.mouseOver();
}
}
//Next File//***************************************************************
//* Particle
//**************************************************************/
public class Particle
{
Vector3D myPosition;
Vector3D myVelocity;
Vector3D myForce;
float myMass;
float age;
boolean dead;
boolean fixed;
public Particle( float m )
{
myPosition = new Vector3D(0, 0, 0);
myVelocity = new Vector3D(0, 0, 0);
myForce = new Vector3D(0, 0, 0);
myMass = m;
age = 0;
fixed = false;
dead = false;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#distanceTo(traer.physics.Particle)
*/
public float distanceTo( Particle p )
{
return this.position().distanceTo( p.position() );
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#makeFixed()
*/
public void makeFixed()
{
fixed = true;
myVelocity.clear();
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#isFixed()
*/
public boolean isFixed()
{
return fixed;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#isFree()
*/
public boolean isFree()
{
return !fixed;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#makeFree()
*/
public void makeFree()
{
fixed = false;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#position()
*/
public Vector3D position()
{
return myPosition;
}
public Vector3D velocity()
{
return myVelocity;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#mass()
*/
public float mass()
{
return myMass;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#setMass(float)
*/
public void setMass( float m )
{
myMass = m;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#force()
*/
public Vector3D force()
{
return myForce;
}
/* (non-Javadoc)
* @see traer.physics.AbstractParticle#age()
*/
// public float age()
// {
// return myAge;
// }
void reset()
{
age = 0;
dead = false;
position.clear();
myVelocity.clear();
myForce.clear();
myMass = 1;
}
}
//Next File//***************************************************************
//* ParticleSystem
//**************************************************************/
public class ParticleSystem
{
static int RUNGE_KUTTA = 0;
static int MODIFIED_EULER = 1;
static float DEFAULT_GRAVITY = 0;
static float DEFAULT_DRAG = 0.001f;
ArrayList particles;
ArrayList springs;
ArrayList attractions;
ArrayList customForces;
Integrator integrator;
Vector3D gravity;
float drag;
boolean hasDeadParticles = false;
// public ParticleSystem( float g, float somedrag )
// {
// integrator = new RungeKuttaIntegrator( this );
// particles = new ArrayList();
// springs = new ArrayList();
// attractions = new ArrayList();
// gravity = new Vector3D( 0, g, 0 );
// drag = somedrag;
// }
// common: new ParticleSystem(0, x, 0, somedrag)
public ParticleSystem( float gx, float gy, float gz, float somedrag )
{
customForces = new ArrayList();
integrator = new RungeKuttaIntegrator( this );
//integrator = new ModifiedEulerIntegrator( this );
particles = new ArrayList();
springs = new ArrayList();
attractions = new ArrayList();
gravity = new Vector3D( gx, gy, gz );
drag = somedrag;
}
// public ParticleSystem()
// {
// integrator = new RungeKuttaIntegrator( this );
// particles = new ArrayList();
// springs = new ArrayList();
// attractions = new ArrayList();
// gravity = new Vector3D( 0, ParticleSystem.DEFAULT_GRAVITY, 0 );
// drag = ParticleSystem.DEFAULT_DRAG;
// }
public void setIntegrator( int integrator )
{
switch ( integrator )
{
case RUNGE_KUTTA:
this.integrator = new RungeKuttaIntegrator( this );
break;
case MODIFIED_EULER:
this.integrator = new ModifiedEulerIntegrator( this );
break;
}
}
public void setGravity( float x, float y, float z )
{
gravity.set( x, y, z );
}
public void setDrag( float d )
{
drag = d;
}
// public void tick()
// {
// tick( 1 );
// }
public void tick( float t )
{
integrator.step( t );
}
public void tickOnce() {
integrator.step( 1.0 );
}
public Particle makeParticle( float mass, float x, float y, float z )
{
Particle p = new Particle( mass );
// makeParticle
p.position().set( x, y, z );
particles.add( p );
return p;
}
// public Particle makeOrdinaryParticle()
// {
// return makeParticle( 1.0, 0.0, 0.0, 0.0 );
// }
public Spring makeSpring( Particle a, Particle b, float ks, float d, float r )
{
Spring s = new Spring( a, b, ks, d, r );
springs.add( s );
return s;
}
public Attraction makeAttraction( Particle a, Particle b, float k, float minDistance )
{
Attraction m = new Attraction( a, b, k, minDistance );
attractions.add( m );
return m;
}
public void clear()
{
particles.clear();
springs.clear();
attractions.clear();
}
public void applyForces()
{
if ( !gravity.isZero() )
{
for ( int i = 0; i < particles.size(); ++i )
{
Particle p = particles.get( i );
p.force().add( gravity );
}
}
for ( int i = 0; i < particles.size(); ++i )
{
Particle p = particles.get( i );
xx = p.force().add( p.velocity().x * -drag, p.velocity().y * -drag, p.velocity().z * -drag );
}
for ( int i = 0; i < springs.size(); i++ )
{
Spring f = springs.get( i );
f.apply();
}
for ( int i = 0; i < attractions.size(); i++ )
{
Attraction f = attractions.get( i );
f.apply();
}
for ( int i = 0; i < customForces.size(); i++ )
{
Force f = customForces.get( i );
f.apply();
}
}
// calls clear on each particle's force
void clearForces()
{
for ( int i = 0; i < particles.size(); i++ ) {
Particle p = particles.get( i );
p.force().clear();
}
}
public int numberOfParticles()
{
return particles.size();
}
public int numberOfSprings()
{
return springs.size();
}
public int numberOfAttractions()
{
return attractions.size();
}
public Particle getParticle( int i )
{
return (Particle)particles.get( i );
}
public Spring getSpring( int i )
{
return springs.get( i );
}
public Attraction getAttraction( int i )
{
return attractions.get( i );
}
public void addCustomForce( Force f )
{
customForces.add( f );
}
public int numberOfCustomForces()
{
return customForces.size();
}
public Force getCustomForce( int i )
{
return customForces.get( i );
}
public Force removeCustomForce( int i )
{
return customForces.remove( i );
}
public void removeParticle( Particle p )
{
var idx = $.inArray(p, particles);
if (idx>=0)
particles.remove(idx);
}
// public Spring removeSpring( int i )
// {
// return springs.remove( i );
// }
// public Attraction removeAttraction( int i )
// {
// return attractions.remove( i );
// }
public void removeAttraction( Attraction a )
{
var idx = $.inArray(a, attractions);
if (idx>=0)
attractions.remove(idx);
}
public void removeSpring( Spring s )
{
var idx = $.inArray(s, springs);
if (idx>=0)
springs.remove(idx);
}
public void removeCustomForce( Force f )
{
customForces.remove( f );
}
}//Next File//***************************************************************
//* Resource
//**************************************************************/
public class Resource {
boolean hovering = false;
boolean dragging = false;
boolean loading = true;
Tween resize;
Donut donut;
String state = "open";
boolean loading = true;
Attribute selectedAttribute = null;
Attribute previousSelectedAttribute = null;
boolean open = true;
int numValues = 0;
int idx = 0; // the resource's unique numeric id in the graph
float x;
float y;
// internals
ArrayList attributes;
int radius = RADIUS_CLOSED;
float angle = 0; // REMOVE?
String id = "";
String name = "";
String html = "";
int NUM_LOADING_SEGMENTS = 11;
int progress = 0;
public Resource(String id, String name, String html) {
var that = this;
this.attributes = new ArrayList();
this.id = id;
this.name = name;
this.html = html;
donut = new Donut(275, 275, RADIUS_CLOSED); // TODO!
//FIXME--djue
// donut.segmentChanged = function() {
// this refers to the donut object
// Attributes.select(this.selectedSegment);
// };
//my attempt at fixing it--djue
donut.segmentChanged = Attributes.select(this.selectedSegment);
// initialize tweens
resize = new Tween(donut, "radius", Tween.strongEaseInOut, RADIUS_CLOSED, RADIUS_OPENED, 1);
//not sure what this does, it's not called anywhere --djue
// resize.finished = function() {
// if (that.state=="open") {
// that.donut.showLabels = true;
// }
// };
}
public void fetchData() {
var json;
var that = this;
this.loading = true;
/**
$.ajax({
async: true,
type: "GET",
url: "/rest/node/show",
data: $("#nodeSearch").serialize(),
dataType: "json",
success: function(response) {
// apply fetched data
that.id = response.data.id;
that.name = response.data.name;
that.html = response.details_html;
$("#explanation").html(response.details_html);
int numValues = 0;
for (int i = 0; i < response.data.attributes.length(); i++) {
Attribute attr = new Attribute(response.data.attributes[i].id, response.data.attributes[i].name, that);
DonutSegment seg = new DonutSegment(attr, that.donut);
for (int j = 0; j < response.data.attributes[i].values.length(); j++) {
Value val = attr.addValue(response.data.attributes[i].values[j].id, response.data.attributes[i].values[j].name);
seg.addSlice(val);
numValues++;
}
that.addAttribute(attr);
that.donut.addSegment(seg);
}
// kill this node because it's useless with no values at all
if (numValues==0) {
g.removeNode(getNodeById(that.id)); // TODO: does not work properly
return
}
// attributes are initialized based on what's in the donut
Attributes.init(that.donut);
// double work but necessary for now
Attributes.select(that.donut.selectedSegment);
that.numValues = numValues;
that.loading = false;
that.resize.start(); // tweening
Node n = g.getNodeById(that.id);
Path.addNode(n);
},
error: function() {
that.loading = false;
g.removeNode(getNodeById(that.id)); // TODO: does not work properly
// TODO: get rid of that dead node!
}
});
*/
}
public void setPos(float x, float y) {
this.x = x; // TODO: do we need this.x? -> yes we do / Resource#getX() that delegates to donut.x may help
this.y = y;
this.donut.x = x;
this.donut.y = y;
}
public void getSelectedAttribute() {
if (!this.donut.selectedSegment) return null;
return this.donut.selectedSegment.subject;
}
public void getSelectedValue() {
if (!this.donut.selectedSlice) return null;
return this.donut.selectedSlice.subject;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public void setClosed() {
this.state = "closed";
if (this.donut.selectedSlice)
this.donut.selectedSlice.hovering = false;
this.donut.showLabels = false;
this.resize.continueTo(RADIUS_CLOSED, 1);
}
public void setOpen() {
if (this.state != "open") {
this.state = "open";
// attributes are initialized based on what's in the donut
Attributes.init(this.donut);
Attributes.select(this.donut.selectedSegment);
this.resize.continueTo(RADIUS_OPENED, 1);
}
}
public void setState(String thestate) {
this.state = thestate;
}
public String getType() {
return this.type;
}
public void setNumValues(int numValues) {
this.numValues = numValues;
}
void setHovering(boolean b) {
hovering = b;
}
// returns true if mouse is over resource but not hovering a donut slice
public boolean isHovering() {
return hovering && (!donut.selectedSlice || !donut.selectedSlice.hovering);
}
void setDragging(boolean b) {
dragging = b;
}
public boolean isDragging() {
return dragging;
}
public void addAttribute(Attribute attr) {
attributes.add(attr);
}
// sets the selected attribute / corresponding segment/slice by attribute id
public void setSelectedAttribute(String attrId) {
DonutSegment s;
for (int i=0; i<donut.segments.size(); i++) {
if (donut.segments[i].subject.id == attrId)
s = donut.segments[i];
}
if (s) {
donut.setSelectedSlice(s.slices[0]);
}
}
// a modulo function that behaves like that one in vvvv
public int vvvvmod(int a, int b) {
int res = a % b;
return (res>=0) ? res : 100 + res;
}
public int d1(int i) {
return vvvvmod((this.progress-(100/NUM_LOADING_SEGMENTS)*i), 100);
}
public int d2(int i) {
return vvvvmod(((100/NUM_LOADING_SEGMENTS)*i-this.progress), 100);
}
public float alpha(int i) {
var a = max(-(1/25)*(d1(i))+1, -(1/25)*(d2(i))+1);
return max(a, 0.1);
}
public void update() {
this.progress = (this.progress+3) % 100;
resize.tick(); // triggering the tween if active
donut.update();
}
public void draw() {
noStroke();
if (loading) { // draw loading
// spacer
fill(255);
ellipse(this.x, this.y, donut.radius*2+35, donut.radius*2+35);
float angle = 0;
noFill();
stroke(DONUT_BACKGROUND);
// segments
for (int i=0; i<NUM_LOADING_SEGMENTS; i++) {
curContext.lineCap = "butt"; // processing.js patch!
stroke(colors[i*2%11]);
curContext.globalAlpha = alpha(i);
strokeWeight(25);
float angleStart = angle;
angle += TWO_PI/NUM_LOADING_SEGMENTS;
arc(donut.x, donut.y, donut.radius*2, donut.radius*2, angleStart, angle);
}
curContext.globalAlpha = 0.6;
// segments
for (int i=0; i<NUM_LOADING_SEGMENTS; i++) {
angle += TWO_PI/NUM_LOADING_SEGMENTS;
stroke(255);
strokeWeight(1);
line(this.x, this.y, this.x+cos(angle)*(donut.radius+15), this.y+sin(angle)*(donut.radius+15));
}
curContext.globalAlpha = 1.0;
}
else {
//was a triple equals
if (this == g.selectedNode.subject)
donut.alpha = 1.0;
else if (this.hovering) {
donut.alpha = 0.7;
}
else {
donut.alpha = 0.5;
}
noStroke();
donut.draw();
}
if (hovering)
fill(0, 0, 0, 150);
else
fill(66, 66, 66, 100);
noStroke();
curContext.textAlign = "center";
if (!loading && !(state=="open" && getSelectedValue().hovering)) {
pushMatrix();
translate(10, 0); // shift it a bit for centering
noStroke();
fill(255);
curContext.font = "16px GraublauWeb";
float fWidth = curContext.measureText(this.getName()).width+25;
float yOffset = donut.radius+donut.selectedSegment.relativeBreadth()/2+15;
// label background
roundedRect(this.x-fWidth/2, this.y+yOffset, fWidth, 22, 10);
if (state=="open")
fill(73, 71, 59);
else
fill(182, 187, 171);
ellipse(this.x-fWidth/2-5, this.y+yOffset+11, 30, 30);
// draw label
fill(33);
curContext.fillText(this.getName(), this.x+2, this.y+yOffset+15);
fill(255);
// draw resource index
curContext.font = "bold 18px Century Gothic";
curContext.textBaseline = "middle";
String idxstr = (this.idx<10) ? "0"+this.idx : this.idx;
curContext.fillText(idxstr, this.x-fWidth/2-5, this.y+yOffset+11);
noStroke();
curContext.textBaseline = "alphabetic";
popMatrix();
}
if (donut.selectedSegment && state != "closed")
fill(donut.selectedSegment.col);
else
fill(233);
}
// based on current mouse position
void checkSelected() {
for (int i=0; i < donut.segments.size(); i++) {
for (int j=0; j < donut.segments[i].slices.size(); j++) {
donut.segments[i].slices[j].checkSelected();
}
}
}
public float currentRadius() {
return donut.radius+35;
}
public boolean mouseOver() {
float disX = this.x - mouseX;
float disY = this.y - mouseY;
if (sqrt(sq(disX) + sq(disY)) < donut.radius+STROKE_WEIGHT_COLLAPSED/2 ) {
hovering = true;
return true;
}
else {
hovering = false;
return false;
}
}
}
//Next File//***************************************************************
//* RungeKuttaIntegrator
//**************************************************************/
public class RungeKuttaIntegrator
{
ArrayList originalPositions;
ArrayList originalVelocities;
ArrayList k1Forces;
ArrayList k1Velocities;
ArrayList k2Forces;
ArrayList k2Velocities;
ArrayList k3Forces;
ArrayList k3Velocities;
ArrayList k4Forces;
ArrayList k4Velocities;
ParticleSystem s;
public RungeKuttaIntegrator( ParticleSystem s )
{
this.s = s;
originalPositions = new ArrayList();
originalVelocities = new ArrayList();
k1Forces = new ArrayList();
k1Velocities = new ArrayList();
k2Forces = new ArrayList();
k2Velocities = new ArrayList();
k3Forces = new ArrayList();
k3Velocities = new ArrayList();
k4Forces = new ArrayList();
k4Velocities = new ArrayList();
}
void allocateParticles()
{
while ( s.particles.size () > originalPositions.size() )
{
originalPositions.add( new Vector3D() );
originalVelocities.add( new Vector3D() );
k1Forces.add( new Vector3D() );
k1Velocities.add( new Vector3D() );
k2Forces.add( new Vector3D() );
k2Velocities.add( new Vector3D() );
k3Forces.add( new Vector3D() );
k3Velocities.add( new Vector3D() );
k4Forces.add( new Vector3D() );
k4Velocities.add( new Vector3D() );
}
}
public void step( float deltaT )
{
allocateParticles();
/////////////////////////////////////////////////////////
// save original position and velocities
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
(originalPositions.get( i )).set( p.position() );
(originalVelocities.get( i )).set( p.velocity() );
}
p.force().clear(); // and clear the forces
}
////////////////////////////////////////////////////////
// get all the k1 values
s.applyForces();
// save the intermediate forces
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
(k1Forces.get( i )).set( p.force() );
(k1Velocities.get( i )).set( p.velocity() );
}
p.force().clear();
}
////////////////////////////////////////////////////////////////
// get k2 values
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
Vector3D originalPosition = originalPositions.get( i );
Vector3D k1Velocity = k1Velocities.get( i );
p.position().x = originalPosition.x + k1Velocity.x * 0.5 * deltaT;
p.position().y = originalPosition.y + k1Velocity.y * 0.5 * deltaT;
p.position().z = originalPosition.z + k1Velocity.z * 0.5 * deltaT;
Vector3D originalVelocity = originalVelocities.get( i );
Vector3D k1Force = k1Forces.get( i );
p.velocity().x = originalVelocity.x + k1Force.x * 0.5 * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k1Force.y * 0.5 * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k1Force.z * 0.5 * deltaT / p.mass();
}
}
return
s.applyForces();
// save the intermediate forces
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
(k2Forces.get( i )).set( p.force() );
(k2Velocities.get( i )).set( p.velocity() );
}
p.force().clear(); // and clear the forces now that we are done with them
}
/////////////////////////////////////////////////////
// get k3 values
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = (Particle)s.particles.get( i );
if ( p.isFree() )
{
Vector3D originalPosition = originalPositions.get( i );
Vector3D k2Velocity = k2Velocities.get( i );
p.position().x = originalPosition.x + k2Velocity.x * 0.5 * deltaT;
p.position().y = originalPosition.y + k2Velocity.y * 0.5 * deltaT;
p.position().z = originalPosition.z + k2Velocity.z * 0.5 * deltaT;
Vector3D originalVelocity = originalVelocities.get( i );
Vector3D k2Force = k2Forces.get( i );
p.velocity().x = originalVelocity.x + k2Force.x * 0.5 * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k2Force.y * 0.5 * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k2Force.z * 0.5 * deltaT / p.mass();
}
}
s.applyForces();
// save the intermediate forces
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
(k3Forces.get( i )).set( p.force() );
(k3Velocities.get( i )).set( p.velocity() );
}
p.force().clear(); // and clear the forces now that we are done with them
}
//////////////////////////////////////////////////
// get k4 values
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
Vector3D originalPosition = (Vector3D)originalPositions.get( i );
Vector3D k3Velocity = (Vector3D)k3Velocities.get( i );
p.position().x = originalPosition.x + k3Velocity.x * deltaT;
p.position().y = originalPosition.y + k3Velocity.y * deltaT;
p.position().z = originalPosition.z + k3Velocity.z * deltaT;
Vector3D originalVelocity = (Vector3D)originalVelocities.get( i );
Vector3D k3Force = (Vector3D)k3Forces.get( i );
p.velocity().x = originalVelocity.x + k3Force.x * deltaT / p.mass();
p.velocity().y = originalVelocity.y + k3Force.y * deltaT / p.mass();
p.velocity().z = originalVelocity.z + k3Force.z * deltaT / p.mass();
}
}
s.applyForces();
// save the intermediate forces
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
if ( p.isFree() )
{
(k4Forces.get( i )).set( p.force() );
(k4Velocities.get( i )).set( p.velocity() );
}
}
/////////////////////////////////////////////////////////////
// put them all together and what do you get?
for ( int i = 0; i < s.particles.size(); ++i )
{
Particle p = s.particles.get( i );
p.age += deltaT;
if ( p.isFree() )
{
// update position
Vector3D originalPosition = originalPositions.get( i );
Vector3D k1Velocity = k1Velocities.get( i );
Vector3D k2Velocity = k2Velocities.get( i );
Vector3D k3Velocity = k3Velocities.get( i );
Vector3D k4Velocity = k4Velocities.get( i );
p.position().x = originalPosition.x + deltaT / 6.0 * ( k1Velocity.x + 2.0*k2Velocity.x + 2.0*k3Velocity.x + k4Velocity.x );
p.position().y = originalPosition.y + deltaT / 6.0 * ( k1Velocity.y + 2.0*k2Velocity.y + 2.0*k3Velocity.y + k4Velocity.y );
p.position().z = originalPosition.z + deltaT / 6.0 * ( k1Velocity.z + 2.0*k2Velocity.z + 2.0*k3Velocity.z + k4Velocity.z );
// update velocity
Vector3D originalVelocity = originalVelocities.get( i );
Vector3D k1Force = k1Forces.get( i );
Vector3D k2Force = k2Forces.get( i );
Vector3D k3Force = k3Forces.get( i );
Vector3D k4Force = k4Forces.get( i );
p.velocity().x = originalVelocity.x + deltaT / ( 6.0 * p.mass() ) * ( k1Force.x + 2.0*k2Force.x + 2.0*k3Force.x + k4Force.x );
p.velocity().y = originalVelocity.y + deltaT / ( 6.0 * p.mass() ) * ( k1Force.y + 2.0*k2Force.y + 2.0*k3Force.y + k4Force.y );
p.velocity().z = originalVelocity.z + deltaT / ( 6.0 * p.mass() ) * ( k1Force.z + 2.0*k2Force.z + 2.0*k3Force.z + k4Force.z );
}
}
}
}
//Next File//***************************************************************
//* Spring
//**************************************************************/
public class Spring
{
float springConstant;
float myDamping;
float myRestLength;
Particle a, b;
boolean on;
public Spring( Particle A, Particle B, float ks, float d, float r )
{
springConstant = ks;
myDamping = d;
myRestLength = r;
a = A;
b = B;
on = true;
}
public void turnOff()
{
on = false;
}
public void turnOn()
{
on = true;
}
public boolean isOn()
{
return on;
}
public boolean isOff()
{
return !on;
}
public Particle getOneEnd()
{
return a;
}
public Particle getTheOtherEnd()
{
return b;
}
public float currentLength()
{
return a.position().distanceTo( b.position() );
}
public float restLength()
{
return myRestLength;
}
public float strength()
{
return springConstant;
}
public void setStrength( float ks )
{
springConstant = ks;
}
public float damping()
{
return myDamping;
}
public void setDamping( float d )
{
myDamping = d;
}
public void setRestLength( float l )
{
myRestLength = l;
}
public void apply()
{
if ( on && ( a.isFree() || b.isFree() ) )
{
float a2bX = a.position().x - b.position().x;
float a2bY = a.position().y - b.position().y;
float a2bZ = a.position().z - b.position().z;
float a2bDistance = (float)Math.sqrt( a2bX*a2bX + a2bY*a2bY + a2bZ*a2bZ );
if ( a2bDistance == 0 )
{
a2bX = 0;
a2bY = 0;
a2bZ = 0;
}
else
{
a2bX /= a2bDistance;
a2bY /= a2bDistance;
a2bZ /= a2bDistance;
}
// spring force is proportional to how much it stretched
float springForce = -( a2bDistance - myRestLength ) * springConstant;
// want velocity along line b/w a & b, damping force is proportional to this
float Va2bX = a.velocity().x - b.velocity().x;
float Va2bY = a.velocity().y - b.velocity().y;
float Va2bZ = a.velocity().z - b.velocity().z;
float dampingForce = -myDamping * ( a2bX*Va2bX + a2bY*Va2bY + a2bZ*Va2bZ );
// forceB is same as forceA in opposite direction
float r = springForce + dampingForce;
a2bX *= r;
a2bY *= r;
a2bZ *= r;
if ( a.isFree() )
a.force().add( a2bX, a2bY, a2bZ );
if ( b.isFree() )
b.force().add( -a2bX, -a2bY, -a2bZ );
}
}
public void setA( Particle p )
{
a = p;
}
public void setB( Particle p )
{
b = p;
}
}
//Next File//***************************************************************
//* Value (This version was taken from Resource.pjs and is much shorter than the unused standalone Value class in value.pjs)
//**************************************************************/
public class Value {
String id = "";
String name = "";
String html = "";
Attribute attr;
boolean hovering = false; // shares the hovering property from the slice
public Value(String id, String name, Attribute attr) {
this.id = id;
this.name = name;
this.attr = attr;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
//Next File//***************************************************************
//* Vector3D
//**************************************************************/
public class Vector3D
{
float x;
float y;
float z;
public Vector3D( float X, float Y, float Z ) {
x = X;
y = Y;
z = Z;
}
// public Vector3D() { x = 0; y = 0; z = 0; }
// public Vector3D( Vector3D p ) { x = p.x; y = p.y; z = p.z; }
// access these attributes using p.x etc.
// public float z() { return z; }
// public float y() { return y; }
// public float x() { return x; }
public void setX( float X ) {
x = X;
}
public void setY( float Y ) {
y = Y;
}
public void setZ( float Z ) {
z = Z;
}
public void set( float X, float Y, float Z ) {
x = X;
y = Y;
z = Z;
}
public void set( Vector3D p ) {
x = p.x;
y = p.y;
z = p.z;
}
public void add( Vector3D p ) {
x += p.x;
y += p.y;
z += p.z;
}
public void subtract( Vector3D p ) {
x -= p.x;
y -= p.y;
z -= p.z;
}
public void add( float a, float b, float c ) {
x += a;
y += b;
z += c;
}
public void subtract( float a, float b, float c ) {
x -= a;
y -= b;
z -= c;
}
public Vector3D multiplyBy( float f ) {
x *= f;
y *= f;
z*= f;
return this;
}
public float distanceTo( Vector3D p ) {
return (float)Math.sqrt( distanceSquaredTo( p ) );
}
public float distanceSquaredTo( Vector3D p ) {
float dx = x-p.x;
float dy = y-p.y;
float dz = z-p.z;
return dx*dx + dy*dy + dz*dz;
}
public float distanceTo( float x, float y, float z )
{
float dx = this.x - x;
float dy = this.y - y;
float dz = this.z - z;
return (float)Math.sqrt( dx*dx + dy*dy + dz*dz );
}
public float dot( Vector3D p ) {
return x*p.x + y*p.y + z*p.z;
}
public float length() {
return (float)Math.sqrt( x*x + y*y + z*z );
}
public float lengthSquared() {
return x*x + y*y + z*z;
}
public void clear() {
x = 0;
y = 0;
z = 0;
}
public String toString() {
return new String( "(" + x + ", " + y + ", " + z + ")" );
}
public Vector3D cross( Vector3D p )
{
return new Vector3D( this.y*p.z - this.z*p.y,
this.x*p.z - this.z*p.x,
this.x*p.y - this.y*p.x );
}
public boolean isZero()
{
return x == 0 && y == 0 && z == 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment