Calculating curviness

Hi,

I just created a bezier link and added a custom resize handle exactly in the middle (spot=MiddleRight)
Now, when i drag this new custom handle i need to recalculate the new Curviness value of the link and then call the CalculateRoute method.
I'm having problem calculating the new curviness value becuase i don't really understand what are exactly the roles of origRect and newPoint arguments.
In the overriden DoResize method, I calculate the curviness like this:
float gap = newPoint.X - origRect.Right;
this.AdjustingStyle = GoLinkAdjustingStyle.Calculate;
this.Curviness = origRect.Right+gap;
this.CalculateRoute();
But the results are not accurate enough.
Could you please send me the correct formula for calculating the new Curviness?
Hope i was clear.
Thanks,

Here’s a complete TransitionLink that you can drop into StateCharter, starting with your code posted earlier:

[code]
[Serializable]
public class TransitionLink : GoLink {
public TransitionLink() {}

public override void DoResize(GoView view, RectangleF origRect, PointF newPoint,
int whichHandle, GoInputState evttype, SizeF min, SizeF max) {
if ((whichHandle == SharpnessID) &&
(this.ResizesRealtime || evttype == GoInputState.Start|| evttype == GoInputState.Finish || evttype == GoInputState.Cancel)) {
if (evttype == GoInputState.Start) {
origPoint = newPoint;
} else {
float gap = origPoint.X - newPoint.X;
this.Curviness = gap;
this.AdjustingStyle = GoLinkAdjustingStyle.Calculate;
this.CalculateRoute();
}
} else {
base.DoResize(view, origRect, newPoint, whichHandle, evttype, min, max);
this.AdjustingStyle = GoLinkAdjustingStyle.Scale;
}
}
public override void AddSelectionHandles(GoSelection sel, GoObject selectedObj) {
base.AddSelectionHandles(sel, selectedObj);
PointF handlePoint = this.GetSpotLocation(GoObject.MiddleRight);
IGoHandle handle = sel.CreateResizeHandle(this, selectedObj, handlePoint, SharpnessID, true);
GoHandle goh = handle.GoObject as GoHandle;
if (goh != null) {
goh.Style = GoHandleStyle.Diamond;
goh.BrushColor = Color.Yellow;
RectangleF bounds = goh.Bounds;
bounds.Inflate(1, 1);
goh.Bounds = bounds;
}
}
public const int SharpnessID = 101;
[NonSerialized]
PointF origPoint;
}
[/code]
The behavior here is to set curviness to the offset between the mouse-down X position on the curvi-handle and the current X position.
So, moving the mouse left and right changes the curviness.
It may not be the UI you want, but you should be able to take it from here....

New and Improved: uses view.FirstInput.DocPoint and handles X/Y movement of mouse.

[code]
[Serializable]
public class TransitionLink : GoLink {
public TransitionLink() {}
public override void DoResize(GoView view, RectangleF origRect, PointF newPoint,
int whichHandle, GoInputState evttype, SizeF min, SizeF max) {
if ((whichHandle == SharpnessID) &&
(this.ResizesRealtime || evttype == GoInputState.Finish || evttype == GoInputState.Cancel)) {
float gap = view.FirstInput.DocPoint.X - newPoint.X;
float gapY = view.FirstInput.DocPoint.Y - newPoint.Y;
if (Math.Abs(gapY) > Math.Abs(gap)) gap = gapY;
this.Curviness = gap;
this.AdjustingStyle = GoLinkAdjustingStyle.Calculate;
this.CalculateRoute();
} else {
base.DoResize(view, origRect, newPoint, whichHandle, evttype, min, max);
this.AdjustingStyle = GoLinkAdjustingStyle.Scale;
}
}
public override void AddSelectionHandles(GoSelection sel, GoObject selectedObj) {
base.AddSelectionHandles(sel, selectedObj);
PointF handlePoint = this.GetSpotLocation(GoObject.MiddleRight);
IGoHandle handle = sel.CreateResizeHandle(this, selectedObj, handlePoint, SharpnessID, true);
GoHandle goh = handle.GoObject as GoHandle;
if (goh != null) {
goh.Style = GoHandleStyle.Diamond;
goh.BrushColor = Color.Yellow;
RectangleF bounds = goh.Bounds;
bounds.Inflate(1, 1);
goh.Bounds = bounds;
}
}
public const int SharpnessID = 101;
}
[/code]

Thanks a lot Jake!
As usual your support is great!!
In case you’re intereseted i post the final calculation which works perfect. It looks like you have to copy the curviness before the resizing process begins and add it to the gap otherwise it doesn’t behave correctly.
public override void DoResize(GoView view, RectangleF origRect, PointF newPoint,int whichHandle, GoInputState evttype, SizeF min, SizeF max)

{
if ((whichHandle == SharpnessID) && (this.ResizesRealtime || evttype == GoInputState.Finish || evttype==GoInputState.Start || evttype == GoInputState.Cancel)) { if (evttype == GoInputState.Start) _startCurviness = this.Curviness; float gap = newPoint.X - view.FirstInput.DocPoint.X; float gapY = newPoint.Y - view.FirstInput.DocPoint.Y; if (Math.Abs(gapY) > Math.Abs(gap)) gap = gapY; this.Curviness = _startCurviness + gap;
this.AdjustingStyle = GoLinkAdjustingStyle.Calculate;
this.CalculateRoute(); if (evttype == GoInputState.Finish) _startCurviness = this.Curviness; } else { base.DoResize(view, origRect, newPoint, whichHandle, evttype, min, max); this.AdjustingStyle = GoLinkAdjustingStyle.Scale; } }
Also, i'm not sure i quite understand the HandleID thing. why do i have to decide in advance the HandleID number and not just get it as a result of calling the CreateResizeHandle method? It looks fragile. don't you think?
Thanks again,

GoObject uses TopLeft, MiddleTop, etc for resize handle ids… GoStroke and GoLink are a little different because they don’t have “spots” like that. So what you end up with is mostly an “enum” sort of an input that has situations where a static enum isn’t enough.

But you don't want the system generating the ids because that would take storage to remember them.

OK, I understand.

I guess that if the DoResize method would get the relevant IGoHandle instead of the whichHandle integer it will be a cleaner design and without a storage penalty. I just hate hard-coding values in my code. But anyway it works fine.
Thanks,