Setting Max Length of Links in D3 Tree Layout - javascript

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.
})

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.

d3.js Sankey Chart: Manually Position SINKS Along X Axis

The stackoverflow community has a great solution for moving nodes in a sankey chart along the x axis (link here).
However, I noticed one cannot manually change the position of sink nodes (i.e. those nodes auto-assigned to the far-right). Because I am incorporating time into the sankey graph, I need to have certain sink nodes fixed at manually specified x positions.
Here is a JSFiddle example that needs this capability. Specifically, I need node "6": "Departed (6 mo.)" to be fixed to the x position '1'.
"nodes":[
...
{"node":6,"name":"Departed (6 mo.)","xPos":1}, // <-- need to move to position x=1; manual override not taking effect
...
Per the above-mentioned solution, I have updated computeNodeBreadths() within d3.sankey() and have included "xPos":1 within the node of interest; but the change is not taking effect.
Does anyone have a recommended update to the above-mentioned solution that allows one to manually adjust sink node x positions?
After some research, the answer is to comment out the line moveSinksRight(x) within the d3.sankey() method computeNodeBreadths(). Credit goes to Greg Ross: https://stackoverflow.com/a/21540569/4245462

Force positions of some nodes with CoSE Bilkent layout

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.

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

Categories

Resources