5. Node Graph
• Uses Canvas (via the HTML5 getContext()
object.
• The getContext("2d") object has methods to
draw lines, boxes, circles, and more.
• Uses the Arbor js framework to store nodes
and edges and handle updating their
coordinates as the simulation progresses.
6. Node Graph - Creation
arbor.ParticleSystem()
• Parameters
– Repulsion (the force repelling nodes from each other)
– Stiffness (600 the rigidity of the edges)
– Friction (the amount of damping in the system)
– Gravity (an additional force attracting nodes to the origin)
– Fps (frames per second)
– Dt (timestep to use for stepping the simulation)
– Precision (accuracy vs. speed in force calculations
(zero is fast but jittery, one is smooth but cpu-intensive)
(stored in web.config passed to the view)
7. Feeding the graph
• Three calls to the server for graph data
loadInitialData
loadChildNodes
search
8. Feed the graph… “NodeGraphDTO”
• JSON from the server “NodeGraphDTO”
9. Feed the graph… “NodeGraphDTO”
• Lists of :
Entities Relationships
10. Feed the graph… API
foreach(grant in Grants){
If (showGrants()) {
ParticleSystem.addNode(
Id,
{data we define such as
size, colour, label text
etc })
}
}
… Do for each type in NodeGraphDTO
11. Feed the graph… API
if(showPeople() && showGrants(){
foreach (rel in grantPersons) {
get the grant
get the person
ParticleSystem.addEdge(
grantId
personId
}
}
12. Node Graph – API Callbacks
• redraw() Gets called repeatedly for each
frame
• We handle callbacks for:
– particleSystem.eachEdge(edge, pt1 pt2)
• Draw a gradient line between pt1 and pt2
– particleSystem.eachNode(node, pt)
• Work out what type of node we have
• Draw it out accordingly (Shape? ,Text? Size? Colour?)
13. Node Graph – API Callbacks
• initMouseHandling
– Moved used to determine whether to display
hover text
– Clicked
– Dragged
– Dropped determine whether to load child
nodes and quick details
14. JS – (as DRY as possible?)
$(document).ready(function () {
//Instantiate control objects
_restoreManager = new RestoreManager();
_state = new SystemState();
_aData = new DataHandler();
_controlsManager = new ControlsManager();
_nodeController = new NodeController();
//Initialise controls
_controlsManager.initialiseControls();
//Load initial data
_aData.loadInitialData();
});
15. General Usage
//Define object function ‘ControlsManager’
function ControlsManager() {
var self = this;
//Fix context of ‘this’ to the object
function
self.aPublicFunction = function(param) {
//I’m public
}
function aPrivateFunction (){
I’m private//
}
}
16. ControlsManager
//Define controls once as private
var showGrantsChk =
$("input:checkbox[id=ShowGran
ts]");
var showOutcomesChk =
$("input:checkbox[id=ShowOutc
omes]");
etc…
17. ControlsManager
//access them via public functions
self.initialiseControls =
function () {
…on(‘click’,…) etc.
}
self.clearDetails =
function() {…}
18. DataHandler
self.saveNodeGraphData(data) {
//Stores NodeGraphDTO object
//from server
}
self.childData = [];
//can contain child DataHandler(s)
//retrieved when clicking on nodes
self.addChildData(childDataHandler)
21. NodeController
self.doGraphObjects() {
buildThemes();
buildPeople();
//and all other nodes
buildPeopleToGrantEdges();
//and all other edges
for (var i = 0; i <
_aData.childData.length; i++) {
var childDataHandler =
_aData.childData[i];
self.doChildObjects
(childDataHandler);
}
}
24. NodeController -
buildPeopleToGrantEdges
buildPeopleToGrantEdges () {
if (_state.showPeople() && _state.showGrants()) {
for (var i = 0; i <
_aData.peopleToGrants.length; i++) {
var pg = _aData.peopleToGrants[i];
var personNode = sys.getNode(pg.PersonId);
var grantNode = sys.getNode(pg.GrantId);
if (personNode !=undefined && grantNode !=
undefined) {
sys.addEdge(pg.PersonId, pg.GrantId,
{ color: edgeColour });
}
}
}
};
25. NodeControler - doChildObjects
self.doChildObjects = function(cData){
var parent = sys.getNode
(cData.rootData.Id);
//If the parent is null it is not
//a child object so do nothing
if (parent != undefined) {
addChildPeopleNodes(parent,
cData.peopleData);
//And all the other types
//(grants…, research areas…)
}
};
26. NodeController -
addCildPeopleNodes
function addChildPeopleNodes(parentNode, peopleDataArr) {
if (_state.showPeople()) {
for (var i = 0; i < peopleDataArr.length; i++) {
var person = peopleDataArr[i];
//If the node is root it ain’t a child!
if (!_state.isCurrentRoot(person.Id)) {
var exisitng = sys.getNode(person.Id);
if (exisitng == undefined) {
addPersonNode(person);
_aData.addNodeId(person.Id);
}
sys.addEdge(
parentNode.data.display,
person.Id, { color: edgeColour });
}
}
}
}