Set custom points for connections

Hello,

I want to set implement a function, wehere the user can set custom route points by a context menu entry. The user shall insert new points an remove existing custom route points. I tried to realize that function by using the folowing code:

foreach (SwConnectorViewModel element in this.elements.OfType())
{
Link link = this.diagram.PartManager.FindLinkForData(element, this.diagramModel);

if (link != null)
{
int segment = link.Route.FindClosestSegment(this.lastInputPosition);

link.Route.InsertPoint(segment + 1, new Point(this.lastInputPosition.X, this.lastInputPosition.Y));
link.Route.UpdatePoints();
}
}

The code inserts new points within a route, but it does not work very well. The inserted points will only be visible by reselection the specified route within the diagram and the custom points cannot be moved in each direction by using the mouse.

Thanks for your help!

Regards,

Benedikt

First I should say that I hope you are not really going to insert a point on each Link in your diagram. I suggest that it only operate on the selected Link (Diagram.SelectedLink).

Here is a WPF project that demonstrates reshaping a polygon or polyline shape and that uses a context menu for inserting and removing points: PolyDemo.zip. That isn’t the same as doing so for Links, but it’s pretty close.

Furthermore we are planning for the next release adding functionality to Link and LinkReshapingTool to allow users to automatically add and remove points from a Link.Route without the use of context menus. I recently back-ported some of this code to run on version 2.1, which you can find in this adaptation of the Piping sample: Piping2.zip.

Hello Walter,

the “Piping2” solution works find, but I have still one problem. When I remove one custom point by using the context menu the adornments of the link does not update. The “yellow rectangle” will not be deleted but moves to the end of the link. If I reselect the specified link everything is fine and the deleted point has no “yellow rectangle”. I use the following code:

diagram.StartTransaction(“Remove Point”);

foreach (SwConnectorViewModel element in this.elements.OfType())
{
int indexToRemove = int.MinValue;
double distance = double.MaxValue;
Link link = this.diagram.PartManager.FindLinkForData(element, this.diagramModel);

for (int i = 2; i < link.Route.Points.Count - 2; i++)
{
Point point = link.Route.Points;
double tmpDistance = point.Distance(this.lastInputPosition);

if (tmpDistance < distance)
{
indexToRemove = i;
distance = tmpDistance;
}
}

if (indexToRemove != int.MinValue)
{
link.Route.RemovePoint(indexToRemove);
}

link.Remeasure();
link.UpdateAdornments();
}

diagram.CommitTransaction(“Remove Point”);

By the way there is a loop but i only edit the current selected link.

Well, you call UpdateAdornments(), so the Adornments for the Link ought to be updated OK. I wonder how your circumstances are different from PolyDemo. You are still going for the ContextMenu design, not the “resegmentable” alternative implemented in Piping2, aren’t you?

Although PolyDemo works on Nodes instead of Links, does it do what you are asking for?

I used the Piping2 reshaping tool and it works fine, but I have also to provide a “Remove custom point” function. This function I try to realize via cotext menu, because I dont find a way to remove custom points by using the reshaping tool. Is there a way doing this by using the LinkReshapingTool from the Piping2 demo? In my scenario I have nodes, which can be connected with links. On these links there shall be the custom points so it should work on links not on nodes. So I currently try to find a way to remove custom points created by the LinkReshapingTool of the Piping2 demo.

It may be important to tell you, that the CustomLinkReshapingTool is active when I try to remove a custom point. I think it works when I do a kind of refresh to the currently active CustomLinkReshapingTool

With the Piping2 code, when the user drags a point so that the adjacent segments are in a line, that point is automatically removed, thereby removing a segment (or two if orthogonal) and simplifying the route.

It works if I increase the ResegmentingDistance from 3 to 10. Maybe 3 was a little bit to small for my scenario. Is there additionally a way to support this function by using the context menu. I think its more intuitive for our users. With GoDiagram we give the user a opportunity to remove that points by using the context menu so I have to implement that function to.

Sure, I do not see any reason why you couldn’t implement both the custom LinkReshapingTool and have a ContextMenuService.ContextMenu on the Link.

Yes, but if I try to implement an additional context menu I got the described problem:

When I remove one custom point by using the context menu the adornments of the link does not update. The “yellow rectangle” will not be deleted but moves to the end of the link. If I reselect the specified link everything is fine and the deleted point has no “yellow rectangle”. I use the following code:

diagram.StartTransaction(“Remove Point”);

foreach (SwConnectorViewModel element in this.elements.OfType())
{
int indexToRemove = int.MinValue;
double distance = double.MaxValue;
Link link = this.diagram.PartManager.FindLinkForData(element, this.diagramModel);

for (int i = 2; i < link.Route.Points.Count - 2; i++)
{
Point point = link.Route.Points;
double tmpDistance = point.Distance(this.lastInputPosition);

if (tmpDistance < distance)
{
indexToRemove = i;
distance = tmpDistance;
}
}

if (indexToRemove != int.MinValue)
{
link.Route.RemovePoint(indexToRemove);
}

link.Remeasure();
link.UpdateAdornments();
}

diagram.CommitTransaction(“Remove Point”);

Can you tell me how I can implement a context menu function, which removes a custom point from a link and afterwards updates the active CustomLinkReshapingTool?

But that’s what PolyDemo does (i.e. call Remeasure() and UpdateAdornments()) and that updates as I think you would expect. So I wonder what else might be different. Your statement that the LinkReshapingTool is active might account for that. But I do not understand why that would be the case.

Oh wait – are you putting the context menu on the Adornment rather than on the Link itself? Although even then I would think that the calls to UpdateAdornments() would work.

Yes me too. As ou can see in the sample code I do that too. I call link.Remeasure(); and link.UpdateAdornments(); on the modified (removed custom point link) but that does not work. I think the "link.Remeasure(); and link.UpdateAdornments(); " solution does not work, bekause during the modification of the link points the reshaping tool of the Piping2 demo is active.

Could you download Piping2.zip again? I have updated it to include a context menu on the Link that adds and removes points from the link route.

The problem with the updating of the LinkReshapingTool Adornment is that it didn’t rebuild the Adornment when the number of handles needed to change. So I just replaced the call to Remeasure(), which I believe is unneeded, with a call to link.SetAdornment(“ReshapingTool”, null), which removes the old Adornment so that the call to UpdateAdornments() creates it anew.

That works great! Thank you very much :)

Hello Walter,
can you please fix the download link for sample “Piping2.zip” ?
Thanks,
Robert

I was unable to figure out how to update the URL rewriting rules to allow all of the files at nwoods.com/forum/uploads/* and nwoods.com/forum/useruploads/* to be served normally, while still having other URLs go to forum.nwoods.com.

But you can get the file now at a different directory:
http://www.nwoods.com/forumFiles/uploads/Piping2.zip