Andrei
Andrei

Reputation: 63

Why does Rect.Intersect return a non-empty Rect for two rectangles who are not intersected?

I have a small project in WPF, in which I am required to interchange UIElements. Something resembling iGoogle's functionality.

Due to the fact that I can't post pictures (not enough reputation) I will explain in text. I have a 3x3 grid defined like this:

   0   1   2
 0 C   e   C
 1 e   e   e
 2 L   e   C

Where C = canvas, L = label, e = empty cell (column+row).

In the MouseMove event, I'm keeping track of my currently selected canvas and I go through a list of all the other canvases available in the grid to check if they are overlapping. And here comes the problem; even though I'm moving the canvas from (0,0) to the right by 1 pixel, it detects that it is intersecting with the canvas from (2,2).

I am using Rect.Intersect(r1, r2) to determine the intersected area and it should return an empty Rect, because r1 is not overlapping r2, but instead it always returns a non-empty Rect.

        // Create the rectangle with the moving element width and height
        Size draggedElementSize = new Size(this.DraggedElement.ActualWidth, this.DraggedElement.ActualHeight);
        Rect draggedElementRect = new Rect(draggedElementSize);

        foreach (Canvas c in canvases)
        {
            // Create a rectangle for each canvas
            Size s = new Size(c.ActualWidth, c.ActualHeight);
            Rect r = new Rect(s);

            // Get the intersected area
            Rect currentIntersection = Rect.Intersect(r, draggedElementRect);

            if (currentIntersection == Rect.Empty) // this is never true
                return;

        } // end-foreach

I am doing various other things inside the loop, but they don't interact in any way with this, since this isn't working properly.

I'd appreciate any help whatsoever.

Thanks.

Upvotes: 4

Views: 1026

Answers (2)

Lee Louviere
Lee Louviere

Reputation: 5262

Nowhere in your code example are you offsetting the rects by location. You're only setting the rects size.

So of course, all your rects start at Point(0,0), and therefore all intersect.

You'll need to transform the rects from the element your checking, to their parent.

The quickest way to accomplish this is VisualTreeHelper.GetOffset

    // Create the rectangle with the moving element width and height
    Size draggedElementSize = new Size(this.DraggedElement.ActualWidth, this.DraggedElement.ActualHeight);
    Rect draggedElementRect = new Rect(draggedElementSize);
    draggedElementRect.offset(VisualTreeHelper.GetOffset(this.DraggedElement));

    foreach (Canvas c in canvases)
    {
        if (this.DraggedElement == c) continue; // skip dragged element.
        // Create a rectangle for each canvas
        Size s = new Size(c.ActualWidth, c.ActualHeight);
        Rect r = new Rect(s);
        r.offset(VisualTreeHelper.GetOffset(c));

        // Get the intersected area
        Rect currentIntersection = Rect.Intersect(r, draggedElementRect);

        if (currentIntersection == Rect.Empty) // this is never true
            return;

    } // end-foreach

You might want to make sure you skip the currently dragged element, as indicated.

Upvotes: 1

nvoigt
nvoigt

Reputation: 77334

I don't see any references to positions in your code, only width and height. Do you really want to start all your rectangles at 0/0? Most likely, they will all overlap. You need to include the x/y coordinates.

Upvotes: 1

Related Questions