I recently found need of a library to perform graphing, and stumbled across TSimpleGraph, and the ExtGraph project.
I have to say I am very impressed, however I did discover a small "bug" which you may wish to hear about.
I use the term "bug" loosely here because I am not sure if it is a code problem, or just a limitation of the types available.
I originally found the bug using a program I created which layed out about 320 nodes with about 1000 links programatically, and sometimes the nodes would be at coordinates such as 3020,3020, linked back to nodes at near 0,0.
Once the nodes have been inserted, and the links created, moving the mouse about over the canvas area of the TSimpleGraph usually caused an "EInvalidOP" error with message "Invalid Floating Point Operation"
I have attached an example program source code, and compiled executable all in ZIP format. Its a delphi 6 file so anything greater should read it. You need to have the TSimpleGraph component installed obviously.
You can recreate the bug, by using the following code:
- Code: Select all
procedure test1:
var PR: PRect;
R: TRect;
N1: TGraphNode;
N2: TGraphNode;
begin
R.Left := 0;
R.top := 0;
R.Bottom := 20;
R.Right := 20;
PR := @R;
N1 := SimpleGraph1.InsertNode(PR, TRoundRectangularNode);
R.Left := 3020;
R.top := 3020;
R.Bottom := R.top + 20;
R.Right := R.Left + 20;
N2 := SimpleGraph1.InsertNode(PR, TRoundRectangularNode);
SimpleGraph1.LinkNodes(N1, N2);
end;
Please note it is intermittent with this test code, you may wish to try moving both nodes about, and scrolling around, moving the mouse widely. I have found the following generally helps make it crash faster:
1) Scroll vertically and then horizontally to the bottom-right corner by dragging the peas in the scrollbars
2) Move the node there furthur away by about 200 pixels (exact amount unimportant) - thus expanding the canvas area
3) Scroll the bars to the bottom-right again to bring the node back into view (do this by clicking in the bar, rather than dragging the pea)
4) Scroll the horizontal bar back about halfway very quickly, and then move the mouse upwards over the canvas. Sometimes you must release the mouse as you move upwards, before you actually move over the canvas. This is the tricky bit
Once the program starts producing the errors when you move the mouse over the simplegraph canvas, it will keep doing it until the program is shut down.
I am using Borland Delphi 6.0 (Build 6.163) on W2k SP3.
I spent some time (several hours) tracking this down, and found it to be in the v1.542 (oct 12th) build of SimpleGraph.pas:980 DistanceToLine routine:
- Code: Select all
Result := Round(Sqrt(Sqr(QueryPt.X - Pt.X) + Sqr(QueryPt.Y - Pt.Y)));
The reason for this error? Well value inspection reveals the following:
QueryPt.X := 219;
QueryPt.Y := 3;
Pt.X := -90372;
Pt.Y := -88337;
These values vary from run to run - but the critical point is the X, Y values for "Pt" are somewhere around -80000 (although I have had it occur with values of -40000).
This causes the Sqrt command to produce the EInvalidOP error (invalid floating point operation).
I broke the issue down into a standalone procedure:
- Code: Select all
procedure test();
var ResultInt : integer;
QueryPt : TPoint;
Pt : TPoint;
X : integer;
Y : integer;
Squared1 : Extended;
Squared2 : Extended;
Squared : Extended;
Sqroot : Extended;
begin
{sqr(-83126) + sqr(-80755)
6909931876 + 6521370025
sqrt(13431301901)
115893.4938}
QueryPt.X := 219;
Pt.X := -90372;
QueryPt.Y := 3;
Pt.Y := -88337;
X := QueryPt.X - Pt.X;
Y := QueryPt.Y - Pt.Y;
Squared1 := Sqr(X);
Squared2 := Sqr(Y);
Squared := Squared1 + Squared2;
sqroot := Sqrt(Squared);
ResultInt := Round(sqroot);
ShowMessage(IntToStr(ResultInt));
end;
Interestingly if I change the variable types as follows:
- Code: Select all
X : Extended;
Y : Extended;
You no longer get the error message.
I am not sure what is going on here - I suspect a simple overflow, but then surely changing those two variables to extended should not have any effect (especially since the error occurs after those values have been calculated and written back).
Am I actually using the InsertNode and LinkNodes routines correctly, or do I need to use new to create a new version of TRect for the first parameter to point to each time?
Anyway, hope this is not something serious cause I'd like to get my program working a bit more stably.
Any ideas?