How to set angle of edge into child?

How would one set the angle from which the edge “arrives” into the child? If it’s possible?

Or is it possible to have different types of alignments per edge or vertex based on the child type?

Here is an example of what we would like to achieve:
ExampleTreeByType

If these are not possible via one edge, would it be possible to use two edges instead, one for each type of child?

What I found till now is that we are limited to one alignment and one angle per parent no matter the amount of edges that come out of it.

Thank you for the intended screenshot. It looks like you want to use a custom TreeLayout that not only supports a regular tree layout (blue root node to orange child nodes) but also supports those green child nodes as well. This sample demonstrates that: Org Chart Editor with Assistants

And I think you want to set TreeLayout.alignment to go.TreeLayout.AlignmentStart, so that the orange child nodes start at the same X coordinate as the parent node and additional children are placed toward the right.

1 Like

Great, it looks like this should be the solution. I will try it and report back with the results.

Thanks for the quick response and your helpful answer! :)

@walter, I’m getting closer to the preffered solution, I just have a few problems left.

  1. I added code for adding dummy assistants before each assistant, so that all assistants are on the right side. It works almost as intended. The problem is when there are more than one assistant nodes, the first node gets a strange link(to its right side) and till now I have yet to found the solution. The screenshot is below.

// if (acount % 2 == 1) {
// var dummy = net.createVertex();
// net.addVertex(dummy);
// net.linkVertexes(parent, dummy, asstedges.first().link);
// }
// now PARENT should get all of the assistant children
eit = asstedges.iterator;
while (eit.next()) {
var dummy = net.createVertex();
net.addVertex(dummy);
net.linkVertexes(parent, dummy, asstedges.first().link);
parent.addDestinationEdge(eit.value);
}

  1. I can’t get the first non-assistant nodes to start at the same X coordinate as the parent node. Also in the same screenshot.
    EDIT: I set the alignment of the nodes to AlignmentStart.

31

Thanks for your help!

The custom SideTreeLayout defined and used in that sample makes use of the “Bus” alignment, which lays out the assistants in two columns on either side of “the aisle of a bus”. So if you had implemented your assistant-adding functionality in the following manner:

    function addAssistant() {
      myDiagram.model.commit(function(m) {
        m.addNodeData({ name: "new person", title: "something fancy", isAssistant: true, parent: 1 });
      }, "added assistant");
    }

you would have found that the assistants would alternate sides rather than stay on just the right side. The natural inclination would be to change that TreeVertex.alignment from go.TreeLayout.AlignmentBus to go.TreeLayout.AlignmentBottomRightBus in the override of assignTreeVertexValues. However that would make all of the children be aligned on the right, which happens to be something like what you show in your screenshot.

In your situation the cause of the link coming in on the right side rather than the (shorter, more natural left side) is due to the code that implements “Bus” alignment. It’s thinking that that node really belongs on the left side, which is why the link is coming into the node’s right side.

But if you are using a TreeVertex.alignment of go.TreeLayout.AlignmentBottomRightBus in the override of assignTreeVertexValues, then you don’t need to worry about having dummy vertexes in the LayoutNetwork to pretend to be on the left side of the bus. So you can change the override of makeNetwork not create any dummy vertexes.

    SideTreeLayout.prototype.makeNetwork = function(coll) {
      var net = go.TreeLayout.prototype.makeNetwork.call(this, coll);
      // copy the collection of TreeVertexes, because we will modify the network
      var vertexcoll = new go.Set(/*go.TreeVertex*/);
      vertexcoll.addAll(net.vertexes);
      for (var it = vertexcoll.iterator; it.next();) {
        var parent = it.value;
        // count the number of assistants
        var acount = 0;
        var ait = parent.destinationVertexes;
        while (ait.next()) {
          if (isAssistant(ait.value.node)) acount++;
        }
        // if a vertex has some number of children that should be assistants
        if (acount > 0) {
          // remember the assistant edges and the regular child edges
          var asstedges = new go.Set(/*go.TreeEdge*/);
          var childedges = new go.Set(/*go.TreeEdge*/);
          var eit = parent.destinationEdges;
          while (eit.next()) {
            var e = eit.value;
            if (isAssistant(e.toVertex.node)) {
              asstedges.add(e);
            } else {
              childedges.add(e);
            }
          }
          // first remove all edges from PARENT
          eit = asstedges.iterator;
          while (eit.next()) { parent.deleteDestinationEdge(eit.value); }
          eit = childedges.iterator;
          while (eit.next()) { parent.deleteDestinationEdge(eit.value); }
          // now PARENT should get all of the assistant children
          eit = asstedges.iterator;
          while (eit.next()) {
            parent.addDestinationEdge(eit.value);
          }
          // create substitute vertex to be new parent of all regular children
          var subst = net.createVertex();
          net.addVertex(subst);
          // reparent regular children to the new substitute vertex
          eit = childedges.iterator;
          while (eit.next()) {
            var ce = eit.value;
            ce.fromVertex = subst;
            subst.addDestinationEdge(ce);
          }
          // finally can add substitute vertex as the final odd child,
          // to be positioned at the end of the PARENT's immediate subtree.
          var newedge = net.linkVertexes(parent, subst, null);
        }
      }
      return net;
    };

    SideTreeLayout.prototype.assignTreeVertexValues = function(v) {
      // if a vertex has any assistants, use Bus alignment
      var any = false;
      var children = v.children;
      for (var i = 0; i < children.length; i++) {
        var c = children[i];
        if (isAssistant(c.node)) {
          any = true;
          break;
        }
      }
      if (any) {
        // this is the parent for the assistant(s)
        v.alignment = go.TreeLayout.AlignmentBottomRightBus;  // this is required
        v.nodeSpacing = 50; // control the distance of the assistants from the parent's main links
      } else if (v.node == null && v.childrenCount > 0) {
        // found the substitute parent for non-assistant children
        v.alignment = go.TreeLayout.AlignmentStart;
        v.nodeIndent = -200;
        v.layerSpacing = 0;
      }
    };

I’m not sure about trying to line up the left side of the parent node with the left side of the first non-assistant child node. My first attempt was to set v.nodeIndent of the dummy parent node for the non-assistant children, but that didn’t work – it doesn’t accept negative values, such as the -200 that I tried.

1 Like

Thank you, this worked perfectly! I’m sure anything is possible with GoJS with enough knowledge and experience with it. This is such a simple solution yet I struggled to find it my self. :)

Yes I tried with setting the nodeIndent myself, but it did not work.

Thanks for your help!

The problem with the X coordinate of the first non-assistant child no being the same as its parents node is because it is not its true parent?

// reparent regular children to the new substitute vertex
eit = childedges.iterator;
while (eit.next()) {
var ce = eit.value;
ce.fromVertex = subst;
subst.addDestinationEdge(ce);
}
// finally can add substitute vertex as the final odd child,
// to be positioned at the end of the PARENT’s immediate subtree.
var newedge = net.linkVertexes(parent, subst, null);

Maybe the solution would be to try and set the fake parent to that X coordinate in some way.

Sorry, but I don’t have a good, easy answer for you at this time.

It’s ok, I was just “thinking out loud” :) Don’t worry the solution we have is close enough for now and you have helped plenty. Thanks again for the great solutions and your time.