Graph.op.morph

124 views
Skip to first unread message

Rasmus Aveskogh

unread,
Nov 10, 2009, 11:32:36 AM11/10/09
to javascript-information...@googlegroups.com

How mature is the Graph.op.morph-functionality? I get some obscure
results when trying to exchange and/or reorder models (with common
root).

Layout is distorted.. nodes disappear.. etc. Tweaking between
animation styles and types such as fade/replot affects the results in
different directions
but it doesn't seem to work fully...

-ra

Nico Garcia Belmonte

unread,
Nov 10, 2009, 11:38:30 AM11/10/09
to javascript-information...@googlegroups.com
What are you trying to do exactly? perhaps morphing is not the operation you're looking for.

Could you be more explicit on what you're trying to do exactly and also describe exactly the result?


It's been used in various examples and by some other people and it always worked fine (which of course doesn't mean it's completely bug-free).

If you think you've found a bug, a link to a page showing me this would be a good start.
--
I would never die for my beliefs because I might be wrong.

Bertrand Russell

Rasmus Aveskogh

unread,
Nov 10, 2009, 12:42:00 PM11/10/09
to javascript-information...@googlegroups.com

Thanks for the feedback Nico,


Things get really odd if the root-node isn't selected when morphing between the two data-sets..

-ra

Nico Garcia Belmonte

unread,
Nov 10, 2009, 1:32:04 PM11/10/09
to javascript-information...@googlegroups.com
Yeah,

I think this is because you're morphing the tree into a tree that doesn't have the clicked node in it, so it doesn't really know what to do to center the tree now, since the node doesn't exist.

You could try two things (which I'm not sure they work, but they probably should).

a) You could try also including the clicked node (and perhaps its path 'til the root node) in your morphed json data, which of course perhaps isn't what you want since, well, they currently aren't included in your structure.

b) This is perhaps the best "choice". When you pass the configuration object in the morph operation, try specifying the id of the node you'd like to be the "clickedNode" (i.e the current centered node in the new graph visualization). For example:

st.op.morph(json2, {
type: 'fade',
duration: 3000,
hideLabels: false,
transition: Trans.Quart.easeOut,
id: 'idofnodetobecentered'
});

if this node exists in the new structure it will be set as the current clicked node.

Rasmus Aveskogh

unread,
Nov 10, 2009, 1:44:31 PM11/10/09
to javascript-information...@googlegroups.com

Thanks again Nico,

I tried your second approach (which would work with my use case since I will always have a common root),
but well, it's still very easy to provoke obscure behavior..


Even the first morph to json2 puts the first child of the root on a different offset than expected (one level down..).

-ra

Rasmus Aveskogh

unread,
Nov 11, 2009, 8:50:09 AM11/11/09
to javascript-information...@googlegroups.com

Hi again,

Any theories to why this happens?

-ra

Nico Garcia Belmonte

unread,
Nov 11, 2009, 8:55:21 AM11/11/09
to javascript-information...@googlegroups.com
Hi,

Indeed the code for the general morphing operation is only tested in the Hypertree/RGraph visualizations but not in the Spacetree visualization.
This is because I made some high level methods that wrap this object with (what I thought was) useful Tree specific functions like addSubtree and removeSubtree:

http://thejit.org/docs/files/Spacetree-js.html#ST.addSubtree

I think I spotted the bug though. I also created an issue at github. I don't have time right now to check if this works, but you can try it if you want.

Search for the "$design" function in jit.js. You'll find the Graph.eachSubnode method like this:

         GUtil.eachSubnode(node, function(n) {
             if(n.exist && (!multitree || 
                     ('$orn' in n.data) &&
                     n.data.$orn == orn)) {
                 
                 if(!chmaxsize)
                    chmaxsize = getBoundaries(graph, config, n._depth, orn);
                
                 var s = $design(n, chmaxsize[nots], acum + chacum);
                 trees.push(s.tree);
                 extents.push(s.extent);
             }
         });

This iterator should ignore all nodes that are going to be removed by the morphing operation. These nodes are flagged with "ignore=true". This is done by adding a flag list as third parameter to GUtil.eachSubnode:

         GUtil.eachSubnode(node, function(n) {
             if(n.exist && (!multitree || 
                     ('$orn' in n.data) &&
                     n.data.$orn == orn)) {
                 
                 if(!chmaxsize)
                    chmaxsize = getBoundaries(graph, config, n._depth, orn);
                
                 var s = $design(n, chmaxsize[nots], acum + chacum);
                 trees.push(s.tree);
                 extents.push(s.extent);
             }
         }, "ignore");

More info on this method can be found here:

http://thejit.org/docs/files/Graph-js.html#Graph.Util.eachSubnode

Lets hope that works ;)

Rasmus Aveskogh

unread,
Nov 11, 2009, 9:09:14 AM11/11/09
to javascript-information...@googlegroups.com

Thanks!

It works "a little better". :)

Although, morphing with another node selected than the root node, or morphing forth and back a couple of times, still causes nodes to disappear etc.

You can see the fix applied at: http://www.xy.org/u/racer/jit_test/

-ra

Nico Garcia Belmonte

unread,
Nov 13, 2009, 3:17:42 PM11/13/09
to javascript-information...@googlegroups.com
Hey,

Could you try adding this right after you instanciate an st?

st.constrained = false;

ST.implement({
  refresh: function() {
    this.reposition();
    this.select(this.root);
  },

  reposition: function(){
     Graph.Util.computeLevels(this.graph, this.root, 0, "ignore");
     this.geom.setRightLevelToShow(this.graph.getNode(this.root), this.canvas);
     Graph.Util.eachNode(this.graph, function(n) {
       if(n.exist) n.drawn = true;
     });
     this.compute('endPos');
  }
 
});

This code changes the "constrained" configuration property and monkeypatches the refresh and reposition functions in the ST class.
Also try to change the line 2788 (aprox.):

modes: ['polar'].concat(modes),

for:

modes: ['linear'].concat(modes),

Hope it helps,

Rasmus Aveskogh

unread,
Nov 13, 2009, 3:43:34 PM11/13/09
to javascript-information...@googlegroups.com

Hi again Nico,

It works a lot better.. I also discovered that the root-subtree disappears when I invoke the morph-method before a previous morph has completed.

This is not completely obvious though as it takes a second or two for the execution to actually finish after the nodes seem to have settled graphically.

I'm not sure whether this is a bug or a limitation one has to make sure doesn't happen (by disabling the possibility to morph during a morph for example).

The patched version is still available at: http://www.xy.org/u/racer/jit_test/

-ra

Nico Garcia Belmonte

unread,
Nov 14, 2009, 3:06:40 AM11/14/09
to javascript-information...@googlegroups.com
I guess you can set a flag:

var morphing = false;

/* ... */

onclick=

if(morphing == false) {
  morphing = true;
  st.op.morph(json, {
     onComplete: function() {
        morphing = false;
     }
  });
Reply all
Reply to author
Forward
0 new messages