dagre icon indicating copy to clipboard operation
dagre copied to clipboard

Maintain the structure when dynamically add nodes

Open yodahuang opened this issue 8 years ago • 7 comments

Hey there, I'm working on a project where I will append nodes dynamically when I click on the existing nodes. But it comes out that Dagre will do some "optimizations" for me, liking switching the position of the existing nodes. I found a similar stack overflow questions here, but it was to old, and the dagre.layout().orderIters(-1) method does not work. Is there some ways to work around this? I really like Dagre and don't want to switch to other libraries.

yodahuang avatar Jun 21 '16 00:06 yodahuang

In general this is a hard problem because you (probably) do want some optimization, but you want stability more. The two goals conflict.

There are also some changes that must change the positions of existing nodes, for example if an edge insertion causes a new rank to be added between existing nodes.

gordonwoodhull avatar Aug 10 '16 17:08 gordonwoodhull

So is this possible? Are there any other libraries that provide "stable" algorithms?

Thanks.

graymur avatar Apr 10 '17 15:04 graymur

Found a solution. You have to replace these lines: https://github.com/cpettitt/dagre/blob/master/lib/order/index.js#L40-L50 with best = _.cloneDeep(util.buildLayerMatrix(g));

graymur avatar Apr 11 '17 12:04 graymur

Looks like that basically disables crossing minimization, correct?

I wonder if it would make sense to add an option to dagre.layout() to disable this step. So that you could e.g. do full layout with crossing minimization on the initial graph, then more stable layouts for incremental changes.

(That is, if someone takes up maintainership of this library.)

gordonwoodhull avatar Apr 11 '17 12:04 gordonwoodhull

It seems that it does. I've got an idea from a comment in this fiddle: http://jsfiddle.net/gke2dann/1/ , mentioned in the Stackoverflow question from the first message in this thread.

I've tried to add an option, but g object is some internal representation of a graph (I think from graphlib package) and does not carry options like ranksep and others. So I didn't find an easy way to pass an option to that function.

Seemes like at some point it was possible to configure this, but later this was removed. Didn't find anything in the commits history, though.

graymur avatar Apr 11 '17 12:04 graymur

I was looking at the options which are passed to dagre.layout() in the second parameter. However, I haven't looked very closely and I don't know if this would work.

It's probably not worth worrying about until we find a new maintainer. AFAIK dagre is unique and it's not likely someone else will implement a similar library in JavaScript.

(I built a similar library in C++ a while back, and I rely on dagre for some of my projects, so I guess I'd be a natural fit. However, the list of open issues is intimidating and I'm not sure I want to take this on.)

gordonwoodhull avatar Apr 11 '17 14:04 gordonwoodhull

@graymur if you replace those lines then is the idea that you can call layout(), then addNode(), then layout() on the same dagre graph and get some level of stability when adding nodes?

mx2323 avatar Jun 25 '20 23:06 mx2323