Menu

Using multiple layout algorithms in one view

yugen
2002-11-22
2002-12-03
  • yugen

    yugen - 2002-11-22

    [Continued from https://sourceforge.net/forum/message.php?msg_id=1766768 .]

    > Can I use different layout algorithms within the same graph?
    >
    > For example, I want to use GVF to layout UML elements.
    > For Inheritance relationships, I want to use the Hirerachy layout, and
    > for association relationships, I want to use the Ring layout.
    > Is that possible?

    > One think I can think of is to use a 2 steps approach.
    > - walk thru the whole graph and find nodes with inheritance
    > relationship only,
    > build  Graph, Node, Edges objects for that
    > - use GVF to layout that Graph ONLY using Hirerachy layout.
    > - lock all the nodes.
    > -add Node, Edges objects for nodes with association relationship,
    > - use GVF to layout the graph again using Ring layout.

    Two ideas occur to me.

    (1) The approach you have described should work.  You will have to define your own hybrid layout class, which isn't as hard as it might sound.  In this scenario, you would label every edge as either "inheritance" or "association".  In your hybrid layout's computePositions() method, you would make two passes. 

    On the first pass, you would construct the inheritance graph by starting at the root node (representing the common base class in your UML diagram), and then following all "inheritance" edges.  Then construct a Hierarchy layout object, lay out this graph, and then simply copy the coordinates over to your main hybrid layout object. 

    On the second pass, you would start at the root node, recursively follow all the "inheritance" edges, and, at each node you visit, you look to see if it has any edges labeled "association".  If it does, you build up a new Graph instance containing the node and all its "association" neighbors.  Then you construct a Ring layout object and lay out this graph with it.  Then you have to do some simple math to translate the ring layout's coordinates into your main layout's coordinates space.

    (2) Alternatively, you could use a CompoundLayout, and define its superlayout to be Hierarchy, and define its sublayout to be Ring.  Then, create a subgraph (metanode) for every set of nodes in your UML diagram that share an association relationship.  (CompoundLayouts allow you to use different layout strategies for subgraphs -- see the screen shots at http://gvf.sourceforge.net/ .)  When the CompoundLayout's computePositions() method is called, it will use a Hierarchy layout for the top-level graph.  This will render all the class inheritance nodes as a hierarchy.  If you want to see the association relationships for any particular one of these nodes, you would open the metanode in the UI, and all the association relationships for that node would be rendered as a ring.  Of course, each association ring will be placed inside an open metanode's rectangular area, so they will appear somewhat "compressed" compared with the inheritance graph.

    There is a catch: If two separate nodes in your inheritance hierarchy both share an association relationship with some common third node, then third node would belong to two separate subgraphs.  This may or may not be suitable for you.

     
    • sam

      sam - 2002-11-22

      Thanks for your help again.

      The catch you mentioned. Does it apply only to the second method or both method?

      And how can I LOCK all the nodes's location after the frist pass?

      And does GVF take care of does with different size? I saw code in Node class does that, but it got comment out.

      I would want the node not to overlap. But in the sample code I should you, the layout algorithm does not know the size of each node. Can I change the layout to look at the size of each node when it computes the location of the node?

      Thank you.

       
    • yugen

      yugen - 2002-11-24

      > The catch you mentioned. Does it apply only to
      > the second method or both method?

      The possibility that the node might share an association relationship with two (or more) nodes is a concern for either method, but primarily for the CompoundLayout approach. 

      If you use the "hybrid layout" approach, then you'll end up assigning coordinates to the same node multiple times, but you can probably resolve this safely by just choosing (for example) the first set of node coordinates, or possibly the centroid of all the coordinates for that node.

      If you use a CompoundLayout, you'll have a different issue: the same node will appear in two (or more) different subgraphs.  This may be visually unsatisfying.  Also, I should mention that all of our test cases assume a one-to-one correspondence between nodes in the graph and nodes rendered in the UI.  Using CompoundLayout in the manner described above would be new (untested) ground.

      > And how can I LOCK all the nodes's location after the frist pass?

      In the case of the hybrid layout approach, the coordinates will be "locked" by virtue of the fact that you control which coordinates get copied into your main layout's coordinates set.  After the first pass is complete, you'll have coordinates for all the nodes in your inheritance hierarchy (computed by a Hierarchy layout object, which you will copy into your hybrid layout's coordinates set).  Those coordinates will not be altered unless you explicitly clobber them. 

      During the second pass, you'll go through every node in the inheritance hierarchy, and use a Ring layout object to assign coordinates to the node and all its "association" neighbors.  But these coordinates will only exist in a ring layout's coordinates set.  The original coordinates of the inheritance node will remain unaltered (or, if you prefer, "locked") in your hybrid layout's coordinates set.  You'll need to perform some simple math to translate the ring layout's coordinates into the main hybrid layout's coordinates space, so that when you transfer the ring-layout-assigned coordinates over to the main hybrid layout, the inheritance node keeps its original coordinates.

      > And does GVF take care of does with different
      > size? I saw code in Node class does that, but it
      > got comment out.

      You can issue a "resize <node name> by <factor>" command to resize metanodes.

      > I would want the node not to overlap. But in
      > the sample code I should you, the layout
      > algorithm does not know the size of each node.
      > Can I change the layout to look at the size of
      > each node when it computes the location of the
      > node?

      This can be done, but you'll have to write the logic for this yourself.

       
    • sam

      sam - 2002-11-24

      >> And does GVF take care of does with different
      >> size? I saw code in Node class does that, but it
      >> got comment out.

      >You can issue a "resize <node name> by <factor>"
      > command to resize metanodes.

      >> I would want the node not to overlap. But in
      >> the sample code I should you, the layout
      >> algorithm does not know the size of each node.
      >> Can I change the layout to look at the size of
      >> each node when it computes the location of the
      >> node?

      >This can be done, but you'll have to write the logic for
      >this yourself.

      Will the "resize" command trigger another layout? otherwise, nodes will be overlapped after I issue a "resize" command, right?

      When you mention I need to write logic, do you mean I need to write logic to resize each node individually and GVF will take care of layouting nodes with different sizes, or I need to write logic for a new layout algorithm to take into the account of different node sizes during layout?

       
      • yugen

        yugen - 2002-11-26

        > Will the "resize" command trigger another
        > layout? otherwise, nodes will be overlapped
        > after I issue a "resize" command, right?

        Resizing a node does trigger a re-layout.  (See the source for View.handleResizeMessage() -- it calls the redoLayout() method.)

        However, nodes will not necessarily overlap after resizing.  It all depends on node proximity and how much you enlarge them.

        > When you mention I need to write logic, do you
        > mean I need to write logic to
        > resize each node individually and GVF will take
        > care of layouting nodes with
        > different sizes, or I need to write logic for a new
        > layout algorithm to take into the account of
        > different node sizes during layout?

        GVF will handle node resizing when the user issues a "resize" command.  If you're afraid this will cause overlap (which is a reasonable concern), you have two choices:

        (1) You can override the computePositions() method of whatever layout algorithm you're using to accommodate variable node sizes.  This can be tricky, because if your logic repositions an open metanode to prevent overlap, you have to deal with the possibility that it may end up obscuring another node.  In short, you may be forced to implement dynamic feedback logic (to emulate TouchGraph, for example), and even then, there's no guarantee you'll avoid all overlap.

        (2) You can live with the possibility of open metanodes overlapping initially, but manually rearrange them with the mouse after graph has been rendered in the view.

         
    • sam

      sam - 2002-11-27

      How can I issue a Resize command programmically?
      I am not using royerce standalone application with GUI.

      I am just using the layout library that royerce provided.
      Thanks.

       
      • yugen

        yugen - 2002-11-27

        > How can I issue a Resize command
        > programmically?

        From View.handleResizeMessage():

        // Resize the node
        double multiplier = node.hasProperty(Keys.NODE_SIZE_MULTIPLIER) ?
        node.getPropertyAsDouble(Keys.NODE_SIZE_MULTIPLIER) : 1.0;
        multiplier *= rm.getMultiplier();
        node.setProperty(Keys.NODE_SIZE_MULTIPLIER, new Double(multiplier));

         
    • sam

      sam - 2002-11-29

      I try the hybrid approach, it does not work very good. The reason is there are a lot of "associate" nodes with are common in a lot of sub-graph. This results in a lot of intersection and overlap.

      I am thinking about doing this instead:
      1. layout the whole graph with Spring Layout.
      2. layout the inheritance graph with Tree Layout
      3. relocate the "inheritance" nodes in the spring layout graph to the co-ordinates in the Tree Layout.

      My questions are:
      1. why the LayoutFactory does not allow me to create SpringLayout (GEM)?
      2. when I relocate the inheritance nodes, will it cause the whole graph to relayout?

      Thanks

       
      • yugen

        yugen - 2002-12-03

        > 1. why the LayoutFactory does not allow me to
        > create SpringLayout (GEM)?

        What happens when you do

        import royere.bath.layout.GEM;
        ...
            GEM layout = (GEM)LayoutFactory.createLayout("GEM Force-directed");

        > 2. when I relocate the inheritance nodes, will it > cause the whole graph to relayout?

        Reassigning coordinates to particular nodes (via the Layout.setCoordinates() method) will not force a re-layout.

        The graph will only be re-laid out if the Layout.position() method or the Layout.computePositions() method is called.

         

Log in to post a comment.