How to custom the link shape between nodes

Hello!
I am trying to make a link between two nodes that follow a bezier shape. The link has two control points so i don’t want to use a simple bezier link. The documentation describes here http://gojs.net/latest/intro/geometry.html how to create a Cubic Bezier Curves. My bezier curve is described in the property “geometryString” but i can figure out how to make it work. My code looks something like :
linkTemplate =
$(go.Link,
$(go.Shape, new go.Binding(“geometryString”, “geometryString”), new go.Binding(“stroke”, “strokeLink”)),
$(go.Shape, { toArrow: “Standard” }, new go.Binding(“fill”, “fillArrow”), new go.Binding(“stroke”, “strokeArrow”))
);
My link model is a list. Here what looks like one of the element :
“{
“key”: “1”,
“from”: “Reponse&Loop”,
“to”: “Reponse&Done”,
“text”: “Done”,
“geometryString”: “F M599,175 C683,214 711,-11 806,58z”,
“__gohashid”: 1188
}”.
I also noticed that we can use routing property but it doesn’t seem to be a “cubic Bézier curve” property.

Set the Link.curve property. Setting curve: go.Link.Bezier is actually telling the Link to use a Bezier curve for its Link.path’s Shape.geometry.

The Link.routing property tells the Link how to determine the points of its route, Link.points. The Link.curve property is independent of the route – it just determines what kind of Geometry is built given the route.

I’m not sure that you can just set the Shape.geometry (or equally the Shape.geometryString), because it will normally be replaced automatically as the Link is routed and then given a geometry according to the route and the curve and other Link properties.

Thanks for your answer.
So do you think that there is a way to customize the route in a way that it matches a given Geometry ?
In other word, is there a routing property that correspond to the “cubic Bézier curve” geometry ?
I just want to set a route with a Bezier curve given 2 control points. Here an image of what i want to achieve https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands

There are a lot of examples on that page. Could you please be specific about what you are trying to achieve? Please provide examples of or explanations for what should happen if one of the two connected Nodes is moved.

The most general answer is that you can override Link.computePoints (or set various properties and override various other methods) in order to customize the route, and you can override Link.makeGeometry (or set a few properties) to customize the geometry given the route.

Let’s suppose that the graph is static and that we cant’ move the nodes.

What i want to achieve is the following :
Given 4 points,
P1: inital point
P2: destination point
C1: first control point
C2: second control point

So i want to draw a bezier curve that go from P1 to P2 and follow the direction of C1 and C2. It is a “cubic Bézier curve”. The problem is that the classic bezier curve don’t take into consideration the control points C1 and C2. It only takes into consideration P1 and P2 (“from”, “to” properties).
That’s why i want to customize the link route.
Is it clear ?

OK, that’s easy – just set the Link.points property. http://gojs.net/latest/api/symbols/Link.html#points

Normally that is done via a data Binding:

    new go.Binding("points")

so that you just need to set that property on the link data:

  { from: ..., to: ..., points: [599,175, 683, 214, 711, -11, 806, 58] }

And in case you change your mind and want the model to be updated whenever the node moves or the user makes other changes causing the route to be recomputed, just make the Binding a TwoWay binding: .makeTwoWay(). Also you might want to learn about the Link.adjusting property.

Thanks for you answuer it helped a lot. However, i notice that the link route change when i do a transition on a related node. Is it possible to make the link route unchangeable ?
The transition before transaction :


The transition after transaction :

We can notice that the transition going from the state Loop to the state Loop has changed. So, can we make its route unchangeable ?

In my opinion all of the link routes do not look good beforehand and they look better afterward. And it isn’t only the reflexive link at the “Loop” node that got rerouted – for example, so did the “test” link going from “Entry Point” to “Done”, which is not connected with “Loop” at all.

If nodes get moved or if they change size, I really think you want to allow link routes to be rerouted.

Unfortunately I do not believe there is a simple mechanism for avoiding link route invalidation as nodes change size or location, or due to any number of other properties that should cause a link route to be recomputed. If you could be very specific about what changes might happen in your diagram, and which ones should invalidate link routes and which ones should not, we might be able to figure out a work-around.

In the specific case of the reflexive link, you can set (bind) Link.curviness so that the link route effectively has a certain height.

It is true that the links in the first place do not look very good, so i would like to come back to my first problem please.
So given 2 control points (C1,C2) and 2 states “EntryPoint” and “Loop” (“from” “to” properties), i would like to draw a bezier curve between the states “EntryPoint” and “Loop”.
Here the result i want to get:

Do you think it is possible ?
I can’t really use Link.Points because it needs also the coordinates of P1 and P2 which are not very accurate as you noticed in my previous post. The fact that P1 and P2 are not very accurate make the transition a bit far from the corresponding state.

Do you really need to specify C1 and C2? If not, just data bind Link.curviness.

I really need to specify C1 and C2. Otherwise, it is just a simple bezier link from the state “EntryPoint” to the state “Loop”. Do you think it is possible to make the link using C1 and C2 and the states “EntryPoint” and “Loop”?

It’s going to be a “simple Bezier curve” in any case. So I do not understand your requirements.

I think there is a solution to what you are asking for, but I want to understand why you want to specify C1 and C2 separately for each link. What coordinate system are those two points supposed to be using?

We have an application that allow the user to draw states and links between them. https://github.com/xcomponent/xcomponent
The user can change manually the route of the link by drag and drop. The position of the states and the links are in an xml file. I just have to reproduce exactly the model that the user created using the data in this xml. The bezier curve depends on the control points. So, if the user changes a link route, the gojs model has to adapt and the show the same link’s route. That’s why i need C1 and C2 to draw the link.
We are working in a Cartesian coordinate system.

OK, you are saying that you get the C1 and C2 points in your data, and that they came from the user’s reshaping of the Bezier curve link.

So that also implies that the C1 and C2 points are in the same coordinate system as the points for the node locations, yes?

Yes, all the data has the same coordinate system. So, you want to calculate the P1 and P2 points using the node locations?

OK, take a look at the implementation of http://gojs.net/temp/linkBezierControls.html.

It assumes that the two control points are in an Array on the link data object. You can adapt the code if the control points are structured or formatted differently.

Note that loadControls is only called in an “InitialLayoutCompleted” DiagramEvent. That’s to make sure that every node is where it will be and that every node has the size that it should have.

That works as expected thanks.
However i would like to come back to my previous problem.
In fact, the link is being recomputed when the text of the node is being modified by a transaction. But when the color is modified, the link’s route remains the same. You said previously that we can avoid “link route invalidation”. Could you tell me how to achieve that ?

Before transaction:

After transaction:

We can notice that the links of the “Loop” state changed.

I said there was no general way to avoid link route invalidation when nodes change size or are moved.

But if you set or bind Link.curviness to a real number, then the route will seem much more predictable.

Also, in version 1.7 we have optimized some cases of link route invalidation. Try http://gojs.net/beta to see if link route invalidation does not happen in that case where you change the text outside of the port and not causing the port to move.

The state route doesn’t change with the Beta version. So it works as expected :). Thanks.
Also, i noticed that when i click on the SubGraphExpanderButton, the link is being recomputed. So, it would be interesting to make some optimizations on that level.
Finally, i would be interested to know when this beta version is going to be released because our company is interested to buy the license of gojs.