Links break from nodes

Hi,

Is there a way where I can tell the graph to always stay connected ?

for example ,i create the following graph with nodesize(140,140)

then i change the node size (140,50)

the link breaks .

I can get it to connect to the ports by not specifying points ,

what I want is to check if the links are connected properly to the nodes , if it is not connected , connect them automatically. I want to give high priority to the ports than the points (path that the link takes ) ? is this possible ?

Having links always be routed so as to connect physically with both nodes is always the default behavior. None of the sample apps or documentation examples exhibit this behavior.

What are you doing (and when) to change the size of a node?

How (and when) are you specifying the points of each link’s route?

I am changing the node sizes in the json object ,

change the node sizes without changing the points of the path that the links take

What are the actualBounds of the nodes after you have changed the size of the shapes? Perhaps they have not changed, and the links connect with the whole node rather than to the visible rectangular shape.

We really can only speculate what is going on in your app. What changes can I make to the FlowChart sample to get it to behave in the manner that you experience now? Can you provide a CodePen or other sample for us to see this very odd behavior?

sample case

  1. in your flowchartexample , do some changes
    2)click save button
  2. in the json , change the loc of a node
  3. load the json

used json

{ “class”: “go.GraphLinksModel”,
“linkFromPortIdProperty”: “fromPort”,
“linkToPortIdProperty”: “toPort”,
“nodeDataArray”: [
{“category”:“Comment”, “loc”:“360 -10”, “text”:“Kookie Brittle”, “key”:-13},
{“key”:-1, “category”:“Start”, “loc”:“175 0”, “text”:“Start”},
{“key”:0, “loc”:“0 77”, “text”:“Preheat oven to 375 F”},
{“key”:1, “loc”:“50 100”, “text”:“In a bowl, blend: 1 cup margarine, 1.5 teaspoon vanilla, 1 teaspoon salt”},
{“key”:2, “loc”:“175 190”, “text”:“Gradually beat in 1 cup sugar and 2 cups sifted flour”},
{“key”:3, “loc”:“175 270”, “text”:“Mix in 6 oz (1 cup) Nestle’s Semi-Sweet Chocolate Morsels”},
{“key”:4, “loc”:“175 370”, “text”:“Press evenly into ungreased 15x10x1 pan”},
{“key”:5, “loc”:“352 85”, “text”:“Finely chop 1/2 cup of your choice of nuts”},
{“key”:6, “loc”:“175 440”, “text”:“Sprinkle nuts on top”},
{“key”:7, “loc”:“175 500”, “text”:“Bake for 25 minutes and let cool”},
{“key”:8, “loc”:“175 570”, “text”:“Cut into rectangular grid”},
{“key”:-2, “category”:“End”, “loc”:“175.00000000000006 657.8000030517576”, “text”:“Enjoy!”}
],
“linkDataArray”: [
{“from”:1, “to”:2, “fromPort”:“B”, “toPort”:“T”, “points”:[175,140.2508972167969,175,150.2508972167969,175,150.2508972167969,175,147.68682708740235,175,147.68682708740235,175,157.68682708740235]},
{“from”:2, “to”:3, “fromPort”:“B”, “toPort”:“T”, “points”:[175,222.31317291259768,175,232.31317291259768,175,232.31317291259768,175,227.68682708740235,175,227.68682708740235,175,237.68682708740235]},
{“from”:3, “to”:4, “fromPort”:“B”, “toPort”:“T”, “points”:[175,302.3131729125977,175,312.3131729125977,175,320,175,320,175,327.6868270874023,175,337.6868270874023]},
{“from”:4, “to”:6, “fromPort”:“B”, “toPort”:“T”, “points”:[175,402.3131729125976,175,412.3131729125976,175,412.9377243041992,175,412.9377243041992,175,413.5622756958008,175,423.5622756958008]},
{“from”:6, “to”:7, “fromPort”:“B”, “toPort”:“T”, “points”:[175,456.4377243041992,175,466.4377243041992,175,466.4377243041992,175,465.6245513916016,175,465.6245513916016,175,475.6245513916016]},
{“from”:7, “to”:8, “fromPort”:“B”, “toPort”:“T”, “points”:[175,524.3754486083984,175,534.3754486083984,175,535,175,535,175,535.6245513916016,175,545.6245513916016]},
{“from”:8, “to”:-2, “fromPort”:“B”, “toPort”:“T”, “points”:[175,594.3754486083984,175,604.3754486083984,175,609.5601242775141,175,609.5601242775141,175,614.7447999466298,175,624.7447999466298]},
{“from”:-1, “to”:0, “fromPort”:“B”, “toPort”:“T”, “points”:[175,24.773340092148892,175,34.77334009214889,175,42.66780789397484,0,42.66780789397484,0,50.56227569580078,0,60.56227569580078]},
{“from”:-1, “to”:1, “fromPort”:“B”, “toPort”:“T”, “points”:[175,24.773340092148892,175,34.77334009214889,175,42.261221437676014,175,42.261221437676014,175,49.74910278320313,175,59.74910278320313]},
{“from”:-1, “to”:5, “fromPort”:“B”, “toPort”:“T”, “points”:[175,24.773340092148892,175,34.77334009214889,175,42.69894574187523,352,42.69894574187523,352,50.624551391601564,352,60.624551391601564]},
{“from”:5, “to”:4, “fromPort”:“B”, “toPort”:“T”, “points”:[352,109.37544860839844,352,119.37544860839844,352,116,352,116,352,316,175,316,175,327.6868270874023,175,337.6868270874023]},
{“from”:0, “to”:4, “fromPort”:“B”, “toPort”:“T”, “points”:[0,93.43772430419921,0,103.43772430419921,0,100,0,100,0,316,175,316,175,327.6868270874023,175,337.6868270874023]}
]}

Ah, I see. If you’re going to do that, you’ll also need to remove the “points” from all of the connected link data.

Hmmm, you might need to do that also for all links that cross over the area occupied by the moved node, so that they can be re-routed to go around the new node’s bounds.

is there any way where I can prioritise port connection over link path ?

scenario:

I setup a graph with nodes size (40,40)

after couple of months i will have like 1000 graph json in my database.

now if I want to change my node size , i would like atleast the paths to stay connected .

The problem is that if you have a Binding on Link.points and it gets a value from the link data, that’s the route it will have after loading. (Note for example if you modify the “points” array of numbers in the JSON-text and then load – the link could be anywhere, completely unrelated to the connected nodes!)

The same goes for the node size and/or location.

But if you change a Node in the Diagram rather than in the JSON-formatted text before loading, the connected Link routes will be automatically updated.

If you really need to modify the model data such as the node size, you could invalidate the link routes explicitly so that their routes will be recomputed. So, for example, if you have changed the size of a node in the JSON data, you could call aNode.linksConnected.each(function(l) { l.invalidateRoute(); }). If you are changing the size of all nodes, you could do myDiagram.links.each(function(l) { l.invalidateRoute(); }). I believe you could do these invalidations in an “InitialLayoutCompleted” DiagramEvent listener.

However it seems to me that if you are assuming all nodes are 40x40 (or whatever) and that you want to change them all to be 50x50 (or whatever), you should not be storing that information in the model. That should be a matter of replacing the template, which will cause all connected link routes to be automatically invalidated.

I agree with you , but i want to check if there is a link that is disconnected like the following

new go.Binding(“points”,function checkifconnected(points){
if(starting point of link is same as position of the connected start port and ending point of link is same as position of the connected end port ){
return points
}else{
calculate new route for link and return the points
});

is there a way where I can get the ports location and check if it is the starting point of a link ?

That cannot be done reliably, because at the time the Binding is evaluated, one or both nodes connected by the link may not yet be at their intended locations. Or the nodes might not yet be fully measured and arranged, if it has data bindings that might alter its size or location. In fact, the link might not yet be connected with both nodes.

I did this by following

  1. for a node get connected links
  2. check if it is fromlink or tolink
  3. get node’s location
  4. find the distance between the 1stpoint(fromlink) or lastpoint(tolink) and the nodeslocation
    5)if the distance is greater than something say 100 (relevant to your diagram) , call link.invalidateroute()

this worked for me .

this is dependent on modeldata so ,i think it should be reliable ?

That’s rather unreliable, I think, if the geometrical disconnect is large enough to be noticed but still within the 100 (or whatever) distance.

Why not use something like

    aNode.actualBounds.copy().inflate(2, 2).contains(p)

where p is the first or last point of the Link.points?

Hmmm, even that would be bad if the ports are not along the edges of the node or if the node has decreased in size since the model was saved.

The more general solution would be to call Link.getLinkPoint, but that is more complicated to program.