Geometry of multiple links between nodes


How can I disable this behavior:


When the second link is drawn, the geometry of both links gets modified and an additional link point is added. Can I disable this by some setting?

The desired behavior: Link drawing behavior is the same regardless whether a link already exists.


Set Link.curviness to zero.


This seems to work but when I transform my link to a Bezier link by settings the following properties:

reshapable: true
adjusting: Stretch
curve: Bezier

I seem to loose one control point:


If I do not have multiple links (without curviness: 0); transforming to Bezier and back to Direct seems to work well:


But you see when I add an additional link, it starts modifying the points. How should I fix this?

I do not understand what you want.

Maybe when a second link is drawn you want to delete that new link and just change the appearance of the first link by adding an arrowhead and changing your code to treat the link as undirected or both-ways?

The problem is that when I use:

curviness: 0

The bezier link does not hold 2 control points anymore when I try to reshape it; only one.

When I remove this attribute, my default behavior works fine.

I use the following attributes for my bezier link:

reshapable: true
adjusting: Stretch
curve: Bezier

I still don’t understand the problem. Can’t you only set Link.curviness to zero when it’s not a Bezier curve? And even when the curve is Bezier, there really are two control points in the link route. Maybe they happen to be coincident.

Maybe this gif illustrates it better. Now I replaced the curviness from an attribute to a binding based on the whether it is a bezier link (as you described): direct=0, bezier=NaN.


So here you see that it works nicely when creating new links:

  • Left: 2 bezier links with 2 control points
  • Right: 2 direct links without any control points.

So far so good. However, when I transform the link from a bezier link to a direct link and back, I loose my control points. I only have one control point left as shown.

The following properties are bound on the bezier state:

  Binding('curviness', (g) => (isBezier(g) ? NaN : 0)),
  Binding('curve', (g) => (isBezier(g) ? go.Link.Bezier : go.Link.None)),
  Binding('adjusting', (g) => (isBezier(g) ? go.Link.Stretch : go.Link.None)),
  Binding('reshapable', isBezier),

The problem is caused by the binding (or setting) of Link.adjusting. When adjusting is Stretch or Scale or End, the routing depends on the previous route that it had. Since a straight link with a specified curviness and no fromSpot or toSpot will have three points, those points are what it starts with when the curve becomes Bezier.

If you comment out the setting or binding of Link.adjusting, the problem you report should go away. But if you need to have adjusting be Stretch, I wonder if you could implement a hack where the converter, besides returning either Stretch or None also set Link.points to an empty List. Here’s what I just tried:

  myDiagram.linkTemplate =
      { curviness: 0, curve: go.Link.None, reshapable: false },  // defaults assume straight, not curved
      new go.Binding('curviness', "bezier", b => b ? NaN : 0),
      new go.Binding('curve', "bezier", b => b ? go.Link.Bezier : go.Link.None),
      new go.Binding('adjusting', "bezier", (b, link) => {
        if (b && link.adjusting === go.Link.None && link.pointsCount > 2) link.points = new go.List();
        return b ? go.Link.Stretch : go.Link.None;
      new go.Binding('reshapable', "bezier"),
      $(go.Shape, { strokeWidth: 2 }),
      { toShortLength: 2 },
      $(go.Shape, { toArrow: "OpenTriangle" }),
      $(go.TextBlock, { background: "white" },
        new go.Binding("text", "points", lst => lst.count).ofObject())

Thanks, this did the trick:

new go.Binding('adjusting', "bezier", (b, link) => {

        if (b && link.adjusting === go.Link.None && link.pointsCount > 2) link.points = new go.List();

        return b ? go.Link.Stretch : go.Link.None;