Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Strange behaviour when using LINQ (Read 2000 times)
pelion
Junior Member
**
Offline



Posts: 61
Joined: Nov 12th, 2006
Strange behaviour when using LINQ
Jun 20th, 2008 at 12:13am
Print Post  
Hi Stoyo,

I realise that this problem may be out of your area of control, but I thought I'd mention it, in case you can provide some insight, or have seen it before.

I am trying to get a sorted list of the Boxes on a chart, first by their X, then Y, coordinates, for example

{0,1} {0,2} {0,3} {1,0} {1,3} etc

I decided to use LINQ for Objects for its simplicity.

First to get a List that LINQ could work with I added a method (performance-wise, not an ideal start. If I can get it working, I'll probably eventually override the GetEnumerator() method and add an orderBy Extension):

Code
Select All
private static List<Box> GetBoxesAsList(FlowChart chart)
        {
            List<Box> boxes = new List<Box>();

            foreach (Box box in chart.Boxes)
            {
                boxes.Add(box);
            }

            return boxes;
        }
 



This returns a List of Type Box, and in the debugger their positions are apparently in a random (in fact order of added) order.

I then added an extension method to the chart
Code
Select All
public static List<Box> GetBoxesByPosition(this FlowChart chart, Orientation orientation)
{
if (orientation == Orientation.Auto)
                orientation = Orientation.Horizontal;

            var result = from b in chart.GetBoxesAsList()
                         orderby orientation == Orientation.Horizontal ? b.BoundingRect.X : b.BoundingRect.Y,
                                 orientation == Orientation.Horizontal ? b.BoundingRect.Y : b.BoundingRect.X
                         select b;

            return result.ToList<Box>();
}
 



but the outcome always gave me a list of Boxes at position (5.0, 5.0) (they were different boxes, just with their positions reset)

To see if I was mucking something up with my orierntation condition, or the double order, I first tried

Code
Select All
orderby b.BoundingRect.X, b.BoundingRect.Y
 



and

Code
Select All
orderby b.BoundingRect.X
 



but still every box was getting its position reset to (5.0, 5.0)

I thought I'd try simple lambda (I can't believe I used the term 'simple' and the term 'lambda' next to each other)

Code
Select All
return GetBoxesAsList(chart).OrderBy(p => p.BoundingRect.X).ThenBy(p => p.BoundingRect.Y).ToList();
 



but still 5,5

I even tried specifying p.BoundingRect.Location.X and Y, but by then I was getting the strong impression that I was just doing the same thing over and over in a different way.

I am wondering if the Location Coordinates 5.0, 5.0 give any hints to what might be going on.

I am now facing the realisation that I am going to have to code up my own sorting algorithm Sad dammit

Thanks in advance for any advice you may give
JC
  
Back to top
 
IP Logged
 
pelion
Junior Member
**
Offline



Posts: 61
Joined: Nov 12th, 2006
Re: Strange behaviour when using LINQ
Reply #1 - Jun 20th, 2008 at 12:33am
Print Post  
I've tested the lambda code with

Code
Select All
class objWithPosition
    {
	  public objWithPosition(RectangleF f)
	  {
		BoundingRect = f;
	  }
	  public RectangleF BoundingRect { get; set; }
    }

...

public static List<Box> GetBoxesByPosition(this FlowChart chart, Orientation orientation)
	  {

		//Test bug
		List<objWithPosition> test = new List<objWithPosition>();

		test.Add(new objWithPosition(new RectangleF(1,2,3,4)));
		test.Add(new objWithPosition(new RectangleF(3,4,2,1)));
		test.Add(new objWithPosition(new RectangleF(6,3,6,9)));
		test.Add(new objWithPosition(new RectangleF(4,9,4,2)));

		List<objWithPosition> sorted = test.OrderBy(p => p.BoundingRect.Location.X).ThenBy(p => p.BoundingRect.Location.Y).ToList();
 



and it doesn't reset the internal BoundingRect.

It all seems very quantum, affecting something simply by observing it  Wink
  
Back to top
 
IP Logged
 
pelion
Junior Member
**
Offline



Posts: 61
Joined: Nov 12th, 2006
Re: Strange behaviour when using LINQ
Reply #2 - Jun 20th, 2008 at 1:08am
Print Post  
The plot thickens, it appears to be something about hashing boxes

In order to get around this for the moment, I returned from my LINQ Query a List of Box Tags (all unique), then compared them to a dictionary of boxes by tags.

Code
Select All
foreach (object tag in tags)


{


    boxToAdd = _boxByTag[tag];//get box first to test its position


    boxes.Add(_boxByTag[tag]);


}
 



In the dictionary (or hashtable) the position of the box is correct (as a watch or in the immediate window), but when I retreive it (into a variable like boxToAdd), it loses its position (5.0, 5.0).

Are you overriding the GetHashKey function for the chart Nodes?

BTW, we are still, prehistorically, on v4.2.2, but don't have the luxury of time to upgrade just yet.

[edit]
chart.FindBox(tag); is also resetting my positions
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Strange behaviour when using LINQ
Reply #3 - Jun 20th, 2008 at 7:40am
Print Post  
To my shame, I know nothing of LINQ yet 8) You could try this more traditional method:

Code
Select All
class NodeComparer : IComparer<DiagramNode>
{
	public int Compare(DiagramNode n1, DiagramNode n2)
	{
		if (n1.Bounds.X < n2.Bounds.X) return -1;
		if (n1.Bounds.X > n2.Bounds.X) return 1;
		if (n1.Bounds.Y < n2.Bounds.Y) return -1;
		if (n1.Bounds.Y > n2.Bounds.Y) return 1;
		return 0;
	}
}

List<DiagramNode> nodes = GetNodesAsList(diagram);
nodes.Sort(new NodeComparer());
 



I can't find GetHashKey overridden anywhere in the Flowchart.NET code, but I'll get our developer to investigate.

Stoyan
  
Back to top
 
IP Logged
 
pelion
Junior Member
**
Offline



Posts: 61
Joined: Nov 12th, 2006
Re: Strange behaviour when using LINQ
Reply #4 - Jun 20th, 2008 at 10:21am
Print Post  
No worries Stoyo, thanks for that.

From further investigation, the problem only seems to arise when the box size is (1,1), not sure why (I'm using the tree layout for positioning purposes only at this stage, them applying them to a grid).

Thanks for the 'trad' code.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint