mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/triAGENS/ArangoDB into devel
This commit is contained in:
commit
302c516030
|
@ -155,5 +155,8 @@ function JSONAdapter(jsonPath, nodes, edges, width, height) {
|
|||
throw "Sorry this adapter is read-only";
|
||||
};
|
||||
|
||||
self.setNodeLimit = function (limit) {
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -530,4 +530,8 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
api.edge = api.base + "edge?collection=" + edgeCollection;
|
||||
};
|
||||
|
||||
self.setNodeLimit = function (limit) {
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -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];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -158,7 +158,9 @@
|
|||
jasmine.any(Object),
|
||||
jasmine.any(Object),
|
||||
jasmine.any(NodeShaper),
|
||||
jasmine.any(EdgeShaper)
|
||||
jasmine.any(EdgeShaper),
|
||||
{},
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
}());
|
Loading…
Reference in New Issue