Page Index Toggle Pages: [1] 2  Send TopicPrint
Hot Topic (More than 10 Replies) Set anchor points for link (Read 7120 times)
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Set anchor points for link
Jul 25th, 2018 at 6:34pm
Print Post  
Hi,

it's me again  Roll Eyes

My goal is align the anchor points for the diagram nodes programmatically. Therefore I wrote a method which re-aligns the anchor points for a diagram node (origin and destination).
Just now right, I realized that
Code (Javascript)
Select All
diagram.getFactory().createDiagramLink(orig, dest)
 


does not offer parameters for the new calculated anchorpoints.

Why do I want to do that? The links are not starting from the anchor point and not ending at the destination point. I have followed this tutorial: https://www.mindfusion.eu/onlinehelp/jsdiagram/index.htm. It seems like the anchors are searching for the shortest way. Nevertheless, I reorder the position of the anchor points at runtime when some specific user interactions happen.

Additionally to the mentioned tutorial, I made some slight changes:
After creating the diagram, I call
Code (Javascript)
Select All
    diagram.setLinkShape = MindFusion.Diagramming.LinkShape.Cascading;
    diagram.showAnchors = ShowAnchor.Always;
 



I also edited the nodes ForEach, to provide a unique AnchorPattern for each diagram node:
Code (Javascript)
Select All
 var nodes = graph.nodes;
    nodes.forEach(node => {
      var diagramNode = diagram.getFactory().createShapeNode(bounds);
      nodeMap[node.id] = diagramNode;
      diagramNode.setText(node.name);
      diagramNode.setTextAlignment(MindFusion.Diagramming.Alignment.Center);
      diagramNode.setLineAlignment(MindFusion.Diagramming.Alignment.Near);
      diagramNode.setBrush("#e0e9e9");
      diagramNode.setAnchorPattern(new AnchorPattern([]));
    });
 



In the links loop, I do the same before, just trying to manage the new alignment now:
Code (Javascript)
Select All
var links = graph.links;
    links.forEach(link => {
      var link = diagram.getFactory().createDiagramLink(
        nodeMap[link.origin],
        nodeMap[link.target]);

      this.manageNewLink(link);
    });
 



The function manageNewLink determine where to play the new AnchorPoint and what to do with already existing ones.
So the result of that method consists of two anchor points, one for the origin, one for the destination.
What I'm looking for, is a way to say
Code (Javascript)
Select All
link.setOriginAnchor(anchorPointOrigin);
link.setDestinationAnchor(anchorPointDestination);
 


but actually this method expects a number as argument, not a AnchorPoint object.

What can I do to assign the anchorpoints to the link?
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #1 - Jul 25th, 2018 at 6:47pm
Print Post  
Hey,

AnchorPoint objects should be placed inside node's AnchorPattern. If they exist at the time you call createDiagramLink, the link should automatically connect to the closest ones. If you need to change anchor points later, call setOriginAnchor and/or setDestinationAnchor with the integer index of point inside pattern as argument. If you simply want to specify coordinates for end points, you can avoid the Anchor* APIs and call links' setStartPoint / setEndPoint methods.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #2 - Jul 25th, 2018 at 7:26pm
Print Post  
Hi,

thanks for your quick response.
I do place the new AnchorPoints within the point list for the specific DiagramNode. This is what happens in "this.manageNewLink(link);".
The AnchorPoints created there are showing up perfectly, but the links dont.

In manageNewLink, all I do is:
Code (Javascript)
Select All
 var newOrigAP: MindFusion.Diagramming.AnchorPoint = this.manageNewAddedLink(link.getOrigin(), 100, true, false);
    var newDestAP: MindFusion.Diagramming.AnchorPoint = this.manageNewAddedLink(link.getDestination(), 0, false, true);
    link.setStartPoint(new MindFusion.Drawing.Point(newOrigAP.getX(), newOrigAP.getY()));
    link.setEndPoint(new MindFusion.Drawing.Point(newDestAP.getX(), newDestAP.getY()));
 



where link is the link object from createDiagramLink(...) in the for-Each loop.
The start and end points are looking correct so far (while debugging) for the link objects, but it seems like there is no visual effect on the graph. The links are not moving.
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #3 - Jul 25th, 2018 at 9:05pm
Print Post  
I played a little bit around and found out, that the LayeredLayout seems to re-assign my links. I iterated through each of my link and printed it to my console to check the coordinates of the start and end point. It's correct. But the actual drawn line is missplaced tho.

Code (Javascript)
Select All
    var layout = new LayeredLayout();
    layout.anchoring = MindFusion.Graphs.Anchoring.Reassign;
 



Seems to partially fix it, although the shortest anchor point is chosen anyway, when a DiagramNode has multiple anchor points.I think I will need to keep track of the position change of an anchor point and reset the link then.

I'll try it out tomorrow or so.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #4 - Jul 26th, 2018 at 7:14am
Print Post  
Quote:
The start and end points are looking correct so far (while debugging) for the link objects, but it seems like there is no visual effect on the graph. The links are not moving.


setStart/End methods only change the elements in controlPoints array without actually repainting. Try also calling link.updateFromPoints after modifying coordinates.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #5 - Jul 29th, 2018 at 11:13am
Print Post  
Ok, the links are changing their start- and endpoint right now. But the arrange Method of the LayeredLayout missplace them again.

For example, look at this:
Code
Select All
link text start activity 2
link text end task 6
link start point MindFusion.Drawing.Point {x: 60.150000000000006, y: 32.5, type: "MindFusion.Drawing.Point"}
link end point MindFusion.Drawing.Point {x: 40.150000000000006, y: 97.5, type: "MindFusion.Drawing.Point"}
 



The above output is after arranging the nodes, by calling
Code
Select All
var layout = new LayeredLayout();
    layout.anchoring = MindFusion.Graphs.Anchoring.Reassign;
    layout.nodeDistance = 10;
    layout.layerDistance = 10;

    this.diagram.arrange(layout);
 



Actually, it should look like this:
Code
Select All
link text start activity 2
link text end task 6
link start point MindFusion.Drawing.Point {x: 100, y: 75, type: "MindFusion.Drawing.Point"}
link start point MindFusion.Drawing.Point {x: 0, y: 75, type: "MindFusion.Drawing.Point"}
 



When I use "KEEP" instead of "REASSIGN", then the anchor points are more chaotic. They even swap their site (from x=100 to x=0 or vice versa).

Can I somehow disable or overriding the anchoring? I really need the functionality to move around anchor points (and add/remove them on the fly) while keeping the corresponding link connected to the correct anchor points.

The problem I have with Reassign is, that it seems to take the shortest path to any anchor attached to a node. That's not what I want. The path itself should be the shortest, but not reassigning the anchors.

Is there yet another way to override the path search? I'd like to implement my own one.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #6 - Jul 30th, 2018 at 3:52pm
Print Post  
The keep and reassign options only work for nodes whose AnchorPattern property is set, I'm not sure what they would do for null patterns. If you need links to preserve their relative coordinates along node sides without actually using AnchorPattern/Point objects, you will need to save and restore them before and after layout at this time. E.g. this works in my test -

Code
Select All
var n1 = diagram.factory.createShapeNode(10, 10, 20, 20);
var n2 = diagram.factory.createShapeNode(80, 10, 20, 20);
var l = diagram.factory.createDiagramLink(n1, n2);

l.setStartPoint(l.getStartPoint().newWithOffset(0, -5));
l.setEndPoint(l.getEndPoint().newWithOffset(0, -5));
l.updateFromPoints();

// record relative positions
for (var i = 0; i < diagram.links.length; i++)
{
	var link = diagram.links[i];
	link._relativeStart = link.originConnection.relativePosition;
	link._relativeEnd = link.destinationConnection.relativePosition;
}

var layout = new MindFusion.Graphs.LayeredLayout();
layout.direction = MindFusion.Graphs.LayoutDirection.LeftToRight;
diagram.arrange(layout);

var Utils = MindFusion.Diagramming.Utils;
for (var i = 0; i < diagram.links.length; i++)
{
	var link = diagram.links[i];
	link.setStartPoint(
		Utils.rectPtFromPercent(
			link._relativeStart, link.getOrigin().getBounds()));
	link.setEndPoint(
		Utils.rectPtFromPercent(
			link._relativeEnd, link.getDestination().getBounds()));
	link.updateFromPoints();
} 



Quote:
Is there yet another way to override the path search? I'd like to implement my own one.


Layout and interaction code call a DiagramLink.prototype.updateIntersections() method to select end point coordinates for links when not using AnchorPattern/Point objects; so you could replace that function with your own to select different coordinates.

If you decide to use AnchorPattern/Point objects, the arrange method ends with this code in the Reassign case:

Code
Select All
var oanchor = link.origin.getNearestAnchor(link.points[0], link, false);
var danchor = link.destination.getNearestAnchor(link.points[link.points.length - 1], link, true);
link.setOriginAnchor(oanchor.index);
link.setDestinationAnchor(danchor.index); 



So then you could replace DiagramNode.prototype.getNearestAnchor function to select different anchor points.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #7 - Aug 1st, 2018 at 10:27am
Print Post  
I'd rather would like to use AnchorPoints for that.

The problem that I have is that I'm not using JavaScript but TypeScript, and the "newWithOffset" and the Namespace "Utils" is missing, unfortunately.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #8 - Aug 2nd, 2018 at 7:46am
Print Post  
Okay, could you explain what was the original problem when using AnchorPoints? You should be able to call setOriginAnchor and setDestinationAnchor after createDiagramLink to snap the link to respective points, where the arguments are integer indices specifying element inside AnchorPattern.
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #9 - Aug 9th, 2018 at 4:02pm
Print Post  
The original problem was that the arrange layout method snapped the links to different anchor points.
I tried it with setDestinationAnchor but maybe I used it the wrong way.
I will try it again and write back tomorrow.

The idea is that each link has two unique anchor points. So when creating a new link, two new anchor points are created automatically and all anchor points of the two nodes  (that the new link connects) will move along the y-axis to make place for the newly created anchor point. So the shortest distance for a link in relation to the anchor points do not care, while the shortest distance for the link itself between its anchor points does.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #10 - Aug 10th, 2018 at 9:50am
Print Post  
We could implement a new Anchoring option if you let us know by what criteria to select the points if different from closest pair. Or we could add some callback that lets you select the points yourself if you prefer that.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #11 - Aug 10th, 2018 at 6:34pm
Print Post  
Thanks for the offer! That would be awesome.
Maybe a callback is enough. So you spend time and we have more general control about the graph drawing flow.

I appreciate your work!  Smiley

  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3153
Joined: Oct 19th, 2005
Re: Set anchor points for link
Reply #12 - Sep 1st, 2018 at 10:16am
Print Post  
This build adds an Anchoring.Custom element -
https://mindfusion.eu/_beta/jsdiag322.zip

Code
Select All
var ll = new MindFusion.Graphs.LayeredLayout();
ll.setAnchoring(Anchoring.Custom);
ll.selectAnchorPoints = function (link)
{
	var ox = link.getOrigin().getCenter().x;
	var dx = link.getDestination().getCenter().x;
	var indices = ox > dx ?
		{
			origin: 1,
			destination: 3
		} :
		{
			origin: 4,
			destination: 0
		};
	return indices;
};
diagram.arrange(ll); 



Regards,
Slavcho
  
Back to top
 
IP Logged
 
Davaaron
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 42
Joined: Jul 12th, 2018
Re: Set anchor points for link
Reply #13 - Sep 1st, 2018 at 12:37pm
Print Post  
Thanks, that's awesome! I'll try that out. Thanks for your effort.

Just another quick question. Meanwhile I looked through the source code and found a lot of functions like
Code (Javascript)
Select All
(function(mdiag){
// methods and fields

})(MindFusion.Diagramming);
 



I know this is called whenever the window or document is ready. The parameter mdiag confuses me. As far as I know, parameters are not available for that kind of function and I couldn't find the global reference to that mdiag Object (which is of type Object). I'm just wondering because I want to override the LayeredLayout arrange method and would like to access mdiag to be able to use the LayoutUtils class. But it's fine if it's not possible Smiley
  
Back to top
 
IP Logged
 
Lyubo
God Member
*****
Offline


MindFusion team

Posts: 511
Joined: Jun 17th, 2010
Re: Set anchor points for link
Reply #14 - Sep 3rd, 2018 at 6:05am
Print Post  
Hi,

These are just self-invoking functions and mdiag is the alias of the MindFusion.Diagramming object parameter that is passed to the method. So you can use access LayoutUtils via MindFusion.Diagramming. The LayeredLayout class is in the MindFusion.Graphs namespace.

Regards,
Lyubo
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: [1] 2 
Send TopicPrint