Created
August 19, 2015 17:29
-
-
Save moebio/ec78bdeb94085f166899 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
draw = function(g){ | |
c.l('***', g); | |
g.setStroke('black', 2); | |
g.line(0,0,g.cW,g.cH); | |
if(network == null) return; | |
if(MODE==2 || MODE==8) { | |
var i; | |
for(i=0; i<configuration.physics.nStepsPerframe; i++){ | |
forces(); | |
} | |
} | |
if(e3D) forces3D(); | |
if(MODE==7){ | |
var rSphere; | |
if(clustersTable){ | |
var i = 0; | |
clustersTable.forEach(function(nodeList){ | |
rSphere = 200 - 150*i/clustersTable.length; | |
i++; | |
nodeList.forEach(function(node){ | |
var norm = Math.sqrt(Math.pow(node._x, 2) + Math.pow(node._y, 2) + Math.pow(node._z, 2)); | |
node._x = rSphere*node._x/norm; | |
node._y = rSphere*node._y/norm; | |
node._z = rSphere*node._z/norm; | |
}); | |
}); | |
} else { | |
rSphere = 150; | |
network.nodeList.forEach(function(node){ | |
var norm = Math.sqrt(Math.pow(node._x, 2) + Math.pow(node._y, 2) + Math.pow(node._z, 2)); | |
node._x = rSphere*node._x/norm; | |
node._y = rSphere*node._y/norm; | |
node._z = rSphere*node._z/norm; | |
}); | |
} | |
} | |
//project nodes | |
if(e3D==null){ | |
network.nodeList.forEach(function(node){ | |
projectNode(node) | |
}); | |
} | |
//loops | |
if(configuration.loops.show && loops) drawLoops(g); | |
//draw relations | |
thicknesFadingRelations = 0.9*thicknesFadingRelations + 0.1*( ( (!prevNodeOver && !prevRelationOver) || nodePressed )?1:0 ); | |
if(!MOVING_RELATIONS && toGenerateRelationsCapture && configuration.relations.RELATIONS_BITMAP_ON_STASIS){ | |
clearTimeout(timerGenerateCapture); | |
timerGenerateCapture = setTimeout(generateCaptureAllRelations, 100); | |
waitingToGenerateCapture = true; | |
toGenerateRelationsCapture = false; | |
} | |
if(MOVING_RELATIONS || !configuration.relations.RELATIONS_BITMAP_ON_STASIS){ | |
if(e3D==null) drawRelations(g); | |
} else { | |
if(!waitingToGenerateCapture) g.drawImage(captureAllRelations,0,0); | |
} | |
//draw nodes | |
drawNodes(g); | |
if(nodeOver) relationOver = null; | |
//draw cluster circles and forces | |
if(MODE==8 && clusterCircles) drawClustersCircles(g); | |
//general info | |
if(configuration.graphic.displayInfo){ | |
g.setText('black', 12); | |
g.setStroke('white', 3); | |
g.fsText("n nodes: "+network.nodeList.length+", n relations:"+network.relationList.length, 12, 12); | |
g.fsText("friction: "+Math.floor(friction*1000)/1000+", kEq:"+kEq+", kSep:"+kSep+", forces "+(MOVING_RELATIONS?'active':'inactive'), 12, 26); | |
g.fsText("ANTI_COLLISION_FACTOR: "+Math.floor(ANTI_COLLISION_FACTOR*1000)/1000, 12, 40); | |
g.fsText("scale, centerX, centerY: "+Math.floor(scale*100)/100+", "+Math.floor(centerX*100)/100+", "+Math.floor(centerY*100)/100, 12, 54); | |
} | |
if(g.MOUSE_UP_FAST){ | |
selectedNode = nodeOver; | |
selectedRelation = relationOver; | |
if(selectedNode!=null){ | |
lastSelectedNode = selectedNode; | |
placeNodesInSelectionLayout(selectedNode); | |
} else { | |
selectionLayout = false; | |
pathsLayout = false; | |
} | |
} | |
if(nodeOver && g.MOUSE_DOWN){//} && !selectionLayout){ | |
nodePressed = nodeOver; | |
xOnNode = g.mX - nodePressed._x; | |
yOnNode = g.mY - nodePressed._y; | |
} | |
if(relationOver && g.MOUSE_DOWN) relationPressed = relationOver; | |
if(nodePressed && g.T_MOUSE_PRESSED>400 && g.mX==g.mX_DOWN && g.mY==g.mY_DOWN){ | |
nodeSuperPressed = nodePressed; | |
nodePressed = null; | |
} | |
//superpressed | |
if(nodeSuperPressed){ | |
//c.l('--> nodeSuperPressed', nodeSuperPressed.id); | |
var R = 40; | |
var R2 = R+3; | |
g.setStroke('rgba(255,0,0,0.5)', 6); | |
g.sCircle(nodeSuperPressed._x, nodeSuperPressed._y, R); | |
var dx = g.mX-nodeSuperPressed._x; | |
var dy = g.mY-nodeSuperPressed._y; | |
var angle = Math.atan2(dy, dx); | |
if(nodeOver && nodeOver!=nodeSuperPressed){ | |
g.line(nodeSuperPressed._x + R2*Math.cos(angle), nodeSuperPressed._y + R2*Math.sin(angle), nodeOver._x - R2*Math.cos(angle), nodeOver._y - R2*Math.sin(angle)); | |
g.sCircle(nodeOver._x, nodeOver._y, R); | |
} else { | |
if( (dx*dx+dy*dy) >R2*R2) g.line(nodeSuperPressed._x + R2*Math.cos(angle), nodeSuperPressed._y + R2*Math.sin(angle), g.mX, g.mY); | |
} | |
} | |
//tooltip | |
if(!g.MOUSE_PRESSED){ | |
if( nodeOver!=null && configuration.nodes.tooltip.show && (Math.pow(nodeOver._x-g.mX, 2)+Math.pow(nodeOver._y-g.mY, 2)<40) ){ | |
drawToolTip(g, nodeOver); | |
} else if( relationOver!=null && configuration.relations.tooltip.show ) drawToolTip(g, relationOver); | |
} | |
if(g.MOUSE_UP){ | |
nodePressed = null; | |
relationPressed = null; | |
__storedFirstShortPath = null; | |
clearInterval(__shortestPathsTimer); | |
if(nodeSuperPressed && nodeOver && nodeSuperPressed!=nodeOver){ | |
placeNodesShortestPaths(nodeSuperPressed, nodeOver); | |
selectedRelation = network.relationList.getFirstRelationBetweenNodes(nodeSuperPressed, nodeOver); | |
} | |
nodeSuperPressed = null; | |
} | |
///send data | |
var send = false; | |
//nodes | |
if(nodeOver!=prevNodeOver){ | |
outputArray[0].value = nodeOver; | |
if(nodeOver!=null) outputArray[1].value = nodeOver; | |
send = true; | |
} | |
if(selectedNode!=outputArray[2].value){ | |
outputArray[2].value = selectedNode; | |
if(selectedNode!=null) outputArray[3].value = selectedNode; | |
send = true; | |
} | |
//relation | |
if(relationOver!=prevRelationOver){ | |
outputArray[4].value = relationOver; | |
if(relationOver!=null) outputArray[5].value = relationOver; | |
send = true; | |
} | |
if(selectedRelation!=outputArray[6].value){ | |
outputArray[6].value = selectedRelation; | |
if(selectedRelation!=null) outputArray[7].value = selectedRelation; | |
send = true; | |
} | |
if(send){ | |
outputArray = [outputArray[0], outputArray[1], outputArray[2], outputArray[3], outputArray[4], outputArray[5], outputArray[6], outputArray[7], outputArray[8], outputArray[9]]; | |
outputArray.isOutput = true; | |
__sendData(outputArray); | |
} | |
prevNodeOver = nodeOver; | |
prevRelationOver = relationOver; | |
if(nodeOver) lastNodeOver = nodeOver; | |
if(relationOver) lastRelationOver = relationOver; | |
//positions memory | |
if(nMemorizedPositions>0 && nF%200==0){ | |
var i; | |
for(i=0; network.nodeList[i]!=null; i++){ | |
pair = [ Math.round(network.nodeList[i].x), Math.round(network.nodeList[i].y) ]; | |
positionsMemory[network.id+"@"+network.nodeList[i].id] = pair; | |
} | |
__saveData(positionsMemory); | |
} else if(nMemorizedPositions==-1){ | |
__saveData({}); | |
} | |
} | |
drawToolTip = function(g, node){ | |
var x = g.mX; | |
var y = g.mY; | |
var w = configuration.nodes.tooltip.width; | |
var x0 = x; | |
var title; | |
var content; | |
var contentLines; | |
var list; | |
if(node.type=='Node'){ | |
title = node[configuration.nodes.tooltip.titleProperty]; | |
content = node[configuration.nodes.tooltip.contentProperty]; | |
} else { | |
title = node[configuration.relations.tooltip.titleProperty]; | |
content = node[configuration.relations.tooltip.contentProperty]; | |
} | |
content = content==null?"":content; | |
g.setText('white', 14, null, null, null, 'bold'); | |
var wTitle = g.getTextW(title); | |
w = content==""?(wTitle+10):(Math.max(w, wTitle+10)); | |
if(configuration.nodes.tooltip.image && node.image) w = Math.max(w, node.image.width+10); | |
if(content==""){ | |
contentLines = []; | |
} else { | |
g.setText('white', 12); | |
contentLines = mo.DrawTexts.textWordWrapReturnLines(content, w-10, 0, 12); | |
} | |
var h = 30 + 12*contentLines.length; | |
var y0 = y - h - 20; | |
if(configuration.nodes.tooltip.image && node.image){ | |
h += node.image.height+10; | |
y0 -= node.image.height+10; | |
} | |
g.setFill('rgb(50,50,50)'); | |
g.fLines( | |
x, y, | |
x0,y-20, | |
x0,y0, | |
x0+w,y0, | |
x0+w,y0+h, | |
x+20,y0+h | |
); | |
if(configuration.nodes.tooltip.image && node.image){ | |
g.drawImage(node.image, x0+5, y0+5); | |
y0+=node.image.height+10; | |
} | |
g.setText('white', 14, null, null, null, 'bold'); | |
g.fText(title, x0+5, y0+5); | |
g.setText('white', 12); | |
mo.DrawTexts.fillTextRectangleWithTextLines(contentLines, x0+5, y0+20, 0, 12,null,g);//TODO:update this when fillTextRectangleWithTextLines updates and receives g as 1st param | |
} | |
generateCaptureAllRelations = function(){ | |
captureAllRelations = drawAndcapture(drawRelations, cW,cH); | |
waitingToGenerateCapture = false; | |
} | |
////loops | |
/// | |
drawLoops = function(g){ | |
mo.c.l(configuration.loops.colors, configuration.loops.dashed); | |
g.setStroke(configuration.loops.color, configuration.loops.thickness); | |
if(configuration.loops.dashed) g.context.setLineDash([2,3]); | |
loops.forEach(function(loop){ | |
if(configuration.loops.colors) g.setStroke(loop.color, configuration.loops.thickness); | |
for(i=0; loop[i]!=null; i++){ | |
loop.polygon[i].x = loop[i]._x; | |
loop.polygon[i].y = loop[i]._y; | |
} | |
_drawSmoothPolygon(g, loop.polygon, true, 80*scale); | |
}); | |
g.context.setLineDash([]); | |
} | |
_drawSmoothPolygon = function(g, polygon, closed, amount) { | |
amount = amount==null?30:amount; | |
var controlPoints; | |
if(polygon.length<2) return null; | |
g.context.beginPath(); | |
if(polygon.length==2){ | |
var a = Math.atan2(polygon[1].y-polygon[0].y, polygon[1].x-polygon[0].x)-0.5*Math.PI; | |
var cosa = amount*Math.cos(a); | |
var sina = amount*Math.sin(a); | |
g.context.moveTo(polygon[0].x, polygon[0].y); | |
g.context.bezierCurveTo( | |
polygon[0].x + cosa, polygon[0].y + sina, | |
polygon[1].x + cosa, polygon[1].y + sina, | |
polygon[1].x, polygon[1].y | |
); | |
g.context.bezierCurveTo( | |
polygon[1].x - cosa, polygon[1].y - sina, | |
polygon[0].x - cosa, polygon[0].y - sina, | |
polygon[0].x, polygon[0].y | |
); | |
g.context.stroke(); | |
return; | |
} | |
var i; | |
var nPoints = polygon.length; | |
var prevPoint = polygon[nPoints-1]; | |
var point = polygon[0]; | |
var nextPoint = polygon[1]; | |
controlPoints = mo.GeometryOperators.getSoftenControlPoints(prevPoint, point, nextPoint, amount); | |
var prevCP = controlPoints[1]; | |
var cP; | |
g.context.moveTo(point.x, point.y); | |
prevPoint = point; | |
var arrows = []; | |
for(i=1;i<nPoints+1;i++){ | |
point = polygon[i%nPoints]; | |
nextPoint = polygon[(i+1)%nPoints]; | |
controlPoints = GeometryOperators.getSoftenControlPoints(prevPoint, point, nextPoint, amount); | |
cP = controlPoints[0]; | |
g.context.bezierCurveTo(prevCP.x, prevCP.y, cP.x, cP.y, point.x, point.y); | |
//arrow | |
if(i%2==0){ | |
p0 = mo.GeometryOperators.bezierCurvePoints( | |
prevPoint.x, prevPoint.y, | |
prevCP.x, prevCP.y, | |
cP.x, cP.y, | |
point.x, point.y, | |
0.49 | |
); | |
p1 = mo.GeometryOperators.bezierCurvePoints( | |
prevPoint.x, prevPoint.y, | |
prevCP.x, prevCP.y, | |
cP.x, cP.y, | |
point.x, point.y, | |
0.51 | |
); | |
a = Math.atan2(p1.y-p0.y,p1.x-p0.x); | |
arrows.push((p0.x+p1.x)*0.5, (p0.y+p1.y)*0.5, a); | |
} | |
prevCP = controlPoints[1]; | |
prevPoint = point; | |
} | |
g.context.stroke(); | |
for(i=0; arrows[i]!=null;i+=3){ | |
//triangle(arrows[i], arrows[i+1], arrows[i+2]); | |
} | |
} | |
drawClustersCircles = function(g){ | |
var x, y, maxD; | |
var points; | |
var intensity = 1 - 0.01*friction; | |
var anti = 1 - intensity; | |
var circle, circle1; | |
var i, j; | |
var dx, dy, delta; | |
g.setStroke('black', 1); | |
clustersTable.forEach(function(nodeList, i){ | |
points = []; | |
circle = clusterCircles[i]; | |
//r = nodeList.length*5000; | |
// x = 0; | |
// y = 0; | |
// maxD = 0; | |
nodeList.forEach(function(node){ | |
// x+=node._x; | |
// y+=node._y; | |
// maxD = Math.max(maxD, Math.sqrt(Math.pow(circle.x-node._x, 2)+Math.pow(circle.y-node._y, 2))); | |
// if(Math.pow(node.x-anti*circle.x, 2)+Math.pow(node.y-anti*circle.y, 2)>r){ | |
node.x = intensity*node.x + anti*circle.x; | |
node.y = intensity*node.y + anti*circle.y; | |
// } | |
points.push({x:node._x, y:node._y}); | |
}); | |
// circle.x = x/nodeList.length; | |
// circle.y = y/nodeList.length; | |
// circle.r = maxD; | |
nc = makeCircle(points); | |
if(nc==null) nc = {x:0, y:0, r:0}; | |
circle.x = nc.x; | |
circle.y = nc.y; | |
circle.r = nc.r; | |
g.sCircle(circle.x, circle.y, circle.r+5); | |
}); | |
for(var mm=0; mm<20; mm++){ | |
var circles = clusterCircles.getSortedRandom(); | |
for(i=0; circles[i+1]!=null; i++){ | |
circle = circles[i]; | |
for(j=i+1; circles[j]!=null; j++){ | |
circle1 = circles[j]; | |
dx = circle1.x - circle.x; | |
dy = circle1.y - circle.y; | |
d = Math.sqrt(Math.pow(dx, 2)+Math.pow(dy, 2)); | |
delta = (circle.r+circle1.r+10)*1.1-d; | |
if(delta>0){ | |
delta*=0.2; | |
circle.x -= delta*dx; | |
circle.y -= delta*dy; | |
circle1.x += delta*dx; | |
circle1.y += delta*dy; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment