Force positions of some nodes with CoSE Bilkent layout - javascript

I'm working with compound graphs. I know the positions (e.g.: geographic coordinates) of the parent nodes and I want to layout the children nodes in order to minimize the intersection of the edges. The final position of the children does not matter, provided that they are close to each other.
The CoSE Bilkent algorithm with Cytoscape.js gives me the right kind of layout but I would like to set the positions of the parent nodes and lock them in place.
What I've done:
Started with this example but with less nodes;
Set the position for each group:
Only the parent;
Same coordinates for parent and its children;
Adjusted some options of the layout;
Tried the attribute locked with no luck
The best I got is this.
So far, the relative positions of the groups is correct but if I add a new group g5 I got this.
The desired result would be something like this:
I'm open to use another library if needed.

(1) A parent's position and dimensions are implied by the positions and dimensions of its children.
(2) You can run a layout on a subset of the graph (e.g. children only): http://js.cytoscape.org/#collection/layout
(3) Avoiding edges from overlapping each other in a layout in a performant way is an active, unsolved research problem. Additionally, some graphs just aren't planar.
Try using (2) to run a layout on the subgraph of each parent's descendants:
var topLvlParents = cy.nodes().orphans(':parent');
topLvlParents.forEach(function( parent ){
var descendants = parent.descendants();
var edges = nodes.edgesWith( nodes );
descendants.union( edges ).layout( someLayoutOptions );
});
You can use cose-bilkent as the subgraph layout and adjust the positions to your desired bounding box on layoutstop (and this would be easier with boundingBox natively supported in cose-bilkent). Or you could use cose -- which isn't as sophisticated as cose-bilkent but allows for direct boundingBox placement today.
If your compound parent-child hierarchy is only one level, then you could try using any of the noncompound layouts on the children with boundingBox as well.
My understanding is that CoSE Bilkent is the most state of the art algorithm for compound node layout. It's from a university lab that specialises in graph theory, layouts, etc.

Related

Vis.js: Lessen layout noise for multiple central nodes (radial force)

I'm working with vis.js to display some graphs. The problem is that layouts with multiple central nodes get noisy (the central nodes' neighbours overlap). A layout similar to the attached image is desirable.
Is it possible to achieve this using vis.js?
Looks like there is an option that should solve your issue (I've found it after playing with physicsConfiguration like I suggested earlier):
physics has avoidOverlap property (float between 0 and 1) that can be used like this:
var options = {
...
physics: {
barnesHut: {
avoidOverlap: 0.5
},
...
}
}
If you try it in the configuration demo, you'll see that with avoidOverlap equal to 0 it's quite possible to drag and move nodes so that those overlap edges and the network stays in that position:
but once we increase this value, nodes start to be bounced from edges and can't really stay in that position:
Note though, that this option doesn't prevent edge-edge crossing, only edge-node overlapping (see physics/barnesHut/avoidOverlap). The physics docs page doesn't contain the word "cross" at all and each occurance of "overlap" is about edge-node thing.
So this will make the layout less noisy, but won't eliminate crossed edges.

Setting variable width on d3 tree nodes

I'm using d3 to create an Org Chart, which has some nodes with longer names.
I've managed to modify the width of longer nodes, but have trouble properly placing their children and the lines (paths) to their children.
I tried calculating myself with determineChildXValue(), but that didn't work properly.
Is there a way to initialize the tree with variable widths so it will take care of the calculations of translations for child nodes?
Currently, I'm initializing it with hard-coded node sizes:
var tree = d3.layout.tree().nodeSize([70, 40]);
I've replicated the behavior in this example - expand Departments, then DEPARTMENT STORES to see the overlap.
Thanks in advance!
I consulted a colleague who was able to build a proper fix:
Define the source and target properties (before the projection is set) for the diagonal (paths)
Track the tierDisplacementX and cumulativeDisplacementX
Use these when translating the positions of the child nodes and their paths
See this fiddle to see the working code.

Positioning items inside container

I have a mathematical problem that I am trying to solve and want to realize in javascript.
I have a "space" meaning: a rectangular format. This shall work as a kind of container.
Then I have smaller forms: other rectangular ones and circles.
I need to find out a solution how to calculate how many of these forms fit into the container.
So I kind of need the ideal way, how to stack these items in there.
If it is too many, leaving out some. And if it is too few, stacking them from bottom up.
I am trying to realize this in Javascript but not getting far.
From my vision it should be kind of like this:
var items = [circle1,2],[rect1,2,4],[rect2,5,6]]; // array with the forms to put inside container, stating a radius for circle and width/height for rectangles
var container = [10, 4]; // given the size of the container in width and height.
function stackItIn (container, items){
// now this is where I am totally lost
}
The premium part would be even showing it graphically at the end.
Any help would be appreciated!
Thank you!
You can try a treemap. Sort the tiles and pick the first and create a node in a tree. Split the tree on both axis and pick the next tile and find the best fit of the nodes.

D3 Tree layout with all leaves same distance from root

I'm using this example as a base D3.js Drag and Drop, Zoomable, Panning, Collapsible Tree with auto-sizing.
What I need is a tree where all the leaf nodes are the same distance from the root.
It should look something like the Cluster Dendrogram.
I would use the Cluster Dendrogram but it lacks the zooming, panning and collapsibilty options (I've cut out node dragging). Also the difference between the two examples is that one uses tree layout whereas the other cluster layout.
All your help and suggestions would be much appreciated.
It likely won't be easy to implement because the tree layout likes it's depth but you could do something like this.
nodes.forEach(function(d) {if(!d.children){
d.depth = 3; //3 should be replaced with whatever your lowest depth is
//you could write a function to find it too. let me know if you need that
}})
nodes.forEach(function (d) {d.y = d.depth * 300;});
this will accomplish part of what you are talking about but there is nothing to prevent the nodes from overlapping here. This post: Avoid overlapping of nodes in tree layout in d3.js about node spacing could potentially help

Setting Max Length of Links in D3 Tree Layout

I have a tree graph very similar to the one here: http://bl.ocks.org/mbostock/999346 and I would like to limit the spacing vertically of the nodes; if you look at the tree you will see that when there are just two nodes, they take up the entire canvas (the link between the two nodes is very long), and as other nodes are inserted, the link(s) are resized to fit. I would like to limit the link length to some max number so that the tree is more compact with fewer nodes.
Jason Davies' approach of looping over the nodes after d3.layout.tree has run and overwriting each node's y-value works well for me. (described in this d3 github issue comment)
So, something like
nodes.forEach(function(node){
node.y = (node.depth * 90); // 90px per level.
})

Categories

Resources