Список C # <T>.Find (x => x.Rectangle.Contains (Point)) FAIL - PullRequest
3 голосов
/ 04 февраля 2010

Для жизни я не могу понять, почему этот код производит следующий вывод ...

Я думаю, что есть ошибка или что-то подобное при использовании List и lambda, если тип предоставляет свойство Rectangle, и вы используете метод Contains объекта прямоугольника ... и явная итерация подтверждается, в то время как метод List Find не работает ... .

Oneway

Код

public GridSquare WorldToKeyPadSub(Point location)
    {
        location = _Map.WorldToClient(location);
        GridSquare gs = this.Find(x => x.Rectangle.Contains(location));
        GridSquare kp = gs.Find(x => x.Rectangle.Contains(location));
        List<GridSquare> list = kp.FindAll(x=>x.Rectangle.Contains(location));
        u.dp(list.Count);
        GridSquare sub = kp.Find(x => x.Rectangle.Contains(location));

        if (sub == null)
        {
            u.dp("Location to look for " + location);
            u.dp("Found Location in grid square " + gs.ToString());
            u.dp("grid square bounds " + gs.Rectangle.ToString());
            u.dp("Found Location in Keypad " + kp.ToString());
            u.dp("key pad bounds " + kp.Rectangle.ToString());
            u.dp("Sub Key Pads Print All sub keys in this grid.keypad");
            foreach (GridSquare t in kp)
            {
                u.dp(t.ToString() + "  " + t.Rectangle.ToString());                   

            }
            u.dp("Sub Key Pads Print Explicit Finds");
            foreach (GridSquare t in kp)
            {
                if (location.X >= t.Location.X
                    && location.Y >= t.Location.Y
                    && location.X <= t.Location.X + t.Rectangle.Width
                    && location.Y <= t.Location.Y + t.Rectangle.Height)
                {
                    u.dp(true);
                    u.dp(t.ToString() + "  " + t.Rectangle.ToString());
                }

            }
        }
        return sub;
    }

Это дает следующий вывод ...

Обратите внимание, как явный Rectangle (он же ручной метод) находит квадраты сетки, которые содержат местоположение .... внутренняя версия GDI не работает ....

Location to look for {X=1476,Y=1716}
Found Location in grid square GS: 14.3.0.0
grid square bounds {X=1398,Y=1650,Width=100,Height=100}
Found Location in Keypad GS: 14.3.6.0
key pad bounds {X=1465,Y=1683,Width=33,Height=34}
Sub Key Pads Print All sub keys in this grid.keypad
GS: 14.3.6.7  {X=1465,Y=1683,Width=11,Height=11}
GS: 14.3.6.8  {X=1476,Y=1683,Width=11,Height=11}
GS: 14.3.6.9  {X=1487,Y=1683,Width=11,Height=11}
GS: 14.3.6.4  {X=1465,Y=1694,Width=11,Height=11}
GS: 14.3.6.5  {X=1476,Y=1694,Width=11,Height=11}
GS: 14.3.6.6  {X=1487,Y=1694,Width=11,Height=11}
GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}
GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}
GS: 14.3.6.3  {X=1487,Y=1705,Width=11,Height=11}
Sub Key Pads Print Explicit Finds
True
GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}
True
GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}
A first chance exception of type 'System.NullReferenceException'

Ответы [ 3 ]

6 голосов
/ 04 февраля 2010

Rectangle.Contains(Point) является исключительным (строго меньшим) в верхних границах прямоугольника.

Например, эквивалентная проверка, выполненная Rectangle.Contains(Point) в вашем контексте, будет:

foreach (GridSquare t in kp) 
{ 
    if (location.X >= t.Location.X 
        && location.Y >= t.Location.Y 
        && location.X < t.Location.X + t.Rectangle.Width   // < instead of <=
        && location.Y < t.Location.Y + t.Rectangle.Height) // < instead of <=
    { 
        u.dp(true); 
        u.dp(t.ToString() + "  " + t.Rectangle.ToString()); 
    } 

} 

Как видите, верхние границы проверяются как строго меньшие, чем вместо меньших или равных, разница между вашим методом и Rectangle.Contains(Point) лежит именно там.

Местоположение, переданное в вашем примере: {X = 1476, Y = 1716}, то есть когда передается Содержит эти прямоугольники:

GS: 14.3.6.1  {X=1465,Y=1705,Width=11,Height=11}  
GS: 14.3.6.2  {X=1476,Y=1705,Width=11,Height=11}  

вернет false, когда ваш вернет true.

Вот почему kp.Find(x => x.Rectangle.Contains(location)); возвращает ноль, а ваши ручные проверки возвращают true.

2 голосов
/ 11 февраля 2010

Это то, что я узнал ...

Рассмотрим на мгновение прямоугольник, который определен 0,0,100,100 ...

Можно предположить, что эта точка 100,100 находится внутри этой точки.прямоугольник, но это совсем не так ...

Rectangle.Contains исключает границы ... другими словами, он будет возвращать true только для всех точек от 0,0 до 99,99 впрямоугольник, определенный как 0,0,100,100 ...

Проблема, с которой я столкнулся, заключается в том, что когда вы используете GDI для рисования этого прямоугольника ... пиксели рисуются смещенными вниз и вправо ...

Чистый эффект заключается в том, что Rectangle.Contains включительно для верхней и левой ветви прямоугольника и исключительно для нижней и правой ветви прямоугольника ... и с графической точки зрения ... и вы можете увеличить масштаб до уровня пикселейво время теста попадания мышью ...

Курсор может показаться как раз внутри границы прямоугольника вправо и вниз ... но тест попадания возвращает false из-за исключительной природы Rectangle.Containsдля риGHT и нижние ноги ...

SW

0 голосов
/ 04 февраля 2010

Я вижу две вещи, которые вы можете проверить:

  1. Ваш явный чек является включающим - меньше и равно, больше и равно.Если Rectangle.Contains является эксклюзивным, то обе найденные вами явные проверки будут опущены.

  2. Вы уверены, что x.Location.X и .Y всегда совпадают с x.Прямоугольник.Х и .Y?

...