Как пересекаются прямоугольники с отрицательным размером?

Может кто-нибудь объяснить, почему отрицательный размер Rectangle пересекается так, как они делают?

var r  = new Rectangle(0, 0,  3,  3);
var r0 = new Rectangle(0, 0, -1, -1);
var r1 = new Rectangle(1, 1, -1, -1);
var r2 = new Rectangle(2, 2, -1, -1);
var r3 = new Rectangle(3, 3, -1, -1);

System.Console.WriteLine(r.IntersectsWith(r0)); // False
System.Console.WriteLine(r.IntersectsWith(r1)); // False
System.Console.WriteLine(r.IntersectsWith(r2)); // True
System.Console.WriteLine(r.IntersectsWith(r3)); // False

Я бы подумал, что r1 и r2 должны всегда пересекаться с r, даже если они этого не делают. r3 должен пересекаться, если вы считаете их отрицательный размер. Если отрицательные размеры не учитываются, r0 должен пересекаться.

Почему это работает так, как это делается, и какие другие оговорки я должен искать при работе с структурами Rectangle?

Ответ 1

Если вы создаете прямоугольник с отрицательной шириной, он рисует прямоугольник, который начинается с исходной (x, y) точки и рисует влево, а не вправо.

Если вы создаете прямоугольник с отрицательной высотой, он рисует прямоугольник, который начинается с исходной (x, y) точки и рисует вверх, а не вниз.

Таким образом, если вы создаете прямоугольник с say new Rectangle(5, 4, -1, -2);, тогда вы получите прямоугольник со следующими точками: (5,4), (4,4), (5,2), (4,2).

Выполните следующий код для примера:

    Rectangle negWidthHeightRect = new Rectangle(5, 4, -1, -2);
    Console.WriteLine(negWidthHeightRect.Left);
    Console.WriteLine(negWidthHeightRect.Right);
    Console.WriteLine(negWidthHeightRect.Bottom);
    Console.WriteLine(negWidthHeightRect.Top);
    Console.WriteLine(negWidthHeightRect.Width);
    Console.WriteLine(negWidthHeightRect.Height);
    Console.ReadLine();

Выход выглядит следующим образом:

5
4
2
4
-1
-2

Поведение несколько ожидаемо, учитывая комментарии Microsoft к другим элементам, подобным прямоугольнику (помимо System.Drawing.Rectangle). См. MSDM здесь.

Теперь, почему метод прямоугольника IntersectsWith создает такие странные результаты. Это связано с тем, что для реализации метода IntersectsWith используется следующий код:

public bool IntersectsWith(Rectangle rect)
{
    return ((((rect.X < (this.X + this.Width)) && (this.X < (rect.X + rect.Width))) && (rect.Y < (this.Y + this.Height))) && (this.Y < (rect.Y + rect.Height)));
}

Если вы будете следовать логике самостоятельно, вы поймете, почему вы получаете ответы, которые вы получаете. Вероятно, Microsoft должна сделать следующее:

1), когда он видит отрицательную ширину/высоту, сделайте ширину/высоту положительной и отрегулируйте Left/Top

2) Или в IntersectsWith логике, они должны делать некоторые Min (x, x + width) и Min (y, y + width) при выполнении логики.

Некоторые другие умнее меня могут иметь еще более умный способ сделать это.

Ответ 2

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