1
0
Fork 0

Merge branch 'devel' of https://github.com/triAGENS/ArangoDB into devel

This commit is contained in:
Jan Steemann 2013-05-17 14:54:41 +02:00
commit 302c516030
9 changed files with 170 additions and 22 deletions

View File

@ -155,5 +155,8 @@ function JSONAdapter(jsonPath, nodes, edges, width, height) {
throw "Sorry this adapter is read-only";
};
self.setNodeLimit = function (limit) {
};
}

View File

@ -530,4 +530,8 @@ function ArangoAdapter(nodes, edges, config) {
api.edge = api.base + "edge?collection=" + edgeCollection;
};
self.setNodeLimit = function (limit) {
};
}

View File

@ -82,10 +82,13 @@ function NodeReducer(nodes, edges) {
});
},
joinCommunities = function(sID, lID, coms) {
var old = coms[sID] || [sID],
newC = coms[lID] || [lID];
coms[lID] = old.concat(newC);
joinCommunities = function(sID, lID, coms, heap, val) {
coms[sID] = coms[sID] || {com: [sID], q: 0};
coms[lID] = coms[lID] || {com: [lID], q: 0};
var old = coms[sID].com,
newC = coms[lID].com;
coms[lID].com = old.concat(newC);
coms[lID].q += coms[sID].q + val;
delete coms[sID];
},
@ -168,12 +171,93 @@ function NodeReducer(nodes, edges) {
delete a[sID];
},
sortBySize = function(a, b) {
return b.length - a.length;
},
neighbors = function(sID) {
var neigh = [];
_.each(edges, function(e) {
if (e.source._id === sID) {
neigh.push(e.target._id);
return;
}
if (e.target._id === sID) {
neigh.push(e.source._id);
return;
}
});
return neigh;
},
minDist = function(dist) {
return function(a) {
return dist[a];
}
},
dijkstra = function(sID) {
var dist = {},
toDo, next, neigh;
toDo = _.pluck(nodes, "_id");
_.each(toDo, function(n) {
dist[n] = Number.POSITIVE_INFINITY;
});
dist[sID] = 0;
while(toDo.length > 0) {
next = _.min(toDo, minDist(dist));
if (next === Number.POSITIVE_INFINITY) {
break;
}
toDo = toDo.filter(function(e) {return e !== next});
neigh = neighbors(next);
_.each(neigh, function(v) {
if (_.contains(toDo, v)) {
if (dist[v] > dist[next] + 1) {
dist[v] = dist[next] + 1;
}
}
});
}
return dist;
},
floatDistStep = function(dist, depth, todo) {
if (todo.length === 0) {
return true;
}
var nextTodo = [];
_.each(todo, function(t) {
if (dist[t] !== Number.POSITIVE_INFINITY) {
return;
}
dist[t] = depth;
nextTodo = nextTodo.concat(neighbors(t));
});
return floatDistStep(dist, depth+1, nextTodo);
},
floatDist = function(sID) {
var dist = {};
_.each(_.pluck(nodes, "_id"), function(n) {
dist[n] = Number.POSITIVE_INFINITY;
});
dist[sID] = 0;
if (floatDistStep(dist, 1, neighbors(sID))) {
return dist;
}
throw "FAIL!";
},
communityDetectionStep = function(dQ, a, heap, coms) {
//console.log("COMS: " + JSON.stringify(coms));
//console.log("HEAP: " + JSON.stringify(heap));
var l = getLargestOnHeap(heap);
if (l.val < 0) {
if (l === Number.NEGATIVE_INFINITY || l.val < 0) {
return false;
}
joinCommunities(l.sID, l.lID, coms);
joinCommunities(l.sID, l.lID, coms, heap, l.val);
updateValues(l, dQ, a, heap);
return true;
};
@ -184,22 +268,37 @@ function NodeReducer(nodes, edges) {
var dQ = {},
a = {},
heap = {},
q = 0,
coms = {},
res = [];
res = [],
dist = {},
dist2 = {},
sortByDistance = function (a, b) {
var d1 = dist[_.min(a,minDist(dist))],
d2 = dist[_.min(b,minDist(dist))],
val = d2 - d1;
if (val === 0) {
val = coms[b[b.length-1]].q - coms[a[a.length-1]].q;
}
return val;
};
if (nodes.length === 0 || edges.length === 0) {
throw "Load some nodes first.";
}
populateValues(dQ, a, heap);
var max = 0;
while (communityDetectionStep(dQ, a, heap, coms)) {
max++;
if (max > 100) {
break;
//console.log(max);
}
}
res = _.values(coms);
res.sort(function(a, b) {
return b.length - a.length;
});
if (_.contains(res[0], focus)) {
return res[1];
}
//console.log(max);
res = _.pluck(_.values(coms), "com");
dist = floatDist(focus._id);
res = res.filter(function(e) {return !_.contains(e, focus._id)});
res = res.filter(function(e) {return e.length > 1});
res.sort(sortByDistance);
return res[0];
};
}

View File

@ -29,7 +29,7 @@
////////////////////////////////////////////////////////////////////////////////
function ZoomManager(width, height, svg, g, nodeShaper, edgeShaper, config) {
function ZoomManager(width, height, svg, g, nodeShaper, edgeShaper, config, limitCallback) {
"use strict";
if (width === undefined || width < 0) {
@ -75,6 +75,7 @@ function ZoomManager(width, height, svg, g, nodeShaper, edgeShaper, config) {
baseDRadius,
size = width * height,
zoom,
limitCB = limitCallback || function() {},
calcNodeLimit = function () {
var div, reqSize;
@ -123,6 +124,7 @@ function ZoomManager(width, height, svg, g, nodeShaper, edgeShaper, config) {
.on("zoom", function() {
currentZoom = d3.event.scale;
currentLimit = calcNodeLimit();
limitCB(currentLimit);
nodeShaper.activateLabel(currentZoom >= labelToggle);
edgeShaper.activateLabel(currentZoom >= labelToggle);
calcDistortionValues();

View File

@ -84,10 +84,15 @@ function GraphViewer(svg, width, height, adapterConfig, config) {
}
},
nodeLimitCallBack = function(limit) {
self.adapter.setNodeLimit(limit);
},
parseZoomConfig = function(config) {
if (config) {
zoomManager = new ZoomManager(width, height, svg,
graphContainer, self.nodeShaper, self.edgeShaper);
graphContainer, self.nodeShaper, self.edgeShaper,
{}, nodeLimitCallBack);
}
},

View File

@ -65,6 +65,7 @@ var describeInterface = function (testee) {
expect(testee).toHaveFunction("createNode", 2);
expect(testee).toHaveFunction("deleteNode", 2);
expect(testee).toHaveFunction("patchNode", 3);
expect(testee).toHaveFunction("setNodeLimit", 1);
});
};

View File

@ -44,6 +44,7 @@ describe("Graph Viewer", function() {
beforeEach(function() {
docSVG = document.createElement("svg");
docSVG.id = "outersvg";
document.body.appendChild(docSVG);
svg = d3.select("svg");
window.communicationMock(spyOn);
@ -242,7 +243,7 @@ describe("Graph Viewer", function() {
if (window.ZoomManager === undefined) {
window.ZoomManager = {};
}
spyOn(window, "ZoomManager");
spyOn(window, "ZoomManager").andCallThrough();
adapterConfig = {type: "json", path: "../test_data/"};
var config = {
zoom: true
@ -257,10 +258,18 @@ describe("Graph Viewer", function() {
jasmine.any(Object),
jasmine.any(Object),
jasmine.any(NodeShaper),
jasmine.any(EdgeShaper)
jasmine.any(EdgeShaper),
{},
jasmine.any(Function)
);
});
it('should trigger the adapter if zoom level is changed', function() {
spyOn(viewer.adapter, "setNodeLimit");
helper.simulateScrollUpMouseEvent("outersvg");
expect(viewer.adapter.setNodeLimit).wasCalled();
});
});

View File

@ -158,7 +158,9 @@
jasmine.any(Object),
jasmine.any(Object),
jasmine.any(NodeShaper),
jasmine.any(EdgeShaper)
jasmine.any(EdgeShaper),
{},
jasmine.any(Function)
);
});

View File

@ -452,8 +452,31 @@
});
it('if a nodelimit callback is defined it should be invoked on zoom-in', function() {
var w = 200,
h = 200,
nl = -1 ,
callback = function(n) {
nl = n;
},
manager = new ZoomManager(w, h, svg, g, nodeShaperMock, edgeShaperMock, {}, callback);
simulateZoomIn();
expect(nl).toEqual(manager.getNodeLimit());
});
it('if a nodelimit callback is defined it should be invoked on zoom-out', function() {
var w = 200,
h = 200,
nl = -1 ,
callback = function(n) {
nl = n;
},
manager = new ZoomManager(w, h, svg, g, nodeShaperMock, edgeShaperMock, {}, callback);
simulateZoomOut();
expect(nl).toEqual(manager.getNodeLimit());
});
});
}());