Skip to content

Commit

Permalink
Update extension to allow functions for some options iVis-at-Bilkent/…
Browse files Browse the repository at this point in the history
  • Loading branch information
hasanbalci committed Dec 29, 2020
1 parent 9fec803 commit 6d85b7e
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 43 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ var defaultOptions = {
// Whether to enable incremental mode
randomize: true,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: 4500,
// Ideal (intra-graph) edge length
idealEdgeLength: 50,
nodeRepulsion: function ( node ){ return 4500; },
// Ideal edge (non nested) length
idealEdgeLength: function (edge){ return 50; },
// Divisor to compute edge forces
edgeElasticity: 0.45,
edgeElasticity: function ( edge ){ return 0.45; },
// Nesting factor (multiplier) to compute ideal edge length for inter-graph edges
nestingFactor: 0.1,
// Gravity force (constant)
Expand Down
70 changes: 53 additions & 17 deletions cytoscape-cose-bilkent.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,17 @@ var defaults = {
// Whether to enable incremental mode
randomize: true,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: 4500,
nodeRepulsion: function nodeRepulsion(node) {
return 4500;
},
// Ideal edge (non nested) length
idealEdgeLength: 50,
idealEdgeLength: function idealEdgeLength(edge) {
return 50;
},
// Divisor to compute edge forces
edgeElasticity: 0.45,
edgeElasticity: function edgeElasticity(edge) {
return 0.45;
},
// Nesting factor (multiplier) to compute ideal edge length for nested edges
nestingFactor: 0.1,
// Gravity force (constant)
Expand Down Expand Up @@ -165,15 +171,24 @@ function extend(defaults, options) {
return obj;
};

function isFn(fn) {
return typeof fn === 'function';
};

function optFn(opt, ele) {
if (isFn(opt)) {
return opt(ele);
} else {
return opt;
}
};

function _CoSELayout(_options) {
this.options = extend(defaults, _options);
getUserOptions(this.options);
}

var getUserOptions = function getUserOptions(options) {
if (options.nodeRepulsion != null) CoSEConstants.DEFAULT_REPULSION_STRENGTH = FDLayoutConstants.DEFAULT_REPULSION_STRENGTH = options.nodeRepulsion;
if (options.idealEdgeLength != null) CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;
if (options.edgeElasticity != null) CoSEConstants.DEFAULT_SPRING_STRENGTH = FDLayoutConstants.DEFAULT_SPRING_STRENGTH = options.edgeElasticity;
if (options.nestingFactor != null) CoSEConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = options.nestingFactor;
if (options.gravity != null) CoSEConstants.DEFAULT_GRAVITY_STRENGTH = FDLayoutConstants.DEFAULT_GRAVITY_STRENGTH = options.gravity;
if (options.numIter != null) CoSEConstants.MAX_ITERATIONS = FDLayoutConstants.MAX_ITERATIONS = options.numIter;
Expand Down Expand Up @@ -215,16 +230,7 @@ _CoSELayout.prototype.run = function () {

this.root = gm.addRoot();
this.processChildrenList(this.root, this.getTopMostNodes(nodes), layout);

for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var sourceNode = this.idToLNode[edge.data("source")];
var targetNode = this.idToLNode[edge.data("target")];
if (sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0) {
var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
e1.id = edge.id();
}
}
this.processEdgeList(this.gm, edges, layout);

var getPositions = function getPositions(ele, i) {
if (typeof ele === "number") {
Expand Down Expand Up @@ -395,8 +401,9 @@ _CoSELayout.prototype.processChildrenList = function (parent, children, layout)
} else {
theNode = parent.add(new CoSENode(this.graphManager));
}
// Attach id to the layout node
// Attach id and repulsion value to the layout node
theNode.id = theChild.data("id");
theNode.nodeRepulsion = optFn(this.options.nodeRepulsion, theChild);
// Attach the paddings of cy node to layout node
theNode.paddingLeft = parseInt(theChild.css('padding'));
theNode.paddingTop = parseInt(theChild.css('padding'));
Expand Down Expand Up @@ -432,6 +439,35 @@ _CoSELayout.prototype.processChildrenList = function (parent, children, layout)
}
};

_CoSELayout.prototype.processEdgeList = function (gm, edges, layout) {
var idealLengthTotal = 0;
var edgeCount = 0;

for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var sourceNode = this.idToLNode[edge.data("source")];
var targetNode = this.idToLNode[edge.data("target")];
if (sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0) {
var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
e1.id = edge.id();
e1.idealLength = optFn(this.options.idealEdgeLength, edge);
e1.edgeElasticity = optFn(this.options.edgeElasticity, edge);
idealLengthTotal += e1.idealLength;
edgeCount++;
}
}
// we need to update the ideal edge length constant with the avg. ideal length value after processing edges
// in case there is no edge, use other options
if (this.options.idealEdgeLength != null) {
if (edges.length > 0) CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = idealLengthTotal / edgeCount;else if (!isFn(options.idealEdgeLength)) // in case there is no edge, but option gives a value to use
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;else // in case there is no edge and we cannot get a value from option (because it's a function)
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = 50;
// we need to update these constant values based on the ideal edge length constant
CoSEConstants.MIN_REPULSION_DIST = FDLayoutConstants.MIN_REPULSION_DIST = FDLayoutConstants.DEFAULT_EDGE_LENGTH / 10.0;
CoSEConstants.DEFAULT_RADIAL_SEPARATION = FDLayoutConstants.DEFAULT_EDGE_LENGTH;
}
};

/**
* @brief : called on continuous layouts to stop them before they finish
*/
Expand Down
73 changes: 51 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ var defaults = {
// Whether to enable incremental mode
randomize: true,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: 4500,
nodeRepulsion: function ( node ){ return 4500; },
// Ideal edge (non nested) length
idealEdgeLength: 50,
idealEdgeLength: function (edge){ return 50; },
// Divisor to compute edge forces
edgeElasticity: 0.45,
edgeElasticity: function ( edge ){ return 0.45; },
// Nesting factor (multiplier) to compute ideal edge length for nested edges
nestingFactor: 0.1,
// Gravity force (constant)
Expand Down Expand Up @@ -78,18 +78,24 @@ function extend(defaults, options) {
return obj;
};

function isFn(fn) {
return typeof fn === 'function';
};

function optFn(opt, ele) {
if (isFn(opt)) {
return opt(ele);
} else {
return opt;
}
};

function _CoSELayout(_options) {
this.options = extend(defaults, _options);
getUserOptions(this.options);
}

var getUserOptions = function (options) {
if (options.nodeRepulsion != null)
CoSEConstants.DEFAULT_REPULSION_STRENGTH = FDLayoutConstants.DEFAULT_REPULSION_STRENGTH = options.nodeRepulsion;
if (options.idealEdgeLength != null)
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;
if (options.edgeElasticity != null)
CoSEConstants.DEFAULT_SPRING_STRENGTH = FDLayoutConstants.DEFAULT_SPRING_STRENGTH = options.edgeElasticity;
if (options.nestingFactor != null)
CoSEConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = options.nestingFactor;
if (options.gravity != null)
Expand Down Expand Up @@ -146,19 +152,9 @@ _CoSELayout.prototype.run = function () {

this.root = gm.addRoot();
this.processChildrenList(this.root, this.getTopMostNodes(nodes), layout);


for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var sourceNode = this.idToLNode[edge.data("source")];
var targetNode = this.idToLNode[edge.data("target")];
if(sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0){
var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
e1.id = edge.id();
}
}
this.processEdgeList(this.gm, edges, layout);

var getPositions = function(ele, i){
var getPositions = function(ele, i){
if(typeof ele === "number") {
ele = i;
}
Expand Down Expand Up @@ -331,8 +327,9 @@ _CoSELayout.prototype.processChildrenList = function (parent, children, layout)
else {
theNode = parent.add(new CoSENode(this.graphManager));
}
// Attach id to the layout node
// Attach id and repulsion value to the layout node
theNode.id = theChild.data("id");
theNode.nodeRepulsion = optFn(this.options.nodeRepulsion, theChild);
// Attach the paddings of cy node to layout node
theNode.paddingLeft = parseInt( theChild.css('padding') );
theNode.paddingTop = parseInt( theChild.css('padding') );
Expand Down Expand Up @@ -368,6 +365,38 @@ _CoSELayout.prototype.processChildrenList = function (parent, children, layout)
}
};

_CoSELayout.prototype.processEdgeList = function (gm, edges, layout) {
var idealLengthTotal = 0;
var edgeCount = 0;

for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var sourceNode = this.idToLNode[edge.data("source")];
var targetNode = this.idToLNode[edge.data("target")];
if(sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0){
var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
e1.id = edge.id();
e1.idealLength = optFn(this.options.idealEdgeLength, edge);
e1.edgeElasticity = optFn(this.options.edgeElasticity, edge);
idealLengthTotal += e1.idealLength;
edgeCount++;
}
}
// we need to update the ideal edge length constant with the avg. ideal length value after processing edges
// in case there is no edge, use other options
if (this.options.idealEdgeLength != null){
if (edges.length > 0)
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = idealLengthTotal / edgeCount;
else if(!isFn(options.idealEdgeLength)) // in case there is no edge, but option gives a value to use
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;
else // in case there is no edge and we cannot get a value from option (because it's a function)
CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = 50;
// we need to update these constant values based on the ideal edge length constant
CoSEConstants.MIN_REPULSION_DIST = FDLayoutConstants.MIN_REPULSION_DIST = FDLayoutConstants.DEFAULT_EDGE_LENGTH / 10.0;
CoSEConstants.DEFAULT_RADIAL_SEPARATION = FDLayoutConstants.DEFAULT_EDGE_LENGTH;
}
};

/**
* @brief : called on continuous layouts to stop them before they finish
*/
Expand Down

0 comments on commit 6d85b7e

Please sign in to comment.